• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/Lex/Preprocessor.h"
16 #include "clang/Parse/ParseDiagnostic.h"
17 #include "clang/Parse/Parser.h"
18 #include "clang/Sema/LoopHint.h"
19 #include "clang/Sema/Scope.h"
20 #include "llvm/ADT/StringSwitch.h"
21 using namespace clang;
22 
23 namespace {
24 
25 struct PragmaAlignHandler : public PragmaHandler {
PragmaAlignHandler__anon238cf4100111::PragmaAlignHandler26   explicit PragmaAlignHandler() : PragmaHandler("align") {}
27   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
28                     Token &FirstToken) override;
29 };
30 
31 struct PragmaGCCVisibilityHandler : public PragmaHandler {
PragmaGCCVisibilityHandler__anon238cf4100111::PragmaGCCVisibilityHandler32   explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
33   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
34                     Token &FirstToken) override;
35 };
36 
37 struct PragmaOptionsHandler : public PragmaHandler {
PragmaOptionsHandler__anon238cf4100111::PragmaOptionsHandler38   explicit PragmaOptionsHandler() : PragmaHandler("options") {}
39   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
40                     Token &FirstToken) override;
41 };
42 
43 struct PragmaPackHandler : public PragmaHandler {
PragmaPackHandler__anon238cf4100111::PragmaPackHandler44   explicit PragmaPackHandler() : PragmaHandler("pack") {}
45   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
46                     Token &FirstToken) override;
47 };
48 
49 struct PragmaMSStructHandler : public PragmaHandler {
PragmaMSStructHandler__anon238cf4100111::PragmaMSStructHandler50   explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
51   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
52                     Token &FirstToken) override;
53 };
54 
55 struct PragmaUnusedHandler : public PragmaHandler {
PragmaUnusedHandler__anon238cf4100111::PragmaUnusedHandler56   PragmaUnusedHandler() : PragmaHandler("unused") {}
57   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
58                     Token &FirstToken) override;
59 };
60 
61 struct PragmaWeakHandler : public PragmaHandler {
PragmaWeakHandler__anon238cf4100111::PragmaWeakHandler62   explicit PragmaWeakHandler() : PragmaHandler("weak") {}
63   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
64                     Token &FirstToken) override;
65 };
66 
67 struct PragmaRedefineExtnameHandler : public PragmaHandler {
PragmaRedefineExtnameHandler__anon238cf4100111::PragmaRedefineExtnameHandler68   explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
69   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
70                     Token &FirstToken) override;
71 };
72 
73 struct PragmaOpenCLExtensionHandler : public PragmaHandler {
PragmaOpenCLExtensionHandler__anon238cf4100111::PragmaOpenCLExtensionHandler74   PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
75   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
76                     Token &FirstToken) override;
77 };
78 
79 
80 struct PragmaFPContractHandler : public PragmaHandler {
PragmaFPContractHandler__anon238cf4100111::PragmaFPContractHandler81   PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
82   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
83                     Token &FirstToken) override;
84 };
85 
86 struct PragmaNoOpenMPHandler : public PragmaHandler {
PragmaNoOpenMPHandler__anon238cf4100111::PragmaNoOpenMPHandler87   PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
88   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
89                     Token &FirstToken) override;
90 };
91 
92 struct PragmaOpenMPHandler : public PragmaHandler {
PragmaOpenMPHandler__anon238cf4100111::PragmaOpenMPHandler93   PragmaOpenMPHandler() : PragmaHandler("omp") { }
94   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
95                     Token &FirstToken) override;
96 };
97 
98 /// PragmaCommentHandler - "\#pragma comment ...".
99 struct PragmaCommentHandler : public PragmaHandler {
PragmaCommentHandler__anon238cf4100111::PragmaCommentHandler100   PragmaCommentHandler(Sema &Actions)
101     : PragmaHandler("comment"), Actions(Actions) {}
102   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
103                     Token &FirstToken) override;
104 private:
105   Sema &Actions;
106 };
107 
108 struct PragmaDetectMismatchHandler : public PragmaHandler {
PragmaDetectMismatchHandler__anon238cf4100111::PragmaDetectMismatchHandler109   PragmaDetectMismatchHandler(Sema &Actions)
110     : PragmaHandler("detect_mismatch"), Actions(Actions) {}
111   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
112                     Token &FirstToken) override;
113 private:
114   Sema &Actions;
115 };
116 
117 struct PragmaMSPointersToMembers : public PragmaHandler {
PragmaMSPointersToMembers__anon238cf4100111::PragmaMSPointersToMembers118   explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
119   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
120                     Token &FirstToken) override;
121 };
122 
123 struct PragmaMSVtorDisp : public PragmaHandler {
PragmaMSVtorDisp__anon238cf4100111::PragmaMSVtorDisp124   explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
125   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
126                     Token &FirstToken) override;
127 };
128 
129 struct PragmaMSPragma : public PragmaHandler {
PragmaMSPragma__anon238cf4100111::PragmaMSPragma130   explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
131   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
132                     Token &FirstToken) override;
133 };
134 
135 /// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
136 struct PragmaOptimizeHandler : public PragmaHandler {
PragmaOptimizeHandler__anon238cf4100111::PragmaOptimizeHandler137   PragmaOptimizeHandler(Sema &S)
138     : PragmaHandler("optimize"), Actions(S) {}
139   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
140                     Token &FirstToken) override;
141 private:
142   Sema &Actions;
143 };
144 
145 struct PragmaLoopHintHandler : public PragmaHandler {
PragmaLoopHintHandler__anon238cf4100111::PragmaLoopHintHandler146   PragmaLoopHintHandler() : PragmaHandler("loop") {}
147   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
148                     Token &FirstToken) override;
149 };
150 
151 }  // end namespace
152 
initializePragmaHandlers()153 void Parser::initializePragmaHandlers() {
154   AlignHandler.reset(new PragmaAlignHandler());
155   PP.AddPragmaHandler(AlignHandler.get());
156 
157   GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
158   PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
159 
160   OptionsHandler.reset(new PragmaOptionsHandler());
161   PP.AddPragmaHandler(OptionsHandler.get());
162 
163   PackHandler.reset(new PragmaPackHandler());
164   PP.AddPragmaHandler(PackHandler.get());
165 
166   MSStructHandler.reset(new PragmaMSStructHandler());
167   PP.AddPragmaHandler(MSStructHandler.get());
168 
169   UnusedHandler.reset(new PragmaUnusedHandler());
170   PP.AddPragmaHandler(UnusedHandler.get());
171 
172   WeakHandler.reset(new PragmaWeakHandler());
173   PP.AddPragmaHandler(WeakHandler.get());
174 
175   RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
176   PP.AddPragmaHandler(RedefineExtnameHandler.get());
177 
178   FPContractHandler.reset(new PragmaFPContractHandler());
179   PP.AddPragmaHandler("STDC", FPContractHandler.get());
180 
181   if (getLangOpts().OpenCL) {
182     OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
183     PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
184 
185     PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
186   }
187   if (getLangOpts().OpenMP)
188     OpenMPHandler.reset(new PragmaOpenMPHandler());
189   else
190     OpenMPHandler.reset(new PragmaNoOpenMPHandler());
191   PP.AddPragmaHandler(OpenMPHandler.get());
192 
193   if (getLangOpts().MicrosoftExt) {
194     MSCommentHandler.reset(new PragmaCommentHandler(Actions));
195     PP.AddPragmaHandler(MSCommentHandler.get());
196     MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
197     PP.AddPragmaHandler(MSDetectMismatchHandler.get());
198     MSPointersToMembers.reset(new PragmaMSPointersToMembers());
199     PP.AddPragmaHandler(MSPointersToMembers.get());
200     MSVtorDisp.reset(new PragmaMSVtorDisp());
201     PP.AddPragmaHandler(MSVtorDisp.get());
202     MSInitSeg.reset(new PragmaMSPragma("init_seg"));
203     PP.AddPragmaHandler(MSInitSeg.get());
204     MSDataSeg.reset(new PragmaMSPragma("data_seg"));
205     PP.AddPragmaHandler(MSDataSeg.get());
206     MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
207     PP.AddPragmaHandler(MSBSSSeg.get());
208     MSConstSeg.reset(new PragmaMSPragma("const_seg"));
209     PP.AddPragmaHandler(MSConstSeg.get());
210     MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
211     PP.AddPragmaHandler(MSCodeSeg.get());
212     MSSection.reset(new PragmaMSPragma("section"));
213     PP.AddPragmaHandler(MSSection.get());
214   }
215 
216   OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
217   PP.AddPragmaHandler("clang", OptimizeHandler.get());
218 
219   LoopHintHandler.reset(new PragmaLoopHintHandler());
220   PP.AddPragmaHandler("clang", LoopHintHandler.get());
221 }
222 
resetPragmaHandlers()223 void Parser::resetPragmaHandlers() {
224   // Remove the pragma handlers we installed.
225   PP.RemovePragmaHandler(AlignHandler.get());
226   AlignHandler.reset();
227   PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
228   GCCVisibilityHandler.reset();
229   PP.RemovePragmaHandler(OptionsHandler.get());
230   OptionsHandler.reset();
231   PP.RemovePragmaHandler(PackHandler.get());
232   PackHandler.reset();
233   PP.RemovePragmaHandler(MSStructHandler.get());
234   MSStructHandler.reset();
235   PP.RemovePragmaHandler(UnusedHandler.get());
236   UnusedHandler.reset();
237   PP.RemovePragmaHandler(WeakHandler.get());
238   WeakHandler.reset();
239   PP.RemovePragmaHandler(RedefineExtnameHandler.get());
240   RedefineExtnameHandler.reset();
241 
242   if (getLangOpts().OpenCL) {
243     PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
244     OpenCLExtensionHandler.reset();
245     PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
246   }
247   PP.RemovePragmaHandler(OpenMPHandler.get());
248   OpenMPHandler.reset();
249 
250   if (getLangOpts().MicrosoftExt) {
251     PP.RemovePragmaHandler(MSCommentHandler.get());
252     MSCommentHandler.reset();
253     PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
254     MSDetectMismatchHandler.reset();
255     PP.RemovePragmaHandler(MSPointersToMembers.get());
256     MSPointersToMembers.reset();
257     PP.RemovePragmaHandler(MSVtorDisp.get());
258     MSVtorDisp.reset();
259     PP.RemovePragmaHandler(MSInitSeg.get());
260     MSInitSeg.reset();
261     PP.RemovePragmaHandler(MSDataSeg.get());
262     MSDataSeg.reset();
263     PP.RemovePragmaHandler(MSBSSSeg.get());
264     MSBSSSeg.reset();
265     PP.RemovePragmaHandler(MSConstSeg.get());
266     MSConstSeg.reset();
267     PP.RemovePragmaHandler(MSCodeSeg.get());
268     MSCodeSeg.reset();
269     PP.RemovePragmaHandler(MSSection.get());
270     MSSection.reset();
271   }
272 
273   PP.RemovePragmaHandler("STDC", FPContractHandler.get());
274   FPContractHandler.reset();
275 
276   PP.RemovePragmaHandler("clang", OptimizeHandler.get());
277   OptimizeHandler.reset();
278 
279   PP.RemovePragmaHandler("clang", LoopHintHandler.get());
280   LoopHintHandler.reset();
281 }
282 
283 /// \brief Handle the annotation token produced for #pragma unused(...)
284 ///
285 /// Each annot_pragma_unused is followed by the argument token so e.g.
286 /// "#pragma unused(x,y)" becomes:
287 /// annot_pragma_unused 'x' annot_pragma_unused 'y'
HandlePragmaUnused()288 void Parser::HandlePragmaUnused() {
289   assert(Tok.is(tok::annot_pragma_unused));
290   SourceLocation UnusedLoc = ConsumeToken();
291   Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
292   ConsumeToken(); // The argument token.
293 }
294 
HandlePragmaVisibility()295 void Parser::HandlePragmaVisibility() {
296   assert(Tok.is(tok::annot_pragma_vis));
297   const IdentifierInfo *VisType =
298     static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
299   SourceLocation VisLoc = ConsumeToken();
300   Actions.ActOnPragmaVisibility(VisType, VisLoc);
301 }
302 
303 struct PragmaPackInfo {
304   Sema::PragmaPackKind Kind;
305   IdentifierInfo *Name;
306   Token Alignment;
307   SourceLocation LParenLoc;
308   SourceLocation RParenLoc;
309 };
310 
HandlePragmaPack()311 void Parser::HandlePragmaPack() {
312   assert(Tok.is(tok::annot_pragma_pack));
313   PragmaPackInfo *Info =
314     static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
315   SourceLocation PragmaLoc = ConsumeToken();
316   ExprResult Alignment;
317   if (Info->Alignment.is(tok::numeric_constant)) {
318     Alignment = Actions.ActOnNumericConstant(Info->Alignment);
319     if (Alignment.isInvalid())
320       return;
321   }
322   Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
323                           Info->LParenLoc, Info->RParenLoc);
324 }
325 
HandlePragmaMSStruct()326 void Parser::HandlePragmaMSStruct() {
327   assert(Tok.is(tok::annot_pragma_msstruct));
328   Sema::PragmaMSStructKind Kind =
329     static_cast<Sema::PragmaMSStructKind>(
330     reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
331   Actions.ActOnPragmaMSStruct(Kind);
332   ConsumeToken(); // The annotation token.
333 }
334 
HandlePragmaAlign()335 void Parser::HandlePragmaAlign() {
336   assert(Tok.is(tok::annot_pragma_align));
337   Sema::PragmaOptionsAlignKind Kind =
338     static_cast<Sema::PragmaOptionsAlignKind>(
339     reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
340   SourceLocation PragmaLoc = ConsumeToken();
341   Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
342 }
343 
HandlePragmaWeak()344 void Parser::HandlePragmaWeak() {
345   assert(Tok.is(tok::annot_pragma_weak));
346   SourceLocation PragmaLoc = ConsumeToken();
347   Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
348                             Tok.getLocation());
349   ConsumeToken(); // The weak name.
350 }
351 
HandlePragmaWeakAlias()352 void Parser::HandlePragmaWeakAlias() {
353   assert(Tok.is(tok::annot_pragma_weakalias));
354   SourceLocation PragmaLoc = ConsumeToken();
355   IdentifierInfo *WeakName = Tok.getIdentifierInfo();
356   SourceLocation WeakNameLoc = Tok.getLocation();
357   ConsumeToken();
358   IdentifierInfo *AliasName = Tok.getIdentifierInfo();
359   SourceLocation AliasNameLoc = Tok.getLocation();
360   ConsumeToken();
361   Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
362                                WeakNameLoc, AliasNameLoc);
363 
364 }
365 
HandlePragmaRedefineExtname()366 void Parser::HandlePragmaRedefineExtname() {
367   assert(Tok.is(tok::annot_pragma_redefine_extname));
368   SourceLocation RedefLoc = ConsumeToken();
369   IdentifierInfo *RedefName = Tok.getIdentifierInfo();
370   SourceLocation RedefNameLoc = Tok.getLocation();
371   ConsumeToken();
372   IdentifierInfo *AliasName = Tok.getIdentifierInfo();
373   SourceLocation AliasNameLoc = Tok.getLocation();
374   ConsumeToken();
375   Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
376                                      RedefNameLoc, AliasNameLoc);
377 }
378 
HandlePragmaFPContract()379 void Parser::HandlePragmaFPContract() {
380   assert(Tok.is(tok::annot_pragma_fp_contract));
381   tok::OnOffSwitch OOS =
382     static_cast<tok::OnOffSwitch>(
383     reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
384   Actions.ActOnPragmaFPContract(OOS);
385   ConsumeToken(); // The annotation token.
386 }
387 
HandlePragmaCaptured()388 StmtResult Parser::HandlePragmaCaptured()
389 {
390   assert(Tok.is(tok::annot_pragma_captured));
391   ConsumeToken();
392 
393   if (Tok.isNot(tok::l_brace)) {
394     PP.Diag(Tok, diag::err_expected) << tok::l_brace;
395     return StmtError();
396   }
397 
398   SourceLocation Loc = Tok.getLocation();
399 
400   ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
401   Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
402                                    /*NumParams=*/1);
403 
404   StmtResult R = ParseCompoundStatement();
405   CapturedRegionScope.Exit();
406 
407   if (R.isInvalid()) {
408     Actions.ActOnCapturedRegionError();
409     return StmtError();
410   }
411 
412   return Actions.ActOnCapturedRegionEnd(R.get());
413 }
414 
415 namespace {
416   typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
417 }
418 
HandlePragmaOpenCLExtension()419 void Parser::HandlePragmaOpenCLExtension() {
420   assert(Tok.is(tok::annot_pragma_opencl_extension));
421   OpenCLExtData data =
422       OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
423   unsigned state = data.getInt();
424   IdentifierInfo *ename = data.getPointer();
425   SourceLocation NameLoc = Tok.getLocation();
426   ConsumeToken(); // The annotation token.
427 
428   OpenCLOptions &f = Actions.getOpenCLOptions();
429   // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
430   // overriding all previously issued extension directives, but only if the
431   // behavior is set to disable."
432   if (state == 0 && ename->isStr("all")) {
433 #define OPENCLEXT(nm)   f.nm = 0;
434 #include "clang/Basic/OpenCLExtensions.def"
435   }
436 #define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
437 #include "clang/Basic/OpenCLExtensions.def"
438   else {
439     PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
440     return;
441   }
442 }
443 
HandlePragmaMSPointersToMembers()444 void Parser::HandlePragmaMSPointersToMembers() {
445   assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
446   LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
447       static_cast<LangOptions::PragmaMSPointersToMembersKind>(
448           reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
449   SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
450   Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
451 }
452 
HandlePragmaMSVtorDisp()453 void Parser::HandlePragmaMSVtorDisp() {
454   assert(Tok.is(tok::annot_pragma_ms_vtordisp));
455   uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
456   Sema::PragmaVtorDispKind Kind =
457       static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
458   MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
459   SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
460   Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
461 }
462 
HandlePragmaMSPragma()463 void Parser::HandlePragmaMSPragma() {
464   assert(Tok.is(tok::annot_pragma_ms_pragma));
465   // Grab the tokens out of the annotation and enter them into the stream.
466   auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue();
467   PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
468   SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
469   assert(Tok.isAnyIdentifier());
470   llvm::StringRef PragmaName = Tok.getIdentifierInfo()->getName();
471   PP.Lex(Tok); // pragma kind
472   // Figure out which #pragma we're dealing with.  The switch has no default
473   // because lex shouldn't emit the annotation token for unrecognized pragmas.
474   typedef unsigned (Parser::*PragmaHandler)(llvm::StringRef, SourceLocation);
475   PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
476     .Case("data_seg", &Parser::HandlePragmaMSSegment)
477     .Case("bss_seg", &Parser::HandlePragmaMSSegment)
478     .Case("const_seg", &Parser::HandlePragmaMSSegment)
479     .Case("code_seg", &Parser::HandlePragmaMSSegment)
480     .Case("section", &Parser::HandlePragmaMSSection)
481     .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
482   if (auto DiagID = (this->*Handler)(PragmaName, PragmaLocation)) {
483     PP.Diag(PragmaLocation, DiagID) << PragmaName;
484     while (Tok.isNot(tok::eof))
485       PP.Lex(Tok);
486     PP.Lex(Tok);
487   }
488 }
489 
HandlePragmaMSSection(llvm::StringRef PragmaName,SourceLocation PragmaLocation)490 unsigned Parser::HandlePragmaMSSection(llvm::StringRef PragmaName,
491                                        SourceLocation PragmaLocation) {
492   if (Tok.isNot(tok::l_paren))
493     return diag::warn_pragma_expected_lparen;
494   PP.Lex(Tok); // (
495   // Parsing code for pragma section
496   if (Tok.isNot(tok::string_literal))
497     return diag::warn_pragma_expected_section_name;
498   StringLiteral *SegmentName =
499     cast<StringLiteral>(ParseStringLiteralExpression().get());
500   int SectionFlags = 0;
501   while (Tok.is(tok::comma)) {
502     PP.Lex(Tok); // ,
503     if (!Tok.isAnyIdentifier())
504       return diag::warn_pragma_expected_action_or_r_paren;
505     Sema::PragmaSectionFlag Flag =
506       llvm::StringSwitch<Sema::PragmaSectionFlag>(
507       Tok.getIdentifierInfo()->getName())
508       .Case("read", Sema::PSF_Read)
509       .Case("write", Sema::PSF_Write)
510       .Case("execute", Sema::PSF_Execute)
511       .Case("shared", Sema::PSF_Invalid)
512       .Case("nopage", Sema::PSF_Invalid)
513       .Case("nocache", Sema::PSF_Invalid)
514       .Case("discard", Sema::PSF_Invalid)
515       .Case("remove", Sema::PSF_Invalid)
516       .Default(Sema::PSF_None);
517     if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) {
518       PP.Diag(PragmaLocation, Flag == Sema::PSF_None ?
519                               diag::warn_pragma_invalid_specific_action :
520                               diag::warn_pragma_unsupported_action)
521           << PragmaName << Tok.getIdentifierInfo()->getName();
522       while (Tok.isNot(tok::eof))
523         PP.Lex(Tok);
524       PP.Lex(Tok);
525       return 0;
526     }
527     SectionFlags |= Flag;
528     PP.Lex(Tok); // Identifier
529   }
530   if (Tok.isNot(tok::r_paren))
531     return diag::warn_pragma_expected_rparen;
532   PP.Lex(Tok); // )
533   if (Tok.isNot(tok::eof))
534     return diag::warn_pragma_extra_tokens_at_eol;
535   PP.Lex(Tok); // eof
536   Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
537   return 0;
538 }
539 
HandlePragmaMSSegment(llvm::StringRef PragmaName,SourceLocation PragmaLocation)540 unsigned Parser::HandlePragmaMSSegment(llvm::StringRef PragmaName,
541                                       SourceLocation PragmaLocation) {
542   if (Tok.isNot(tok::l_paren))
543     return diag::warn_pragma_expected_lparen;
544   PP.Lex(Tok); // (
545   Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
546   llvm::StringRef SlotLabel;
547   if (Tok.isAnyIdentifier()) {
548     llvm::StringRef PushPop = Tok.getIdentifierInfo()->getName();
549     if (PushPop == "push")
550       Action = Sema::PSK_Push;
551     else if (PushPop == "pop")
552       Action = Sema::PSK_Pop;
553     else
554       return diag::warn_pragma_expected_section_push_pop_or_name;
555     if (Action != Sema::PSK_Reset) {
556       PP.Lex(Tok); // push | pop
557       if (Tok.is(tok::comma)) {
558         PP.Lex(Tok); // ,
559         // If we've got a comma, we either need a label or a string.
560         if (Tok.isAnyIdentifier()) {
561           SlotLabel = Tok.getIdentifierInfo()->getName();
562           PP.Lex(Tok); // identifier
563           if (Tok.is(tok::comma))
564             PP.Lex(Tok);
565           else if (Tok.isNot(tok::r_paren))
566             return diag::warn_pragma_expected_punc;
567         }
568       } else if (Tok.isNot(tok::r_paren))
569         return diag::warn_pragma_expected_punc;
570     }
571   }
572   // Grab the string literal for our section name.
573   StringLiteral *SegmentName = nullptr;
574   if (Tok.isNot(tok::r_paren)) {
575     if (Tok.isNot(tok::string_literal))
576       return Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
577           diag::warn_pragma_expected_section_name :
578           diag::warn_pragma_expected_section_label_or_name :
579           diag::warn_pragma_expected_section_push_pop_or_name;
580     SegmentName = cast<StringLiteral>(ParseStringLiteralExpression().get());
581     // Setting section "" has no effect
582     if (SegmentName->getLength())
583       Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
584   }
585   if (Tok.isNot(tok::r_paren))
586     return diag::warn_pragma_expected_rparen;
587   PP.Lex(Tok); // )
588   if (Tok.isNot(tok::eof))
589     return diag::warn_pragma_extra_tokens_at_eol;
590   PP.Lex(Tok); // eof
591   Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
592                            SegmentName, PragmaName);
593   return 0;
594 }
595 
HandlePragmaMSInitSeg(llvm::StringRef PragmaName,SourceLocation PragmaLocation)596 unsigned Parser::HandlePragmaMSInitSeg(llvm::StringRef PragmaName,
597                                        SourceLocation PragmaLocation) {
598   return PP.getDiagnostics().getCustomDiagID(
599       DiagnosticsEngine::Error, "'#pragma %0' not implemented.");
600 }
601 
602 struct PragmaLoopHintInfo {
603   Token Loop;
604   Token Value;
605   Token Option;
606 };
607 
HandlePragmaLoopHint()608 LoopHint Parser::HandlePragmaLoopHint() {
609   assert(Tok.is(tok::annot_pragma_loop_hint));
610   PragmaLoopHintInfo *Info =
611       static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
612 
613   LoopHint Hint;
614   Hint.LoopLoc =
615       IdentifierLoc::create(Actions.Context, Info->Loop.getLocation(),
616                             Info->Loop.getIdentifierInfo());
617   Hint.OptionLoc =
618       IdentifierLoc::create(Actions.Context, Info->Option.getLocation(),
619                             Info->Option.getIdentifierInfo());
620   Hint.ValueLoc =
621       IdentifierLoc::create(Actions.Context, Info->Value.getLocation(),
622                             Info->Value.getIdentifierInfo());
623   Hint.Range =
624       SourceRange(Info->Option.getLocation(), Info->Value.getLocation());
625 
626   // FIXME: We should allow non-type template parameters for the loop hint
627   // value. See bug report #19610
628   if (Info->Value.is(tok::numeric_constant))
629     Hint.ValueExpr = Actions.ActOnNumericConstant(Info->Value).get();
630   else
631     Hint.ValueExpr = nullptr;
632 
633   return Hint;
634 }
635 
636 // #pragma GCC visibility comes in two variants:
637 //   'push' '(' [visibility] ')'
638 //   'pop'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & VisTok)639 void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
640                                               PragmaIntroducerKind Introducer,
641                                               Token &VisTok) {
642   SourceLocation VisLoc = VisTok.getLocation();
643 
644   Token Tok;
645   PP.LexUnexpandedToken(Tok);
646 
647   const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
648 
649   const IdentifierInfo *VisType;
650   if (PushPop && PushPop->isStr("pop")) {
651     VisType = nullptr;
652   } else if (PushPop && PushPop->isStr("push")) {
653     PP.LexUnexpandedToken(Tok);
654     if (Tok.isNot(tok::l_paren)) {
655       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
656         << "visibility";
657       return;
658     }
659     PP.LexUnexpandedToken(Tok);
660     VisType = Tok.getIdentifierInfo();
661     if (!VisType) {
662       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
663         << "visibility";
664       return;
665     }
666     PP.LexUnexpandedToken(Tok);
667     if (Tok.isNot(tok::r_paren)) {
668       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
669         << "visibility";
670       return;
671     }
672   } else {
673     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
674       << "visibility";
675     return;
676   }
677   PP.LexUnexpandedToken(Tok);
678   if (Tok.isNot(tok::eod)) {
679     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
680       << "visibility";
681     return;
682   }
683 
684   Token *Toks = new Token[1];
685   Toks[0].startToken();
686   Toks[0].setKind(tok::annot_pragma_vis);
687   Toks[0].setLocation(VisLoc);
688   Toks[0].setAnnotationValue(
689                           const_cast<void*>(static_cast<const void*>(VisType)));
690   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
691                       /*OwnsTokens=*/true);
692 }
693 
694 // #pragma pack(...) comes in the following delicious flavors:
695 //   pack '(' [integer] ')'
696 //   pack '(' 'show' ')'
697 //   pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & PackTok)698 void PragmaPackHandler::HandlePragma(Preprocessor &PP,
699                                      PragmaIntroducerKind Introducer,
700                                      Token &PackTok) {
701   SourceLocation PackLoc = PackTok.getLocation();
702 
703   Token Tok;
704   PP.Lex(Tok);
705   if (Tok.isNot(tok::l_paren)) {
706     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
707     return;
708   }
709 
710   Sema::PragmaPackKind Kind = Sema::PPK_Default;
711   IdentifierInfo *Name = nullptr;
712   Token Alignment;
713   Alignment.startToken();
714   SourceLocation LParenLoc = Tok.getLocation();
715   PP.Lex(Tok);
716   if (Tok.is(tok::numeric_constant)) {
717     Alignment = Tok;
718 
719     PP.Lex(Tok);
720 
721     // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
722     // the push/pop stack.
723     // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
724     if (PP.getLangOpts().ApplePragmaPack)
725       Kind = Sema::PPK_Push;
726   } else if (Tok.is(tok::identifier)) {
727     const IdentifierInfo *II = Tok.getIdentifierInfo();
728     if (II->isStr("show")) {
729       Kind = Sema::PPK_Show;
730       PP.Lex(Tok);
731     } else {
732       if (II->isStr("push")) {
733         Kind = Sema::PPK_Push;
734       } else if (II->isStr("pop")) {
735         Kind = Sema::PPK_Pop;
736       } else {
737         PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
738         return;
739       }
740       PP.Lex(Tok);
741 
742       if (Tok.is(tok::comma)) {
743         PP.Lex(Tok);
744 
745         if (Tok.is(tok::numeric_constant)) {
746           Alignment = Tok;
747 
748           PP.Lex(Tok);
749         } else if (Tok.is(tok::identifier)) {
750           Name = Tok.getIdentifierInfo();
751           PP.Lex(Tok);
752 
753           if (Tok.is(tok::comma)) {
754             PP.Lex(Tok);
755 
756             if (Tok.isNot(tok::numeric_constant)) {
757               PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
758               return;
759             }
760 
761             Alignment = Tok;
762 
763             PP.Lex(Tok);
764           }
765         } else {
766           PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
767           return;
768         }
769       }
770     }
771   } else if (PP.getLangOpts().ApplePragmaPack) {
772     // In MSVC/gcc, #pragma pack() resets the alignment without affecting
773     // the push/pop stack.
774     // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
775     Kind = Sema::PPK_Pop;
776   }
777 
778   if (Tok.isNot(tok::r_paren)) {
779     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
780     return;
781   }
782 
783   SourceLocation RParenLoc = Tok.getLocation();
784   PP.Lex(Tok);
785   if (Tok.isNot(tok::eod)) {
786     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
787     return;
788   }
789 
790   PragmaPackInfo *Info =
791     (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
792       sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
793   new (Info) PragmaPackInfo();
794   Info->Kind = Kind;
795   Info->Name = Name;
796   Info->Alignment = Alignment;
797   Info->LParenLoc = LParenLoc;
798   Info->RParenLoc = RParenLoc;
799 
800   Token *Toks =
801     (Token*) PP.getPreprocessorAllocator().Allocate(
802       sizeof(Token) * 1, llvm::alignOf<Token>());
803   new (Toks) Token();
804   Toks[0].startToken();
805   Toks[0].setKind(tok::annot_pragma_pack);
806   Toks[0].setLocation(PackLoc);
807   Toks[0].setAnnotationValue(static_cast<void*>(Info));
808   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
809                       /*OwnsTokens=*/false);
810 }
811 
812 // #pragma ms_struct on
813 // #pragma ms_struct off
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & MSStructTok)814 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
815                                          PragmaIntroducerKind Introducer,
816                                          Token &MSStructTok) {
817   Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
818 
819   Token Tok;
820   PP.Lex(Tok);
821   if (Tok.isNot(tok::identifier)) {
822     PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
823     return;
824   }
825   const IdentifierInfo *II = Tok.getIdentifierInfo();
826   if (II->isStr("on")) {
827     Kind = Sema::PMSST_ON;
828     PP.Lex(Tok);
829   }
830   else if (II->isStr("off") || II->isStr("reset"))
831     PP.Lex(Tok);
832   else {
833     PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
834     return;
835   }
836 
837   if (Tok.isNot(tok::eod)) {
838     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
839       << "ms_struct";
840     return;
841   }
842 
843   Token *Toks =
844     (Token*) PP.getPreprocessorAllocator().Allocate(
845       sizeof(Token) * 1, llvm::alignOf<Token>());
846   new (Toks) Token();
847   Toks[0].startToken();
848   Toks[0].setKind(tok::annot_pragma_msstruct);
849   Toks[0].setLocation(MSStructTok.getLocation());
850   Toks[0].setAnnotationValue(reinterpret_cast<void*>(
851                              static_cast<uintptr_t>(Kind)));
852   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
853                       /*OwnsTokens=*/false);
854 }
855 
856 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
857 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
ParseAlignPragma(Preprocessor & PP,Token & FirstTok,bool IsOptions)858 static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
859                              bool IsOptions) {
860   Token Tok;
861 
862   if (IsOptions) {
863     PP.Lex(Tok);
864     if (Tok.isNot(tok::identifier) ||
865         !Tok.getIdentifierInfo()->isStr("align")) {
866       PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
867       return;
868     }
869   }
870 
871   PP.Lex(Tok);
872   if (Tok.isNot(tok::equal)) {
873     PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
874       << IsOptions;
875     return;
876   }
877 
878   PP.Lex(Tok);
879   if (Tok.isNot(tok::identifier)) {
880     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
881       << (IsOptions ? "options" : "align");
882     return;
883   }
884 
885   Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
886   const IdentifierInfo *II = Tok.getIdentifierInfo();
887   if (II->isStr("native"))
888     Kind = Sema::POAK_Native;
889   else if (II->isStr("natural"))
890     Kind = Sema::POAK_Natural;
891   else if (II->isStr("packed"))
892     Kind = Sema::POAK_Packed;
893   else if (II->isStr("power"))
894     Kind = Sema::POAK_Power;
895   else if (II->isStr("mac68k"))
896     Kind = Sema::POAK_Mac68k;
897   else if (II->isStr("reset"))
898     Kind = Sema::POAK_Reset;
899   else {
900     PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
901       << IsOptions;
902     return;
903   }
904 
905   PP.Lex(Tok);
906   if (Tok.isNot(tok::eod)) {
907     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
908       << (IsOptions ? "options" : "align");
909     return;
910   }
911 
912   Token *Toks =
913     (Token*) PP.getPreprocessorAllocator().Allocate(
914       sizeof(Token) * 1, llvm::alignOf<Token>());
915   new (Toks) Token();
916   Toks[0].startToken();
917   Toks[0].setKind(tok::annot_pragma_align);
918   Toks[0].setLocation(FirstTok.getLocation());
919   Toks[0].setAnnotationValue(reinterpret_cast<void*>(
920                              static_cast<uintptr_t>(Kind)));
921   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
922                       /*OwnsTokens=*/false);
923 }
924 
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & AlignTok)925 void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
926                                       PragmaIntroducerKind Introducer,
927                                       Token &AlignTok) {
928   ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
929 }
930 
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & OptionsTok)931 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
932                                         PragmaIntroducerKind Introducer,
933                                         Token &OptionsTok) {
934   ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
935 }
936 
937 // #pragma unused(identifier)
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & UnusedTok)938 void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
939                                        PragmaIntroducerKind Introducer,
940                                        Token &UnusedTok) {
941   // FIXME: Should we be expanding macros here? My guess is no.
942   SourceLocation UnusedLoc = UnusedTok.getLocation();
943 
944   // Lex the left '('.
945   Token Tok;
946   PP.Lex(Tok);
947   if (Tok.isNot(tok::l_paren)) {
948     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
949     return;
950   }
951 
952   // Lex the declaration reference(s).
953   SmallVector<Token, 5> Identifiers;
954   SourceLocation RParenLoc;
955   bool LexID = true;
956 
957   while (true) {
958     PP.Lex(Tok);
959 
960     if (LexID) {
961       if (Tok.is(tok::identifier)) {
962         Identifiers.push_back(Tok);
963         LexID = false;
964         continue;
965       }
966 
967       // Illegal token!
968       PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
969       return;
970     }
971 
972     // We are execting a ')' or a ','.
973     if (Tok.is(tok::comma)) {
974       LexID = true;
975       continue;
976     }
977 
978     if (Tok.is(tok::r_paren)) {
979       RParenLoc = Tok.getLocation();
980       break;
981     }
982 
983     // Illegal token!
984     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
985     return;
986   }
987 
988   PP.Lex(Tok);
989   if (Tok.isNot(tok::eod)) {
990     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
991         "unused";
992     return;
993   }
994 
995   // Verify that we have a location for the right parenthesis.
996   assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
997   assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
998 
999   // For each identifier token, insert into the token stream a
1000   // annot_pragma_unused token followed by the identifier token.
1001   // This allows us to cache a "#pragma unused" that occurs inside an inline
1002   // C++ member function.
1003 
1004   Token *Toks =
1005     (Token*) PP.getPreprocessorAllocator().Allocate(
1006       sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
1007   for (unsigned i=0; i != Identifiers.size(); i++) {
1008     Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1009     pragmaUnusedTok.startToken();
1010     pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1011     pragmaUnusedTok.setLocation(UnusedLoc);
1012     idTok = Identifiers[i];
1013   }
1014   PP.EnterTokenStream(Toks, 2*Identifiers.size(),
1015                       /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1016 }
1017 
1018 // #pragma weak identifier
1019 // #pragma weak identifier '=' identifier
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & WeakTok)1020 void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1021                                      PragmaIntroducerKind Introducer,
1022                                      Token &WeakTok) {
1023   SourceLocation WeakLoc = WeakTok.getLocation();
1024 
1025   Token Tok;
1026   PP.Lex(Tok);
1027   if (Tok.isNot(tok::identifier)) {
1028     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1029     return;
1030   }
1031 
1032   Token WeakName = Tok;
1033   bool HasAlias = false;
1034   Token AliasName;
1035 
1036   PP.Lex(Tok);
1037   if (Tok.is(tok::equal)) {
1038     HasAlias = true;
1039     PP.Lex(Tok);
1040     if (Tok.isNot(tok::identifier)) {
1041       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1042           << "weak";
1043       return;
1044     }
1045     AliasName = Tok;
1046     PP.Lex(Tok);
1047   }
1048 
1049   if (Tok.isNot(tok::eod)) {
1050     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1051     return;
1052   }
1053 
1054   if (HasAlias) {
1055     Token *Toks =
1056       (Token*) PP.getPreprocessorAllocator().Allocate(
1057         sizeof(Token) * 3, llvm::alignOf<Token>());
1058     Token &pragmaUnusedTok = Toks[0];
1059     pragmaUnusedTok.startToken();
1060     pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1061     pragmaUnusedTok.setLocation(WeakLoc);
1062     Toks[1] = WeakName;
1063     Toks[2] = AliasName;
1064     PP.EnterTokenStream(Toks, 3,
1065                         /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1066   } else {
1067     Token *Toks =
1068       (Token*) PP.getPreprocessorAllocator().Allocate(
1069         sizeof(Token) * 2, llvm::alignOf<Token>());
1070     Token &pragmaUnusedTok = Toks[0];
1071     pragmaUnusedTok.startToken();
1072     pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1073     pragmaUnusedTok.setLocation(WeakLoc);
1074     Toks[1] = WeakName;
1075     PP.EnterTokenStream(Toks, 2,
1076                         /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1077   }
1078 }
1079 
1080 // #pragma redefine_extname identifier identifier
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & RedefToken)1081 void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1082                                                PragmaIntroducerKind Introducer,
1083                                                 Token &RedefToken) {
1084   SourceLocation RedefLoc = RedefToken.getLocation();
1085 
1086   Token Tok;
1087   PP.Lex(Tok);
1088   if (Tok.isNot(tok::identifier)) {
1089     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1090       "redefine_extname";
1091     return;
1092   }
1093 
1094   Token RedefName = Tok;
1095   PP.Lex(Tok);
1096 
1097   if (Tok.isNot(tok::identifier)) {
1098     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1099         << "redefine_extname";
1100     return;
1101   }
1102 
1103   Token AliasName = Tok;
1104   PP.Lex(Tok);
1105 
1106   if (Tok.isNot(tok::eod)) {
1107     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1108       "redefine_extname";
1109     return;
1110   }
1111 
1112   Token *Toks =
1113     (Token*) PP.getPreprocessorAllocator().Allocate(
1114       sizeof(Token) * 3, llvm::alignOf<Token>());
1115   Token &pragmaRedefTok = Toks[0];
1116   pragmaRedefTok.startToken();
1117   pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1118   pragmaRedefTok.setLocation(RedefLoc);
1119   Toks[1] = RedefName;
1120   Toks[2] = AliasName;
1121   PP.EnterTokenStream(Toks, 3,
1122                       /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1123 }
1124 
1125 
1126 void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1127 PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
1128                                       PragmaIntroducerKind Introducer,
1129                                       Token &Tok) {
1130   tok::OnOffSwitch OOS;
1131   if (PP.LexOnOffSwitch(OOS))
1132     return;
1133 
1134   Token *Toks =
1135     (Token*) PP.getPreprocessorAllocator().Allocate(
1136       sizeof(Token) * 1, llvm::alignOf<Token>());
1137   new (Toks) Token();
1138   Toks[0].startToken();
1139   Toks[0].setKind(tok::annot_pragma_fp_contract);
1140   Toks[0].setLocation(Tok.getLocation());
1141   Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1142                              static_cast<uintptr_t>(OOS)));
1143   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1144                       /*OwnsTokens=*/false);
1145 }
1146 
1147 void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1148 PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
1149                                            PragmaIntroducerKind Introducer,
1150                                            Token &Tok) {
1151   PP.LexUnexpandedToken(Tok);
1152   if (Tok.isNot(tok::identifier)) {
1153     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1154       "OPENCL";
1155     return;
1156   }
1157   IdentifierInfo *ename = Tok.getIdentifierInfo();
1158   SourceLocation NameLoc = Tok.getLocation();
1159 
1160   PP.Lex(Tok);
1161   if (Tok.isNot(tok::colon)) {
1162     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
1163     return;
1164   }
1165 
1166   PP.Lex(Tok);
1167   if (Tok.isNot(tok::identifier)) {
1168     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1169     return;
1170   }
1171   IdentifierInfo *op = Tok.getIdentifierInfo();
1172 
1173   unsigned state;
1174   if (op->isStr("enable")) {
1175     state = 1;
1176   } else if (op->isStr("disable")) {
1177     state = 0;
1178   } else {
1179     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1180     return;
1181   }
1182   SourceLocation StateLoc = Tok.getLocation();
1183 
1184   PP.Lex(Tok);
1185   if (Tok.isNot(tok::eod)) {
1186     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1187       "OPENCL EXTENSION";
1188     return;
1189   }
1190 
1191   OpenCLExtData data(ename, state);
1192   Token *Toks =
1193     (Token*) PP.getPreprocessorAllocator().Allocate(
1194       sizeof(Token) * 1, llvm::alignOf<Token>());
1195   new (Toks) Token();
1196   Toks[0].startToken();
1197   Toks[0].setKind(tok::annot_pragma_opencl_extension);
1198   Toks[0].setLocation(NameLoc);
1199   Toks[0].setAnnotationValue(data.getOpaqueValue());
1200   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1201                       /*OwnsTokens=*/false);
1202 
1203   if (PP.getPPCallbacks())
1204     PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
1205                                                StateLoc, state);
1206 }
1207 
1208 /// \brief Handle '#pragma omp ...' when OpenMP is disabled.
1209 ///
1210 void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & FirstTok)1211 PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
1212                                     PragmaIntroducerKind Introducer,
1213                                     Token &FirstTok) {
1214   if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
1215                                      FirstTok.getLocation())) {
1216     PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
1217     PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
1218                                     diag::Severity::Ignored, SourceLocation());
1219   }
1220   PP.DiscardUntilEndOfDirective();
1221 }
1222 
1223 /// \brief Handle '#pragma omp ...' when OpenMP is enabled.
1224 ///
1225 void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & FirstTok)1226 PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
1227                                   PragmaIntroducerKind Introducer,
1228                                   Token &FirstTok) {
1229   SmallVector<Token, 16> Pragma;
1230   Token Tok;
1231   Tok.startToken();
1232   Tok.setKind(tok::annot_pragma_openmp);
1233   Tok.setLocation(FirstTok.getLocation());
1234 
1235   while (Tok.isNot(tok::eod)) {
1236     Pragma.push_back(Tok);
1237     PP.Lex(Tok);
1238   }
1239   SourceLocation EodLoc = Tok.getLocation();
1240   Tok.startToken();
1241   Tok.setKind(tok::annot_pragma_openmp_end);
1242   Tok.setLocation(EodLoc);
1243   Pragma.push_back(Tok);
1244 
1245   Token *Toks = new Token[Pragma.size()];
1246   std::copy(Pragma.begin(), Pragma.end(), Toks);
1247   PP.EnterTokenStream(Toks, Pragma.size(),
1248                       /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
1249 }
1250 
1251 /// \brief Handle '#pragma pointers_to_members'
1252 // The grammar for this pragma is as follows:
1253 //
1254 // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
1255 //
1256 // #pragma pointers_to_members '(' 'best_case' ')'
1257 // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
1258 // #pragma pointers_to_members '(' inheritance-model ')'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1259 void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
1260                                              PragmaIntroducerKind Introducer,
1261                                              Token &Tok) {
1262   SourceLocation PointersToMembersLoc = Tok.getLocation();
1263   PP.Lex(Tok);
1264   if (Tok.isNot(tok::l_paren)) {
1265     PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
1266       << "pointers_to_members";
1267     return;
1268   }
1269   PP.Lex(Tok);
1270   const IdentifierInfo *Arg = Tok.getIdentifierInfo();
1271   if (!Arg) {
1272     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1273       << "pointers_to_members";
1274     return;
1275   }
1276   PP.Lex(Tok);
1277 
1278   LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
1279   if (Arg->isStr("best_case")) {
1280     RepresentationMethod = LangOptions::PPTMK_BestCase;
1281   } else {
1282     if (Arg->isStr("full_generality")) {
1283       if (Tok.is(tok::comma)) {
1284         PP.Lex(Tok);
1285 
1286         Arg = Tok.getIdentifierInfo();
1287         if (!Arg) {
1288           PP.Diag(Tok.getLocation(),
1289                   diag::err_pragma_pointers_to_members_unknown_kind)
1290               << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
1291           return;
1292         }
1293         PP.Lex(Tok);
1294       } else if (Tok.is(tok::r_paren)) {
1295         // #pragma pointers_to_members(full_generality) implicitly specifies
1296         // virtual_inheritance.
1297         Arg = nullptr;
1298         RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1299       } else {
1300         PP.Diag(Tok.getLocation(), diag::err_expected_punc)
1301             << "full_generality";
1302         return;
1303       }
1304     }
1305 
1306     if (Arg) {
1307       if (Arg->isStr("single_inheritance")) {
1308         RepresentationMethod =
1309             LangOptions::PPTMK_FullGeneralitySingleInheritance;
1310       } else if (Arg->isStr("multiple_inheritance")) {
1311         RepresentationMethod =
1312             LangOptions::PPTMK_FullGeneralityMultipleInheritance;
1313       } else if (Arg->isStr("virtual_inheritance")) {
1314         RepresentationMethod =
1315             LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1316       } else {
1317         PP.Diag(Tok.getLocation(),
1318                 diag::err_pragma_pointers_to_members_unknown_kind)
1319             << Arg << /*HasPointerDeclaration*/ 1;
1320         return;
1321       }
1322     }
1323   }
1324 
1325   if (Tok.isNot(tok::r_paren)) {
1326     PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
1327         << (Arg ? Arg->getName() : "full_generality");
1328     return;
1329   }
1330 
1331   PP.Lex(Tok);
1332   if (Tok.isNot(tok::eod)) {
1333     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1334       << "pointers_to_members";
1335     return;
1336   }
1337 
1338   Token AnnotTok;
1339   AnnotTok.startToken();
1340   AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
1341   AnnotTok.setLocation(PointersToMembersLoc);
1342   AnnotTok.setAnnotationValue(
1343       reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
1344   PP.EnterToken(AnnotTok);
1345 }
1346 
1347 /// \brief Handle '#pragma vtordisp'
1348 // The grammar for this pragma is as follows:
1349 //
1350 // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
1351 //
1352 // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
1353 // #pragma vtordisp '(' 'pop' ')'
1354 // #pragma vtordisp '(' ')'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1355 void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
1356                                     PragmaIntroducerKind Introducer,
1357                                     Token &Tok) {
1358   SourceLocation VtorDispLoc = Tok.getLocation();
1359   PP.Lex(Tok);
1360   if (Tok.isNot(tok::l_paren)) {
1361     PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
1362     return;
1363   }
1364   PP.Lex(Tok);
1365 
1366   Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
1367   const IdentifierInfo *II = Tok.getIdentifierInfo();
1368   if (II) {
1369     if (II->isStr("push")) {
1370       // #pragma vtordisp(push, mode)
1371       PP.Lex(Tok);
1372       if (Tok.isNot(tok::comma)) {
1373         PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
1374         return;
1375       }
1376       PP.Lex(Tok);
1377       Kind = Sema::PVDK_Push;
1378       // not push, could be on/off
1379     } else if (II->isStr("pop")) {
1380       // #pragma vtordisp(pop)
1381       PP.Lex(Tok);
1382       Kind = Sema::PVDK_Pop;
1383     }
1384     // not push or pop, could be on/off
1385   } else {
1386     if (Tok.is(tok::r_paren)) {
1387       // #pragma vtordisp()
1388       Kind = Sema::PVDK_Reset;
1389     }
1390   }
1391 
1392 
1393   uint64_t Value = 0;
1394   if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
1395     const IdentifierInfo *II = Tok.getIdentifierInfo();
1396     if (II && II->isStr("off")) {
1397       PP.Lex(Tok);
1398       Value = 0;
1399     } else if (II && II->isStr("on")) {
1400       PP.Lex(Tok);
1401       Value = 1;
1402     } else if (Tok.is(tok::numeric_constant) &&
1403                PP.parseSimpleIntegerLiteral(Tok, Value)) {
1404       if (Value > 2) {
1405         PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
1406             << 0 << 2 << "vtordisp";
1407         return;
1408       }
1409     } else {
1410       PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1411           << "vtordisp";
1412       return;
1413     }
1414   }
1415 
1416   // Finish the pragma: ')' $
1417   if (Tok.isNot(tok::r_paren)) {
1418     PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
1419     return;
1420   }
1421   PP.Lex(Tok);
1422   if (Tok.isNot(tok::eod)) {
1423     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1424         << "vtordisp";
1425     return;
1426   }
1427 
1428   // Enter the annotation.
1429   Token AnnotTok;
1430   AnnotTok.startToken();
1431   AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1432   AnnotTok.setLocation(VtorDispLoc);
1433   AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
1434       static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
1435   PP.EnterToken(AnnotTok);
1436 }
1437 
1438 /// \brief Handle all MS pragmas.  Simply forwards the tokens after inserting
1439 /// an annotation token.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1440 void PragmaMSPragma::HandlePragma(Preprocessor &PP,
1441                                   PragmaIntroducerKind Introducer,
1442                                   Token &Tok) {
1443   Token EoF, AnnotTok;
1444   EoF.startToken();
1445   EoF.setKind(tok::eof);
1446   AnnotTok.startToken();
1447   AnnotTok.setKind(tok::annot_pragma_ms_pragma);
1448   AnnotTok.setLocation(Tok.getLocation());
1449   SmallVector<Token, 8> TokenVector;
1450   // Suck up all of the tokens before the eod.
1451   for (; Tok.isNot(tok::eod); PP.Lex(Tok))
1452     TokenVector.push_back(Tok);
1453   // Add a sentinal EoF token to the end of the list.
1454   TokenVector.push_back(EoF);
1455   // We must allocate this array with new because EnterTokenStream is going to
1456   // delete it later.
1457   Token *TokenArray = new Token[TokenVector.size()];
1458   std::copy(TokenVector.begin(), TokenVector.end(), TokenArray);
1459   auto Value = new (PP.getPreprocessorAllocator())
1460       std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size()));
1461   AnnotTok.setAnnotationValue(Value);
1462   PP.EnterToken(AnnotTok);
1463 }
1464 
1465 /// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1466 ///
1467 /// The syntax is:
1468 /// \code
1469 ///   #pragma detect_mismatch("name", "value")
1470 /// \endcode
1471 /// Where 'name' and 'value' are quoted strings.  The values are embedded in
1472 /// the object file and passed along to the linker.  If the linker detects a
1473 /// mismatch in the object file's values for the given name, a LNK2038 error
1474 /// is emitted.  See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1475 void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1476                                                PragmaIntroducerKind Introducer,
1477                                                Token &Tok) {
1478   SourceLocation CommentLoc = Tok.getLocation();
1479   PP.Lex(Tok);
1480   if (Tok.isNot(tok::l_paren)) {
1481     PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
1482     return;
1483   }
1484 
1485   // Read the name to embed, which must be a string literal.
1486   std::string NameString;
1487   if (!PP.LexStringLiteral(Tok, NameString,
1488                            "pragma detect_mismatch",
1489                            /*MacroExpansion=*/true))
1490     return;
1491 
1492   // Read the comma followed by a second string literal.
1493   std::string ValueString;
1494   if (Tok.isNot(tok::comma)) {
1495     PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1496     return;
1497   }
1498 
1499   if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1500                            /*MacroExpansion=*/true))
1501     return;
1502 
1503   if (Tok.isNot(tok::r_paren)) {
1504     PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1505     return;
1506   }
1507   PP.Lex(Tok);  // Eat the r_paren.
1508 
1509   if (Tok.isNot(tok::eod)) {
1510     PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1511     return;
1512   }
1513 
1514   // If the pragma is lexically sound, notify any interested PPCallbacks.
1515   if (PP.getPPCallbacks())
1516     PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
1517                                               ValueString);
1518 
1519   Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
1520 }
1521 
1522 /// \brief Handle the microsoft \#pragma comment extension.
1523 ///
1524 /// The syntax is:
1525 /// \code
1526 ///   #pragma comment(linker, "foo")
1527 /// \endcode
1528 /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1529 /// "foo" is a string, which is fully macro expanded, and permits string
1530 /// concatenation, embedded escape characters etc.  See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1531 void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1532                                         PragmaIntroducerKind Introducer,
1533                                         Token &Tok) {
1534   SourceLocation CommentLoc = Tok.getLocation();
1535   PP.Lex(Tok);
1536   if (Tok.isNot(tok::l_paren)) {
1537     PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1538     return;
1539   }
1540 
1541   // Read the identifier.
1542   PP.Lex(Tok);
1543   if (Tok.isNot(tok::identifier)) {
1544     PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1545     return;
1546   }
1547 
1548   // Verify that this is one of the 5 whitelisted options.
1549   IdentifierInfo *II = Tok.getIdentifierInfo();
1550   Sema::PragmaMSCommentKind Kind =
1551     llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
1552     .Case("linker",   Sema::PCK_Linker)
1553     .Case("lib",      Sema::PCK_Lib)
1554     .Case("compiler", Sema::PCK_Compiler)
1555     .Case("exestr",   Sema::PCK_ExeStr)
1556     .Case("user",     Sema::PCK_User)
1557     .Default(Sema::PCK_Unknown);
1558   if (Kind == Sema::PCK_Unknown) {
1559     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1560     return;
1561   }
1562 
1563   // Read the optional string if present.
1564   PP.Lex(Tok);
1565   std::string ArgumentString;
1566   if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1567                                                  "pragma comment",
1568                                                  /*MacroExpansion=*/true))
1569     return;
1570 
1571   // FIXME: warn that 'exestr' is deprecated.
1572   // FIXME: If the kind is "compiler" warn if the string is present (it is
1573   // ignored).
1574   // The MSDN docs say that "lib" and "linker" require a string and have a short
1575   // whitelist of linker options they support, but in practice MSVC doesn't
1576   // issue a diagnostic.  Therefore neither does clang.
1577 
1578   if (Tok.isNot(tok::r_paren)) {
1579     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1580     return;
1581   }
1582   PP.Lex(Tok);  // eat the r_paren.
1583 
1584   if (Tok.isNot(tok::eod)) {
1585     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1586     return;
1587   }
1588 
1589   // If the pragma is lexically sound, notify any interested PPCallbacks.
1590   if (PP.getPPCallbacks())
1591     PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
1592 
1593   Actions.ActOnPragmaMSComment(Kind, ArgumentString);
1594 }
1595 
1596 // #pragma clang optimize off
1597 // #pragma clang optimize on
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & FirstToken)1598 void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
1599                                         PragmaIntroducerKind Introducer,
1600                                         Token &FirstToken) {
1601   Token Tok;
1602   PP.Lex(Tok);
1603   if (Tok.is(tok::eod)) {
1604     PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_missing_argument);
1605     return;
1606   }
1607   if (Tok.isNot(tok::identifier)) {
1608     PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1609       << PP.getSpelling(Tok);
1610     return;
1611   }
1612   const IdentifierInfo *II = Tok.getIdentifierInfo();
1613   // The only accepted values are 'on' or 'off'.
1614   bool IsOn = false;
1615   if (II->isStr("on")) {
1616     IsOn = true;
1617   } else if (!II->isStr("off")) {
1618     PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1619       << PP.getSpelling(Tok);
1620     return;
1621   }
1622   PP.Lex(Tok);
1623 
1624   if (Tok.isNot(tok::eod)) {
1625     PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
1626       << PP.getSpelling(Tok);
1627     return;
1628   }
1629 
1630   Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
1631 }
1632 
1633 /// \brief Handle the \#pragma clang loop directive.
1634 ///  #pragma clang 'loop' loop-hints
1635 ///
1636 ///  loop-hints:
1637 ///    loop-hint loop-hints[opt]
1638 ///
1639 ///  loop-hint:
1640 ///    'vectorize' '(' loop-hint-keyword ')'
1641 ///    'interleave' '(' loop-hint-keyword ')'
1642 ///    'unroll' '(' loop-hint-keyword ')'
1643 ///    'vectorize_width' '(' loop-hint-value ')'
1644 ///    'interleave_count' '(' loop-hint-value ')'
1645 ///    'unroll_count' '(' loop-hint-value ')'
1646 ///
1647 ///  loop-hint-keyword:
1648 ///    'enable'
1649 ///    'disable'
1650 ///
1651 ///  loop-hint-value:
1652 ///    constant-expression
1653 ///
1654 /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
1655 /// try vectorizing the instructions of the loop it precedes. Specifying
1656 /// interleave(enable) or interleave_count(_value_) instructs llvm to try
1657 /// interleaving multiple iterations of the loop it precedes. The width of the
1658 /// vector instructions is specified by vectorize_width() and the number of
1659 /// interleaved loop iterations is specified by interleave_count(). Specifying a
1660 /// value of 1 effectively disables vectorization/interleaving, even if it is
1661 /// possible and profitable, and 0 is invalid. The loop vectorizer currently
1662 /// only works on inner loops.
1663 ///
1664 /// The unroll and unroll_count directives control the concatenation
1665 /// unroller. Specifying unroll(enable) instructs llvm to try to
1666 /// unroll the loop completely, and unroll(disable) disables unrolling
1667 /// for the loop. Specifying unroll_count(_value_) instructs llvm to
1668 /// try to unroll the loop the number of times indicated by the value.
1669 /// If unroll(enable) and unroll_count are both specified only
1670 /// unroll_count takes effect.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1671 void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
1672                                          PragmaIntroducerKind Introducer,
1673                                          Token &Tok) {
1674   Token Loop = Tok;
1675   SmallVector<Token, 1> TokenList;
1676 
1677   // Lex the optimization option and verify it is an identifier.
1678   PP.Lex(Tok);
1679   if (Tok.isNot(tok::identifier)) {
1680     PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
1681         << /*MissingOption=*/true << "";
1682     return;
1683   }
1684 
1685   while (Tok.is(tok::identifier)) {
1686     Token Option = Tok;
1687     IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
1688 
1689     bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
1690         .Case("vectorize", true)
1691         .Case("interleave", true)
1692         .Case("unroll", true)
1693         .Case("vectorize_width", true)
1694         .Case("interleave_count", true)
1695         .Case("unroll_count", true)
1696         .Default(false);
1697     if (!OptionValid) {
1698       PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
1699           << /*MissingOption=*/false << OptionInfo;
1700       return;
1701     }
1702 
1703     // Read '('
1704     PP.Lex(Tok);
1705     if (Tok.isNot(tok::l_paren)) {
1706       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
1707       return;
1708     }
1709 
1710     // FIXME: All tokens between '(' and ')' should be stored and parsed as a
1711     // constant expression.
1712     PP.Lex(Tok);
1713     if (Tok.is(tok::r_paren)) {
1714       // Nothing between the parentheses.
1715       PP.Diag(Tok.getLocation(), diag::err_pragma_loop_missing_argument)
1716           << OptionInfo;
1717       return;
1718     }
1719     Token Value = Tok;
1720 
1721     // Read ')'
1722     PP.Lex(Tok);
1723     if (Tok.isNot(tok::r_paren)) {
1724       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1725       return;
1726     }
1727 
1728     // Get next optimization option.
1729     PP.Lex(Tok);
1730 
1731     auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
1732     Info->Loop = Loop;
1733     Info->Option = Option;
1734     Info->Value = Value;
1735 
1736     // Generate the vectorization hint token.
1737     Token LoopHintTok;
1738     LoopHintTok.startToken();
1739     LoopHintTok.setKind(tok::annot_pragma_loop_hint);
1740     LoopHintTok.setLocation(Loop.getLocation());
1741     LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
1742     TokenList.push_back(LoopHintTok);
1743   }
1744 
1745   if (Tok.isNot(tok::eod)) {
1746     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1747         << "clang loop";
1748     return;
1749   }
1750 
1751   Token *TokenArray = new Token[TokenList.size()];
1752   std::copy(TokenList.begin(), TokenList.end(), TokenArray);
1753 
1754   PP.EnterTokenStream(TokenArray, TokenList.size(),
1755                       /*DisableMacroExpansion=*/false,
1756                       /*OwnsTokens=*/true);
1757 }
1758