1 //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the language specific #pragma handlers.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "RAIIObjectsForParser.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/Basic/TargetInfo.h"
17 #include "clang/Lex/Preprocessor.h"
18 #include "clang/Parse/ParseDiagnostic.h"
19 #include "clang/Parse/Parser.h"
20 #include "clang/Sema/LoopHint.h"
21 #include "clang/Sema/Scope.h"
22 #include "llvm/ADT/StringSwitch.h"
23 using namespace clang;
24 
25 namespace {
26 
27 struct PragmaAlignHandler : public PragmaHandler {
PragmaAlignHandler__anon62b95dc20111::PragmaAlignHandler28   explicit PragmaAlignHandler() : PragmaHandler("align") {}
29   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
30                     Token &FirstToken) override;
31 };
32 
33 struct PragmaGCCVisibilityHandler : public PragmaHandler {
PragmaGCCVisibilityHandler__anon62b95dc20111::PragmaGCCVisibilityHandler34   explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
35   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
36                     Token &FirstToken) override;
37 };
38 
39 struct PragmaOptionsHandler : public PragmaHandler {
PragmaOptionsHandler__anon62b95dc20111::PragmaOptionsHandler40   explicit PragmaOptionsHandler() : PragmaHandler("options") {}
41   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
42                     Token &FirstToken) override;
43 };
44 
45 struct PragmaPackHandler : public PragmaHandler {
PragmaPackHandler__anon62b95dc20111::PragmaPackHandler46   explicit PragmaPackHandler() : PragmaHandler("pack") {}
47   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
48                     Token &FirstToken) override;
49 };
50 
51 struct PragmaMSStructHandler : public PragmaHandler {
PragmaMSStructHandler__anon62b95dc20111::PragmaMSStructHandler52   explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
53   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
54                     Token &FirstToken) override;
55 };
56 
57 struct PragmaUnusedHandler : public PragmaHandler {
PragmaUnusedHandler__anon62b95dc20111::PragmaUnusedHandler58   PragmaUnusedHandler() : PragmaHandler("unused") {}
59   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
60                     Token &FirstToken) override;
61 };
62 
63 struct PragmaWeakHandler : public PragmaHandler {
PragmaWeakHandler__anon62b95dc20111::PragmaWeakHandler64   explicit PragmaWeakHandler() : PragmaHandler("weak") {}
65   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
66                     Token &FirstToken) override;
67 };
68 
69 struct PragmaRedefineExtnameHandler : public PragmaHandler {
PragmaRedefineExtnameHandler__anon62b95dc20111::PragmaRedefineExtnameHandler70   explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
71   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
72                     Token &FirstToken) override;
73 };
74 
75 struct PragmaOpenCLExtensionHandler : public PragmaHandler {
PragmaOpenCLExtensionHandler__anon62b95dc20111::PragmaOpenCLExtensionHandler76   PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
77   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
78                     Token &FirstToken) override;
79 };
80 
81 
82 struct PragmaFPContractHandler : public PragmaHandler {
PragmaFPContractHandler__anon62b95dc20111::PragmaFPContractHandler83   PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
84   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
85                     Token &FirstToken) override;
86 };
87 
88 struct PragmaNoOpenMPHandler : public PragmaHandler {
PragmaNoOpenMPHandler__anon62b95dc20111::PragmaNoOpenMPHandler89   PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
90   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
91                     Token &FirstToken) override;
92 };
93 
94 struct PragmaOpenMPHandler : public PragmaHandler {
PragmaOpenMPHandler__anon62b95dc20111::PragmaOpenMPHandler95   PragmaOpenMPHandler() : PragmaHandler("omp") { }
96   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
97                     Token &FirstToken) override;
98 };
99 
100 /// PragmaCommentHandler - "\#pragma comment ...".
101 struct PragmaCommentHandler : public PragmaHandler {
PragmaCommentHandler__anon62b95dc20111::PragmaCommentHandler102   PragmaCommentHandler(Sema &Actions)
103     : PragmaHandler("comment"), Actions(Actions) {}
104   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
105                     Token &FirstToken) override;
106 private:
107   Sema &Actions;
108 };
109 
110 struct PragmaDetectMismatchHandler : public PragmaHandler {
PragmaDetectMismatchHandler__anon62b95dc20111::PragmaDetectMismatchHandler111   PragmaDetectMismatchHandler(Sema &Actions)
112     : PragmaHandler("detect_mismatch"), Actions(Actions) {}
113   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
114                     Token &FirstToken) override;
115 private:
116   Sema &Actions;
117 };
118 
119 struct PragmaMSPointersToMembers : public PragmaHandler {
PragmaMSPointersToMembers__anon62b95dc20111::PragmaMSPointersToMembers120   explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
121   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
122                     Token &FirstToken) override;
123 };
124 
125 struct PragmaMSVtorDisp : public PragmaHandler {
PragmaMSVtorDisp__anon62b95dc20111::PragmaMSVtorDisp126   explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
127   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
128                     Token &FirstToken) override;
129 };
130 
131 struct PragmaMSPragma : public PragmaHandler {
PragmaMSPragma__anon62b95dc20111::PragmaMSPragma132   explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
133   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
134                     Token &FirstToken) override;
135 };
136 
137 /// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
138 struct PragmaOptimizeHandler : public PragmaHandler {
PragmaOptimizeHandler__anon62b95dc20111::PragmaOptimizeHandler139   PragmaOptimizeHandler(Sema &S)
140     : PragmaHandler("optimize"), Actions(S) {}
141   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
142                     Token &FirstToken) override;
143 private:
144   Sema &Actions;
145 };
146 
147 struct PragmaLoopHintHandler : public PragmaHandler {
PragmaLoopHintHandler__anon62b95dc20111::PragmaLoopHintHandler148   PragmaLoopHintHandler() : PragmaHandler("loop") {}
149   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
150                     Token &FirstToken) override;
151 };
152 
153 struct PragmaUnrollHintHandler : public PragmaHandler {
PragmaUnrollHintHandler__anon62b95dc20111::PragmaUnrollHintHandler154   PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
155   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
156                     Token &FirstToken) override;
157 };
158 
159 }  // end namespace
160 
initializePragmaHandlers()161 void Parser::initializePragmaHandlers() {
162   AlignHandler.reset(new PragmaAlignHandler());
163   PP.AddPragmaHandler(AlignHandler.get());
164 
165   GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
166   PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
167 
168   OptionsHandler.reset(new PragmaOptionsHandler());
169   PP.AddPragmaHandler(OptionsHandler.get());
170 
171   PackHandler.reset(new PragmaPackHandler());
172   PP.AddPragmaHandler(PackHandler.get());
173 
174   MSStructHandler.reset(new PragmaMSStructHandler());
175   PP.AddPragmaHandler(MSStructHandler.get());
176 
177   UnusedHandler.reset(new PragmaUnusedHandler());
178   PP.AddPragmaHandler(UnusedHandler.get());
179 
180   WeakHandler.reset(new PragmaWeakHandler());
181   PP.AddPragmaHandler(WeakHandler.get());
182 
183   RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
184   PP.AddPragmaHandler(RedefineExtnameHandler.get());
185 
186   FPContractHandler.reset(new PragmaFPContractHandler());
187   PP.AddPragmaHandler("STDC", FPContractHandler.get());
188 
189   if (getLangOpts().OpenCL) {
190     OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
191     PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
192 
193     PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
194   }
195   if (getLangOpts().OpenMP)
196     OpenMPHandler.reset(new PragmaOpenMPHandler());
197   else
198     OpenMPHandler.reset(new PragmaNoOpenMPHandler());
199   PP.AddPragmaHandler(OpenMPHandler.get());
200 
201   if (getLangOpts().MicrosoftExt) {
202     MSCommentHandler.reset(new PragmaCommentHandler(Actions));
203     PP.AddPragmaHandler(MSCommentHandler.get());
204     MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
205     PP.AddPragmaHandler(MSDetectMismatchHandler.get());
206     MSPointersToMembers.reset(new PragmaMSPointersToMembers());
207     PP.AddPragmaHandler(MSPointersToMembers.get());
208     MSVtorDisp.reset(new PragmaMSVtorDisp());
209     PP.AddPragmaHandler(MSVtorDisp.get());
210     MSInitSeg.reset(new PragmaMSPragma("init_seg"));
211     PP.AddPragmaHandler(MSInitSeg.get());
212     MSDataSeg.reset(new PragmaMSPragma("data_seg"));
213     PP.AddPragmaHandler(MSDataSeg.get());
214     MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
215     PP.AddPragmaHandler(MSBSSSeg.get());
216     MSConstSeg.reset(new PragmaMSPragma("const_seg"));
217     PP.AddPragmaHandler(MSConstSeg.get());
218     MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
219     PP.AddPragmaHandler(MSCodeSeg.get());
220     MSSection.reset(new PragmaMSPragma("section"));
221     PP.AddPragmaHandler(MSSection.get());
222   }
223 
224   OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
225   PP.AddPragmaHandler("clang", OptimizeHandler.get());
226 
227   LoopHintHandler.reset(new PragmaLoopHintHandler());
228   PP.AddPragmaHandler("clang", LoopHintHandler.get());
229 
230   UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
231   PP.AddPragmaHandler(UnrollHintHandler.get());
232 
233   NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
234   PP.AddPragmaHandler(NoUnrollHintHandler.get());
235 }
236 
resetPragmaHandlers()237 void Parser::resetPragmaHandlers() {
238   // Remove the pragma handlers we installed.
239   PP.RemovePragmaHandler(AlignHandler.get());
240   AlignHandler.reset();
241   PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
242   GCCVisibilityHandler.reset();
243   PP.RemovePragmaHandler(OptionsHandler.get());
244   OptionsHandler.reset();
245   PP.RemovePragmaHandler(PackHandler.get());
246   PackHandler.reset();
247   PP.RemovePragmaHandler(MSStructHandler.get());
248   MSStructHandler.reset();
249   PP.RemovePragmaHandler(UnusedHandler.get());
250   UnusedHandler.reset();
251   PP.RemovePragmaHandler(WeakHandler.get());
252   WeakHandler.reset();
253   PP.RemovePragmaHandler(RedefineExtnameHandler.get());
254   RedefineExtnameHandler.reset();
255 
256   if (getLangOpts().OpenCL) {
257     PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
258     OpenCLExtensionHandler.reset();
259     PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
260   }
261   PP.RemovePragmaHandler(OpenMPHandler.get());
262   OpenMPHandler.reset();
263 
264   if (getLangOpts().MicrosoftExt) {
265     PP.RemovePragmaHandler(MSCommentHandler.get());
266     MSCommentHandler.reset();
267     PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
268     MSDetectMismatchHandler.reset();
269     PP.RemovePragmaHandler(MSPointersToMembers.get());
270     MSPointersToMembers.reset();
271     PP.RemovePragmaHandler(MSVtorDisp.get());
272     MSVtorDisp.reset();
273     PP.RemovePragmaHandler(MSInitSeg.get());
274     MSInitSeg.reset();
275     PP.RemovePragmaHandler(MSDataSeg.get());
276     MSDataSeg.reset();
277     PP.RemovePragmaHandler(MSBSSSeg.get());
278     MSBSSSeg.reset();
279     PP.RemovePragmaHandler(MSConstSeg.get());
280     MSConstSeg.reset();
281     PP.RemovePragmaHandler(MSCodeSeg.get());
282     MSCodeSeg.reset();
283     PP.RemovePragmaHandler(MSSection.get());
284     MSSection.reset();
285   }
286 
287   PP.RemovePragmaHandler("STDC", FPContractHandler.get());
288   FPContractHandler.reset();
289 
290   PP.RemovePragmaHandler("clang", OptimizeHandler.get());
291   OptimizeHandler.reset();
292 
293   PP.RemovePragmaHandler("clang", LoopHintHandler.get());
294   LoopHintHandler.reset();
295 
296   PP.RemovePragmaHandler(UnrollHintHandler.get());
297   UnrollHintHandler.reset();
298 
299   PP.RemovePragmaHandler(NoUnrollHintHandler.get());
300   NoUnrollHintHandler.reset();
301 }
302 
303 /// \brief Handle the annotation token produced for #pragma unused(...)
304 ///
305 /// Each annot_pragma_unused is followed by the argument token so e.g.
306 /// "#pragma unused(x,y)" becomes:
307 /// annot_pragma_unused 'x' annot_pragma_unused 'y'
HandlePragmaUnused()308 void Parser::HandlePragmaUnused() {
309   assert(Tok.is(tok::annot_pragma_unused));
310   SourceLocation UnusedLoc = ConsumeToken();
311   Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
312   ConsumeToken(); // The argument token.
313 }
314 
HandlePragmaVisibility()315 void Parser::HandlePragmaVisibility() {
316   assert(Tok.is(tok::annot_pragma_vis));
317   const IdentifierInfo *VisType =
318     static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
319   SourceLocation VisLoc = ConsumeToken();
320   Actions.ActOnPragmaVisibility(VisType, VisLoc);
321 }
322 
323 struct PragmaPackInfo {
324   Sema::PragmaPackKind Kind;
325   IdentifierInfo *Name;
326   Token Alignment;
327   SourceLocation LParenLoc;
328   SourceLocation RParenLoc;
329 };
330 
HandlePragmaPack()331 void Parser::HandlePragmaPack() {
332   assert(Tok.is(tok::annot_pragma_pack));
333   PragmaPackInfo *Info =
334     static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
335   SourceLocation PragmaLoc = ConsumeToken();
336   ExprResult Alignment;
337   if (Info->Alignment.is(tok::numeric_constant)) {
338     Alignment = Actions.ActOnNumericConstant(Info->Alignment);
339     if (Alignment.isInvalid())
340       return;
341   }
342   Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
343                           Info->LParenLoc, Info->RParenLoc);
344 }
345 
HandlePragmaMSStruct()346 void Parser::HandlePragmaMSStruct() {
347   assert(Tok.is(tok::annot_pragma_msstruct));
348   Sema::PragmaMSStructKind Kind =
349     static_cast<Sema::PragmaMSStructKind>(
350     reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
351   Actions.ActOnPragmaMSStruct(Kind);
352   ConsumeToken(); // The annotation token.
353 }
354 
HandlePragmaAlign()355 void Parser::HandlePragmaAlign() {
356   assert(Tok.is(tok::annot_pragma_align));
357   Sema::PragmaOptionsAlignKind Kind =
358     static_cast<Sema::PragmaOptionsAlignKind>(
359     reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
360   SourceLocation PragmaLoc = ConsumeToken();
361   Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
362 }
363 
HandlePragmaWeak()364 void Parser::HandlePragmaWeak() {
365   assert(Tok.is(tok::annot_pragma_weak));
366   SourceLocation PragmaLoc = ConsumeToken();
367   Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
368                             Tok.getLocation());
369   ConsumeToken(); // The weak name.
370 }
371 
HandlePragmaWeakAlias()372 void Parser::HandlePragmaWeakAlias() {
373   assert(Tok.is(tok::annot_pragma_weakalias));
374   SourceLocation PragmaLoc = ConsumeToken();
375   IdentifierInfo *WeakName = Tok.getIdentifierInfo();
376   SourceLocation WeakNameLoc = Tok.getLocation();
377   ConsumeToken();
378   IdentifierInfo *AliasName = Tok.getIdentifierInfo();
379   SourceLocation AliasNameLoc = Tok.getLocation();
380   ConsumeToken();
381   Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
382                                WeakNameLoc, AliasNameLoc);
383 
384 }
385 
HandlePragmaRedefineExtname()386 void Parser::HandlePragmaRedefineExtname() {
387   assert(Tok.is(tok::annot_pragma_redefine_extname));
388   SourceLocation RedefLoc = ConsumeToken();
389   IdentifierInfo *RedefName = Tok.getIdentifierInfo();
390   SourceLocation RedefNameLoc = Tok.getLocation();
391   ConsumeToken();
392   IdentifierInfo *AliasName = Tok.getIdentifierInfo();
393   SourceLocation AliasNameLoc = Tok.getLocation();
394   ConsumeToken();
395   Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
396                                      RedefNameLoc, AliasNameLoc);
397 }
398 
HandlePragmaFPContract()399 void Parser::HandlePragmaFPContract() {
400   assert(Tok.is(tok::annot_pragma_fp_contract));
401   tok::OnOffSwitch OOS =
402     static_cast<tok::OnOffSwitch>(
403     reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
404   Actions.ActOnPragmaFPContract(OOS);
405   ConsumeToken(); // The annotation token.
406 }
407 
HandlePragmaCaptured()408 StmtResult Parser::HandlePragmaCaptured()
409 {
410   assert(Tok.is(tok::annot_pragma_captured));
411   ConsumeToken();
412 
413   if (Tok.isNot(tok::l_brace)) {
414     PP.Diag(Tok, diag::err_expected) << tok::l_brace;
415     return StmtError();
416   }
417 
418   SourceLocation Loc = Tok.getLocation();
419 
420   ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
421   Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
422                                    /*NumParams=*/1);
423 
424   StmtResult R = ParseCompoundStatement();
425   CapturedRegionScope.Exit();
426 
427   if (R.isInvalid()) {
428     Actions.ActOnCapturedRegionError();
429     return StmtError();
430   }
431 
432   return Actions.ActOnCapturedRegionEnd(R.get());
433 }
434 
435 namespace {
436   typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
437 }
438 
HandlePragmaOpenCLExtension()439 void Parser::HandlePragmaOpenCLExtension() {
440   assert(Tok.is(tok::annot_pragma_opencl_extension));
441   OpenCLExtData data =
442       OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
443   unsigned state = data.getInt();
444   IdentifierInfo *ename = data.getPointer();
445   SourceLocation NameLoc = Tok.getLocation();
446   ConsumeToken(); // The annotation token.
447 
448   OpenCLOptions &f = Actions.getOpenCLOptions();
449   // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
450   // overriding all previously issued extension directives, but only if the
451   // behavior is set to disable."
452   if (state == 0 && ename->isStr("all")) {
453 #define OPENCLEXT(nm)   f.nm = 0;
454 #include "clang/Basic/OpenCLExtensions.def"
455   }
456 #define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
457 #include "clang/Basic/OpenCLExtensions.def"
458   else {
459     PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
460     return;
461   }
462 }
463 
HandlePragmaMSPointersToMembers()464 void Parser::HandlePragmaMSPointersToMembers() {
465   assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
466   LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
467       static_cast<LangOptions::PragmaMSPointersToMembersKind>(
468           reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
469   SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
470   Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
471 }
472 
HandlePragmaMSVtorDisp()473 void Parser::HandlePragmaMSVtorDisp() {
474   assert(Tok.is(tok::annot_pragma_ms_vtordisp));
475   uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
476   Sema::PragmaVtorDispKind Kind =
477       static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
478   MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
479   SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
480   Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
481 }
482 
HandlePragmaMSPragma()483 void Parser::HandlePragmaMSPragma() {
484   assert(Tok.is(tok::annot_pragma_ms_pragma));
485   // Grab the tokens out of the annotation and enter them into the stream.
486   auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue();
487   PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
488   SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
489   assert(Tok.isAnyIdentifier());
490   StringRef PragmaName = Tok.getIdentifierInfo()->getName();
491   PP.Lex(Tok); // pragma kind
492 
493   // Figure out which #pragma we're dealing with.  The switch has no default
494   // because lex shouldn't emit the annotation token for unrecognized pragmas.
495   typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
496   PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
497     .Case("data_seg", &Parser::HandlePragmaMSSegment)
498     .Case("bss_seg", &Parser::HandlePragmaMSSegment)
499     .Case("const_seg", &Parser::HandlePragmaMSSegment)
500     .Case("code_seg", &Parser::HandlePragmaMSSegment)
501     .Case("section", &Parser::HandlePragmaMSSection)
502     .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
503 
504   if (!(this->*Handler)(PragmaName, PragmaLocation)) {
505     // Pragma handling failed, and has been diagnosed.  Slurp up the tokens
506     // until eof (really end of line) to prevent follow-on errors.
507     while (Tok.isNot(tok::eof))
508       PP.Lex(Tok);
509     PP.Lex(Tok);
510   }
511 }
512 
HandlePragmaMSSection(StringRef PragmaName,SourceLocation PragmaLocation)513 bool Parser::HandlePragmaMSSection(StringRef PragmaName,
514                                    SourceLocation PragmaLocation) {
515   if (Tok.isNot(tok::l_paren)) {
516     PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
517     return false;
518   }
519   PP.Lex(Tok); // (
520   // Parsing code for pragma section
521   if (Tok.isNot(tok::string_literal)) {
522     PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
523         << PragmaName;
524     return false;
525   }
526   ExprResult StringResult = ParseStringLiteralExpression();
527   if (StringResult.isInvalid())
528     return false; // Already diagnosed.
529   StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
530   if (SegmentName->getCharByteWidth() != 1) {
531     PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
532         << PragmaName;
533     return false;
534   }
535   int SectionFlags = ASTContext::PSF_Read;
536   bool SectionFlagsAreDefault = true;
537   while (Tok.is(tok::comma)) {
538     PP.Lex(Tok); // ,
539     // Ignore "long" and "short".
540     // They are undocumented, but widely used, section attributes which appear
541     // to do nothing.
542     if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
543       PP.Lex(Tok); // long/short
544       continue;
545     }
546 
547     if (!Tok.isAnyIdentifier()) {
548       PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
549           << PragmaName;
550       return false;
551     }
552     ASTContext::PragmaSectionFlag Flag =
553       llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
554       Tok.getIdentifierInfo()->getName())
555       .Case("read", ASTContext::PSF_Read)
556       .Case("write", ASTContext::PSF_Write)
557       .Case("execute", ASTContext::PSF_Execute)
558       .Case("shared", ASTContext::PSF_Invalid)
559       .Case("nopage", ASTContext::PSF_Invalid)
560       .Case("nocache", ASTContext::PSF_Invalid)
561       .Case("discard", ASTContext::PSF_Invalid)
562       .Case("remove", ASTContext::PSF_Invalid)
563       .Default(ASTContext::PSF_None);
564     if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
565       PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
566                                   ? diag::warn_pragma_invalid_specific_action
567                                   : diag::warn_pragma_unsupported_action)
568           << PragmaName << Tok.getIdentifierInfo()->getName();
569       return false;
570     }
571     SectionFlags |= Flag;
572     SectionFlagsAreDefault = false;
573     PP.Lex(Tok); // Identifier
574   }
575   // If no section attributes are specified, the section will be marked as
576   // read/write.
577   if (SectionFlagsAreDefault)
578     SectionFlags |= ASTContext::PSF_Write;
579   if (Tok.isNot(tok::r_paren)) {
580     PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
581     return false;
582   }
583   PP.Lex(Tok); // )
584   if (Tok.isNot(tok::eof)) {
585     PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
586         << PragmaName;
587     return false;
588   }
589   PP.Lex(Tok); // eof
590   Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
591   return true;
592 }
593 
HandlePragmaMSSegment(StringRef PragmaName,SourceLocation PragmaLocation)594 bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
595                                    SourceLocation PragmaLocation) {
596   if (Tok.isNot(tok::l_paren)) {
597     PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
598     return false;
599   }
600   PP.Lex(Tok); // (
601   Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
602   StringRef SlotLabel;
603   if (Tok.isAnyIdentifier()) {
604     StringRef PushPop = Tok.getIdentifierInfo()->getName();
605     if (PushPop == "push")
606       Action = Sema::PSK_Push;
607     else if (PushPop == "pop")
608       Action = Sema::PSK_Pop;
609     else {
610       PP.Diag(PragmaLocation,
611               diag::warn_pragma_expected_section_push_pop_or_name)
612           << PragmaName;
613       return false;
614     }
615     if (Action != Sema::PSK_Reset) {
616       PP.Lex(Tok); // push | pop
617       if (Tok.is(tok::comma)) {
618         PP.Lex(Tok); // ,
619         // If we've got a comma, we either need a label or a string.
620         if (Tok.isAnyIdentifier()) {
621           SlotLabel = Tok.getIdentifierInfo()->getName();
622           PP.Lex(Tok); // identifier
623           if (Tok.is(tok::comma))
624             PP.Lex(Tok);
625           else if (Tok.isNot(tok::r_paren)) {
626             PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
627                 << PragmaName;
628             return false;
629           }
630         }
631       } else if (Tok.isNot(tok::r_paren)) {
632         PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
633         return false;
634       }
635     }
636   }
637   // Grab the string literal for our section name.
638   StringLiteral *SegmentName = nullptr;
639   if (Tok.isNot(tok::r_paren)) {
640     if (Tok.isNot(tok::string_literal)) {
641       unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
642           diag::warn_pragma_expected_section_name :
643           diag::warn_pragma_expected_section_label_or_name :
644           diag::warn_pragma_expected_section_push_pop_or_name;
645       PP.Diag(PragmaLocation, DiagID) << PragmaName;
646       return false;
647     }
648     ExprResult StringResult = ParseStringLiteralExpression();
649     if (StringResult.isInvalid())
650       return false; // Already diagnosed.
651     SegmentName = cast<StringLiteral>(StringResult.get());
652     if (SegmentName->getCharByteWidth() != 1) {
653       PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
654           << PragmaName;
655       return false;
656     }
657     // Setting section "" has no effect
658     if (SegmentName->getLength())
659       Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
660   }
661   if (Tok.isNot(tok::r_paren)) {
662     PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
663     return false;
664   }
665   PP.Lex(Tok); // )
666   if (Tok.isNot(tok::eof)) {
667     PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
668         << PragmaName;
669     return false;
670   }
671   PP.Lex(Tok); // eof
672   Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
673                            SegmentName, PragmaName);
674   return true;
675 }
676 
677 // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
HandlePragmaMSInitSeg(StringRef PragmaName,SourceLocation PragmaLocation)678 bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
679                                    SourceLocation PragmaLocation) {
680   if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
681     PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
682     return false;
683   }
684 
685   if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
686                        PragmaName))
687     return false;
688 
689   // Parse either the known section names or the string section name.
690   StringLiteral *SegmentName = nullptr;
691   if (Tok.isAnyIdentifier()) {
692     auto *II = Tok.getIdentifierInfo();
693     StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
694                             .Case("compiler", "\".CRT$XCC\"")
695                             .Case("lib", "\".CRT$XCL\"")
696                             .Case("user", "\".CRT$XCU\"")
697                             .Default("");
698 
699     if (!Section.empty()) {
700       // Pretend the user wrote the appropriate string literal here.
701       Token Toks[1];
702       Toks[0].startToken();
703       Toks[0].setKind(tok::string_literal);
704       Toks[0].setLocation(Tok.getLocation());
705       Toks[0].setLiteralData(Section.data());
706       Toks[0].setLength(Section.size());
707       SegmentName =
708           cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
709       PP.Lex(Tok);
710     }
711   } else if (Tok.is(tok::string_literal)) {
712     ExprResult StringResult = ParseStringLiteralExpression();
713     if (StringResult.isInvalid())
714       return false;
715     SegmentName = cast<StringLiteral>(StringResult.get());
716     if (SegmentName->getCharByteWidth() != 1) {
717       PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
718           << PragmaName;
719       return false;
720     }
721     // FIXME: Add support for the '[, func-name]' part of the pragma.
722   }
723 
724   if (!SegmentName) {
725     PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
726     return false;
727   }
728 
729   if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
730                        PragmaName) ||
731       ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
732                        PragmaName))
733     return false;
734 
735   Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
736   return true;
737 }
738 
739 struct PragmaLoopHintInfo {
740   Token PragmaName;
741   Token Option;
742   Token *Toks;
743   size_t TokSize;
PragmaLoopHintInfoPragmaLoopHintInfo744   PragmaLoopHintInfo() : Toks(nullptr), TokSize(0) {}
745 };
746 
PragmaLoopHintString(Token PragmaName,Token Option)747 static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
748   std::string PragmaString;
749   if (PragmaName.getIdentifierInfo()->getName() == "loop") {
750     PragmaString = "clang loop ";
751     PragmaString += Option.getIdentifierInfo()->getName();
752   } else {
753     assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
754            "Unexpected pragma name");
755     PragmaString = "unroll";
756   }
757   return PragmaString;
758 }
759 
HandlePragmaLoopHint(LoopHint & Hint)760 bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
761   assert(Tok.is(tok::annot_pragma_loop_hint));
762   PragmaLoopHintInfo *Info =
763       static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
764 
765   IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
766   Hint.PragmaNameLoc = IdentifierLoc::create(
767       Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
768 
769   // It is possible that the loop hint has no option identifier, such as
770   // #pragma unroll(4).
771   IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
772                                    ? Info->Option.getIdentifierInfo()
773                                    : nullptr;
774   Hint.OptionLoc = IdentifierLoc::create(
775       Actions.Context, Info->Option.getLocation(), OptionInfo);
776 
777   Token *Toks = Info->Toks;
778   size_t TokSize = Info->TokSize;
779 
780   // Return a valid hint if pragma unroll or nounroll were specified
781   // without an argument.
782   bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
783   bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
784   if (TokSize == 0 && (PragmaUnroll || PragmaNoUnroll)) {
785     ConsumeToken(); // The annotation token.
786     Hint.Range = Info->PragmaName.getLocation();
787     return true;
788   }
789 
790   // The constant expression is always followed by an eof token, which increases
791   // the TokSize by 1.
792   assert(TokSize > 0 &&
793          "PragmaLoopHintInfo::Toks must contain at least one token.");
794 
795   // If no option is specified the argument is assumed to be a constant expr.
796   bool StateOption = false;
797   if (OptionInfo) { // Pragma unroll does not specify an option.
798     StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
799                       .Case("vectorize", true)
800                       .Case("interleave", true)
801                       .Case("unroll", true)
802                       .Default(false);
803   }
804 
805   // Verify loop hint has an argument.
806   if (Toks[0].is(tok::eof)) {
807     ConsumeToken(); // The annotation token.
808     Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
809         << /*StateArgument=*/StateOption << /*FullKeyword=*/PragmaUnroll;
810     return false;
811   }
812 
813   // Validate the argument.
814   if (StateOption) {
815     ConsumeToken(); // The annotation token.
816     bool OptionUnroll = OptionInfo->isStr("unroll");
817     SourceLocation StateLoc = Toks[0].getLocation();
818     IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
819     if (!StateInfo || ((OptionUnroll ? !StateInfo->isStr("full")
820                                      : !StateInfo->isStr("enable")) &&
821                        !StateInfo->isStr("disable"))) {
822       Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
823           << /*FullKeyword=*/OptionUnroll;
824       return false;
825     }
826     if (TokSize > 2)
827       Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
828           << PragmaLoopHintString(Info->PragmaName, Info->Option);
829     Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
830   } else {
831     // Enter constant expression including eof terminator into token stream.
832     PP.EnterTokenStream(Toks, TokSize, /*DisableMacroExpansion=*/false,
833                         /*OwnsTokens=*/false);
834     ConsumeToken(); // The annotation token.
835 
836     ExprResult R = ParseConstantExpression();
837 
838     // Tokens following an error in an ill-formed constant expression will
839     // remain in the token stream and must be removed.
840     if (Tok.isNot(tok::eof)) {
841       Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
842           << PragmaLoopHintString(Info->PragmaName, Info->Option);
843       while (Tok.isNot(tok::eof))
844         ConsumeAnyToken();
845     }
846 
847     ConsumeToken(); // Consume the constant expression eof terminator.
848 
849     if (R.isInvalid() ||
850         Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
851       return false;
852 
853     // Argument is a constant expression with an integer type.
854     Hint.ValueExpr = R.get();
855   }
856 
857   Hint.Range = SourceRange(Info->PragmaName.getLocation(),
858                            Info->Toks[TokSize - 1].getLocation());
859   return true;
860 }
861 
862 // #pragma GCC visibility comes in two variants:
863 //   'push' '(' [visibility] ')'
864 //   'pop'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & VisTok)865 void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
866                                               PragmaIntroducerKind Introducer,
867                                               Token &VisTok) {
868   SourceLocation VisLoc = VisTok.getLocation();
869 
870   Token Tok;
871   PP.LexUnexpandedToken(Tok);
872 
873   const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
874 
875   const IdentifierInfo *VisType;
876   if (PushPop && PushPop->isStr("pop")) {
877     VisType = nullptr;
878   } else if (PushPop && PushPop->isStr("push")) {
879     PP.LexUnexpandedToken(Tok);
880     if (Tok.isNot(tok::l_paren)) {
881       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
882         << "visibility";
883       return;
884     }
885     PP.LexUnexpandedToken(Tok);
886     VisType = Tok.getIdentifierInfo();
887     if (!VisType) {
888       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
889         << "visibility";
890       return;
891     }
892     PP.LexUnexpandedToken(Tok);
893     if (Tok.isNot(tok::r_paren)) {
894       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
895         << "visibility";
896       return;
897     }
898   } else {
899     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
900       << "visibility";
901     return;
902   }
903   PP.LexUnexpandedToken(Tok);
904   if (Tok.isNot(tok::eod)) {
905     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
906       << "visibility";
907     return;
908   }
909 
910   Token *Toks = new Token[1];
911   Toks[0].startToken();
912   Toks[0].setKind(tok::annot_pragma_vis);
913   Toks[0].setLocation(VisLoc);
914   Toks[0].setAnnotationValue(
915                           const_cast<void*>(static_cast<const void*>(VisType)));
916   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
917                       /*OwnsTokens=*/true);
918 }
919 
920 // #pragma pack(...) comes in the following delicious flavors:
921 //   pack '(' [integer] ')'
922 //   pack '(' 'show' ')'
923 //   pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & PackTok)924 void PragmaPackHandler::HandlePragma(Preprocessor &PP,
925                                      PragmaIntroducerKind Introducer,
926                                      Token &PackTok) {
927   SourceLocation PackLoc = PackTok.getLocation();
928 
929   Token Tok;
930   PP.Lex(Tok);
931   if (Tok.isNot(tok::l_paren)) {
932     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
933     return;
934   }
935 
936   Sema::PragmaPackKind Kind = Sema::PPK_Default;
937   IdentifierInfo *Name = nullptr;
938   Token Alignment;
939   Alignment.startToken();
940   SourceLocation LParenLoc = Tok.getLocation();
941   PP.Lex(Tok);
942   if (Tok.is(tok::numeric_constant)) {
943     Alignment = Tok;
944 
945     PP.Lex(Tok);
946 
947     // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
948     // the push/pop stack.
949     // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
950     if (PP.getLangOpts().ApplePragmaPack)
951       Kind = Sema::PPK_Push;
952   } else if (Tok.is(tok::identifier)) {
953     const IdentifierInfo *II = Tok.getIdentifierInfo();
954     if (II->isStr("show")) {
955       Kind = Sema::PPK_Show;
956       PP.Lex(Tok);
957     } else {
958       if (II->isStr("push")) {
959         Kind = Sema::PPK_Push;
960       } else if (II->isStr("pop")) {
961         Kind = Sema::PPK_Pop;
962       } else {
963         PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
964         return;
965       }
966       PP.Lex(Tok);
967 
968       if (Tok.is(tok::comma)) {
969         PP.Lex(Tok);
970 
971         if (Tok.is(tok::numeric_constant)) {
972           Alignment = Tok;
973 
974           PP.Lex(Tok);
975         } else if (Tok.is(tok::identifier)) {
976           Name = Tok.getIdentifierInfo();
977           PP.Lex(Tok);
978 
979           if (Tok.is(tok::comma)) {
980             PP.Lex(Tok);
981 
982             if (Tok.isNot(tok::numeric_constant)) {
983               PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
984               return;
985             }
986 
987             Alignment = Tok;
988 
989             PP.Lex(Tok);
990           }
991         } else {
992           PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
993           return;
994         }
995       }
996     }
997   } else if (PP.getLangOpts().ApplePragmaPack) {
998     // In MSVC/gcc, #pragma pack() resets the alignment without affecting
999     // the push/pop stack.
1000     // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
1001     Kind = Sema::PPK_Pop;
1002   }
1003 
1004   if (Tok.isNot(tok::r_paren)) {
1005     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
1006     return;
1007   }
1008 
1009   SourceLocation RParenLoc = Tok.getLocation();
1010   PP.Lex(Tok);
1011   if (Tok.isNot(tok::eod)) {
1012     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1013     return;
1014   }
1015 
1016   PragmaPackInfo *Info =
1017     (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
1018       sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
1019   new (Info) PragmaPackInfo();
1020   Info->Kind = Kind;
1021   Info->Name = Name;
1022   Info->Alignment = Alignment;
1023   Info->LParenLoc = LParenLoc;
1024   Info->RParenLoc = RParenLoc;
1025 
1026   Token *Toks =
1027     (Token*) PP.getPreprocessorAllocator().Allocate(
1028       sizeof(Token) * 1, llvm::alignOf<Token>());
1029   new (Toks) Token();
1030   Toks[0].startToken();
1031   Toks[0].setKind(tok::annot_pragma_pack);
1032   Toks[0].setLocation(PackLoc);
1033   Toks[0].setAnnotationValue(static_cast<void*>(Info));
1034   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1035                       /*OwnsTokens=*/false);
1036 }
1037 
1038 // #pragma ms_struct on
1039 // #pragma ms_struct off
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & MSStructTok)1040 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
1041                                          PragmaIntroducerKind Introducer,
1042                                          Token &MSStructTok) {
1043   Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
1044 
1045   Token Tok;
1046   PP.Lex(Tok);
1047   if (Tok.isNot(tok::identifier)) {
1048     PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1049     return;
1050   }
1051   const IdentifierInfo *II = Tok.getIdentifierInfo();
1052   if (II->isStr("on")) {
1053     Kind = Sema::PMSST_ON;
1054     PP.Lex(Tok);
1055   }
1056   else if (II->isStr("off") || II->isStr("reset"))
1057     PP.Lex(Tok);
1058   else {
1059     PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1060     return;
1061   }
1062 
1063   if (Tok.isNot(tok::eod)) {
1064     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1065       << "ms_struct";
1066     return;
1067   }
1068 
1069   Token *Toks =
1070     (Token*) PP.getPreprocessorAllocator().Allocate(
1071       sizeof(Token) * 1, llvm::alignOf<Token>());
1072   new (Toks) Token();
1073   Toks[0].startToken();
1074   Toks[0].setKind(tok::annot_pragma_msstruct);
1075   Toks[0].setLocation(MSStructTok.getLocation());
1076   Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1077                              static_cast<uintptr_t>(Kind)));
1078   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1079                       /*OwnsTokens=*/false);
1080 }
1081 
1082 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1083 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
ParseAlignPragma(Preprocessor & PP,Token & FirstTok,bool IsOptions)1084 static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
1085                              bool IsOptions) {
1086   Token Tok;
1087 
1088   if (IsOptions) {
1089     PP.Lex(Tok);
1090     if (Tok.isNot(tok::identifier) ||
1091         !Tok.getIdentifierInfo()->isStr("align")) {
1092       PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1093       return;
1094     }
1095   }
1096 
1097   PP.Lex(Tok);
1098   if (Tok.isNot(tok::equal)) {
1099     PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1100       << IsOptions;
1101     return;
1102   }
1103 
1104   PP.Lex(Tok);
1105   if (Tok.isNot(tok::identifier)) {
1106     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1107       << (IsOptions ? "options" : "align");
1108     return;
1109   }
1110 
1111   Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
1112   const IdentifierInfo *II = Tok.getIdentifierInfo();
1113   if (II->isStr("native"))
1114     Kind = Sema::POAK_Native;
1115   else if (II->isStr("natural"))
1116     Kind = Sema::POAK_Natural;
1117   else if (II->isStr("packed"))
1118     Kind = Sema::POAK_Packed;
1119   else if (II->isStr("power"))
1120     Kind = Sema::POAK_Power;
1121   else if (II->isStr("mac68k"))
1122     Kind = Sema::POAK_Mac68k;
1123   else if (II->isStr("reset"))
1124     Kind = Sema::POAK_Reset;
1125   else {
1126     PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1127       << IsOptions;
1128     return;
1129   }
1130 
1131   PP.Lex(Tok);
1132   if (Tok.isNot(tok::eod)) {
1133     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1134       << (IsOptions ? "options" : "align");
1135     return;
1136   }
1137 
1138   Token *Toks =
1139     (Token*) PP.getPreprocessorAllocator().Allocate(
1140       sizeof(Token) * 1, llvm::alignOf<Token>());
1141   new (Toks) Token();
1142   Toks[0].startToken();
1143   Toks[0].setKind(tok::annot_pragma_align);
1144   Toks[0].setLocation(FirstTok.getLocation());
1145   Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1146                              static_cast<uintptr_t>(Kind)));
1147   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1148                       /*OwnsTokens=*/false);
1149 }
1150 
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & AlignTok)1151 void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
1152                                       PragmaIntroducerKind Introducer,
1153                                       Token &AlignTok) {
1154   ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
1155 }
1156 
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & OptionsTok)1157 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
1158                                         PragmaIntroducerKind Introducer,
1159                                         Token &OptionsTok) {
1160   ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
1161 }
1162 
1163 // #pragma unused(identifier)
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & UnusedTok)1164 void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
1165                                        PragmaIntroducerKind Introducer,
1166                                        Token &UnusedTok) {
1167   // FIXME: Should we be expanding macros here? My guess is no.
1168   SourceLocation UnusedLoc = UnusedTok.getLocation();
1169 
1170   // Lex the left '('.
1171   Token Tok;
1172   PP.Lex(Tok);
1173   if (Tok.isNot(tok::l_paren)) {
1174     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1175     return;
1176   }
1177 
1178   // Lex the declaration reference(s).
1179   SmallVector<Token, 5> Identifiers;
1180   SourceLocation RParenLoc;
1181   bool LexID = true;
1182 
1183   while (true) {
1184     PP.Lex(Tok);
1185 
1186     if (LexID) {
1187       if (Tok.is(tok::identifier)) {
1188         Identifiers.push_back(Tok);
1189         LexID = false;
1190         continue;
1191       }
1192 
1193       // Illegal token!
1194       PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1195       return;
1196     }
1197 
1198     // We are execting a ')' or a ','.
1199     if (Tok.is(tok::comma)) {
1200       LexID = true;
1201       continue;
1202     }
1203 
1204     if (Tok.is(tok::r_paren)) {
1205       RParenLoc = Tok.getLocation();
1206       break;
1207     }
1208 
1209     // Illegal token!
1210     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
1211     return;
1212   }
1213 
1214   PP.Lex(Tok);
1215   if (Tok.isNot(tok::eod)) {
1216     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1217         "unused";
1218     return;
1219   }
1220 
1221   // Verify that we have a location for the right parenthesis.
1222   assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
1223   assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
1224 
1225   // For each identifier token, insert into the token stream a
1226   // annot_pragma_unused token followed by the identifier token.
1227   // This allows us to cache a "#pragma unused" that occurs inside an inline
1228   // C++ member function.
1229 
1230   Token *Toks =
1231     (Token*) PP.getPreprocessorAllocator().Allocate(
1232       sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
1233   for (unsigned i=0; i != Identifiers.size(); i++) {
1234     Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1235     pragmaUnusedTok.startToken();
1236     pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1237     pragmaUnusedTok.setLocation(UnusedLoc);
1238     idTok = Identifiers[i];
1239   }
1240   PP.EnterTokenStream(Toks, 2*Identifiers.size(),
1241                       /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1242 }
1243 
1244 // #pragma weak identifier
1245 // #pragma weak identifier '=' identifier
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & WeakTok)1246 void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1247                                      PragmaIntroducerKind Introducer,
1248                                      Token &WeakTok) {
1249   SourceLocation WeakLoc = WeakTok.getLocation();
1250 
1251   Token Tok;
1252   PP.Lex(Tok);
1253   if (Tok.isNot(tok::identifier)) {
1254     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1255     return;
1256   }
1257 
1258   Token WeakName = Tok;
1259   bool HasAlias = false;
1260   Token AliasName;
1261 
1262   PP.Lex(Tok);
1263   if (Tok.is(tok::equal)) {
1264     HasAlias = true;
1265     PP.Lex(Tok);
1266     if (Tok.isNot(tok::identifier)) {
1267       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1268           << "weak";
1269       return;
1270     }
1271     AliasName = Tok;
1272     PP.Lex(Tok);
1273   }
1274 
1275   if (Tok.isNot(tok::eod)) {
1276     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1277     return;
1278   }
1279 
1280   if (HasAlias) {
1281     Token *Toks =
1282       (Token*) PP.getPreprocessorAllocator().Allocate(
1283         sizeof(Token) * 3, llvm::alignOf<Token>());
1284     Token &pragmaUnusedTok = Toks[0];
1285     pragmaUnusedTok.startToken();
1286     pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1287     pragmaUnusedTok.setLocation(WeakLoc);
1288     Toks[1] = WeakName;
1289     Toks[2] = AliasName;
1290     PP.EnterTokenStream(Toks, 3,
1291                         /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1292   } else {
1293     Token *Toks =
1294       (Token*) PP.getPreprocessorAllocator().Allocate(
1295         sizeof(Token) * 2, llvm::alignOf<Token>());
1296     Token &pragmaUnusedTok = Toks[0];
1297     pragmaUnusedTok.startToken();
1298     pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1299     pragmaUnusedTok.setLocation(WeakLoc);
1300     Toks[1] = WeakName;
1301     PP.EnterTokenStream(Toks, 2,
1302                         /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1303   }
1304 }
1305 
1306 // #pragma redefine_extname identifier identifier
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & RedefToken)1307 void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1308                                                PragmaIntroducerKind Introducer,
1309                                                 Token &RedefToken) {
1310   SourceLocation RedefLoc = RedefToken.getLocation();
1311 
1312   Token Tok;
1313   PP.Lex(Tok);
1314   if (Tok.isNot(tok::identifier)) {
1315     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1316       "redefine_extname";
1317     return;
1318   }
1319 
1320   Token RedefName = Tok;
1321   PP.Lex(Tok);
1322 
1323   if (Tok.isNot(tok::identifier)) {
1324     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1325         << "redefine_extname";
1326     return;
1327   }
1328 
1329   Token AliasName = Tok;
1330   PP.Lex(Tok);
1331 
1332   if (Tok.isNot(tok::eod)) {
1333     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1334       "redefine_extname";
1335     return;
1336   }
1337 
1338   Token *Toks =
1339     (Token*) PP.getPreprocessorAllocator().Allocate(
1340       sizeof(Token) * 3, llvm::alignOf<Token>());
1341   Token &pragmaRedefTok = Toks[0];
1342   pragmaRedefTok.startToken();
1343   pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1344   pragmaRedefTok.setLocation(RedefLoc);
1345   Toks[1] = RedefName;
1346   Toks[2] = AliasName;
1347   PP.EnterTokenStream(Toks, 3,
1348                       /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1349 }
1350 
1351 
1352 void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1353 PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
1354                                       PragmaIntroducerKind Introducer,
1355                                       Token &Tok) {
1356   tok::OnOffSwitch OOS;
1357   if (PP.LexOnOffSwitch(OOS))
1358     return;
1359 
1360   Token *Toks =
1361     (Token*) PP.getPreprocessorAllocator().Allocate(
1362       sizeof(Token) * 1, llvm::alignOf<Token>());
1363   new (Toks) Token();
1364   Toks[0].startToken();
1365   Toks[0].setKind(tok::annot_pragma_fp_contract);
1366   Toks[0].setLocation(Tok.getLocation());
1367   Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1368                              static_cast<uintptr_t>(OOS)));
1369   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1370                       /*OwnsTokens=*/false);
1371 }
1372 
1373 void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1374 PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
1375                                            PragmaIntroducerKind Introducer,
1376                                            Token &Tok) {
1377   PP.LexUnexpandedToken(Tok);
1378   if (Tok.isNot(tok::identifier)) {
1379     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1380       "OPENCL";
1381     return;
1382   }
1383   IdentifierInfo *ename = Tok.getIdentifierInfo();
1384   SourceLocation NameLoc = Tok.getLocation();
1385 
1386   PP.Lex(Tok);
1387   if (Tok.isNot(tok::colon)) {
1388     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
1389     return;
1390   }
1391 
1392   PP.Lex(Tok);
1393   if (Tok.isNot(tok::identifier)) {
1394     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1395     return;
1396   }
1397   IdentifierInfo *op = Tok.getIdentifierInfo();
1398 
1399   unsigned state;
1400   if (op->isStr("enable")) {
1401     state = 1;
1402   } else if (op->isStr("disable")) {
1403     state = 0;
1404   } else {
1405     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1406     return;
1407   }
1408   SourceLocation StateLoc = Tok.getLocation();
1409 
1410   PP.Lex(Tok);
1411   if (Tok.isNot(tok::eod)) {
1412     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1413       "OPENCL EXTENSION";
1414     return;
1415   }
1416 
1417   OpenCLExtData data(ename, state);
1418   Token *Toks =
1419     (Token*) PP.getPreprocessorAllocator().Allocate(
1420       sizeof(Token) * 1, llvm::alignOf<Token>());
1421   new (Toks) Token();
1422   Toks[0].startToken();
1423   Toks[0].setKind(tok::annot_pragma_opencl_extension);
1424   Toks[0].setLocation(NameLoc);
1425   Toks[0].setAnnotationValue(data.getOpaqueValue());
1426   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1427                       /*OwnsTokens=*/false);
1428 
1429   if (PP.getPPCallbacks())
1430     PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
1431                                                StateLoc, state);
1432 }
1433 
1434 /// \brief Handle '#pragma omp ...' when OpenMP is disabled.
1435 ///
1436 void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & FirstTok)1437 PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
1438                                     PragmaIntroducerKind Introducer,
1439                                     Token &FirstTok) {
1440   if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
1441                                      FirstTok.getLocation())) {
1442     PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
1443     PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
1444                                     diag::Severity::Ignored, SourceLocation());
1445   }
1446   PP.DiscardUntilEndOfDirective();
1447 }
1448 
1449 /// \brief Handle '#pragma omp ...' when OpenMP is enabled.
1450 ///
1451 void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & FirstTok)1452 PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
1453                                   PragmaIntroducerKind Introducer,
1454                                   Token &FirstTok) {
1455   SmallVector<Token, 16> Pragma;
1456   Token Tok;
1457   Tok.startToken();
1458   Tok.setKind(tok::annot_pragma_openmp);
1459   Tok.setLocation(FirstTok.getLocation());
1460 
1461   while (Tok.isNot(tok::eod)) {
1462     Pragma.push_back(Tok);
1463     PP.Lex(Tok);
1464   }
1465   SourceLocation EodLoc = Tok.getLocation();
1466   Tok.startToken();
1467   Tok.setKind(tok::annot_pragma_openmp_end);
1468   Tok.setLocation(EodLoc);
1469   Pragma.push_back(Tok);
1470 
1471   Token *Toks = new Token[Pragma.size()];
1472   std::copy(Pragma.begin(), Pragma.end(), Toks);
1473   PP.EnterTokenStream(Toks, Pragma.size(),
1474                       /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
1475 }
1476 
1477 /// \brief Handle '#pragma pointers_to_members'
1478 // The grammar for this pragma is as follows:
1479 //
1480 // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
1481 //
1482 // #pragma pointers_to_members '(' 'best_case' ')'
1483 // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
1484 // #pragma pointers_to_members '(' inheritance-model ')'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1485 void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
1486                                              PragmaIntroducerKind Introducer,
1487                                              Token &Tok) {
1488   SourceLocation PointersToMembersLoc = Tok.getLocation();
1489   PP.Lex(Tok);
1490   if (Tok.isNot(tok::l_paren)) {
1491     PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
1492       << "pointers_to_members";
1493     return;
1494   }
1495   PP.Lex(Tok);
1496   const IdentifierInfo *Arg = Tok.getIdentifierInfo();
1497   if (!Arg) {
1498     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1499       << "pointers_to_members";
1500     return;
1501   }
1502   PP.Lex(Tok);
1503 
1504   LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
1505   if (Arg->isStr("best_case")) {
1506     RepresentationMethod = LangOptions::PPTMK_BestCase;
1507   } else {
1508     if (Arg->isStr("full_generality")) {
1509       if (Tok.is(tok::comma)) {
1510         PP.Lex(Tok);
1511 
1512         Arg = Tok.getIdentifierInfo();
1513         if (!Arg) {
1514           PP.Diag(Tok.getLocation(),
1515                   diag::err_pragma_pointers_to_members_unknown_kind)
1516               << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
1517           return;
1518         }
1519         PP.Lex(Tok);
1520       } else if (Tok.is(tok::r_paren)) {
1521         // #pragma pointers_to_members(full_generality) implicitly specifies
1522         // virtual_inheritance.
1523         Arg = nullptr;
1524         RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1525       } else {
1526         PP.Diag(Tok.getLocation(), diag::err_expected_punc)
1527             << "full_generality";
1528         return;
1529       }
1530     }
1531 
1532     if (Arg) {
1533       if (Arg->isStr("single_inheritance")) {
1534         RepresentationMethod =
1535             LangOptions::PPTMK_FullGeneralitySingleInheritance;
1536       } else if (Arg->isStr("multiple_inheritance")) {
1537         RepresentationMethod =
1538             LangOptions::PPTMK_FullGeneralityMultipleInheritance;
1539       } else if (Arg->isStr("virtual_inheritance")) {
1540         RepresentationMethod =
1541             LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1542       } else {
1543         PP.Diag(Tok.getLocation(),
1544                 diag::err_pragma_pointers_to_members_unknown_kind)
1545             << Arg << /*HasPointerDeclaration*/ 1;
1546         return;
1547       }
1548     }
1549   }
1550 
1551   if (Tok.isNot(tok::r_paren)) {
1552     PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
1553         << (Arg ? Arg->getName() : "full_generality");
1554     return;
1555   }
1556 
1557   PP.Lex(Tok);
1558   if (Tok.isNot(tok::eod)) {
1559     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1560       << "pointers_to_members";
1561     return;
1562   }
1563 
1564   Token AnnotTok;
1565   AnnotTok.startToken();
1566   AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
1567   AnnotTok.setLocation(PointersToMembersLoc);
1568   AnnotTok.setAnnotationValue(
1569       reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
1570   PP.EnterToken(AnnotTok);
1571 }
1572 
1573 /// \brief Handle '#pragma vtordisp'
1574 // The grammar for this pragma is as follows:
1575 //
1576 // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
1577 //
1578 // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
1579 // #pragma vtordisp '(' 'pop' ')'
1580 // #pragma vtordisp '(' ')'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1581 void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
1582                                     PragmaIntroducerKind Introducer,
1583                                     Token &Tok) {
1584   SourceLocation VtorDispLoc = Tok.getLocation();
1585   PP.Lex(Tok);
1586   if (Tok.isNot(tok::l_paren)) {
1587     PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
1588     return;
1589   }
1590   PP.Lex(Tok);
1591 
1592   Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
1593   const IdentifierInfo *II = Tok.getIdentifierInfo();
1594   if (II) {
1595     if (II->isStr("push")) {
1596       // #pragma vtordisp(push, mode)
1597       PP.Lex(Tok);
1598       if (Tok.isNot(tok::comma)) {
1599         PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
1600         return;
1601       }
1602       PP.Lex(Tok);
1603       Kind = Sema::PVDK_Push;
1604       // not push, could be on/off
1605     } else if (II->isStr("pop")) {
1606       // #pragma vtordisp(pop)
1607       PP.Lex(Tok);
1608       Kind = Sema::PVDK_Pop;
1609     }
1610     // not push or pop, could be on/off
1611   } else {
1612     if (Tok.is(tok::r_paren)) {
1613       // #pragma vtordisp()
1614       Kind = Sema::PVDK_Reset;
1615     }
1616   }
1617 
1618 
1619   uint64_t Value = 0;
1620   if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
1621     const IdentifierInfo *II = Tok.getIdentifierInfo();
1622     if (II && II->isStr("off")) {
1623       PP.Lex(Tok);
1624       Value = 0;
1625     } else if (II && II->isStr("on")) {
1626       PP.Lex(Tok);
1627       Value = 1;
1628     } else if (Tok.is(tok::numeric_constant) &&
1629                PP.parseSimpleIntegerLiteral(Tok, Value)) {
1630       if (Value > 2) {
1631         PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
1632             << 0 << 2 << "vtordisp";
1633         return;
1634       }
1635     } else {
1636       PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1637           << "vtordisp";
1638       return;
1639     }
1640   }
1641 
1642   // Finish the pragma: ')' $
1643   if (Tok.isNot(tok::r_paren)) {
1644     PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
1645     return;
1646   }
1647   PP.Lex(Tok);
1648   if (Tok.isNot(tok::eod)) {
1649     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1650         << "vtordisp";
1651     return;
1652   }
1653 
1654   // Enter the annotation.
1655   Token AnnotTok;
1656   AnnotTok.startToken();
1657   AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1658   AnnotTok.setLocation(VtorDispLoc);
1659   AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
1660       static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
1661   PP.EnterToken(AnnotTok);
1662 }
1663 
1664 /// \brief Handle all MS pragmas.  Simply forwards the tokens after inserting
1665 /// an annotation token.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1666 void PragmaMSPragma::HandlePragma(Preprocessor &PP,
1667                                   PragmaIntroducerKind Introducer,
1668                                   Token &Tok) {
1669   Token EoF, AnnotTok;
1670   EoF.startToken();
1671   EoF.setKind(tok::eof);
1672   AnnotTok.startToken();
1673   AnnotTok.setKind(tok::annot_pragma_ms_pragma);
1674   AnnotTok.setLocation(Tok.getLocation());
1675   SmallVector<Token, 8> TokenVector;
1676   // Suck up all of the tokens before the eod.
1677   for (; Tok.isNot(tok::eod); PP.Lex(Tok))
1678     TokenVector.push_back(Tok);
1679   // Add a sentinal EoF token to the end of the list.
1680   TokenVector.push_back(EoF);
1681   // We must allocate this array with new because EnterTokenStream is going to
1682   // delete it later.
1683   Token *TokenArray = new Token[TokenVector.size()];
1684   std::copy(TokenVector.begin(), TokenVector.end(), TokenArray);
1685   auto Value = new (PP.getPreprocessorAllocator())
1686       std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size()));
1687   AnnotTok.setAnnotationValue(Value);
1688   PP.EnterToken(AnnotTok);
1689 }
1690 
1691 /// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1692 ///
1693 /// The syntax is:
1694 /// \code
1695 ///   #pragma detect_mismatch("name", "value")
1696 /// \endcode
1697 /// Where 'name' and 'value' are quoted strings.  The values are embedded in
1698 /// the object file and passed along to the linker.  If the linker detects a
1699 /// mismatch in the object file's values for the given name, a LNK2038 error
1700 /// is emitted.  See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1701 void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1702                                                PragmaIntroducerKind Introducer,
1703                                                Token &Tok) {
1704   SourceLocation CommentLoc = Tok.getLocation();
1705   PP.Lex(Tok);
1706   if (Tok.isNot(tok::l_paren)) {
1707     PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
1708     return;
1709   }
1710 
1711   // Read the name to embed, which must be a string literal.
1712   std::string NameString;
1713   if (!PP.LexStringLiteral(Tok, NameString,
1714                            "pragma detect_mismatch",
1715                            /*MacroExpansion=*/true))
1716     return;
1717 
1718   // Read the comma followed by a second string literal.
1719   std::string ValueString;
1720   if (Tok.isNot(tok::comma)) {
1721     PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1722     return;
1723   }
1724 
1725   if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1726                            /*MacroExpansion=*/true))
1727     return;
1728 
1729   if (Tok.isNot(tok::r_paren)) {
1730     PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1731     return;
1732   }
1733   PP.Lex(Tok);  // Eat the r_paren.
1734 
1735   if (Tok.isNot(tok::eod)) {
1736     PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1737     return;
1738   }
1739 
1740   // If the pragma is lexically sound, notify any interested PPCallbacks.
1741   if (PP.getPPCallbacks())
1742     PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
1743                                               ValueString);
1744 
1745   Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
1746 }
1747 
1748 /// \brief Handle the microsoft \#pragma comment extension.
1749 ///
1750 /// The syntax is:
1751 /// \code
1752 ///   #pragma comment(linker, "foo")
1753 /// \endcode
1754 /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1755 /// "foo" is a string, which is fully macro expanded, and permits string
1756 /// concatenation, embedded escape characters etc.  See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1757 void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1758                                         PragmaIntroducerKind Introducer,
1759                                         Token &Tok) {
1760   SourceLocation CommentLoc = Tok.getLocation();
1761   PP.Lex(Tok);
1762   if (Tok.isNot(tok::l_paren)) {
1763     PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1764     return;
1765   }
1766 
1767   // Read the identifier.
1768   PP.Lex(Tok);
1769   if (Tok.isNot(tok::identifier)) {
1770     PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1771     return;
1772   }
1773 
1774   // Verify that this is one of the 5 whitelisted options.
1775   IdentifierInfo *II = Tok.getIdentifierInfo();
1776   Sema::PragmaMSCommentKind Kind =
1777     llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
1778     .Case("linker",   Sema::PCK_Linker)
1779     .Case("lib",      Sema::PCK_Lib)
1780     .Case("compiler", Sema::PCK_Compiler)
1781     .Case("exestr",   Sema::PCK_ExeStr)
1782     .Case("user",     Sema::PCK_User)
1783     .Default(Sema::PCK_Unknown);
1784   if (Kind == Sema::PCK_Unknown) {
1785     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1786     return;
1787   }
1788 
1789   // Read the optional string if present.
1790   PP.Lex(Tok);
1791   std::string ArgumentString;
1792   if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1793                                                  "pragma comment",
1794                                                  /*MacroExpansion=*/true))
1795     return;
1796 
1797   // FIXME: warn that 'exestr' is deprecated.
1798   // FIXME: If the kind is "compiler" warn if the string is present (it is
1799   // ignored).
1800   // The MSDN docs say that "lib" and "linker" require a string and have a short
1801   // whitelist of linker options they support, but in practice MSVC doesn't
1802   // issue a diagnostic.  Therefore neither does clang.
1803 
1804   if (Tok.isNot(tok::r_paren)) {
1805     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1806     return;
1807   }
1808   PP.Lex(Tok);  // eat the r_paren.
1809 
1810   if (Tok.isNot(tok::eod)) {
1811     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1812     return;
1813   }
1814 
1815   // If the pragma is lexically sound, notify any interested PPCallbacks.
1816   if (PP.getPPCallbacks())
1817     PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
1818 
1819   Actions.ActOnPragmaMSComment(Kind, ArgumentString);
1820 }
1821 
1822 // #pragma clang optimize off
1823 // #pragma clang optimize on
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & FirstToken)1824 void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
1825                                         PragmaIntroducerKind Introducer,
1826                                         Token &FirstToken) {
1827   Token Tok;
1828   PP.Lex(Tok);
1829   if (Tok.is(tok::eod)) {
1830     PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
1831         << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
1832     return;
1833   }
1834   if (Tok.isNot(tok::identifier)) {
1835     PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1836       << PP.getSpelling(Tok);
1837     return;
1838   }
1839   const IdentifierInfo *II = Tok.getIdentifierInfo();
1840   // The only accepted values are 'on' or 'off'.
1841   bool IsOn = false;
1842   if (II->isStr("on")) {
1843     IsOn = true;
1844   } else if (!II->isStr("off")) {
1845     PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1846       << PP.getSpelling(Tok);
1847     return;
1848   }
1849   PP.Lex(Tok);
1850 
1851   if (Tok.isNot(tok::eod)) {
1852     PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
1853       << PP.getSpelling(Tok);
1854     return;
1855   }
1856 
1857   Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
1858 }
1859 
1860 /// \brief Parses loop or unroll pragma hint value and fills in Info.
ParseLoopHintValue(Preprocessor & PP,Token & Tok,Token PragmaName,Token Option,bool ValueInParens,PragmaLoopHintInfo & Info)1861 static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
1862                                Token Option, bool ValueInParens,
1863                                PragmaLoopHintInfo &Info) {
1864   SmallVector<Token, 1> ValueList;
1865   int OpenParens = ValueInParens ? 1 : 0;
1866   // Read constant expression.
1867   while (Tok.isNot(tok::eod)) {
1868     if (Tok.is(tok::l_paren))
1869       OpenParens++;
1870     else if (Tok.is(tok::r_paren)) {
1871       OpenParens--;
1872       if (OpenParens == 0 && ValueInParens)
1873         break;
1874     }
1875 
1876     ValueList.push_back(Tok);
1877     PP.Lex(Tok);
1878   }
1879 
1880   if (ValueInParens) {
1881     // Read ')'
1882     if (Tok.isNot(tok::r_paren)) {
1883       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1884       return true;
1885     }
1886     PP.Lex(Tok);
1887   }
1888 
1889   Token EOFTok;
1890   EOFTok.startToken();
1891   EOFTok.setKind(tok::eof);
1892   EOFTok.setLocation(Tok.getLocation());
1893   ValueList.push_back(EOFTok); // Terminates expression for parsing.
1894 
1895   Token *TokenArray = (Token *)PP.getPreprocessorAllocator().Allocate(
1896       ValueList.size() * sizeof(Token), llvm::alignOf<Token>());
1897   std::copy(ValueList.begin(), ValueList.end(), TokenArray);
1898   Info.Toks = TokenArray;
1899   Info.TokSize = ValueList.size();
1900 
1901   Info.PragmaName = PragmaName;
1902   Info.Option = Option;
1903   return false;
1904 }
1905 
1906 /// \brief Handle the \#pragma clang loop directive.
1907 ///  #pragma clang 'loop' loop-hints
1908 ///
1909 ///  loop-hints:
1910 ///    loop-hint loop-hints[opt]
1911 ///
1912 ///  loop-hint:
1913 ///    'vectorize' '(' loop-hint-keyword ')'
1914 ///    'interleave' '(' loop-hint-keyword ')'
1915 ///    'unroll' '(' unroll-hint-keyword ')'
1916 ///    'vectorize_width' '(' loop-hint-value ')'
1917 ///    'interleave_count' '(' loop-hint-value ')'
1918 ///    'unroll_count' '(' loop-hint-value ')'
1919 ///
1920 ///  loop-hint-keyword:
1921 ///    'enable'
1922 ///    'disable'
1923 ///
1924 ///  unroll-hint-keyword:
1925 ///    'full'
1926 ///    'disable'
1927 ///
1928 ///  loop-hint-value:
1929 ///    constant-expression
1930 ///
1931 /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
1932 /// try vectorizing the instructions of the loop it precedes. Specifying
1933 /// interleave(enable) or interleave_count(_value_) instructs llvm to try
1934 /// interleaving multiple iterations of the loop it precedes. The width of the
1935 /// vector instructions is specified by vectorize_width() and the number of
1936 /// interleaved loop iterations is specified by interleave_count(). Specifying a
1937 /// value of 1 effectively disables vectorization/interleaving, even if it is
1938 /// possible and profitable, and 0 is invalid. The loop vectorizer currently
1939 /// only works on inner loops.
1940 ///
1941 /// The unroll and unroll_count directives control the concatenation
1942 /// unroller. Specifying unroll(full) instructs llvm to try to
1943 /// unroll the loop completely, and unroll(disable) disables unrolling
1944 /// for the loop. Specifying unroll_count(_value_) instructs llvm to
1945 /// try to unroll the loop the number of times indicated by the value.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1946 void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
1947                                          PragmaIntroducerKind Introducer,
1948                                          Token &Tok) {
1949   // Incoming token is "loop" from "#pragma clang loop".
1950   Token PragmaName = Tok;
1951   SmallVector<Token, 1> TokenList;
1952 
1953   // Lex the optimization option and verify it is an identifier.
1954   PP.Lex(Tok);
1955   if (Tok.isNot(tok::identifier)) {
1956     PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
1957         << /*MissingOption=*/true << "";
1958     return;
1959   }
1960 
1961   while (Tok.is(tok::identifier)) {
1962     Token Option = Tok;
1963     IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
1964 
1965     bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
1966                            .Case("vectorize", true)
1967                            .Case("interleave", true)
1968                            .Case("unroll", true)
1969                            .Case("vectorize_width", true)
1970                            .Case("interleave_count", true)
1971                            .Case("unroll_count", true)
1972                            .Default(false);
1973     if (!OptionValid) {
1974       PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
1975           << /*MissingOption=*/false << OptionInfo;
1976       return;
1977     }
1978     PP.Lex(Tok);
1979 
1980     // Read '('
1981     if (Tok.isNot(tok::l_paren)) {
1982       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
1983       return;
1984     }
1985     PP.Lex(Tok);
1986 
1987     auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
1988     if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
1989                            *Info))
1990       return;
1991 
1992     // Generate the loop hint token.
1993     Token LoopHintTok;
1994     LoopHintTok.startToken();
1995     LoopHintTok.setKind(tok::annot_pragma_loop_hint);
1996     LoopHintTok.setLocation(PragmaName.getLocation());
1997     LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
1998     TokenList.push_back(LoopHintTok);
1999   }
2000 
2001   if (Tok.isNot(tok::eod)) {
2002     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2003         << "clang loop";
2004     return;
2005   }
2006 
2007   Token *TokenArray = new Token[TokenList.size()];
2008   std::copy(TokenList.begin(), TokenList.end(), TokenArray);
2009 
2010   PP.EnterTokenStream(TokenArray, TokenList.size(),
2011                       /*DisableMacroExpansion=*/false,
2012                       /*OwnsTokens=*/true);
2013 }
2014 
2015 /// \brief Handle the loop unroll optimization pragmas.
2016 ///  #pragma unroll
2017 ///  #pragma unroll unroll-hint-value
2018 ///  #pragma unroll '(' unroll-hint-value ')'
2019 ///  #pragma nounroll
2020 ///
2021 ///  unroll-hint-value:
2022 ///    constant-expression
2023 ///
2024 /// Loop unrolling hints can be specified with '#pragma unroll' or
2025 /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2026 /// contained in parentheses. With no argument the directive instructs llvm to
2027 /// try to unroll the loop completely. A positive integer argument can be
2028 /// specified to indicate the number of times the loop should be unrolled.  To
2029 /// maximize compatibility with other compilers the unroll count argument can be
2030 /// specified with or without parentheses.  Specifying, '#pragma nounroll'
2031 /// disables unrolling of the loop.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)2032 void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
2033                                            PragmaIntroducerKind Introducer,
2034                                            Token &Tok) {
2035   // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2036   // "#pragma nounroll".
2037   Token PragmaName = Tok;
2038   PP.Lex(Tok);
2039   auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2040   if (Tok.is(tok::eod)) {
2041     // nounroll or unroll pragma without an argument.
2042     Info->PragmaName = PragmaName;
2043     Info->Option.startToken();
2044   } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
2045     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2046         << "nounroll";
2047     return;
2048   } else {
2049     // Unroll pragma with an argument: "#pragma unroll N" or
2050     // "#pragma unroll(N)".
2051     // Read '(' if it exists.
2052     bool ValueInParens = Tok.is(tok::l_paren);
2053     if (ValueInParens)
2054       PP.Lex(Tok);
2055 
2056     Token Option;
2057     Option.startToken();
2058     if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
2059       return;
2060 
2061     // In CUDA, the argument to '#pragma unroll' should not be contained in
2062     // parentheses.
2063     if (PP.getLangOpts().CUDA && ValueInParens)
2064       PP.Diag(Info->Toks[0].getLocation(),
2065               diag::warn_pragma_unroll_cuda_value_in_parens);
2066 
2067     if (Tok.isNot(tok::eod)) {
2068       PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2069           << "unroll";
2070       return;
2071     }
2072   }
2073 
2074   // Generate the hint token.
2075   Token *TokenArray = new Token[1];
2076   TokenArray[0].startToken();
2077   TokenArray[0].setKind(tok::annot_pragma_loop_hint);
2078   TokenArray[0].setLocation(PragmaName.getLocation());
2079   TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
2080   PP.EnterTokenStream(TokenArray, 1, /*DisableMacroExpansion=*/false,
2081                       /*OwnsTokens=*/true);
2082 }
2083