1 //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the language specific #pragma handlers.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/AST/ASTContext.h"
14 #include "clang/Basic/PragmaKinds.h"
15 #include "clang/Basic/TargetInfo.h"
16 #include "clang/Lex/Preprocessor.h"
17 #include "clang/Lex/Token.h"
18 #include "clang/Parse/LoopHint.h"
19 #include "clang/Parse/ParseDiagnostic.h"
20 #include "clang/Parse/Parser.h"
21 #include "clang/Parse/RAIIObjectsForParser.h"
22 #include "clang/Sema/EnterExpressionEvaluationContext.h"
23 #include "clang/Sema/Scope.h"
24 #include "llvm/ADT/ArrayRef.h"
25 #include "llvm/ADT/StringSwitch.h"
26 #include <optional>
27 using namespace clang;
28 
29 namespace {
30 
31 struct PragmaAlignHandler : public PragmaHandler {
PragmaAlignHandler__anon11f1a89f0111::PragmaAlignHandler32   explicit PragmaAlignHandler() : PragmaHandler("align") {}
33   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
34                     Token &FirstToken) override;
35 };
36 
37 struct PragmaGCCVisibilityHandler : public PragmaHandler {
PragmaGCCVisibilityHandler__anon11f1a89f0111::PragmaGCCVisibilityHandler38   explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
39   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
40                     Token &FirstToken) override;
41 };
42 
43 struct PragmaOptionsHandler : public PragmaHandler {
PragmaOptionsHandler__anon11f1a89f0111::PragmaOptionsHandler44   explicit PragmaOptionsHandler() : PragmaHandler("options") {}
45   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
46                     Token &FirstToken) override;
47 };
48 
49 struct PragmaPackHandler : public PragmaHandler {
PragmaPackHandler__anon11f1a89f0111::PragmaPackHandler50   explicit PragmaPackHandler() : PragmaHandler("pack") {}
51   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
52                     Token &FirstToken) override;
53 };
54 
55 struct PragmaClangSectionHandler : public PragmaHandler {
PragmaClangSectionHandler__anon11f1a89f0111::PragmaClangSectionHandler56   explicit PragmaClangSectionHandler(Sema &S)
57              : PragmaHandler("section"), Actions(S) {}
58   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
59                     Token &FirstToken) override;
60 
61 private:
62   Sema &Actions;
63 };
64 
65 struct PragmaMSStructHandler : public PragmaHandler {
PragmaMSStructHandler__anon11f1a89f0111::PragmaMSStructHandler66   explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
67   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
68                     Token &FirstToken) override;
69 };
70 
71 struct PragmaUnusedHandler : public PragmaHandler {
PragmaUnusedHandler__anon11f1a89f0111::PragmaUnusedHandler72   PragmaUnusedHandler() : PragmaHandler("unused") {}
73   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
74                     Token &FirstToken) override;
75 };
76 
77 struct PragmaWeakHandler : public PragmaHandler {
PragmaWeakHandler__anon11f1a89f0111::PragmaWeakHandler78   explicit PragmaWeakHandler() : PragmaHandler("weak") {}
79   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
80                     Token &FirstToken) override;
81 };
82 
83 struct PragmaRedefineExtnameHandler : public PragmaHandler {
PragmaRedefineExtnameHandler__anon11f1a89f0111::PragmaRedefineExtnameHandler84   explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
85   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
86                     Token &FirstToken) override;
87 };
88 
89 struct PragmaOpenCLExtensionHandler : public PragmaHandler {
PragmaOpenCLExtensionHandler__anon11f1a89f0111::PragmaOpenCLExtensionHandler90   PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
91   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
92                     Token &FirstToken) override;
93 };
94 
95 
96 struct PragmaFPContractHandler : public PragmaHandler {
PragmaFPContractHandler__anon11f1a89f0111::PragmaFPContractHandler97   PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
98   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
99                     Token &FirstToken) override;
100 };
101 
102 // Pragma STDC implementations.
103 
104 /// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
105 struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
PragmaSTDC_FENV_ACCESSHandler__anon11f1a89f0111::PragmaSTDC_FENV_ACCESSHandler106   PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
107 
HandlePragma__anon11f1a89f0111::PragmaSTDC_FENV_ACCESSHandler108   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
109                     Token &Tok) override {
110     Token PragmaName = Tok;
111     if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
112       PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
113           << PragmaName.getIdentifierInfo()->getName();
114       return;
115     }
116     tok::OnOffSwitch OOS;
117     if (PP.LexOnOffSwitch(OOS))
118      return;
119 
120     MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
121                                 1);
122     Toks[0].startToken();
123     Toks[0].setKind(tok::annot_pragma_fenv_access);
124     Toks[0].setLocation(Tok.getLocation());
125     Toks[0].setAnnotationEndLoc(Tok.getLocation());
126     Toks[0].setAnnotationValue(reinterpret_cast<void*>(
127                                static_cast<uintptr_t>(OOS)));
128     PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
129                         /*IsReinject=*/false);
130   }
131 };
132 
133 /// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
134 struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
PragmaSTDC_CX_LIMITED_RANGEHandler__anon11f1a89f0111::PragmaSTDC_CX_LIMITED_RANGEHandler135   PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
136 
HandlePragma__anon11f1a89f0111::PragmaSTDC_CX_LIMITED_RANGEHandler137   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
138                     Token &Tok) override {
139     tok::OnOffSwitch OOS;
140     if (PP.LexOnOffSwitch(OOS))
141       return;
142 
143     MutableArrayRef<Token> Toks(
144         PP.getPreprocessorAllocator().Allocate<Token>(1), 1);
145 
146     Toks[0].startToken();
147     Toks[0].setKind(tok::annot_pragma_cx_limited_range);
148     Toks[0].setLocation(Tok.getLocation());
149     Toks[0].setAnnotationEndLoc(Tok.getLocation());
150     Toks[0].setAnnotationValue(
151         reinterpret_cast<void *>(static_cast<uintptr_t>(OOS)));
152     PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
153                         /*IsReinject=*/false);
154   }
155 };
156 
157 /// Handler for "\#pragma STDC FENV_ROUND ...".
158 struct PragmaSTDC_FENV_ROUNDHandler : public PragmaHandler {
PragmaSTDC_FENV_ROUNDHandler__anon11f1a89f0111::PragmaSTDC_FENV_ROUNDHandler159   PragmaSTDC_FENV_ROUNDHandler() : PragmaHandler("FENV_ROUND") {}
160 
161   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
162                     Token &Tok) override;
163 };
164 
165 /// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
166 struct PragmaSTDC_UnknownHandler : public PragmaHandler {
167   PragmaSTDC_UnknownHandler() = default;
168 
HandlePragma__anon11f1a89f0111::PragmaSTDC_UnknownHandler169   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
170                     Token &UnknownTok) override {
171     // C99 6.10.6p2, unknown forms are not allowed.
172     PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
173   }
174 };
175 
176 struct PragmaFPHandler : public PragmaHandler {
PragmaFPHandler__anon11f1a89f0111::PragmaFPHandler177   PragmaFPHandler() : PragmaHandler("fp") {}
178   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
179                     Token &FirstToken) override;
180 };
181 
182 // A pragma handler to be the base of the NoOpenMPHandler and NoOpenACCHandler,
183 // which are identical other than the name given to them, and the diagnostic
184 // emitted.
185 template <diag::kind IgnoredDiag>
186 struct PragmaNoSupportHandler : public PragmaHandler {
PragmaNoSupportHandler__anon11f1a89f0111::PragmaNoSupportHandler187   PragmaNoSupportHandler(StringRef Name) : PragmaHandler(Name) {}
188   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
189                     Token &FirstToken) override;
190 };
191 
192 struct PragmaNoOpenMPHandler
193     : public PragmaNoSupportHandler<diag::warn_pragma_omp_ignored> {
PragmaNoOpenMPHandler__anon11f1a89f0111::PragmaNoOpenMPHandler194   PragmaNoOpenMPHandler() : PragmaNoSupportHandler("omp") {}
195 };
196 
197 struct PragmaNoOpenACCHandler
198     : public PragmaNoSupportHandler<diag::warn_pragma_acc_ignored> {
PragmaNoOpenACCHandler__anon11f1a89f0111::PragmaNoOpenACCHandler199   PragmaNoOpenACCHandler() : PragmaNoSupportHandler("acc") {}
200 };
201 
202 // A pragma handler to be the base for the OpenMPHandler and OpenACCHandler,
203 // which are identical other than the tokens used for the start/end of a pragma
204 // section, and some diagnostics.
205 template <tok::TokenKind StartTok, tok::TokenKind EndTok,
206           diag::kind UnexpectedDiag>
207 struct PragmaSupportHandler : public PragmaHandler {
PragmaSupportHandler__anon11f1a89f0111::PragmaSupportHandler208   PragmaSupportHandler(StringRef Name) : PragmaHandler(Name) {}
209   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
210                     Token &FirstToken) override;
211 };
212 
213 struct PragmaOpenMPHandler
214     : public PragmaSupportHandler<tok::annot_pragma_openmp,
215                                   tok::annot_pragma_openmp_end,
216                                   diag::err_omp_unexpected_directive> {
PragmaOpenMPHandler__anon11f1a89f0111::PragmaOpenMPHandler217   PragmaOpenMPHandler() : PragmaSupportHandler("omp") {}
218 };
219 
220 struct PragmaOpenACCHandler
221     : public PragmaSupportHandler<tok::annot_pragma_openacc,
222                                   tok::annot_pragma_openacc_end,
223                                   diag::err_acc_unexpected_directive> {
PragmaOpenACCHandler__anon11f1a89f0111::PragmaOpenACCHandler224   PragmaOpenACCHandler() : PragmaSupportHandler("acc") {}
225 };
226 
227 /// PragmaCommentHandler - "\#pragma comment ...".
228 struct PragmaCommentHandler : public PragmaHandler {
PragmaCommentHandler__anon11f1a89f0111::PragmaCommentHandler229   PragmaCommentHandler(Sema &Actions)
230     : PragmaHandler("comment"), Actions(Actions) {}
231   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
232                     Token &FirstToken) override;
233 
234 private:
235   Sema &Actions;
236 };
237 
238 struct PragmaDetectMismatchHandler : public PragmaHandler {
PragmaDetectMismatchHandler__anon11f1a89f0111::PragmaDetectMismatchHandler239   PragmaDetectMismatchHandler(Sema &Actions)
240     : PragmaHandler("detect_mismatch"), Actions(Actions) {}
241   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
242                     Token &FirstToken) override;
243 
244 private:
245   Sema &Actions;
246 };
247 
248 struct PragmaFloatControlHandler : public PragmaHandler {
PragmaFloatControlHandler__anon11f1a89f0111::PragmaFloatControlHandler249   PragmaFloatControlHandler(Sema &Actions)
250       : PragmaHandler("float_control") {}
251   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
252                     Token &FirstToken) override;
253 };
254 
255 struct PragmaMSPointersToMembers : public PragmaHandler {
PragmaMSPointersToMembers__anon11f1a89f0111::PragmaMSPointersToMembers256   explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
257   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
258                     Token &FirstToken) override;
259 };
260 
261 struct PragmaMSVtorDisp : public PragmaHandler {
PragmaMSVtorDisp__anon11f1a89f0111::PragmaMSVtorDisp262   explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
263   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
264                     Token &FirstToken) override;
265 };
266 
267 struct PragmaMSPragma : public PragmaHandler {
PragmaMSPragma__anon11f1a89f0111::PragmaMSPragma268   explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
269   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
270                     Token &FirstToken) override;
271 };
272 
273 /// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
274 struct PragmaOptimizeHandler : public PragmaHandler {
PragmaOptimizeHandler__anon11f1a89f0111::PragmaOptimizeHandler275   PragmaOptimizeHandler(Sema &S)
276     : PragmaHandler("optimize"), Actions(S) {}
277   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
278                     Token &FirstToken) override;
279 
280 private:
281   Sema &Actions;
282 };
283 
284 struct PragmaLoopHintHandler : public PragmaHandler {
PragmaLoopHintHandler__anon11f1a89f0111::PragmaLoopHintHandler285   PragmaLoopHintHandler() : PragmaHandler("loop") {}
286   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
287                     Token &FirstToken) override;
288 };
289 
290 struct PragmaUnrollHintHandler : public PragmaHandler {
PragmaUnrollHintHandler__anon11f1a89f0111::PragmaUnrollHintHandler291   PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
292   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
293                     Token &FirstToken) override;
294 };
295 
296 struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
PragmaMSRuntimeChecksHandler__anon11f1a89f0111::PragmaMSRuntimeChecksHandler297   PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
298 };
299 
300 struct PragmaMSIntrinsicHandler : public PragmaHandler {
PragmaMSIntrinsicHandler__anon11f1a89f0111::PragmaMSIntrinsicHandler301   PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
302   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
303                     Token &FirstToken) override;
304 };
305 
306 // "\#pragma fenv_access (on)".
307 struct PragmaMSFenvAccessHandler : public PragmaHandler {
PragmaMSFenvAccessHandler__anon11f1a89f0111::PragmaMSFenvAccessHandler308   PragmaMSFenvAccessHandler() : PragmaHandler("fenv_access") {}
HandlePragma__anon11f1a89f0111::PragmaMSFenvAccessHandler309   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
310                     Token &FirstToken) override {
311     StringRef PragmaName = FirstToken.getIdentifierInfo()->getName();
312     if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
313       PP.Diag(FirstToken.getLocation(), diag::warn_pragma_fp_ignored)
314           << PragmaName;
315       return;
316     }
317 
318     Token Tok;
319     PP.Lex(Tok);
320     if (Tok.isNot(tok::l_paren)) {
321       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
322           << PragmaName;
323       return;
324     }
325     PP.Lex(Tok); // Consume the l_paren.
326     if (Tok.isNot(tok::identifier)) {
327       PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
328       return;
329     }
330     const IdentifierInfo *II = Tok.getIdentifierInfo();
331     tok::OnOffSwitch OOS;
332     if (II->isStr("on")) {
333       OOS = tok::OOS_ON;
334       PP.Lex(Tok);
335     } else if (II->isStr("off")) {
336       OOS = tok::OOS_OFF;
337       PP.Lex(Tok);
338     } else {
339       PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
340       return;
341     }
342     if (Tok.isNot(tok::r_paren)) {
343       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
344           << PragmaName;
345       return;
346     }
347     PP.Lex(Tok); // Consume the r_paren.
348 
349     if (Tok.isNot(tok::eod)) {
350       PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
351           << PragmaName;
352       return;
353     }
354 
355     MutableArrayRef<Token> Toks(
356         PP.getPreprocessorAllocator().Allocate<Token>(1), 1);
357     Toks[0].startToken();
358     Toks[0].setKind(tok::annot_pragma_fenv_access_ms);
359     Toks[0].setLocation(FirstToken.getLocation());
360     Toks[0].setAnnotationEndLoc(Tok.getLocation());
361     Toks[0].setAnnotationValue(
362         reinterpret_cast<void*>(static_cast<uintptr_t>(OOS)));
363     PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
364                         /*IsReinject=*/false);
365   }
366 };
367 
368 struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
PragmaForceCUDAHostDeviceHandler__anon11f1a89f0111::PragmaForceCUDAHostDeviceHandler369   PragmaForceCUDAHostDeviceHandler(Sema &Actions)
370       : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
371   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
372                     Token &FirstToken) override;
373 
374 private:
375   Sema &Actions;
376 };
377 
378 /// PragmaAttributeHandler - "\#pragma clang attribute ...".
379 struct PragmaAttributeHandler : public PragmaHandler {
PragmaAttributeHandler__anon11f1a89f0111::PragmaAttributeHandler380   PragmaAttributeHandler(AttributeFactory &AttrFactory)
381       : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
382   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
383                     Token &FirstToken) override;
384 
385   /// A pool of attributes that were parsed in \#pragma clang attribute.
386   ParsedAttributes AttributesForPragmaAttribute;
387 };
388 
389 struct PragmaMaxTokensHereHandler : public PragmaHandler {
PragmaMaxTokensHereHandler__anon11f1a89f0111::PragmaMaxTokensHereHandler390   PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {}
391   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
392                     Token &FirstToken) override;
393 };
394 
395 struct PragmaMaxTokensTotalHandler : public PragmaHandler {
PragmaMaxTokensTotalHandler__anon11f1a89f0111::PragmaMaxTokensTotalHandler396   PragmaMaxTokensTotalHandler() : PragmaHandler("max_tokens_total") {}
397   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
398                     Token &FirstToken) override;
399 };
400 
401 struct PragmaRISCVHandler : public PragmaHandler {
PragmaRISCVHandler__anon11f1a89f0111::PragmaRISCVHandler402   PragmaRISCVHandler(Sema &Actions)
403       : PragmaHandler("riscv"), Actions(Actions) {}
404   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
405                     Token &FirstToken) override;
406 
407 private:
408   Sema &Actions;
409 };
410 
markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks)411 void markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks) {
412   for (auto &T : Toks)
413     T.setFlag(clang::Token::IsReinjected);
414 }
415 }  // end namespace
416 
initializePragmaHandlers()417 void Parser::initializePragmaHandlers() {
418   AlignHandler = std::make_unique<PragmaAlignHandler>();
419   PP.AddPragmaHandler(AlignHandler.get());
420 
421   GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>();
422   PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
423 
424   OptionsHandler = std::make_unique<PragmaOptionsHandler>();
425   PP.AddPragmaHandler(OptionsHandler.get());
426 
427   PackHandler = std::make_unique<PragmaPackHandler>();
428   PP.AddPragmaHandler(PackHandler.get());
429 
430   MSStructHandler = std::make_unique<PragmaMSStructHandler>();
431   PP.AddPragmaHandler(MSStructHandler.get());
432 
433   UnusedHandler = std::make_unique<PragmaUnusedHandler>();
434   PP.AddPragmaHandler(UnusedHandler.get());
435 
436   WeakHandler = std::make_unique<PragmaWeakHandler>();
437   PP.AddPragmaHandler(WeakHandler.get());
438 
439   RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>();
440   PP.AddPragmaHandler(RedefineExtnameHandler.get());
441 
442   FPContractHandler = std::make_unique<PragmaFPContractHandler>();
443   PP.AddPragmaHandler("STDC", FPContractHandler.get());
444 
445   STDCFenvAccessHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
446   PP.AddPragmaHandler("STDC", STDCFenvAccessHandler.get());
447 
448   STDCFenvRoundHandler = std::make_unique<PragmaSTDC_FENV_ROUNDHandler>();
449   PP.AddPragmaHandler("STDC", STDCFenvRoundHandler.get());
450 
451   STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
452   PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
453 
454   STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>();
455   PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
456 
457   PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions);
458   PP.AddPragmaHandler("clang", PCSectionHandler.get());
459 
460   if (getLangOpts().OpenCL) {
461     OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>();
462     PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
463 
464     PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
465   }
466   if (getLangOpts().OpenMP)
467     OpenMPHandler = std::make_unique<PragmaOpenMPHandler>();
468   else
469     OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>();
470   PP.AddPragmaHandler(OpenMPHandler.get());
471 
472   if (getLangOpts().OpenACC)
473     OpenACCHandler = std::make_unique<PragmaOpenACCHandler>();
474   else
475     OpenACCHandler = std::make_unique<PragmaNoOpenACCHandler>();
476   PP.AddPragmaHandler(OpenACCHandler.get());
477 
478   if (getLangOpts().MicrosoftExt ||
479       getTargetInfo().getTriple().isOSBinFormatELF()) {
480     MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions);
481     PP.AddPragmaHandler(MSCommentHandler.get());
482   }
483 
484   FloatControlHandler = std::make_unique<PragmaFloatControlHandler>(Actions);
485   PP.AddPragmaHandler(FloatControlHandler.get());
486   if (getLangOpts().MicrosoftExt) {
487     MSDetectMismatchHandler =
488         std::make_unique<PragmaDetectMismatchHandler>(Actions);
489     PP.AddPragmaHandler(MSDetectMismatchHandler.get());
490     MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>();
491     PP.AddPragmaHandler(MSPointersToMembers.get());
492     MSVtorDisp = std::make_unique<PragmaMSVtorDisp>();
493     PP.AddPragmaHandler(MSVtorDisp.get());
494     MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg");
495     PP.AddPragmaHandler(MSInitSeg.get());
496     MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg");
497     PP.AddPragmaHandler(MSDataSeg.get());
498     MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg");
499     PP.AddPragmaHandler(MSBSSSeg.get());
500     MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg");
501     PP.AddPragmaHandler(MSConstSeg.get());
502     MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg");
503     PP.AddPragmaHandler(MSCodeSeg.get());
504     MSSection = std::make_unique<PragmaMSPragma>("section");
505     PP.AddPragmaHandler(MSSection.get());
506     MSStrictGuardStackCheck =
507         std::make_unique<PragmaMSPragma>("strict_gs_check");
508     PP.AddPragmaHandler(MSStrictGuardStackCheck.get());
509     MSFunction = std::make_unique<PragmaMSPragma>("function");
510     PP.AddPragmaHandler(MSFunction.get());
511     MSAllocText = std::make_unique<PragmaMSPragma>("alloc_text");
512     PP.AddPragmaHandler(MSAllocText.get());
513     MSOptimize = std::make_unique<PragmaMSPragma>("optimize");
514     PP.AddPragmaHandler(MSOptimize.get());
515     MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>();
516     PP.AddPragmaHandler(MSRuntimeChecks.get());
517     MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>();
518     PP.AddPragmaHandler(MSIntrinsic.get());
519     MSFenvAccess = std::make_unique<PragmaMSFenvAccessHandler>();
520     PP.AddPragmaHandler(MSFenvAccess.get());
521   }
522 
523   if (getLangOpts().CUDA) {
524     CUDAForceHostDeviceHandler =
525         std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
526     PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
527   }
528 
529   OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions);
530   PP.AddPragmaHandler("clang", OptimizeHandler.get());
531 
532   LoopHintHandler = std::make_unique<PragmaLoopHintHandler>();
533   PP.AddPragmaHandler("clang", LoopHintHandler.get());
534 
535   UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll");
536   PP.AddPragmaHandler(UnrollHintHandler.get());
537   PP.AddPragmaHandler("GCC", UnrollHintHandler.get());
538 
539   NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll");
540   PP.AddPragmaHandler(NoUnrollHintHandler.get());
541   PP.AddPragmaHandler("GCC", NoUnrollHintHandler.get());
542 
543   UnrollAndJamHintHandler =
544       std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
545   PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
546 
547   NoUnrollAndJamHintHandler =
548       std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
549   PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
550 
551   FPHandler = std::make_unique<PragmaFPHandler>();
552   PP.AddPragmaHandler("clang", FPHandler.get());
553 
554   AttributePragmaHandler =
555       std::make_unique<PragmaAttributeHandler>(AttrFactory);
556   PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
557 
558   MaxTokensHerePragmaHandler = std::make_unique<PragmaMaxTokensHereHandler>();
559   PP.AddPragmaHandler("clang", MaxTokensHerePragmaHandler.get());
560 
561   MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>();
562   PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
563 
564   if (getTargetInfo().getTriple().isRISCV()) {
565     RISCVPragmaHandler = std::make_unique<PragmaRISCVHandler>(Actions);
566     PP.AddPragmaHandler("clang", RISCVPragmaHandler.get());
567   }
568 }
569 
resetPragmaHandlers()570 void Parser::resetPragmaHandlers() {
571   // Remove the pragma handlers we installed.
572   PP.RemovePragmaHandler(AlignHandler.get());
573   AlignHandler.reset();
574   PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
575   GCCVisibilityHandler.reset();
576   PP.RemovePragmaHandler(OptionsHandler.get());
577   OptionsHandler.reset();
578   PP.RemovePragmaHandler(PackHandler.get());
579   PackHandler.reset();
580   PP.RemovePragmaHandler(MSStructHandler.get());
581   MSStructHandler.reset();
582   PP.RemovePragmaHandler(UnusedHandler.get());
583   UnusedHandler.reset();
584   PP.RemovePragmaHandler(WeakHandler.get());
585   WeakHandler.reset();
586   PP.RemovePragmaHandler(RedefineExtnameHandler.get());
587   RedefineExtnameHandler.reset();
588 
589   if (getLangOpts().OpenCL) {
590     PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
591     OpenCLExtensionHandler.reset();
592     PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
593   }
594   PP.RemovePragmaHandler(OpenMPHandler.get());
595   OpenMPHandler.reset();
596 
597   PP.RemovePragmaHandler(OpenACCHandler.get());
598   OpenACCHandler.reset();
599 
600   if (getLangOpts().MicrosoftExt ||
601       getTargetInfo().getTriple().isOSBinFormatELF()) {
602     PP.RemovePragmaHandler(MSCommentHandler.get());
603     MSCommentHandler.reset();
604   }
605 
606   PP.RemovePragmaHandler("clang", PCSectionHandler.get());
607   PCSectionHandler.reset();
608 
609   PP.RemovePragmaHandler(FloatControlHandler.get());
610   FloatControlHandler.reset();
611   if (getLangOpts().MicrosoftExt) {
612     PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
613     MSDetectMismatchHandler.reset();
614     PP.RemovePragmaHandler(MSPointersToMembers.get());
615     MSPointersToMembers.reset();
616     PP.RemovePragmaHandler(MSVtorDisp.get());
617     MSVtorDisp.reset();
618     PP.RemovePragmaHandler(MSInitSeg.get());
619     MSInitSeg.reset();
620     PP.RemovePragmaHandler(MSDataSeg.get());
621     MSDataSeg.reset();
622     PP.RemovePragmaHandler(MSBSSSeg.get());
623     MSBSSSeg.reset();
624     PP.RemovePragmaHandler(MSConstSeg.get());
625     MSConstSeg.reset();
626     PP.RemovePragmaHandler(MSCodeSeg.get());
627     MSCodeSeg.reset();
628     PP.RemovePragmaHandler(MSSection.get());
629     MSSection.reset();
630     PP.RemovePragmaHandler(MSStrictGuardStackCheck.get());
631     MSStrictGuardStackCheck.reset();
632     PP.RemovePragmaHandler(MSFunction.get());
633     MSFunction.reset();
634     PP.RemovePragmaHandler(MSAllocText.get());
635     MSAllocText.reset();
636     PP.RemovePragmaHandler(MSRuntimeChecks.get());
637     MSRuntimeChecks.reset();
638     PP.RemovePragmaHandler(MSIntrinsic.get());
639     MSIntrinsic.reset();
640     PP.RemovePragmaHandler(MSOptimize.get());
641     MSOptimize.reset();
642     PP.RemovePragmaHandler(MSFenvAccess.get());
643     MSFenvAccess.reset();
644   }
645 
646   if (getLangOpts().CUDA) {
647     PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
648     CUDAForceHostDeviceHandler.reset();
649   }
650 
651   PP.RemovePragmaHandler("STDC", FPContractHandler.get());
652   FPContractHandler.reset();
653 
654   PP.RemovePragmaHandler("STDC", STDCFenvAccessHandler.get());
655   STDCFenvAccessHandler.reset();
656 
657   PP.RemovePragmaHandler("STDC", STDCFenvRoundHandler.get());
658   STDCFenvRoundHandler.reset();
659 
660   PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
661   STDCCXLIMITHandler.reset();
662 
663   PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
664   STDCUnknownHandler.reset();
665 
666   PP.RemovePragmaHandler("clang", OptimizeHandler.get());
667   OptimizeHandler.reset();
668 
669   PP.RemovePragmaHandler("clang", LoopHintHandler.get());
670   LoopHintHandler.reset();
671 
672   PP.RemovePragmaHandler(UnrollHintHandler.get());
673   PP.RemovePragmaHandler("GCC", UnrollHintHandler.get());
674   UnrollHintHandler.reset();
675 
676   PP.RemovePragmaHandler(NoUnrollHintHandler.get());
677   PP.RemovePragmaHandler("GCC", NoUnrollHintHandler.get());
678   NoUnrollHintHandler.reset();
679 
680   PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
681   UnrollAndJamHintHandler.reset();
682 
683   PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
684   NoUnrollAndJamHintHandler.reset();
685 
686   PP.RemovePragmaHandler("clang", FPHandler.get());
687   FPHandler.reset();
688 
689   PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
690   AttributePragmaHandler.reset();
691 
692   PP.RemovePragmaHandler("clang", MaxTokensHerePragmaHandler.get());
693   MaxTokensHerePragmaHandler.reset();
694 
695   PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
696   MaxTokensTotalPragmaHandler.reset();
697 
698   if (getTargetInfo().getTriple().isRISCV()) {
699     PP.RemovePragmaHandler("clang", RISCVPragmaHandler.get());
700     RISCVPragmaHandler.reset();
701   }
702 }
703 
704 /// Handle the annotation token produced for #pragma unused(...)
705 ///
706 /// Each annot_pragma_unused is followed by the argument token so e.g.
707 /// "#pragma unused(x,y)" becomes:
708 /// annot_pragma_unused 'x' annot_pragma_unused 'y'
HandlePragmaUnused()709 void Parser::HandlePragmaUnused() {
710   assert(Tok.is(tok::annot_pragma_unused));
711   SourceLocation UnusedLoc = ConsumeAnnotationToken();
712   Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
713   ConsumeToken(); // The argument token.
714 }
715 
HandlePragmaVisibility()716 void Parser::HandlePragmaVisibility() {
717   assert(Tok.is(tok::annot_pragma_vis));
718   const IdentifierInfo *VisType =
719     static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
720   SourceLocation VisLoc = ConsumeAnnotationToken();
721   Actions.ActOnPragmaVisibility(VisType, VisLoc);
722 }
723 
HandlePragmaPack()724 void Parser::HandlePragmaPack() {
725   assert(Tok.is(tok::annot_pragma_pack));
726   Sema::PragmaPackInfo *Info =
727       static_cast<Sema::PragmaPackInfo *>(Tok.getAnnotationValue());
728   SourceLocation PragmaLoc = Tok.getLocation();
729   ExprResult Alignment;
730   if (Info->Alignment.is(tok::numeric_constant)) {
731     Alignment = Actions.ActOnNumericConstant(Info->Alignment);
732     if (Alignment.isInvalid()) {
733       ConsumeAnnotationToken();
734       return;
735     }
736   }
737   Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
738                           Alignment.get());
739   // Consume the token after processing the pragma to enable pragma-specific
740   // #include warnings.
741   ConsumeAnnotationToken();
742 }
743 
HandlePragmaMSStruct()744 void Parser::HandlePragmaMSStruct() {
745   assert(Tok.is(tok::annot_pragma_msstruct));
746   PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
747       reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
748   Actions.ActOnPragmaMSStruct(Kind);
749   ConsumeAnnotationToken();
750 }
751 
HandlePragmaAlign()752 void Parser::HandlePragmaAlign() {
753   assert(Tok.is(tok::annot_pragma_align));
754   Sema::PragmaOptionsAlignKind Kind =
755     static_cast<Sema::PragmaOptionsAlignKind>(
756     reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
757   Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
758   // Consume the token after processing the pragma to enable pragma-specific
759   // #include warnings.
760   ConsumeAnnotationToken();
761 }
762 
HandlePragmaDump()763 void Parser::HandlePragmaDump() {
764   assert(Tok.is(tok::annot_pragma_dump));
765   ConsumeAnnotationToken();
766   if (Tok.is(tok::eod)) {
767     PP.Diag(Tok, diag::warn_pragma_debug_missing_argument) << "dump";
768   } else if (NextToken().is(tok::eod)) {
769     if (Tok.isNot(tok::identifier)) {
770       PP.Diag(Tok, diag::warn_pragma_debug_unexpected_argument);
771       ConsumeAnyToken();
772       ExpectAndConsume(tok::eod);
773       return;
774     }
775     IdentifierInfo *II = Tok.getIdentifierInfo();
776     Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
777     ConsumeToken();
778   } else {
779     SourceLocation StartLoc = Tok.getLocation();
780     EnterExpressionEvaluationContext Ctx(
781       Actions, Sema::ExpressionEvaluationContext::Unevaluated);
782     ExprResult E = ParseExpression();
783     if (!E.isUsable() || E.get()->containsErrors()) {
784       // Diagnostics were emitted during parsing. No action needed.
785     } else if (E.get()->getDependence() != ExprDependence::None) {
786       PP.Diag(StartLoc, diag::warn_pragma_debug_dependent_argument)
787         << E.get()->isTypeDependent()
788         << SourceRange(StartLoc, Tok.getLocation());
789     } else {
790       Actions.ActOnPragmaDump(E.get());
791     }
792     SkipUntil(tok::eod, StopBeforeMatch);
793   }
794   ExpectAndConsume(tok::eod);
795 }
796 
HandlePragmaWeak()797 void Parser::HandlePragmaWeak() {
798   assert(Tok.is(tok::annot_pragma_weak));
799   SourceLocation PragmaLoc = ConsumeAnnotationToken();
800   Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
801                             Tok.getLocation());
802   ConsumeToken(); // The weak name.
803 }
804 
HandlePragmaWeakAlias()805 void Parser::HandlePragmaWeakAlias() {
806   assert(Tok.is(tok::annot_pragma_weakalias));
807   SourceLocation PragmaLoc = ConsumeAnnotationToken();
808   IdentifierInfo *WeakName = Tok.getIdentifierInfo();
809   SourceLocation WeakNameLoc = Tok.getLocation();
810   ConsumeToken();
811   IdentifierInfo *AliasName = Tok.getIdentifierInfo();
812   SourceLocation AliasNameLoc = Tok.getLocation();
813   ConsumeToken();
814   Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
815                                WeakNameLoc, AliasNameLoc);
816 
817 }
818 
HandlePragmaRedefineExtname()819 void Parser::HandlePragmaRedefineExtname() {
820   assert(Tok.is(tok::annot_pragma_redefine_extname));
821   SourceLocation RedefLoc = ConsumeAnnotationToken();
822   IdentifierInfo *RedefName = Tok.getIdentifierInfo();
823   SourceLocation RedefNameLoc = Tok.getLocation();
824   ConsumeToken();
825   IdentifierInfo *AliasName = Tok.getIdentifierInfo();
826   SourceLocation AliasNameLoc = Tok.getLocation();
827   ConsumeToken();
828   Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
829                                      RedefNameLoc, AliasNameLoc);
830 }
831 
HandlePragmaFPContract()832 void Parser::HandlePragmaFPContract() {
833   assert(Tok.is(tok::annot_pragma_fp_contract));
834   tok::OnOffSwitch OOS =
835     static_cast<tok::OnOffSwitch>(
836     reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
837 
838   LangOptions::FPModeKind FPC;
839   switch (OOS) {
840   case tok::OOS_ON:
841     FPC = LangOptions::FPM_On;
842     break;
843   case tok::OOS_OFF:
844     FPC = LangOptions::FPM_Off;
845     break;
846   case tok::OOS_DEFAULT:
847     FPC = getLangOpts().getDefaultFPContractMode();
848     break;
849   }
850 
851   SourceLocation PragmaLoc = ConsumeAnnotationToken();
852   Actions.ActOnPragmaFPContract(PragmaLoc, FPC);
853 }
854 
HandlePragmaFloatControl()855 void Parser::HandlePragmaFloatControl() {
856   assert(Tok.is(tok::annot_pragma_float_control));
857 
858   // The value that is held on the PragmaFloatControlStack encodes
859   // the PragmaFloatControl kind and the MSStackAction kind
860   // into a single 32-bit word. The MsStackAction is the high 16 bits
861   // and the FloatControl is the lower 16 bits. Use shift and bit-and
862   // to decode the parts.
863   uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
864   Sema::PragmaMsStackAction Action =
865       static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
866   PragmaFloatControlKind Kind = PragmaFloatControlKind(Value & 0xFFFF);
867   SourceLocation PragmaLoc = ConsumeAnnotationToken();
868   Actions.ActOnPragmaFloatControl(PragmaLoc, Action, Kind);
869 }
870 
HandlePragmaFEnvAccess()871 void Parser::HandlePragmaFEnvAccess() {
872   assert(Tok.is(tok::annot_pragma_fenv_access) ||
873          Tok.is(tok::annot_pragma_fenv_access_ms));
874   tok::OnOffSwitch OOS =
875     static_cast<tok::OnOffSwitch>(
876     reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
877 
878   bool IsEnabled;
879   switch (OOS) {
880   case tok::OOS_ON:
881     IsEnabled = true;
882     break;
883   case tok::OOS_OFF:
884     IsEnabled = false;
885     break;
886   case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
887     IsEnabled = false;
888     break;
889   }
890 
891   SourceLocation PragmaLoc = ConsumeAnnotationToken();
892   Actions.ActOnPragmaFEnvAccess(PragmaLoc, IsEnabled);
893 }
894 
HandlePragmaFEnvRound()895 void Parser::HandlePragmaFEnvRound() {
896   assert(Tok.is(tok::annot_pragma_fenv_round));
897   auto RM = static_cast<llvm::RoundingMode>(
898       reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
899 
900   SourceLocation PragmaLoc = ConsumeAnnotationToken();
901   Actions.ActOnPragmaFEnvRound(PragmaLoc, RM);
902 }
903 
HandlePragmaCXLimitedRange()904 void Parser::HandlePragmaCXLimitedRange() {
905   assert(Tok.is(tok::annot_pragma_cx_limited_range));
906   tok::OnOffSwitch OOS = static_cast<tok::OnOffSwitch>(
907       reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
908 
909   LangOptions::ComplexRangeKind Range;
910   switch (OOS) {
911   case tok::OOS_ON:
912     Range = LangOptions::CX_Limited;
913     break;
914   case tok::OOS_OFF:
915     Range = LangOptions::CX_Full;
916     break;
917   case tok::OOS_DEFAULT:
918     // According to ISO C99 standard chapter 7.3.4, the default value
919     // for the pragma is ``off'. -fcx-limited-range and -fcx-fortran-rules
920     // control the default value of these pragmas.
921     Range = getLangOpts().getComplexRange();
922     break;
923   }
924 
925   SourceLocation PragmaLoc = ConsumeAnnotationToken();
926   Actions.ActOnPragmaCXLimitedRange(PragmaLoc, Range);
927 }
928 
HandlePragmaCaptured()929 StmtResult Parser::HandlePragmaCaptured()
930 {
931   assert(Tok.is(tok::annot_pragma_captured));
932   ConsumeAnnotationToken();
933 
934   if (Tok.isNot(tok::l_brace)) {
935     PP.Diag(Tok, diag::err_expected) << tok::l_brace;
936     return StmtError();
937   }
938 
939   SourceLocation Loc = Tok.getLocation();
940 
941   ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
942                                            Scope::CompoundStmtScope);
943   Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
944                                    /*NumParams=*/1);
945 
946   StmtResult R = ParseCompoundStatement();
947   CapturedRegionScope.Exit();
948 
949   if (R.isInvalid()) {
950     Actions.ActOnCapturedRegionError();
951     return StmtError();
952   }
953 
954   return Actions.ActOnCapturedRegionEnd(R.get());
955 }
956 
957 namespace {
958   enum OpenCLExtState : char {
959     Disable, Enable, Begin, End
960   };
961   typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
962 }
963 
HandlePragmaOpenCLExtension()964 void Parser::HandlePragmaOpenCLExtension() {
965   assert(Tok.is(tok::annot_pragma_opencl_extension));
966   OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
967   auto State = Data->second;
968   auto Ident = Data->first;
969   SourceLocation NameLoc = Tok.getLocation();
970   ConsumeAnnotationToken();
971 
972   auto &Opt = Actions.getOpenCLOptions();
973   auto Name = Ident->getName();
974   // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
975   // overriding all previously issued extension directives, but only if the
976   // behavior is set to disable."
977   if (Name == "all") {
978     if (State == Disable)
979       Opt.disableAll();
980     else
981       PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
982   } else if (State == Begin) {
983     if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) {
984       Opt.support(Name);
985       // FIXME: Default behavior of the extension pragma is not defined.
986       // Therefore, it should never be added by default.
987       Opt.acceptsPragma(Name);
988     }
989   } else if (State == End) {
990     // There is no behavior for this directive. We only accept this for
991     // backward compatibility.
992   } else if (!Opt.isKnown(Name) || !Opt.isWithPragma(Name))
993     PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
994   else if (Opt.isSupportedExtension(Name, getLangOpts()))
995     Opt.enable(Name, State == Enable);
996   else if (Opt.isSupportedCoreOrOptionalCore(Name, getLangOpts()))
997     PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
998   else
999     PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
1000 }
1001 
HandlePragmaMSPointersToMembers()1002 void Parser::HandlePragmaMSPointersToMembers() {
1003   assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
1004   LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
1005       static_cast<LangOptions::PragmaMSPointersToMembersKind>(
1006           reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
1007   SourceLocation PragmaLoc = ConsumeAnnotationToken();
1008   Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
1009 }
1010 
HandlePragmaMSVtorDisp()1011 void Parser::HandlePragmaMSVtorDisp() {
1012   assert(Tok.is(tok::annot_pragma_ms_vtordisp));
1013   uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
1014   Sema::PragmaMsStackAction Action =
1015       static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
1016   MSVtorDispMode Mode = MSVtorDispMode(Value & 0xFFFF);
1017   SourceLocation PragmaLoc = ConsumeAnnotationToken();
1018   Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
1019 }
1020 
HandlePragmaMSPragma()1021 void Parser::HandlePragmaMSPragma() {
1022   assert(Tok.is(tok::annot_pragma_ms_pragma));
1023   // Grab the tokens out of the annotation and enter them into the stream.
1024   auto TheTokens =
1025       (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
1026   PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true,
1027                       /*IsReinject=*/true);
1028   SourceLocation PragmaLocation = ConsumeAnnotationToken();
1029   assert(Tok.isAnyIdentifier());
1030   StringRef PragmaName = Tok.getIdentifierInfo()->getName();
1031   PP.Lex(Tok); // pragma kind
1032 
1033   // Figure out which #pragma we're dealing with.  The switch has no default
1034   // because lex shouldn't emit the annotation token for unrecognized pragmas.
1035   typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
1036   PragmaHandler Handler =
1037       llvm::StringSwitch<PragmaHandler>(PragmaName)
1038           .Case("data_seg", &Parser::HandlePragmaMSSegment)
1039           .Case("bss_seg", &Parser::HandlePragmaMSSegment)
1040           .Case("const_seg", &Parser::HandlePragmaMSSegment)
1041           .Case("code_seg", &Parser::HandlePragmaMSSegment)
1042           .Case("section", &Parser::HandlePragmaMSSection)
1043           .Case("init_seg", &Parser::HandlePragmaMSInitSeg)
1044           .Case("strict_gs_check", &Parser::HandlePragmaMSStrictGuardStackCheck)
1045           .Case("function", &Parser::HandlePragmaMSFunction)
1046           .Case("alloc_text", &Parser::HandlePragmaMSAllocText)
1047           .Case("optimize", &Parser::HandlePragmaMSOptimize);
1048 
1049   if (!(this->*Handler)(PragmaName, PragmaLocation)) {
1050     // Pragma handling failed, and has been diagnosed.  Slurp up the tokens
1051     // until eof (really end of line) to prevent follow-on errors.
1052     while (Tok.isNot(tok::eof))
1053       PP.Lex(Tok);
1054     PP.Lex(Tok);
1055   }
1056 }
1057 
HandlePragmaMSSection(StringRef PragmaName,SourceLocation PragmaLocation)1058 bool Parser::HandlePragmaMSSection(StringRef PragmaName,
1059                                    SourceLocation PragmaLocation) {
1060   if (Tok.isNot(tok::l_paren)) {
1061     PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
1062     return false;
1063   }
1064   PP.Lex(Tok); // (
1065   // Parsing code for pragma section
1066   if (Tok.isNot(tok::string_literal)) {
1067     PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
1068         << PragmaName;
1069     return false;
1070   }
1071   ExprResult StringResult = ParseStringLiteralExpression();
1072   if (StringResult.isInvalid())
1073     return false; // Already diagnosed.
1074   StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
1075   if (SegmentName->getCharByteWidth() != 1) {
1076     PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1077         << PragmaName;
1078     return false;
1079   }
1080   int SectionFlags = ASTContext::PSF_Read;
1081   bool SectionFlagsAreDefault = true;
1082   while (Tok.is(tok::comma)) {
1083     PP.Lex(Tok); // ,
1084     // Ignore "long" and "short".
1085     // They are undocumented, but widely used, section attributes which appear
1086     // to do nothing.
1087     if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
1088       PP.Lex(Tok); // long/short
1089       continue;
1090     }
1091 
1092     if (!Tok.isAnyIdentifier()) {
1093       PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
1094           << PragmaName;
1095       return false;
1096     }
1097     ASTContext::PragmaSectionFlag Flag =
1098       llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
1099       Tok.getIdentifierInfo()->getName())
1100       .Case("read", ASTContext::PSF_Read)
1101       .Case("write", ASTContext::PSF_Write)
1102       .Case("execute", ASTContext::PSF_Execute)
1103       .Case("shared", ASTContext::PSF_Invalid)
1104       .Case("nopage", ASTContext::PSF_Invalid)
1105       .Case("nocache", ASTContext::PSF_Invalid)
1106       .Case("discard", ASTContext::PSF_Invalid)
1107       .Case("remove", ASTContext::PSF_Invalid)
1108       .Default(ASTContext::PSF_None);
1109     if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
1110       PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
1111                                   ? diag::warn_pragma_invalid_specific_action
1112                                   : diag::warn_pragma_unsupported_action)
1113           << PragmaName << Tok.getIdentifierInfo()->getName();
1114       return false;
1115     }
1116     SectionFlags |= Flag;
1117     SectionFlagsAreDefault = false;
1118     PP.Lex(Tok); // Identifier
1119   }
1120   // If no section attributes are specified, the section will be marked as
1121   // read/write.
1122   if (SectionFlagsAreDefault)
1123     SectionFlags |= ASTContext::PSF_Write;
1124   if (Tok.isNot(tok::r_paren)) {
1125     PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
1126     return false;
1127   }
1128   PP.Lex(Tok); // )
1129   if (Tok.isNot(tok::eof)) {
1130     PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
1131         << PragmaName;
1132     return false;
1133   }
1134   PP.Lex(Tok); // eof
1135   Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
1136   return true;
1137 }
1138 
HandlePragmaMSSegment(StringRef PragmaName,SourceLocation PragmaLocation)1139 bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
1140                                    SourceLocation PragmaLocation) {
1141   if (Tok.isNot(tok::l_paren)) {
1142     PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
1143     return false;
1144   }
1145   PP.Lex(Tok); // (
1146   Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1147   StringRef SlotLabel;
1148   if (Tok.isAnyIdentifier()) {
1149     StringRef PushPop = Tok.getIdentifierInfo()->getName();
1150     if (PushPop == "push")
1151       Action = Sema::PSK_Push;
1152     else if (PushPop == "pop")
1153       Action = Sema::PSK_Pop;
1154     else {
1155       PP.Diag(PragmaLocation,
1156               diag::warn_pragma_expected_section_push_pop_or_name)
1157           << PragmaName;
1158       return false;
1159     }
1160     if (Action != Sema::PSK_Reset) {
1161       PP.Lex(Tok); // push | pop
1162       if (Tok.is(tok::comma)) {
1163         PP.Lex(Tok); // ,
1164         // If we've got a comma, we either need a label or a string.
1165         if (Tok.isAnyIdentifier()) {
1166           SlotLabel = Tok.getIdentifierInfo()->getName();
1167           PP.Lex(Tok); // identifier
1168           if (Tok.is(tok::comma))
1169             PP.Lex(Tok);
1170           else if (Tok.isNot(tok::r_paren)) {
1171             PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
1172                 << PragmaName;
1173             return false;
1174           }
1175         }
1176       } else if (Tok.isNot(tok::r_paren)) {
1177         PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
1178         return false;
1179       }
1180     }
1181   }
1182   // Grab the string literal for our section name.
1183   StringLiteral *SegmentName = nullptr;
1184   if (Tok.isNot(tok::r_paren)) {
1185     if (Tok.isNot(tok::string_literal)) {
1186       unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
1187           diag::warn_pragma_expected_section_name :
1188           diag::warn_pragma_expected_section_label_or_name :
1189           diag::warn_pragma_expected_section_push_pop_or_name;
1190       PP.Diag(PragmaLocation, DiagID) << PragmaName;
1191       return false;
1192     }
1193     ExprResult StringResult = ParseStringLiteralExpression();
1194     if (StringResult.isInvalid())
1195       return false; // Already diagnosed.
1196     SegmentName = cast<StringLiteral>(StringResult.get());
1197     if (SegmentName->getCharByteWidth() != 1) {
1198       PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1199           << PragmaName;
1200       return false;
1201     }
1202     // Setting section "" has no effect
1203     if (SegmentName->getLength())
1204       Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
1205   }
1206   if (Tok.isNot(tok::r_paren)) {
1207     PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
1208     return false;
1209   }
1210   PP.Lex(Tok); // )
1211   if (Tok.isNot(tok::eof)) {
1212     PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
1213         << PragmaName;
1214     return false;
1215   }
1216   PP.Lex(Tok); // eof
1217   Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
1218                            SegmentName, PragmaName);
1219   return true;
1220 }
1221 
1222 // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
HandlePragmaMSInitSeg(StringRef PragmaName,SourceLocation PragmaLocation)1223 bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
1224                                    SourceLocation PragmaLocation) {
1225   if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
1226     PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
1227     return false;
1228   }
1229 
1230   if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1231                        PragmaName))
1232     return false;
1233 
1234   // Parse either the known section names or the string section name.
1235   StringLiteral *SegmentName = nullptr;
1236   if (Tok.isAnyIdentifier()) {
1237     auto *II = Tok.getIdentifierInfo();
1238     StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
1239                             .Case("compiler", "\".CRT$XCC\"")
1240                             .Case("lib", "\".CRT$XCL\"")
1241                             .Case("user", "\".CRT$XCU\"")
1242                             .Default("");
1243 
1244     if (!Section.empty()) {
1245       // Pretend the user wrote the appropriate string literal here.
1246       Token Toks[1];
1247       Toks[0].startToken();
1248       Toks[0].setKind(tok::string_literal);
1249       Toks[0].setLocation(Tok.getLocation());
1250       Toks[0].setLiteralData(Section.data());
1251       Toks[0].setLength(Section.size());
1252       SegmentName =
1253           cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
1254       PP.Lex(Tok);
1255     }
1256   } else if (Tok.is(tok::string_literal)) {
1257     ExprResult StringResult = ParseStringLiteralExpression();
1258     if (StringResult.isInvalid())
1259       return false;
1260     SegmentName = cast<StringLiteral>(StringResult.get());
1261     if (SegmentName->getCharByteWidth() != 1) {
1262       PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1263           << PragmaName;
1264       return false;
1265     }
1266     // FIXME: Add support for the '[, func-name]' part of the pragma.
1267   }
1268 
1269   if (!SegmentName) {
1270     PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
1271     return false;
1272   }
1273 
1274   if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1275                        PragmaName) ||
1276       ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1277                        PragmaName))
1278     return false;
1279 
1280   Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
1281   return true;
1282 }
1283 
1284 // #pragma strict_gs_check(pop)
1285 // #pragma strict_gs_check(push, "on" | "off")
1286 // #pragma strict_gs_check("on" | "off")
HandlePragmaMSStrictGuardStackCheck(StringRef PragmaName,SourceLocation PragmaLocation)1287 bool Parser::HandlePragmaMSStrictGuardStackCheck(
1288     StringRef PragmaName, SourceLocation PragmaLocation) {
1289   if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1290                        PragmaName))
1291     return false;
1292 
1293   Sema::PragmaMsStackAction Action = Sema::PSK_Set;
1294   if (Tok.is(tok::identifier)) {
1295     StringRef PushPop = Tok.getIdentifierInfo()->getName();
1296     if (PushPop == "push") {
1297       PP.Lex(Tok);
1298       Action = Sema::PSK_Push;
1299       if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_punc,
1300                            PragmaName))
1301         return false;
1302     } else if (PushPop == "pop") {
1303       PP.Lex(Tok);
1304       Action = Sema::PSK_Pop;
1305     }
1306   }
1307 
1308   bool Value = false;
1309   if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
1310     const IdentifierInfo *II = Tok.getIdentifierInfo();
1311     if (II && II->isStr("off")) {
1312       PP.Lex(Tok);
1313       Value = false;
1314     } else if (II && II->isStr("on")) {
1315       PP.Lex(Tok);
1316       Value = true;
1317     } else {
1318       PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1319           << PragmaName;
1320       return false;
1321     }
1322   }
1323 
1324   // Finish the pragma: ')' $
1325   if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1326                        PragmaName))
1327     return false;
1328 
1329   if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1330                        PragmaName))
1331     return false;
1332 
1333   Actions.ActOnPragmaMSStrictGuardStackCheck(PragmaLocation, Action, Value);
1334   return true;
1335 }
1336 
HandlePragmaMSAllocText(StringRef PragmaName,SourceLocation PragmaLocation)1337 bool Parser::HandlePragmaMSAllocText(StringRef PragmaName,
1338                                      SourceLocation PragmaLocation) {
1339   Token FirstTok = Tok;
1340   if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1341                        PragmaName))
1342     return false;
1343 
1344   StringRef Section;
1345   if (Tok.is(tok::string_literal)) {
1346     ExprResult StringResult = ParseStringLiteralExpression();
1347     if (StringResult.isInvalid())
1348       return false; // Already diagnosed.
1349     StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
1350     if (SegmentName->getCharByteWidth() != 1) {
1351       PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1352           << PragmaName;
1353       return false;
1354     }
1355     Section = SegmentName->getString();
1356   } else if (Tok.is(tok::identifier)) {
1357     Section = Tok.getIdentifierInfo()->getName();
1358     PP.Lex(Tok);
1359   } else {
1360     PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
1361         << PragmaName;
1362     return false;
1363   }
1364 
1365   if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
1366                        PragmaName))
1367     return false;
1368 
1369   SmallVector<std::tuple<IdentifierInfo *, SourceLocation>> Functions;
1370   while (true) {
1371     if (Tok.isNot(tok::identifier)) {
1372       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1373           << PragmaName;
1374       return false;
1375     }
1376 
1377     IdentifierInfo *II = Tok.getIdentifierInfo();
1378     Functions.emplace_back(II, Tok.getLocation());
1379 
1380     PP.Lex(Tok);
1381     if (Tok.isNot(tok::comma))
1382       break;
1383     PP.Lex(Tok);
1384   }
1385 
1386   if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1387                        PragmaName) ||
1388       ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1389                        PragmaName))
1390     return false;
1391 
1392   Actions.ActOnPragmaMSAllocText(FirstTok.getLocation(), Section, Functions);
1393   return true;
1394 }
1395 
PragmaLoopHintString(Token PragmaName,Token Option)1396 static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
1397   StringRef Str = PragmaName.getIdentifierInfo()->getName();
1398   std::string ClangLoopStr("clang loop ");
1399   if (Str == "loop" && Option.getIdentifierInfo())
1400     ClangLoopStr += Option.getIdentifierInfo()->getName();
1401   return std::string(llvm::StringSwitch<StringRef>(Str)
1402                          .Case("loop", ClangLoopStr)
1403                          .Case("unroll_and_jam", Str)
1404                          .Case("unroll", Str)
1405                          .Default(""));
1406 }
1407 
HandlePragmaLoopHint(LoopHint & Hint)1408 bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
1409   assert(Tok.is(tok::annot_pragma_loop_hint));
1410   PragmaLoopHintInfo *Info =
1411       static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
1412 
1413   IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
1414   Hint.PragmaNameLoc = IdentifierLoc::create(
1415       Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
1416 
1417   // It is possible that the loop hint has no option identifier, such as
1418   // #pragma unroll(4).
1419   IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
1420                                    ? Info->Option.getIdentifierInfo()
1421                                    : nullptr;
1422   Hint.OptionLoc = IdentifierLoc::create(
1423       Actions.Context, Info->Option.getLocation(), OptionInfo);
1424 
1425   llvm::ArrayRef<Token> Toks = Info->Toks;
1426 
1427   // Return a valid hint if pragma unroll or nounroll were specified
1428   // without an argument.
1429   auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName())
1430                         .Cases("unroll", "nounroll", "unroll_and_jam",
1431                                "nounroll_and_jam", true)
1432                         .Default(false);
1433 
1434   if (Toks.empty() && IsLoopHint) {
1435     ConsumeAnnotationToken();
1436     Hint.Range = Info->PragmaName.getLocation();
1437     return true;
1438   }
1439 
1440   // The constant expression is always followed by an eof token, which increases
1441   // the TokSize by 1.
1442   assert(!Toks.empty() &&
1443          "PragmaLoopHintInfo::Toks must contain at least one token.");
1444 
1445   // If no option is specified the argument is assumed to be a constant expr.
1446   bool OptionUnroll = false;
1447   bool OptionUnrollAndJam = false;
1448   bool OptionDistribute = false;
1449   bool OptionPipelineDisabled = false;
1450   bool StateOption = false;
1451   if (OptionInfo) { // Pragma Unroll does not specify an option.
1452     OptionUnroll = OptionInfo->isStr("unroll");
1453     OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
1454     OptionDistribute = OptionInfo->isStr("distribute");
1455     OptionPipelineDisabled = OptionInfo->isStr("pipeline");
1456     StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
1457                       .Case("vectorize", true)
1458                       .Case("interleave", true)
1459                       .Case("vectorize_predicate", true)
1460                       .Default(false) ||
1461                   OptionUnroll || OptionUnrollAndJam || OptionDistribute ||
1462                   OptionPipelineDisabled;
1463   }
1464 
1465   bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam &&
1466                          !OptionDistribute && !OptionPipelineDisabled;
1467   // Verify loop hint has an argument.
1468   if (Toks[0].is(tok::eof)) {
1469     ConsumeAnnotationToken();
1470     Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
1471         << /*StateArgument=*/StateOption
1472         << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
1473         << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1474     return false;
1475   }
1476 
1477   // Validate the argument.
1478   if (StateOption) {
1479     ConsumeAnnotationToken();
1480     SourceLocation StateLoc = Toks[0].getLocation();
1481     IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1482 
1483     bool Valid = StateInfo &&
1484                  llvm::StringSwitch<bool>(StateInfo->getName())
1485                      .Case("disable", true)
1486                      .Case("enable", !OptionPipelineDisabled)
1487                      .Case("full", OptionUnroll || OptionUnrollAndJam)
1488                      .Case("assume_safety", AssumeSafetyArg)
1489                      .Default(false);
1490     if (!Valid) {
1491       if (OptionPipelineDisabled) {
1492         Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
1493       } else {
1494         Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
1495             << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
1496             << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1497       }
1498       return false;
1499     }
1500     if (Toks.size() > 2)
1501       Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1502           << PragmaLoopHintString(Info->PragmaName, Info->Option);
1503     Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1504   } else if (OptionInfo && OptionInfo->getName() == "vectorize_width") {
1505     PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1506                         /*IsReinject=*/false);
1507     ConsumeAnnotationToken();
1508 
1509     SourceLocation StateLoc = Toks[0].getLocation();
1510     IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1511     StringRef IsScalableStr = StateInfo ? StateInfo->getName() : "";
1512 
1513     // Look for vectorize_width(fixed|scalable)
1514     if (IsScalableStr == "scalable" || IsScalableStr == "fixed") {
1515       PP.Lex(Tok); // Identifier
1516 
1517       if (Toks.size() > 2) {
1518         Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1519             << PragmaLoopHintString(Info->PragmaName, Info->Option);
1520         while (Tok.isNot(tok::eof))
1521           ConsumeAnyToken();
1522       }
1523 
1524       Hint.StateLoc =
1525           IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1526 
1527       ConsumeToken(); // Consume the constant expression eof terminator.
1528     } else {
1529       // Enter constant expression including eof terminator into token stream.
1530       ExprResult R = ParseConstantExpression();
1531 
1532       if (R.isInvalid() && !Tok.is(tok::comma))
1533         Diag(Toks[0].getLocation(),
1534              diag::note_pragma_loop_invalid_vectorize_option);
1535 
1536       bool Arg2Error = false;
1537       if (Tok.is(tok::comma)) {
1538         PP.Lex(Tok); // ,
1539 
1540         StateInfo = Tok.getIdentifierInfo();
1541         IsScalableStr = StateInfo->getName();
1542 
1543         if (IsScalableStr != "scalable" && IsScalableStr != "fixed") {
1544           Diag(Tok.getLocation(),
1545                diag::err_pragma_loop_invalid_vectorize_option);
1546           Arg2Error = true;
1547         } else
1548           Hint.StateLoc =
1549               IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1550 
1551         PP.Lex(Tok); // Identifier
1552       }
1553 
1554       // Tokens following an error in an ill-formed constant expression will
1555       // remain in the token stream and must be removed.
1556       if (Tok.isNot(tok::eof)) {
1557         Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1558             << PragmaLoopHintString(Info->PragmaName, Info->Option);
1559         while (Tok.isNot(tok::eof))
1560           ConsumeAnyToken();
1561       }
1562 
1563       ConsumeToken(); // Consume the constant expression eof terminator.
1564 
1565       if (Arg2Error || R.isInvalid() ||
1566           Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1567         return false;
1568 
1569       // Argument is a constant expression with an integer type.
1570       Hint.ValueExpr = R.get();
1571     }
1572   } else {
1573     // Enter constant expression including eof terminator into token stream.
1574     PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1575                         /*IsReinject=*/false);
1576     ConsumeAnnotationToken();
1577     ExprResult R = ParseConstantExpression();
1578 
1579     // Tokens following an error in an ill-formed constant expression will
1580     // remain in the token stream and must be removed.
1581     if (Tok.isNot(tok::eof)) {
1582       Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1583           << PragmaLoopHintString(Info->PragmaName, Info->Option);
1584       while (Tok.isNot(tok::eof))
1585         ConsumeAnyToken();
1586     }
1587 
1588     ConsumeToken(); // Consume the constant expression eof terminator.
1589 
1590     if (R.isInvalid() ||
1591         Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1592       return false;
1593 
1594     // Argument is a constant expression with an integer type.
1595     Hint.ValueExpr = R.get();
1596   }
1597 
1598   Hint.Range = SourceRange(Info->PragmaName.getLocation(),
1599                            Info->Toks.back().getLocation());
1600   return true;
1601 }
1602 
1603 namespace {
1604 struct PragmaAttributeInfo {
1605   enum ActionType { Push, Pop, Attribute };
1606   ParsedAttributes &Attributes;
1607   ActionType Action;
1608   const IdentifierInfo *Namespace = nullptr;
1609   ArrayRef<Token> Tokens;
1610 
PragmaAttributeInfo__anon11f1a89f0311::PragmaAttributeInfo1611   PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1612 };
1613 
1614 #include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1615 
1616 } // end anonymous namespace
1617 
getIdentifier(const Token & Tok)1618 static StringRef getIdentifier(const Token &Tok) {
1619   if (Tok.is(tok::identifier))
1620     return Tok.getIdentifierInfo()->getName();
1621   const char *S = tok::getKeywordSpelling(Tok.getKind());
1622   if (!S)
1623     return "";
1624   return S;
1625 }
1626 
isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule)1627 static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
1628   using namespace attr;
1629   switch (Rule) {
1630 #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract)                           \
1631   case Value:                                                                  \
1632     return IsAbstract;
1633 #include "clang/Basic/AttrSubMatchRulesList.inc"
1634   }
1635   llvm_unreachable("Invalid attribute subject match rule");
1636   return false;
1637 }
1638 
diagnoseExpectedAttributeSubjectSubRule(Parser & PRef,attr::SubjectMatchRule PrimaryRule,StringRef PrimaryRuleName,SourceLocation SubRuleLoc)1639 static void diagnoseExpectedAttributeSubjectSubRule(
1640     Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1641     SourceLocation SubRuleLoc) {
1642   auto Diagnostic =
1643       PRef.Diag(SubRuleLoc,
1644                 diag::err_pragma_attribute_expected_subject_sub_identifier)
1645       << PrimaryRuleName;
1646   if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1647     Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1648   else
1649     Diagnostic << /*SubRulesSupported=*/0;
1650 }
1651 
diagnoseUnknownAttributeSubjectSubRule(Parser & PRef,attr::SubjectMatchRule PrimaryRule,StringRef PrimaryRuleName,StringRef SubRuleName,SourceLocation SubRuleLoc)1652 static void diagnoseUnknownAttributeSubjectSubRule(
1653     Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1654     StringRef SubRuleName, SourceLocation SubRuleLoc) {
1655 
1656   auto Diagnostic =
1657       PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1658       << SubRuleName << PrimaryRuleName;
1659   if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1660     Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1661   else
1662     Diagnostic << /*SubRulesSupported=*/0;
1663 }
1664 
ParsePragmaAttributeSubjectMatchRuleSet(attr::ParsedSubjectMatchRuleSet & SubjectMatchRules,SourceLocation & AnyLoc,SourceLocation & LastMatchRuleEndLoc)1665 bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1666     attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1667     SourceLocation &LastMatchRuleEndLoc) {
1668   bool IsAny = false;
1669   BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1670   if (getIdentifier(Tok) == "any") {
1671     AnyLoc = ConsumeToken();
1672     IsAny = true;
1673     if (AnyParens.expectAndConsume())
1674       return true;
1675   }
1676 
1677   do {
1678     // Parse the subject matcher rule.
1679     StringRef Name = getIdentifier(Tok);
1680     if (Name.empty()) {
1681       Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1682       return true;
1683     }
1684     std::pair<std::optional<attr::SubjectMatchRule>,
1685               std::optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1686         Rule = isAttributeSubjectMatchRule(Name);
1687     if (!Rule.first) {
1688       Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1689       return true;
1690     }
1691     attr::SubjectMatchRule PrimaryRule = *Rule.first;
1692     SourceLocation RuleLoc = ConsumeToken();
1693 
1694     BalancedDelimiterTracker Parens(*this, tok::l_paren);
1695     if (isAbstractAttrMatcherRule(PrimaryRule)) {
1696       if (Parens.expectAndConsume())
1697         return true;
1698     } else if (Parens.consumeOpen()) {
1699       if (!SubjectMatchRules
1700                .insert(
1701                    std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1702                .second)
1703         Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1704             << Name
1705             << FixItHint::CreateRemoval(SourceRange(
1706                    RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
1707       LastMatchRuleEndLoc = RuleLoc;
1708       continue;
1709     }
1710 
1711     // Parse the sub-rules.
1712     StringRef SubRuleName = getIdentifier(Tok);
1713     if (SubRuleName.empty()) {
1714       diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1715                                               Tok.getLocation());
1716       return true;
1717     }
1718     attr::SubjectMatchRule SubRule;
1719     if (SubRuleName == "unless") {
1720       SourceLocation SubRuleLoc = ConsumeToken();
1721       BalancedDelimiterTracker Parens(*this, tok::l_paren);
1722       if (Parens.expectAndConsume())
1723         return true;
1724       SubRuleName = getIdentifier(Tok);
1725       if (SubRuleName.empty()) {
1726         diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1727                                                 SubRuleLoc);
1728         return true;
1729       }
1730       auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1731       if (!SubRuleOrNone) {
1732         std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1733         diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1734                                                SubRuleUnlessName, SubRuleLoc);
1735         return true;
1736       }
1737       SubRule = *SubRuleOrNone;
1738       ConsumeToken();
1739       if (Parens.consumeClose())
1740         return true;
1741     } else {
1742       auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1743       if (!SubRuleOrNone) {
1744         diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1745                                                SubRuleName, Tok.getLocation());
1746         return true;
1747       }
1748       SubRule = *SubRuleOrNone;
1749       ConsumeToken();
1750     }
1751     SourceLocation RuleEndLoc = Tok.getLocation();
1752     LastMatchRuleEndLoc = RuleEndLoc;
1753     if (Parens.consumeClose())
1754       return true;
1755     if (!SubjectMatchRules
1756              .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1757              .second) {
1758       Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1759           << attr::getSubjectMatchRuleSpelling(SubRule)
1760           << FixItHint::CreateRemoval(SourceRange(
1761                  RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
1762       continue;
1763     }
1764   } while (IsAny && TryConsumeToken(tok::comma));
1765 
1766   if (IsAny)
1767     if (AnyParens.consumeClose())
1768       return true;
1769 
1770   return false;
1771 }
1772 
1773 namespace {
1774 
1775 /// Describes the stage at which attribute subject rule parsing was interrupted.
1776 enum class MissingAttributeSubjectRulesRecoveryPoint {
1777   Comma,
1778   ApplyTo,
1779   Equals,
1780   Any,
1781   None,
1782 };
1783 
1784 MissingAttributeSubjectRulesRecoveryPoint
getAttributeSubjectRulesRecoveryPointForToken(const Token & Tok)1785 getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1786   if (const auto *II = Tok.getIdentifierInfo()) {
1787     if (II->isStr("apply_to"))
1788       return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1789     if (II->isStr("any"))
1790       return MissingAttributeSubjectRulesRecoveryPoint::Any;
1791   }
1792   if (Tok.is(tok::equal))
1793     return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1794   return MissingAttributeSubjectRulesRecoveryPoint::None;
1795 }
1796 
1797 /// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1798 /// suggests the possible attribute subject rules in a fix-it together with
1799 /// any other missing tokens.
createExpectedAttributeSubjectRulesTokenDiagnostic(unsigned DiagID,ParsedAttributes & Attrs,MissingAttributeSubjectRulesRecoveryPoint Point,Parser & PRef)1800 DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
1801     unsigned DiagID, ParsedAttributes &Attrs,
1802     MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1803   SourceLocation Loc = PRef.getEndOfPreviousToken();
1804   if (Loc.isInvalid())
1805     Loc = PRef.getCurToken().getLocation();
1806   auto Diagnostic = PRef.Diag(Loc, DiagID);
1807   std::string FixIt;
1808   MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1809       getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1810   if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1811     FixIt = ", ";
1812   if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1813       EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1814     FixIt += "apply_to";
1815   if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1816       EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1817     FixIt += " = ";
1818   SourceRange FixItRange(Loc);
1819   if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1820     // Gather the subject match rules that are supported by the attribute.
1821     // Add all the possible rules initially.
1822     llvm::BitVector IsMatchRuleAvailable(attr::SubjectMatchRule_Last + 1, true);
1823     // Remove the ones that are not supported by any of the attributes.
1824     for (const ParsedAttr &Attribute : Attrs) {
1825       SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> MatchRules;
1826       Attribute.getMatchRules(PRef.getLangOpts(), MatchRules);
1827       llvm::BitVector IsSupported(attr::SubjectMatchRule_Last + 1);
1828       for (const auto &Rule : MatchRules) {
1829         // Ensure that the missing rule is reported in the fix-it only when it's
1830         // supported in the current language mode.
1831         if (!Rule.second)
1832           continue;
1833         IsSupported[Rule.first] = true;
1834       }
1835       IsMatchRuleAvailable &= IsSupported;
1836     }
1837     if (IsMatchRuleAvailable.count() == 0) {
1838       // FIXME: We can emit a "fix-it" with a subject list placeholder when
1839       // placeholders will be supported by the fix-its.
1840       return Diagnostic;
1841     }
1842     FixIt += "any(";
1843     bool NeedsComma = false;
1844     for (unsigned I = 0; I <= attr::SubjectMatchRule_Last; I++) {
1845       if (!IsMatchRuleAvailable[I])
1846         continue;
1847       if (NeedsComma)
1848         FixIt += ", ";
1849       else
1850         NeedsComma = true;
1851       FixIt += attr::getSubjectMatchRuleSpelling(
1852           static_cast<attr::SubjectMatchRule>(I));
1853     }
1854     FixIt += ")";
1855     // Check if we need to remove the range
1856     PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1857     FixItRange.setEnd(PRef.getCurToken().getLocation());
1858   }
1859   if (FixItRange.getBegin() == FixItRange.getEnd())
1860     Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1861   else
1862     Diagnostic << FixItHint::CreateReplacement(
1863         CharSourceRange::getCharRange(FixItRange), FixIt);
1864   return Diagnostic;
1865 }
1866 
1867 } // end anonymous namespace
1868 
HandlePragmaAttribute()1869 void Parser::HandlePragmaAttribute() {
1870   assert(Tok.is(tok::annot_pragma_attribute) &&
1871          "Expected #pragma attribute annotation token");
1872   SourceLocation PragmaLoc = Tok.getLocation();
1873   auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1874   if (Info->Action == PragmaAttributeInfo::Pop) {
1875     ConsumeAnnotationToken();
1876     Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
1877     return;
1878   }
1879   // Parse the actual attribute with its arguments.
1880   assert((Info->Action == PragmaAttributeInfo::Push ||
1881           Info->Action == PragmaAttributeInfo::Attribute) &&
1882          "Unexpected #pragma attribute command");
1883 
1884   if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
1885     ConsumeAnnotationToken();
1886     Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
1887     return;
1888   }
1889 
1890   PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false,
1891                       /*IsReinject=*/false);
1892   ConsumeAnnotationToken();
1893 
1894   ParsedAttributes &Attrs = Info->Attributes;
1895   Attrs.clearListOnly();
1896 
1897   auto SkipToEnd = [this]() {
1898     SkipUntil(tok::eof, StopBeforeMatch);
1899     ConsumeToken();
1900   };
1901 
1902   if ((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) ||
1903       Tok.isRegularKeywordAttribute()) {
1904     // Parse the CXX11 style attribute.
1905     ParseCXX11AttributeSpecifier(Attrs);
1906   } else if (Tok.is(tok::kw___attribute)) {
1907     ConsumeToken();
1908     if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1909                          "attribute"))
1910       return SkipToEnd();
1911     if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1912       return SkipToEnd();
1913 
1914     // FIXME: The practical usefulness of completion here is limited because
1915     // we only get here if the line has balanced parens.
1916     if (Tok.is(tok::code_completion)) {
1917       cutOffParsing();
1918       // FIXME: suppress completion of unsupported attributes?
1919       Actions.CodeCompleteAttribute(AttributeCommonInfo::Syntax::AS_GNU);
1920       return SkipToEnd();
1921     }
1922 
1923     // Parse the comma-separated list of attributes.
1924     do {
1925       if (Tok.isNot(tok::identifier)) {
1926         Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1927         SkipToEnd();
1928         return;
1929       }
1930       IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1931       SourceLocation AttrNameLoc = ConsumeToken();
1932 
1933       if (Tok.isNot(tok::l_paren))
1934         Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
1935                      ParsedAttr::Form::GNU());
1936       else
1937         ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1938                               /*ScopeName=*/nullptr,
1939                               /*ScopeLoc=*/SourceLocation(),
1940                               ParsedAttr::Form::GNU(),
1941                               /*Declarator=*/nullptr);
1942     } while (TryConsumeToken(tok::comma));
1943 
1944     if (ExpectAndConsume(tok::r_paren))
1945       return SkipToEnd();
1946     if (ExpectAndConsume(tok::r_paren))
1947       return SkipToEnd();
1948   } else if (Tok.is(tok::kw___declspec)) {
1949     ParseMicrosoftDeclSpecs(Attrs);
1950   } else {
1951     Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1952     if (Tok.getIdentifierInfo()) {
1953       // If we suspect that this is an attribute suggest the use of
1954       // '__attribute__'.
1955       if (ParsedAttr::getParsedKind(
1956               Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1957               ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) {
1958         SourceLocation InsertStartLoc = Tok.getLocation();
1959         ConsumeToken();
1960         if (Tok.is(tok::l_paren)) {
1961           ConsumeAnyToken();
1962           SkipUntil(tok::r_paren, StopBeforeMatch);
1963           if (Tok.isNot(tok::r_paren))
1964             return SkipToEnd();
1965         }
1966         Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1967             << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1968             << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1969       }
1970     }
1971     SkipToEnd();
1972     return;
1973   }
1974 
1975   if (Attrs.empty() || Attrs.begin()->isInvalid()) {
1976     SkipToEnd();
1977     return;
1978   }
1979 
1980   for (const ParsedAttr &Attribute : Attrs) {
1981     if (!Attribute.isSupportedByPragmaAttribute()) {
1982       Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
1983           << Attribute;
1984       SkipToEnd();
1985       return;
1986     }
1987   }
1988 
1989   // Parse the subject-list.
1990   if (!TryConsumeToken(tok::comma)) {
1991     createExpectedAttributeSubjectRulesTokenDiagnostic(
1992         diag::err_expected, Attrs,
1993         MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1994         << tok::comma;
1995     SkipToEnd();
1996     return;
1997   }
1998 
1999   if (Tok.isNot(tok::identifier)) {
2000     createExpectedAttributeSubjectRulesTokenDiagnostic(
2001         diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
2002         MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
2003     SkipToEnd();
2004     return;
2005   }
2006   const IdentifierInfo *II = Tok.getIdentifierInfo();
2007   if (!II->isStr("apply_to")) {
2008     createExpectedAttributeSubjectRulesTokenDiagnostic(
2009         diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
2010         MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
2011     SkipToEnd();
2012     return;
2013   }
2014   ConsumeToken();
2015 
2016   if (!TryConsumeToken(tok::equal)) {
2017     createExpectedAttributeSubjectRulesTokenDiagnostic(
2018         diag::err_expected, Attrs,
2019         MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
2020         << tok::equal;
2021     SkipToEnd();
2022     return;
2023   }
2024 
2025   attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
2026   SourceLocation AnyLoc, LastMatchRuleEndLoc;
2027   if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
2028                                               LastMatchRuleEndLoc)) {
2029     SkipToEnd();
2030     return;
2031   }
2032 
2033   // Tokens following an ill-formed attribute will remain in the token stream
2034   // and must be removed.
2035   if (Tok.isNot(tok::eof)) {
2036     Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
2037     SkipToEnd();
2038     return;
2039   }
2040 
2041   // Consume the eof terminator token.
2042   ConsumeToken();
2043 
2044   // Handle a mixed push/attribute by desurging to a push, then an attribute.
2045   if (Info->Action == PragmaAttributeInfo::Push)
2046     Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
2047 
2048   for (ParsedAttr &Attribute : Attrs) {
2049     Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
2050                                           SubjectMatchRules);
2051   }
2052 }
2053 
2054 // #pragma GCC visibility comes in two variants:
2055 //   'push' '(' [visibility] ')'
2056 //   'pop'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & VisTok)2057 void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
2058                                               PragmaIntroducer Introducer,
2059                                               Token &VisTok) {
2060   SourceLocation VisLoc = VisTok.getLocation();
2061 
2062   Token Tok;
2063   PP.LexUnexpandedToken(Tok);
2064 
2065   const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
2066 
2067   const IdentifierInfo *VisType;
2068   if (PushPop && PushPop->isStr("pop")) {
2069     VisType = nullptr;
2070   } else if (PushPop && PushPop->isStr("push")) {
2071     PP.LexUnexpandedToken(Tok);
2072     if (Tok.isNot(tok::l_paren)) {
2073       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
2074         << "visibility";
2075       return;
2076     }
2077     PP.LexUnexpandedToken(Tok);
2078     VisType = Tok.getIdentifierInfo();
2079     if (!VisType) {
2080       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2081         << "visibility";
2082       return;
2083     }
2084     PP.LexUnexpandedToken(Tok);
2085     if (Tok.isNot(tok::r_paren)) {
2086       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
2087         << "visibility";
2088       return;
2089     }
2090   } else {
2091     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2092       << "visibility";
2093     return;
2094   }
2095   SourceLocation EndLoc = Tok.getLocation();
2096   PP.LexUnexpandedToken(Tok);
2097   if (Tok.isNot(tok::eod)) {
2098     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2099       << "visibility";
2100     return;
2101   }
2102 
2103   auto Toks = std::make_unique<Token[]>(1);
2104   Toks[0].startToken();
2105   Toks[0].setKind(tok::annot_pragma_vis);
2106   Toks[0].setLocation(VisLoc);
2107   Toks[0].setAnnotationEndLoc(EndLoc);
2108   Toks[0].setAnnotationValue(
2109       const_cast<void *>(static_cast<const void *>(VisType)));
2110   PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true,
2111                       /*IsReinject=*/false);
2112 }
2113 
2114 // #pragma pack(...) comes in the following delicious flavors:
2115 //   pack '(' [integer] ')'
2116 //   pack '(' 'show' ')'
2117 //   pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & PackTok)2118 void PragmaPackHandler::HandlePragma(Preprocessor &PP,
2119                                      PragmaIntroducer Introducer,
2120                                      Token &PackTok) {
2121   SourceLocation PackLoc = PackTok.getLocation();
2122 
2123   Token Tok;
2124   PP.Lex(Tok);
2125   if (Tok.isNot(tok::l_paren)) {
2126     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
2127     return;
2128   }
2129 
2130   Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
2131   StringRef SlotLabel;
2132   Token Alignment;
2133   Alignment.startToken();
2134   PP.Lex(Tok);
2135   if (Tok.is(tok::numeric_constant)) {
2136     Alignment = Tok;
2137 
2138     PP.Lex(Tok);
2139 
2140     // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
2141     // the push/pop stack.
2142     // In Apple gcc/XL, #pragma pack(4) is equivalent to #pragma pack(push, 4)
2143     Action = (PP.getLangOpts().ApplePragmaPack || PP.getLangOpts().XLPragmaPack)
2144                  ? Sema::PSK_Push_Set
2145                  : Sema::PSK_Set;
2146   } else if (Tok.is(tok::identifier)) {
2147     const IdentifierInfo *II = Tok.getIdentifierInfo();
2148     if (II->isStr("show")) {
2149       Action = Sema::PSK_Show;
2150       PP.Lex(Tok);
2151     } else {
2152       if (II->isStr("push")) {
2153         Action = Sema::PSK_Push;
2154       } else if (II->isStr("pop")) {
2155         Action = Sema::PSK_Pop;
2156       } else {
2157         PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
2158         return;
2159       }
2160       PP.Lex(Tok);
2161 
2162       if (Tok.is(tok::comma)) {
2163         PP.Lex(Tok);
2164 
2165         if (Tok.is(tok::numeric_constant)) {
2166           Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
2167           Alignment = Tok;
2168 
2169           PP.Lex(Tok);
2170         } else if (Tok.is(tok::identifier)) {
2171           SlotLabel = Tok.getIdentifierInfo()->getName();
2172           PP.Lex(Tok);
2173 
2174           if (Tok.is(tok::comma)) {
2175             PP.Lex(Tok);
2176 
2177             if (Tok.isNot(tok::numeric_constant)) {
2178               PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
2179               return;
2180             }
2181 
2182             Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
2183             Alignment = Tok;
2184 
2185             PP.Lex(Tok);
2186           }
2187         } else {
2188           PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
2189           return;
2190         }
2191       }
2192     }
2193   } else if (PP.getLangOpts().ApplePragmaPack ||
2194              PP.getLangOpts().XLPragmaPack) {
2195     // In MSVC/gcc, #pragma pack() resets the alignment without affecting
2196     // the push/pop stack.
2197     // In Apple gcc and IBM XL, #pragma pack() is equivalent to #pragma
2198     // pack(pop).
2199     Action = Sema::PSK_Pop;
2200   }
2201 
2202   if (Tok.isNot(tok::r_paren)) {
2203     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
2204     return;
2205   }
2206 
2207   SourceLocation RParenLoc = Tok.getLocation();
2208   PP.Lex(Tok);
2209   if (Tok.isNot(tok::eod)) {
2210     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
2211     return;
2212   }
2213 
2214   Sema::PragmaPackInfo *Info =
2215       PP.getPreprocessorAllocator().Allocate<Sema::PragmaPackInfo>(1);
2216   Info->Action = Action;
2217   Info->SlotLabel = SlotLabel;
2218   Info->Alignment = Alignment;
2219 
2220   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2221                               1);
2222   Toks[0].startToken();
2223   Toks[0].setKind(tok::annot_pragma_pack);
2224   Toks[0].setLocation(PackLoc);
2225   Toks[0].setAnnotationEndLoc(RParenLoc);
2226   Toks[0].setAnnotationValue(static_cast<void*>(Info));
2227   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2228                       /*IsReinject=*/false);
2229 }
2230 
2231 // #pragma ms_struct on
2232 // #pragma ms_struct off
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & MSStructTok)2233 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
2234                                          PragmaIntroducer Introducer,
2235                                          Token &MSStructTok) {
2236   PragmaMSStructKind Kind = PMSST_OFF;
2237 
2238   Token Tok;
2239   PP.Lex(Tok);
2240   if (Tok.isNot(tok::identifier)) {
2241     PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
2242     return;
2243   }
2244   SourceLocation EndLoc = Tok.getLocation();
2245   const IdentifierInfo *II = Tok.getIdentifierInfo();
2246   if (II->isStr("on")) {
2247     Kind = PMSST_ON;
2248     PP.Lex(Tok);
2249   }
2250   else if (II->isStr("off") || II->isStr("reset"))
2251     PP.Lex(Tok);
2252   else {
2253     PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
2254     return;
2255   }
2256 
2257   if (Tok.isNot(tok::eod)) {
2258     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2259       << "ms_struct";
2260     return;
2261   }
2262 
2263   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2264                               1);
2265   Toks[0].startToken();
2266   Toks[0].setKind(tok::annot_pragma_msstruct);
2267   Toks[0].setLocation(MSStructTok.getLocation());
2268   Toks[0].setAnnotationEndLoc(EndLoc);
2269   Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2270                              static_cast<uintptr_t>(Kind)));
2271   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2272                       /*IsReinject=*/false);
2273 }
2274 
2275 // #pragma clang section bss="abc" data="" rodata="def" text="" relro=""
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)2276 void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
2277                                              PragmaIntroducer Introducer,
2278                                              Token &FirstToken) {
2279 
2280   Token Tok;
2281   auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
2282 
2283   PP.Lex(Tok); // eat 'section'
2284   while (Tok.isNot(tok::eod)) {
2285     if (Tok.isNot(tok::identifier)) {
2286       PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
2287       return;
2288     }
2289 
2290     const IdentifierInfo *SecType = Tok.getIdentifierInfo();
2291     if (SecType->isStr("bss"))
2292       SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
2293     else if (SecType->isStr("data"))
2294       SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
2295     else if (SecType->isStr("rodata"))
2296       SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
2297     else if (SecType->isStr("relro"))
2298       SecKind = Sema::PragmaClangSectionKind::PCSK_Relro;
2299     else if (SecType->isStr("text"))
2300       SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
2301     else {
2302       PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
2303       return;
2304     }
2305 
2306     SourceLocation PragmaLocation = Tok.getLocation();
2307     PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
2308     if (Tok.isNot(tok::equal)) {
2309       PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
2310       return;
2311     }
2312 
2313     std::string SecName;
2314     if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
2315       return;
2316 
2317     Actions.ActOnPragmaClangSection(
2318         PragmaLocation,
2319         (SecName.size() ? Sema::PragmaClangSectionAction::PCSA_Set
2320                         : Sema::PragmaClangSectionAction::PCSA_Clear),
2321         SecKind, SecName);
2322   }
2323 }
2324 
2325 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
2326 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
2327 // #pragma 'align' '(' {'native','natural','mac68k','power','reset'} ')'
ParseAlignPragma(Preprocessor & PP,Token & FirstTok,bool IsOptions)2328 static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
2329                              bool IsOptions) {
2330   Token Tok;
2331 
2332   if (IsOptions) {
2333     PP.Lex(Tok);
2334     if (Tok.isNot(tok::identifier) ||
2335         !Tok.getIdentifierInfo()->isStr("align")) {
2336       PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
2337       return;
2338     }
2339   }
2340 
2341   PP.Lex(Tok);
2342   if (PP.getLangOpts().XLPragmaPack) {
2343     if (Tok.isNot(tok::l_paren)) {
2344       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "align";
2345       return;
2346     }
2347   } else if (Tok.isNot(tok::equal)) {
2348     PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
2349       << IsOptions;
2350     return;
2351   }
2352 
2353   PP.Lex(Tok);
2354   if (Tok.isNot(tok::identifier)) {
2355     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2356       << (IsOptions ? "options" : "align");
2357     return;
2358   }
2359 
2360   Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
2361   const IdentifierInfo *II = Tok.getIdentifierInfo();
2362   if (II->isStr("native"))
2363     Kind = Sema::POAK_Native;
2364   else if (II->isStr("natural"))
2365     Kind = Sema::POAK_Natural;
2366   else if (II->isStr("packed"))
2367     Kind = Sema::POAK_Packed;
2368   else if (II->isStr("power"))
2369     Kind = Sema::POAK_Power;
2370   else if (II->isStr("mac68k"))
2371     Kind = Sema::POAK_Mac68k;
2372   else if (II->isStr("reset"))
2373     Kind = Sema::POAK_Reset;
2374   else {
2375     PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
2376       << IsOptions;
2377     return;
2378   }
2379 
2380   if (PP.getLangOpts().XLPragmaPack) {
2381     PP.Lex(Tok);
2382     if (Tok.isNot(tok::r_paren)) {
2383       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "align";
2384       return;
2385     }
2386   }
2387 
2388   SourceLocation EndLoc = Tok.getLocation();
2389   PP.Lex(Tok);
2390   if (Tok.isNot(tok::eod)) {
2391     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2392       << (IsOptions ? "options" : "align");
2393     return;
2394   }
2395 
2396   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2397                               1);
2398   Toks[0].startToken();
2399   Toks[0].setKind(tok::annot_pragma_align);
2400   Toks[0].setLocation(FirstTok.getLocation());
2401   Toks[0].setAnnotationEndLoc(EndLoc);
2402   Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2403                              static_cast<uintptr_t>(Kind)));
2404   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2405                       /*IsReinject=*/false);
2406 }
2407 
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & AlignTok)2408 void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
2409                                       PragmaIntroducer Introducer,
2410                                       Token &AlignTok) {
2411   ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
2412 }
2413 
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & OptionsTok)2414 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
2415                                         PragmaIntroducer Introducer,
2416                                         Token &OptionsTok) {
2417   ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
2418 }
2419 
2420 // #pragma unused(identifier)
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & UnusedTok)2421 void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
2422                                        PragmaIntroducer Introducer,
2423                                        Token &UnusedTok) {
2424   // FIXME: Should we be expanding macros here? My guess is no.
2425   SourceLocation UnusedLoc = UnusedTok.getLocation();
2426 
2427   // Lex the left '('.
2428   Token Tok;
2429   PP.Lex(Tok);
2430   if (Tok.isNot(tok::l_paren)) {
2431     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
2432     return;
2433   }
2434 
2435   // Lex the declaration reference(s).
2436   SmallVector<Token, 5> Identifiers;
2437   SourceLocation RParenLoc;
2438   bool LexID = true;
2439 
2440   while (true) {
2441     PP.Lex(Tok);
2442 
2443     if (LexID) {
2444       if (Tok.is(tok::identifier)) {
2445         Identifiers.push_back(Tok);
2446         LexID = false;
2447         continue;
2448       }
2449 
2450       // Illegal token!
2451       PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
2452       return;
2453     }
2454 
2455     // We are execting a ')' or a ','.
2456     if (Tok.is(tok::comma)) {
2457       LexID = true;
2458       continue;
2459     }
2460 
2461     if (Tok.is(tok::r_paren)) {
2462       RParenLoc = Tok.getLocation();
2463       break;
2464     }
2465 
2466     // Illegal token!
2467     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
2468     return;
2469   }
2470 
2471   PP.Lex(Tok);
2472   if (Tok.isNot(tok::eod)) {
2473     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2474         "unused";
2475     return;
2476   }
2477 
2478   // Verify that we have a location for the right parenthesis.
2479   assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
2480   assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
2481 
2482   // For each identifier token, insert into the token stream a
2483   // annot_pragma_unused token followed by the identifier token.
2484   // This allows us to cache a "#pragma unused" that occurs inside an inline
2485   // C++ member function.
2486 
2487   MutableArrayRef<Token> Toks(
2488       PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
2489       2 * Identifiers.size());
2490   for (unsigned i=0; i != Identifiers.size(); i++) {
2491     Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
2492     pragmaUnusedTok.startToken();
2493     pragmaUnusedTok.setKind(tok::annot_pragma_unused);
2494     pragmaUnusedTok.setLocation(UnusedLoc);
2495     idTok = Identifiers[i];
2496   }
2497   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2498                       /*IsReinject=*/false);
2499 }
2500 
2501 // #pragma weak identifier
2502 // #pragma weak identifier '=' identifier
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & WeakTok)2503 void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
2504                                      PragmaIntroducer Introducer,
2505                                      Token &WeakTok) {
2506   SourceLocation WeakLoc = WeakTok.getLocation();
2507 
2508   Token Tok;
2509   PP.Lex(Tok);
2510   if (Tok.isNot(tok::identifier)) {
2511     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
2512     return;
2513   }
2514 
2515   Token WeakName = Tok;
2516   bool HasAlias = false;
2517   Token AliasName;
2518 
2519   PP.Lex(Tok);
2520   if (Tok.is(tok::equal)) {
2521     HasAlias = true;
2522     PP.Lex(Tok);
2523     if (Tok.isNot(tok::identifier)) {
2524       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2525           << "weak";
2526       return;
2527     }
2528     AliasName = Tok;
2529     PP.Lex(Tok);
2530   }
2531 
2532   if (Tok.isNot(tok::eod)) {
2533     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
2534     return;
2535   }
2536 
2537   if (HasAlias) {
2538     MutableArrayRef<Token> Toks(
2539         PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
2540     Token &pragmaUnusedTok = Toks[0];
2541     pragmaUnusedTok.startToken();
2542     pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
2543     pragmaUnusedTok.setLocation(WeakLoc);
2544     pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
2545     Toks[1] = WeakName;
2546     Toks[2] = AliasName;
2547     PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2548                         /*IsReinject=*/false);
2549   } else {
2550     MutableArrayRef<Token> Toks(
2551         PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
2552     Token &pragmaUnusedTok = Toks[0];
2553     pragmaUnusedTok.startToken();
2554     pragmaUnusedTok.setKind(tok::annot_pragma_weak);
2555     pragmaUnusedTok.setLocation(WeakLoc);
2556     pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
2557     Toks[1] = WeakName;
2558     PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2559                         /*IsReinject=*/false);
2560   }
2561 }
2562 
2563 // #pragma redefine_extname identifier identifier
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & RedefToken)2564 void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
2565                                                 PragmaIntroducer Introducer,
2566                                                 Token &RedefToken) {
2567   SourceLocation RedefLoc = RedefToken.getLocation();
2568 
2569   Token Tok;
2570   PP.Lex(Tok);
2571   if (Tok.isNot(tok::identifier)) {
2572     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2573       "redefine_extname";
2574     return;
2575   }
2576 
2577   Token RedefName = Tok;
2578   PP.Lex(Tok);
2579 
2580   if (Tok.isNot(tok::identifier)) {
2581     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2582         << "redefine_extname";
2583     return;
2584   }
2585 
2586   Token AliasName = Tok;
2587   PP.Lex(Tok);
2588 
2589   if (Tok.isNot(tok::eod)) {
2590     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2591       "redefine_extname";
2592     return;
2593   }
2594 
2595   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
2596                               3);
2597   Token &pragmaRedefTok = Toks[0];
2598   pragmaRedefTok.startToken();
2599   pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
2600   pragmaRedefTok.setLocation(RedefLoc);
2601   pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
2602   Toks[1] = RedefName;
2603   Toks[2] = AliasName;
2604   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2605                       /*IsReinject=*/false);
2606 }
2607 
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2608 void PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
2609                                            PragmaIntroducer Introducer,
2610                                            Token &Tok) {
2611   tok::OnOffSwitch OOS;
2612   if (PP.LexOnOffSwitch(OOS))
2613     return;
2614 
2615   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2616                               1);
2617   Toks[0].startToken();
2618   Toks[0].setKind(tok::annot_pragma_fp_contract);
2619   Toks[0].setLocation(Tok.getLocation());
2620   Toks[0].setAnnotationEndLoc(Tok.getLocation());
2621   Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2622                              static_cast<uintptr_t>(OOS)));
2623   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2624                       /*IsReinject=*/false);
2625 }
2626 
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2627 void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
2628                                                 PragmaIntroducer Introducer,
2629                                                 Token &Tok) {
2630   PP.LexUnexpandedToken(Tok);
2631   if (Tok.isNot(tok::identifier)) {
2632     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2633       "OPENCL";
2634     return;
2635   }
2636   IdentifierInfo *Ext = Tok.getIdentifierInfo();
2637   SourceLocation NameLoc = Tok.getLocation();
2638 
2639   PP.Lex(Tok);
2640   if (Tok.isNot(tok::colon)) {
2641     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
2642     return;
2643   }
2644 
2645   PP.Lex(Tok);
2646   if (Tok.isNot(tok::identifier)) {
2647     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
2648     return;
2649   }
2650   IdentifierInfo *Pred = Tok.getIdentifierInfo();
2651 
2652   OpenCLExtState State;
2653   if (Pred->isStr("enable")) {
2654     State = Enable;
2655   } else if (Pred->isStr("disable")) {
2656     State = Disable;
2657   } else if (Pred->isStr("begin"))
2658     State = Begin;
2659   else if (Pred->isStr("end"))
2660     State = End;
2661   else {
2662     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2663       << Ext->isStr("all");
2664     return;
2665   }
2666   SourceLocation StateLoc = Tok.getLocation();
2667 
2668   PP.Lex(Tok);
2669   if (Tok.isNot(tok::eod)) {
2670     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2671       "OPENCL EXTENSION";
2672     return;
2673   }
2674 
2675   auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2676   Info->first = Ext;
2677   Info->second = State;
2678   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2679                               1);
2680   Toks[0].startToken();
2681   Toks[0].setKind(tok::annot_pragma_opencl_extension);
2682   Toks[0].setLocation(NameLoc);
2683   Toks[0].setAnnotationValue(static_cast<void*>(Info));
2684   Toks[0].setAnnotationEndLoc(StateLoc);
2685   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2686                       /*IsReinject=*/false);
2687 
2688   if (PP.getPPCallbacks())
2689     PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
2690                                                StateLoc, State);
2691 }
2692 
2693 /// Handle '#pragma omp ...' when OpenMP is disabled and '#pragma acc ...' when
2694 /// OpenACC is disabled.
2695 template <diag::kind IgnoredDiag>
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstTok)2696 void PragmaNoSupportHandler<IgnoredDiag>::HandlePragma(
2697     Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstTok) {
2698   if (!PP.getDiagnostics().isIgnored(IgnoredDiag, FirstTok.getLocation())) {
2699     PP.Diag(FirstTok, IgnoredDiag);
2700     PP.getDiagnostics().setSeverity(IgnoredDiag, diag::Severity::Ignored,
2701                                     SourceLocation());
2702   }
2703   PP.DiscardUntilEndOfDirective();
2704 }
2705 
2706 /// Handle '#pragma omp ...' when OpenMP is enabled, and handle '#pragma acc...'
2707 /// when OpenACC is enabled.
2708 template <tok::TokenKind StartTok, tok::TokenKind EndTok,
2709           diag::kind UnexpectedDiag>
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstTok)2710 void PragmaSupportHandler<StartTok, EndTok, UnexpectedDiag>::HandlePragma(
2711     Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstTok) {
2712   SmallVector<Token, 16> Pragma;
2713   Token Tok;
2714   Tok.startToken();
2715   Tok.setKind(StartTok);
2716   Tok.setLocation(Introducer.Loc);
2717 
2718   while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
2719     Pragma.push_back(Tok);
2720     PP.Lex(Tok);
2721     if (Tok.is(StartTok)) {
2722       PP.Diag(Tok, UnexpectedDiag) << 0;
2723       unsigned InnerPragmaCnt = 1;
2724       while (InnerPragmaCnt != 0) {
2725         PP.Lex(Tok);
2726         if (Tok.is(StartTok))
2727           ++InnerPragmaCnt;
2728         else if (Tok.is(EndTok))
2729           --InnerPragmaCnt;
2730       }
2731       PP.Lex(Tok);
2732     }
2733   }
2734   SourceLocation EodLoc = Tok.getLocation();
2735   Tok.startToken();
2736   Tok.setKind(EndTok);
2737   Tok.setLocation(EodLoc);
2738   Pragma.push_back(Tok);
2739 
2740   auto Toks = std::make_unique<Token[]>(Pragma.size());
2741   std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2742   PP.EnterTokenStream(std::move(Toks), Pragma.size(),
2743                       /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2744 }
2745 
2746 /// Handle '#pragma pointers_to_members'
2747 // The grammar for this pragma is as follows:
2748 //
2749 // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2750 //
2751 // #pragma pointers_to_members '(' 'best_case' ')'
2752 // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2753 // #pragma pointers_to_members '(' inheritance-model ')'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2754 void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
2755                                              PragmaIntroducer Introducer,
2756                                              Token &Tok) {
2757   SourceLocation PointersToMembersLoc = Tok.getLocation();
2758   PP.Lex(Tok);
2759   if (Tok.isNot(tok::l_paren)) {
2760     PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2761       << "pointers_to_members";
2762     return;
2763   }
2764   PP.Lex(Tok);
2765   const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2766   if (!Arg) {
2767     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2768       << "pointers_to_members";
2769     return;
2770   }
2771   PP.Lex(Tok);
2772 
2773   LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
2774   if (Arg->isStr("best_case")) {
2775     RepresentationMethod = LangOptions::PPTMK_BestCase;
2776   } else {
2777     if (Arg->isStr("full_generality")) {
2778       if (Tok.is(tok::comma)) {
2779         PP.Lex(Tok);
2780 
2781         Arg = Tok.getIdentifierInfo();
2782         if (!Arg) {
2783           PP.Diag(Tok.getLocation(),
2784                   diag::err_pragma_pointers_to_members_unknown_kind)
2785               << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2786           return;
2787         }
2788         PP.Lex(Tok);
2789       } else if (Tok.is(tok::r_paren)) {
2790         // #pragma pointers_to_members(full_generality) implicitly specifies
2791         // virtual_inheritance.
2792         Arg = nullptr;
2793         RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
2794       } else {
2795         PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2796             << "full_generality";
2797         return;
2798       }
2799     }
2800 
2801     if (Arg) {
2802       if (Arg->isStr("single_inheritance")) {
2803         RepresentationMethod =
2804             LangOptions::PPTMK_FullGeneralitySingleInheritance;
2805       } else if (Arg->isStr("multiple_inheritance")) {
2806         RepresentationMethod =
2807             LangOptions::PPTMK_FullGeneralityMultipleInheritance;
2808       } else if (Arg->isStr("virtual_inheritance")) {
2809         RepresentationMethod =
2810             LangOptions::PPTMK_FullGeneralityVirtualInheritance;
2811       } else {
2812         PP.Diag(Tok.getLocation(),
2813                 diag::err_pragma_pointers_to_members_unknown_kind)
2814             << Arg << /*HasPointerDeclaration*/ 1;
2815         return;
2816       }
2817     }
2818   }
2819 
2820   if (Tok.isNot(tok::r_paren)) {
2821     PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2822         << (Arg ? Arg->getName() : "full_generality");
2823     return;
2824   }
2825 
2826   SourceLocation EndLoc = Tok.getLocation();
2827   PP.Lex(Tok);
2828   if (Tok.isNot(tok::eod)) {
2829     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2830       << "pointers_to_members";
2831     return;
2832   }
2833 
2834   Token AnnotTok;
2835   AnnotTok.startToken();
2836   AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2837   AnnotTok.setLocation(PointersToMembersLoc);
2838   AnnotTok.setAnnotationEndLoc(EndLoc);
2839   AnnotTok.setAnnotationValue(
2840       reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
2841   PP.EnterToken(AnnotTok, /*IsReinject=*/true);
2842 }
2843 
2844 /// Handle '#pragma vtordisp'
2845 // The grammar for this pragma is as follows:
2846 //
2847 // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2848 //
2849 // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2850 // #pragma vtordisp '(' 'pop' ')'
2851 // #pragma vtordisp '(' ')'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2852 void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
2853                                     PragmaIntroducer Introducer, Token &Tok) {
2854   SourceLocation VtorDispLoc = Tok.getLocation();
2855   PP.Lex(Tok);
2856   if (Tok.isNot(tok::l_paren)) {
2857     PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2858     return;
2859   }
2860   PP.Lex(Tok);
2861 
2862   Sema::PragmaMsStackAction Action = Sema::PSK_Set;
2863   const IdentifierInfo *II = Tok.getIdentifierInfo();
2864   if (II) {
2865     if (II->isStr("push")) {
2866       // #pragma vtordisp(push, mode)
2867       PP.Lex(Tok);
2868       if (Tok.isNot(tok::comma)) {
2869         PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2870         return;
2871       }
2872       PP.Lex(Tok);
2873       Action = Sema::PSK_Push_Set;
2874       // not push, could be on/off
2875     } else if (II->isStr("pop")) {
2876       // #pragma vtordisp(pop)
2877       PP.Lex(Tok);
2878       Action = Sema::PSK_Pop;
2879     }
2880     // not push or pop, could be on/off
2881   } else {
2882     if (Tok.is(tok::r_paren)) {
2883       // #pragma vtordisp()
2884       Action = Sema::PSK_Reset;
2885     }
2886   }
2887 
2888 
2889   uint64_t Value = 0;
2890   if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
2891     const IdentifierInfo *II = Tok.getIdentifierInfo();
2892     if (II && II->isStr("off")) {
2893       PP.Lex(Tok);
2894       Value = 0;
2895     } else if (II && II->isStr("on")) {
2896       PP.Lex(Tok);
2897       Value = 1;
2898     } else if (Tok.is(tok::numeric_constant) &&
2899                PP.parseSimpleIntegerLiteral(Tok, Value)) {
2900       if (Value > 2) {
2901         PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2902             << 0 << 2 << "vtordisp";
2903         return;
2904       }
2905     } else {
2906       PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2907           << "vtordisp";
2908       return;
2909     }
2910   }
2911 
2912   // Finish the pragma: ')' $
2913   if (Tok.isNot(tok::r_paren)) {
2914     PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2915     return;
2916   }
2917   SourceLocation EndLoc = Tok.getLocation();
2918   PP.Lex(Tok);
2919   if (Tok.isNot(tok::eod)) {
2920     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2921         << "vtordisp";
2922     return;
2923   }
2924 
2925   // Enter the annotation.
2926   Token AnnotTok;
2927   AnnotTok.startToken();
2928   AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2929   AnnotTok.setLocation(VtorDispLoc);
2930   AnnotTok.setAnnotationEndLoc(EndLoc);
2931   AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
2932       static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
2933   PP.EnterToken(AnnotTok, /*IsReinject=*/false);
2934 }
2935 
2936 /// Handle all MS pragmas.  Simply forwards the tokens after inserting
2937 /// an annotation token.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2938 void PragmaMSPragma::HandlePragma(Preprocessor &PP,
2939                                   PragmaIntroducer Introducer, Token &Tok) {
2940   Token EoF, AnnotTok;
2941   EoF.startToken();
2942   EoF.setKind(tok::eof);
2943   AnnotTok.startToken();
2944   AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2945   AnnotTok.setLocation(Tok.getLocation());
2946   AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2947   SmallVector<Token, 8> TokenVector;
2948   // Suck up all of the tokens before the eod.
2949   for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
2950     TokenVector.push_back(Tok);
2951     AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2952   }
2953   // Add a sentinel EoF token to the end of the list.
2954   TokenVector.push_back(EoF);
2955   // We must allocate this array with new because EnterTokenStream is going to
2956   // delete it later.
2957   markAsReinjectedForRelexing(TokenVector);
2958   auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
2959   std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
2960   auto Value = new (PP.getPreprocessorAllocator())
2961       std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2962                                                   TokenVector.size());
2963   AnnotTok.setAnnotationValue(Value);
2964   PP.EnterToken(AnnotTok, /*IsReinject*/ false);
2965 }
2966 
2967 /// Handle the \#pragma float_control extension.
2968 ///
2969 /// The syntax is:
2970 /// \code
2971 ///   #pragma float_control(keyword[, setting] [,push])
2972 /// \endcode
2973 /// Where 'keyword' and 'setting' are identifiers.
2974 // 'keyword' can be: precise, except, push, pop
2975 // 'setting' can be: on, off
2976 /// The optional arguments 'setting' and 'push' are supported only
2977 /// when the keyword is 'precise' or 'except'.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2978 void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP,
2979                                              PragmaIntroducer Introducer,
2980                                              Token &Tok) {
2981   Sema::PragmaMsStackAction Action = Sema::PSK_Set;
2982   SourceLocation FloatControlLoc = Tok.getLocation();
2983   Token PragmaName = Tok;
2984   if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
2985     PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
2986         << PragmaName.getIdentifierInfo()->getName();
2987     return;
2988   }
2989   PP.Lex(Tok);
2990   if (Tok.isNot(tok::l_paren)) {
2991     PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren;
2992     return;
2993   }
2994 
2995   // Read the identifier.
2996   PP.Lex(Tok);
2997   if (Tok.isNot(tok::identifier)) {
2998     PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2999     return;
3000   }
3001 
3002   // Verify that this is one of the float control options.
3003   IdentifierInfo *II = Tok.getIdentifierInfo();
3004   PragmaFloatControlKind Kind =
3005       llvm::StringSwitch<PragmaFloatControlKind>(II->getName())
3006           .Case("precise", PFC_Precise)
3007           .Case("except", PFC_Except)
3008           .Case("push", PFC_Push)
3009           .Case("pop", PFC_Pop)
3010           .Default(PFC_Unknown);
3011   PP.Lex(Tok); // the identifier
3012   if (Kind == PFC_Unknown) {
3013     PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3014     return;
3015   } else if (Kind == PFC_Push || Kind == PFC_Pop) {
3016     if (Tok.isNot(tok::r_paren)) {
3017       PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3018       return;
3019     }
3020     PP.Lex(Tok); // Eat the r_paren
3021     Action = (Kind == PFC_Pop) ? Sema::PSK_Pop : Sema::PSK_Push;
3022   } else {
3023     if (Tok.is(tok::r_paren))
3024       // Selecting Precise or Except
3025       PP.Lex(Tok); // the r_paren
3026     else if (Tok.isNot(tok::comma)) {
3027       PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3028       return;
3029     } else {
3030       PP.Lex(Tok); // ,
3031       if (!Tok.isAnyIdentifier()) {
3032         PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3033         return;
3034       }
3035       StringRef PushOnOff = Tok.getIdentifierInfo()->getName();
3036       if (PushOnOff == "on")
3037         // Kind is set correctly
3038         ;
3039       else if (PushOnOff == "off") {
3040         if (Kind == PFC_Precise)
3041           Kind = PFC_NoPrecise;
3042         if (Kind == PFC_Except)
3043           Kind = PFC_NoExcept;
3044       } else if (PushOnOff == "push") {
3045         Action = Sema::PSK_Push_Set;
3046       } else {
3047         PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3048         return;
3049       }
3050       PP.Lex(Tok); // the identifier
3051       if (Tok.is(tok::comma)) {
3052         PP.Lex(Tok); // ,
3053         if (!Tok.isAnyIdentifier()) {
3054           PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3055           return;
3056         }
3057         StringRef ExpectedPush = Tok.getIdentifierInfo()->getName();
3058         if (ExpectedPush == "push") {
3059           Action = Sema::PSK_Push_Set;
3060         } else {
3061           PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3062           return;
3063         }
3064         PP.Lex(Tok); // the push identifier
3065       }
3066       if (Tok.isNot(tok::r_paren)) {
3067         PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3068         return;
3069       }
3070       PP.Lex(Tok); // the r_paren
3071     }
3072   }
3073   SourceLocation EndLoc = Tok.getLocation();
3074   if (Tok.isNot(tok::eod)) {
3075     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3076         << "float_control";
3077     return;
3078   }
3079 
3080   // Note: there is no accomodation for PP callback for this pragma.
3081 
3082   // Enter the annotation.
3083   auto TokenArray = std::make_unique<Token[]>(1);
3084   TokenArray[0].startToken();
3085   TokenArray[0].setKind(tok::annot_pragma_float_control);
3086   TokenArray[0].setLocation(FloatControlLoc);
3087   TokenArray[0].setAnnotationEndLoc(EndLoc);
3088   // Create an encoding of Action and Value by shifting the Action into
3089   // the high 16 bits then union with the Kind.
3090   TokenArray[0].setAnnotationValue(reinterpret_cast<void *>(
3091       static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF))));
3092   PP.EnterTokenStream(std::move(TokenArray), 1,
3093                       /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3094 }
3095 
3096 /// Handle the Microsoft \#pragma detect_mismatch extension.
3097 ///
3098 /// The syntax is:
3099 /// \code
3100 ///   #pragma detect_mismatch("name", "value")
3101 /// \endcode
3102 /// Where 'name' and 'value' are quoted strings.  The values are embedded in
3103 /// the object file and passed along to the linker.  If the linker detects a
3104 /// mismatch in the object file's values for the given name, a LNK2038 error
3105 /// is emitted.  See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3106 void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
3107                                                PragmaIntroducer Introducer,
3108                                                Token &Tok) {
3109   SourceLocation DetectMismatchLoc = Tok.getLocation();
3110   PP.Lex(Tok);
3111   if (Tok.isNot(tok::l_paren)) {
3112     PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
3113     return;
3114   }
3115 
3116   // Read the name to embed, which must be a string literal.
3117   std::string NameString;
3118   if (!PP.LexStringLiteral(Tok, NameString,
3119                            "pragma detect_mismatch",
3120                            /*AllowMacroExpansion=*/true))
3121     return;
3122 
3123   // Read the comma followed by a second string literal.
3124   std::string ValueString;
3125   if (Tok.isNot(tok::comma)) {
3126     PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
3127     return;
3128   }
3129 
3130   if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
3131                            /*AllowMacroExpansion=*/true))
3132     return;
3133 
3134   if (Tok.isNot(tok::r_paren)) {
3135     PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3136     return;
3137   }
3138   PP.Lex(Tok);  // Eat the r_paren.
3139 
3140   if (Tok.isNot(tok::eod)) {
3141     PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
3142     return;
3143   }
3144 
3145   // If the pragma is lexically sound, notify any interested PPCallbacks.
3146   if (PP.getPPCallbacks())
3147     PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
3148                                               ValueString);
3149 
3150   Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
3151 }
3152 
3153 /// Handle the microsoft \#pragma comment extension.
3154 ///
3155 /// The syntax is:
3156 /// \code
3157 ///   #pragma comment(linker, "foo")
3158 /// \endcode
3159 /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
3160 /// "foo" is a string, which is fully macro expanded, and permits string
3161 /// concatenation, embedded escape characters etc.  See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3162 void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
3163                                         PragmaIntroducer Introducer,
3164                                         Token &Tok) {
3165   SourceLocation CommentLoc = Tok.getLocation();
3166   PP.Lex(Tok);
3167   if (Tok.isNot(tok::l_paren)) {
3168     PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
3169     return;
3170   }
3171 
3172   // Read the identifier.
3173   PP.Lex(Tok);
3174   if (Tok.isNot(tok::identifier)) {
3175     PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
3176     return;
3177   }
3178 
3179   // Verify that this is one of the 5 explicitly listed options.
3180   IdentifierInfo *II = Tok.getIdentifierInfo();
3181   PragmaMSCommentKind Kind =
3182     llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
3183     .Case("linker",   PCK_Linker)
3184     .Case("lib",      PCK_Lib)
3185     .Case("compiler", PCK_Compiler)
3186     .Case("exestr",   PCK_ExeStr)
3187     .Case("user",     PCK_User)
3188     .Default(PCK_Unknown);
3189   if (Kind == PCK_Unknown) {
3190     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
3191     return;
3192   }
3193 
3194   if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
3195     PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
3196         << II->getName();
3197     return;
3198   }
3199 
3200   // Read the optional string if present.
3201   PP.Lex(Tok);
3202   std::string ArgumentString;
3203   if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
3204                                                  "pragma comment",
3205                                                  /*AllowMacroExpansion=*/true))
3206     return;
3207 
3208   // FIXME: warn that 'exestr' is deprecated.
3209   // FIXME: If the kind is "compiler" warn if the string is present (it is
3210   // ignored).
3211   // The MSDN docs say that "lib" and "linker" require a string and have a short
3212   // list of linker options they support, but in practice MSVC doesn't
3213   // issue a diagnostic.  Therefore neither does clang.
3214 
3215   if (Tok.isNot(tok::r_paren)) {
3216     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
3217     return;
3218   }
3219   PP.Lex(Tok);  // eat the r_paren.
3220 
3221   if (Tok.isNot(tok::eod)) {
3222     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
3223     return;
3224   }
3225 
3226   // If the pragma is lexically sound, notify any interested PPCallbacks.
3227   if (PP.getPPCallbacks())
3228     PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
3229 
3230   Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
3231 }
3232 
3233 // #pragma clang optimize off
3234 // #pragma clang optimize on
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)3235 void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
3236                                          PragmaIntroducer Introducer,
3237                                          Token &FirstToken) {
3238   Token Tok;
3239   PP.Lex(Tok);
3240   if (Tok.is(tok::eod)) {
3241     PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3242         << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
3243     return;
3244   }
3245   if (Tok.isNot(tok::identifier)) {
3246     PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
3247       << PP.getSpelling(Tok);
3248     return;
3249   }
3250   const IdentifierInfo *II = Tok.getIdentifierInfo();
3251   // The only accepted values are 'on' or 'off'.
3252   bool IsOn = false;
3253   if (II->isStr("on")) {
3254     IsOn = true;
3255   } else if (!II->isStr("off")) {
3256     PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
3257       << PP.getSpelling(Tok);
3258     return;
3259   }
3260   PP.Lex(Tok);
3261 
3262   if (Tok.isNot(tok::eod)) {
3263     PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
3264       << PP.getSpelling(Tok);
3265     return;
3266   }
3267 
3268   Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
3269 }
3270 
3271 namespace {
3272 /// Used as the annotation value for tok::annot_pragma_fp.
3273 struct TokFPAnnotValue {
3274   enum FlagValues { On, Off, Fast };
3275 
3276   std::optional<LangOptions::FPModeKind> ContractValue;
3277   std::optional<LangOptions::FPModeKind> ReassociateValue;
3278   std::optional<LangOptions::FPModeKind> ReciprocalValue;
3279   std::optional<LangOptions::FPExceptionModeKind> ExceptionsValue;
3280   std::optional<LangOptions::FPEvalMethodKind> EvalMethodValue;
3281 };
3282 } // end anonymous namespace
3283 
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3284 void PragmaFPHandler::HandlePragma(Preprocessor &PP,
3285                                    PragmaIntroducer Introducer, Token &Tok) {
3286   // fp
3287   Token PragmaName = Tok;
3288   SmallVector<Token, 1> TokenList;
3289 
3290   PP.Lex(Tok);
3291   if (Tok.isNot(tok::identifier)) {
3292     PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
3293         << /*MissingOption=*/true << "";
3294     return;
3295   }
3296 
3297   auto *AnnotValue = new (PP.getPreprocessorAllocator()) TokFPAnnotValue;
3298   while (Tok.is(tok::identifier)) {
3299     IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
3300 
3301     auto FlagKind =
3302         llvm::StringSwitch<std::optional<PragmaFPKind>>(OptionInfo->getName())
3303             .Case("contract", PFK_Contract)
3304             .Case("reassociate", PFK_Reassociate)
3305             .Case("exceptions", PFK_Exceptions)
3306             .Case("eval_method", PFK_EvalMethod)
3307             .Case("reciprocal", PFK_Reciprocal)
3308             .Default(std::nullopt);
3309     if (!FlagKind) {
3310       PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
3311           << /*MissingOption=*/false << OptionInfo;
3312       return;
3313     }
3314     PP.Lex(Tok);
3315 
3316     // Read '('
3317     if (Tok.isNot(tok::l_paren)) {
3318       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3319       return;
3320     }
3321     PP.Lex(Tok);
3322     bool isEvalMethodDouble =
3323         Tok.is(tok::kw_double) && FlagKind == PFK_EvalMethod;
3324 
3325     // Don't diagnose if we have an eval_metod pragma with "double" kind.
3326     if (Tok.isNot(tok::identifier) && !isEvalMethodDouble) {
3327       PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3328           << PP.getSpelling(Tok) << OptionInfo->getName()
3329           << static_cast<int>(*FlagKind);
3330       return;
3331     }
3332     const IdentifierInfo *II = Tok.getIdentifierInfo();
3333 
3334     if (FlagKind == PFK_Contract) {
3335       AnnotValue->ContractValue =
3336           llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(
3337               II->getName())
3338               .Case("on", LangOptions::FPModeKind::FPM_On)
3339               .Case("off", LangOptions::FPModeKind::FPM_Off)
3340               .Case("fast", LangOptions::FPModeKind::FPM_Fast)
3341               .Default(std::nullopt);
3342       if (!AnnotValue->ContractValue) {
3343         PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3344             << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3345         return;
3346       }
3347     } else if (FlagKind == PFK_Reassociate || FlagKind == PFK_Reciprocal) {
3348       auto &Value = FlagKind == PFK_Reassociate ? AnnotValue->ReassociateValue
3349                                                 : AnnotValue->ReciprocalValue;
3350       Value = llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(
3351                   II->getName())
3352                   .Case("on", LangOptions::FPModeKind::FPM_On)
3353                   .Case("off", LangOptions::FPModeKind::FPM_Off)
3354                   .Default(std::nullopt);
3355       if (!Value) {
3356         PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3357             << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3358         return;
3359       }
3360     } else if (FlagKind == PFK_Exceptions) {
3361       AnnotValue->ExceptionsValue =
3362           llvm::StringSwitch<std::optional<LangOptions::FPExceptionModeKind>>(
3363               II->getName())
3364               .Case("ignore", LangOptions::FPE_Ignore)
3365               .Case("maytrap", LangOptions::FPE_MayTrap)
3366               .Case("strict", LangOptions::FPE_Strict)
3367               .Default(std::nullopt);
3368       if (!AnnotValue->ExceptionsValue) {
3369         PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3370             << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3371         return;
3372       }
3373     } else if (FlagKind == PFK_EvalMethod) {
3374       AnnotValue->EvalMethodValue =
3375           llvm::StringSwitch<std::optional<LangOptions::FPEvalMethodKind>>(
3376               II->getName())
3377               .Case("source", LangOptions::FPEvalMethodKind::FEM_Source)
3378               .Case("double", LangOptions::FPEvalMethodKind::FEM_Double)
3379               .Case("extended", LangOptions::FPEvalMethodKind::FEM_Extended)
3380               .Default(std::nullopt);
3381       if (!AnnotValue->EvalMethodValue) {
3382         PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3383             << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3384         return;
3385       }
3386     }
3387     PP.Lex(Tok);
3388 
3389     // Read ')'
3390     if (Tok.isNot(tok::r_paren)) {
3391       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3392       return;
3393     }
3394     PP.Lex(Tok);
3395   }
3396 
3397   if (Tok.isNot(tok::eod)) {
3398     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3399         << "clang fp";
3400     return;
3401   }
3402 
3403   Token FPTok;
3404   FPTok.startToken();
3405   FPTok.setKind(tok::annot_pragma_fp);
3406   FPTok.setLocation(PragmaName.getLocation());
3407   FPTok.setAnnotationEndLoc(PragmaName.getLocation());
3408   FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
3409   TokenList.push_back(FPTok);
3410 
3411   auto TokenArray = std::make_unique<Token[]>(TokenList.size());
3412   std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
3413 
3414   PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
3415                       /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3416 }
3417 
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3418 void PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor &PP,
3419                                                 PragmaIntroducer Introducer,
3420                                                 Token &Tok) {
3421   Token PragmaName = Tok;
3422   SmallVector<Token, 1> TokenList;
3423   if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
3424     PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
3425         << PragmaName.getIdentifierInfo()->getName();
3426     return;
3427   }
3428 
3429   PP.Lex(Tok);
3430   if (Tok.isNot(tok::identifier)) {
3431     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
3432         << PragmaName.getIdentifierInfo()->getName();
3433     return;
3434   }
3435   IdentifierInfo *II = Tok.getIdentifierInfo();
3436 
3437   auto RM =
3438       llvm::StringSwitch<llvm::RoundingMode>(II->getName())
3439           .Case("FE_TOWARDZERO", llvm::RoundingMode::TowardZero)
3440           .Case("FE_TONEAREST", llvm::RoundingMode::NearestTiesToEven)
3441           .Case("FE_UPWARD", llvm::RoundingMode::TowardPositive)
3442           .Case("FE_DOWNWARD", llvm::RoundingMode::TowardNegative)
3443           .Case("FE_TONEARESTFROMZERO", llvm::RoundingMode::NearestTiesToAway)
3444           .Case("FE_DYNAMIC", llvm::RoundingMode::Dynamic)
3445           .Default(llvm::RoundingMode::Invalid);
3446   if (RM == llvm::RoundingMode::Invalid) {
3447     PP.Diag(Tok.getLocation(), diag::warn_stdc_unknown_rounding_mode);
3448     return;
3449   }
3450   PP.Lex(Tok);
3451 
3452   if (Tok.isNot(tok::eod)) {
3453     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3454         << "STDC FENV_ROUND";
3455     return;
3456   }
3457 
3458   // Until the pragma is fully implemented, issue a warning.
3459   PP.Diag(Tok.getLocation(), diag::warn_stdc_fenv_round_not_supported);
3460 
3461   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
3462                               1);
3463   Toks[0].startToken();
3464   Toks[0].setKind(tok::annot_pragma_fenv_round);
3465   Toks[0].setLocation(Tok.getLocation());
3466   Toks[0].setAnnotationEndLoc(Tok.getLocation());
3467   Toks[0].setAnnotationValue(
3468       reinterpret_cast<void *>(static_cast<uintptr_t>(RM)));
3469   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
3470                       /*IsReinject=*/false);
3471 }
3472 
HandlePragmaFP()3473 void Parser::HandlePragmaFP() {
3474   assert(Tok.is(tok::annot_pragma_fp));
3475   auto *AnnotValue =
3476       reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
3477 
3478   if (AnnotValue->ReassociateValue)
3479     Actions.ActOnPragmaFPValueChangingOption(
3480         Tok.getLocation(), PFK_Reassociate,
3481         *AnnotValue->ReassociateValue == LangOptions::FPModeKind::FPM_On);
3482 
3483   if (AnnotValue->ReciprocalValue)
3484     Actions.ActOnPragmaFPValueChangingOption(
3485         Tok.getLocation(), PFK_Reciprocal,
3486         *AnnotValue->ReciprocalValue == LangOptions::FPModeKind::FPM_On);
3487 
3488   if (AnnotValue->ContractValue)
3489     Actions.ActOnPragmaFPContract(Tok.getLocation(),
3490                                   *AnnotValue->ContractValue);
3491   if (AnnotValue->ExceptionsValue)
3492     Actions.ActOnPragmaFPExceptions(Tok.getLocation(),
3493                                     *AnnotValue->ExceptionsValue);
3494   if (AnnotValue->EvalMethodValue)
3495     Actions.ActOnPragmaFPEvalMethod(Tok.getLocation(),
3496                                     *AnnotValue->EvalMethodValue);
3497   ConsumeAnnotationToken();
3498 }
3499 
3500 /// Parses loop or unroll pragma hint value and fills in Info.
ParseLoopHintValue(Preprocessor & PP,Token & Tok,Token PragmaName,Token Option,bool ValueInParens,PragmaLoopHintInfo & Info)3501 static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
3502                                Token Option, bool ValueInParens,
3503                                PragmaLoopHintInfo &Info) {
3504   SmallVector<Token, 1> ValueList;
3505   int OpenParens = ValueInParens ? 1 : 0;
3506   // Read constant expression.
3507   while (Tok.isNot(tok::eod)) {
3508     if (Tok.is(tok::l_paren))
3509       OpenParens++;
3510     else if (Tok.is(tok::r_paren)) {
3511       OpenParens--;
3512       if (OpenParens == 0 && ValueInParens)
3513         break;
3514     }
3515 
3516     ValueList.push_back(Tok);
3517     PP.Lex(Tok);
3518   }
3519 
3520   if (ValueInParens) {
3521     // Read ')'
3522     if (Tok.isNot(tok::r_paren)) {
3523       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3524       return true;
3525     }
3526     PP.Lex(Tok);
3527   }
3528 
3529   Token EOFTok;
3530   EOFTok.startToken();
3531   EOFTok.setKind(tok::eof);
3532   EOFTok.setLocation(Tok.getLocation());
3533   ValueList.push_back(EOFTok); // Terminates expression for parsing.
3534 
3535   markAsReinjectedForRelexing(ValueList);
3536   Info.Toks = llvm::ArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
3537 
3538   Info.PragmaName = PragmaName;
3539   Info.Option = Option;
3540   return false;
3541 }
3542 
3543 /// Handle the \#pragma clang loop directive.
3544 ///  #pragma clang 'loop' loop-hints
3545 ///
3546 ///  loop-hints:
3547 ///    loop-hint loop-hints[opt]
3548 ///
3549 ///  loop-hint:
3550 ///    'vectorize' '(' loop-hint-keyword ')'
3551 ///    'interleave' '(' loop-hint-keyword ')'
3552 ///    'unroll' '(' unroll-hint-keyword ')'
3553 ///    'vectorize_predicate' '(' loop-hint-keyword ')'
3554 ///    'vectorize_width' '(' loop-hint-value ')'
3555 ///    'interleave_count' '(' loop-hint-value ')'
3556 ///    'unroll_count' '(' loop-hint-value ')'
3557 ///    'pipeline' '(' disable ')'
3558 ///    'pipeline_initiation_interval' '(' loop-hint-value ')'
3559 ///
3560 ///  loop-hint-keyword:
3561 ///    'enable'
3562 ///    'disable'
3563 ///    'assume_safety'
3564 ///
3565 ///  unroll-hint-keyword:
3566 ///    'enable'
3567 ///    'disable'
3568 ///    'full'
3569 ///
3570 ///  loop-hint-value:
3571 ///    constant-expression
3572 ///
3573 /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
3574 /// try vectorizing the instructions of the loop it precedes. Specifying
3575 /// interleave(enable) or interleave_count(_value_) instructs llvm to try
3576 /// interleaving multiple iterations of the loop it precedes. The width of the
3577 /// vector instructions is specified by vectorize_width() and the number of
3578 /// interleaved loop iterations is specified by interleave_count(). Specifying a
3579 /// value of 1 effectively disables vectorization/interleaving, even if it is
3580 /// possible and profitable, and 0 is invalid. The loop vectorizer currently
3581 /// only works on inner loops.
3582 ///
3583 /// The unroll and unroll_count directives control the concatenation
3584 /// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
3585 /// completely if the trip count is known at compile time and unroll partially
3586 /// if the trip count is not known.  Specifying unroll(full) is similar to
3587 /// unroll(enable) but will unroll the loop only if the trip count is known at
3588 /// compile time.  Specifying unroll(disable) disables unrolling for the
3589 /// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
3590 /// loop the number of times indicated by the value.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3591 void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
3592                                          PragmaIntroducer Introducer,
3593                                          Token &Tok) {
3594   // Incoming token is "loop" from "#pragma clang loop".
3595   Token PragmaName = Tok;
3596   SmallVector<Token, 1> TokenList;
3597 
3598   // Lex the optimization option and verify it is an identifier.
3599   PP.Lex(Tok);
3600   if (Tok.isNot(tok::identifier)) {
3601     PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3602         << /*MissingOption=*/true << "";
3603     return;
3604   }
3605 
3606   while (Tok.is(tok::identifier)) {
3607     Token Option = Tok;
3608     IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
3609 
3610     bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
3611                            .Case("vectorize", true)
3612                            .Case("interleave", true)
3613                            .Case("unroll", true)
3614                            .Case("distribute", true)
3615                            .Case("vectorize_predicate", true)
3616                            .Case("vectorize_width", true)
3617                            .Case("interleave_count", true)
3618                            .Case("unroll_count", true)
3619                            .Case("pipeline", true)
3620                            .Case("pipeline_initiation_interval", true)
3621                            .Default(false);
3622     if (!OptionValid) {
3623       PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3624           << /*MissingOption=*/false << OptionInfo;
3625       return;
3626     }
3627     PP.Lex(Tok);
3628 
3629     // Read '('
3630     if (Tok.isNot(tok::l_paren)) {
3631       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3632       return;
3633     }
3634     PP.Lex(Tok);
3635 
3636     auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3637     if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
3638                            *Info))
3639       return;
3640 
3641     // Generate the loop hint token.
3642     Token LoopHintTok;
3643     LoopHintTok.startToken();
3644     LoopHintTok.setKind(tok::annot_pragma_loop_hint);
3645     LoopHintTok.setLocation(Introducer.Loc);
3646     LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
3647     LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
3648     TokenList.push_back(LoopHintTok);
3649   }
3650 
3651   if (Tok.isNot(tok::eod)) {
3652     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3653         << "clang loop";
3654     return;
3655   }
3656 
3657   auto TokenArray = std::make_unique<Token[]>(TokenList.size());
3658   std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
3659 
3660   PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
3661                       /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3662 }
3663 
3664 /// Handle the loop unroll optimization pragmas.
3665 ///  #pragma unroll
3666 ///  #pragma unroll unroll-hint-value
3667 ///  #pragma unroll '(' unroll-hint-value ')'
3668 ///  #pragma nounroll
3669 ///  #pragma unroll_and_jam
3670 ///  #pragma unroll_and_jam unroll-hint-value
3671 ///  #pragma unroll_and_jam '(' unroll-hint-value ')'
3672 ///  #pragma nounroll_and_jam
3673 ///
3674 ///  unroll-hint-value:
3675 ///    constant-expression
3676 ///
3677 /// Loop unrolling hints can be specified with '#pragma unroll' or
3678 /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
3679 /// contained in parentheses. With no argument the directive instructs llvm to
3680 /// try to unroll the loop completely. A positive integer argument can be
3681 /// specified to indicate the number of times the loop should be unrolled.  To
3682 /// maximize compatibility with other compilers the unroll count argument can be
3683 /// specified with or without parentheses.  Specifying, '#pragma nounroll'
3684 /// disables unrolling of the loop.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3685 void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
3686                                            PragmaIntroducer Introducer,
3687                                            Token &Tok) {
3688   // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
3689   // "#pragma nounroll".
3690   Token PragmaName = Tok;
3691   PP.Lex(Tok);
3692   auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3693   if (Tok.is(tok::eod)) {
3694     // nounroll or unroll pragma without an argument.
3695     Info->PragmaName = PragmaName;
3696     Info->Option.startToken();
3697   } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
3698              PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
3699     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3700         << PragmaName.getIdentifierInfo()->getName();
3701     return;
3702   } else {
3703     // Unroll pragma with an argument: "#pragma unroll N" or
3704     // "#pragma unroll(N)".
3705     // Read '(' if it exists.
3706     bool ValueInParens = Tok.is(tok::l_paren);
3707     if (ValueInParens)
3708       PP.Lex(Tok);
3709 
3710     Token Option;
3711     Option.startToken();
3712     if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
3713       return;
3714 
3715     // In CUDA, the argument to '#pragma unroll' should not be contained in
3716     // parentheses.
3717     if (PP.getLangOpts().CUDA && ValueInParens)
3718       PP.Diag(Info->Toks[0].getLocation(),
3719               diag::warn_pragma_unroll_cuda_value_in_parens);
3720 
3721     if (Tok.isNot(tok::eod)) {
3722       PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3723           << "unroll";
3724       return;
3725     }
3726   }
3727 
3728   // Generate the hint token.
3729   auto TokenArray = std::make_unique<Token[]>(1);
3730   TokenArray[0].startToken();
3731   TokenArray[0].setKind(tok::annot_pragma_loop_hint);
3732   TokenArray[0].setLocation(Introducer.Loc);
3733   TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
3734   TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3735   PP.EnterTokenStream(std::move(TokenArray), 1,
3736                       /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3737 }
3738 
3739 /// Handle the Microsoft \#pragma intrinsic extension.
3740 ///
3741 /// The syntax is:
3742 /// \code
3743 ///  #pragma intrinsic(memset)
3744 ///  #pragma intrinsic(strlen, memcpy)
3745 /// \endcode
3746 ///
3747 /// Pragma intrisic tells the compiler to use a builtin version of the
3748 /// function. Clang does it anyway, so the pragma doesn't really do anything.
3749 /// Anyway, we emit a warning if the function specified in \#pragma intrinsic
3750 /// isn't an intrinsic in clang and suggest to include intrin.h.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3751 void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
3752                                             PragmaIntroducer Introducer,
3753                                             Token &Tok) {
3754   PP.Lex(Tok);
3755 
3756   if (Tok.isNot(tok::l_paren)) {
3757     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
3758         << "intrinsic";
3759     return;
3760   }
3761   PP.Lex(Tok);
3762 
3763   bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3764 
3765   while (Tok.is(tok::identifier)) {
3766     IdentifierInfo *II = Tok.getIdentifierInfo();
3767     if (!II->getBuiltinID())
3768       PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3769           << II << SuggestIntrinH;
3770 
3771     PP.Lex(Tok);
3772     if (Tok.isNot(tok::comma))
3773       break;
3774     PP.Lex(Tok);
3775   }
3776 
3777   if (Tok.isNot(tok::r_paren)) {
3778     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
3779         << "intrinsic";
3780     return;
3781   }
3782   PP.Lex(Tok);
3783 
3784   if (Tok.isNot(tok::eod))
3785     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3786         << "intrinsic";
3787 }
3788 
HandlePragmaMSFunction(StringRef PragmaName,SourceLocation PragmaLocation)3789 bool Parser::HandlePragmaMSFunction(StringRef PragmaName,
3790                                     SourceLocation PragmaLocation) {
3791   Token FirstTok = Tok;
3792 
3793   if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
3794                        PragmaName))
3795     return false;
3796 
3797   bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3798 
3799   llvm::SmallVector<StringRef> NoBuiltins;
3800   while (Tok.is(tok::identifier)) {
3801     IdentifierInfo *II = Tok.getIdentifierInfo();
3802     if (!II->getBuiltinID())
3803       PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3804           << II << SuggestIntrinH;
3805     else
3806       NoBuiltins.emplace_back(II->getName());
3807 
3808     PP.Lex(Tok);
3809     if (Tok.isNot(tok::comma))
3810       break;
3811     PP.Lex(Tok); // ,
3812   }
3813 
3814   if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
3815                        PragmaName) ||
3816       ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
3817                        PragmaName))
3818     return false;
3819 
3820   Actions.ActOnPragmaMSFunction(FirstTok.getLocation(), NoBuiltins);
3821   return true;
3822 }
3823 
3824 // #pragma optimize("gsty", on|off)
HandlePragmaMSOptimize(StringRef PragmaName,SourceLocation PragmaLocation)3825 bool Parser::HandlePragmaMSOptimize(StringRef PragmaName,
3826                                     SourceLocation PragmaLocation) {
3827   Token FirstTok = Tok;
3828   if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
3829                        PragmaName))
3830     return false;
3831 
3832   if (Tok.isNot(tok::string_literal)) {
3833     PP.Diag(PragmaLocation, diag::warn_pragma_expected_string) << PragmaName;
3834     return false;
3835   }
3836   ExprResult StringResult = ParseStringLiteralExpression();
3837   if (StringResult.isInvalid())
3838     return false; // Already diagnosed.
3839   StringLiteral *OptimizationList = cast<StringLiteral>(StringResult.get());
3840   if (OptimizationList->getCharByteWidth() != 1) {
3841     PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
3842         << PragmaName;
3843     return false;
3844   }
3845 
3846   if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
3847                        PragmaName))
3848     return false;
3849 
3850   if (Tok.is(tok::eof) || Tok.is(tok::r_paren)) {
3851     PP.Diag(PragmaLocation, diag::warn_pragma_missing_argument)
3852         << PragmaName << /*Expected=*/true << "'on' or 'off'";
3853     return false;
3854   }
3855   IdentifierInfo *II = Tok.getIdentifierInfo();
3856   if (!II || (!II->isStr("on") && !II->isStr("off"))) {
3857     PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
3858         << PP.getSpelling(Tok) << PragmaName << /*Expected=*/true
3859         << "'on' or 'off'";
3860     return false;
3861   }
3862   bool IsOn = II->isStr("on");
3863   PP.Lex(Tok);
3864 
3865   if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
3866                        PragmaName))
3867     return false;
3868 
3869   // TODO: Add support for "sgty"
3870   if (!OptimizationList->getString().empty()) {
3871     PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
3872         << OptimizationList->getString() << PragmaName << /*Expected=*/true
3873         << "\"\"";
3874     return false;
3875   }
3876 
3877   if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
3878                        PragmaName))
3879     return false;
3880 
3881   Actions.ActOnPragmaMSOptimize(FirstTok.getLocation(), IsOn);
3882   return true;
3883 }
3884 
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3885 void PragmaForceCUDAHostDeviceHandler::HandlePragma(
3886     Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) {
3887   Token FirstTok = Tok;
3888 
3889   PP.Lex(Tok);
3890   IdentifierInfo *Info = Tok.getIdentifierInfo();
3891   if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
3892     PP.Diag(FirstTok.getLocation(),
3893             diag::warn_pragma_force_cuda_host_device_bad_arg);
3894     return;
3895   }
3896 
3897   if (Info->isStr("begin"))
3898     Actions.PushForceCUDAHostDevice();
3899   else if (!Actions.PopForceCUDAHostDevice())
3900     PP.Diag(FirstTok.getLocation(),
3901             diag::err_pragma_cannot_end_force_cuda_host_device);
3902 
3903   PP.Lex(Tok);
3904   if (!Tok.is(tok::eod))
3905     PP.Diag(FirstTok.getLocation(),
3906             diag::warn_pragma_force_cuda_host_device_bad_arg);
3907 }
3908 
3909 /// Handle the #pragma clang attribute directive.
3910 ///
3911 /// The syntax is:
3912 /// \code
3913 ///  #pragma clang attribute push (attribute, subject-set)
3914 ///  #pragma clang attribute push
3915 ///  #pragma clang attribute (attribute, subject-set)
3916 ///  #pragma clang attribute pop
3917 /// \endcode
3918 ///
3919 /// There are also 'namespace' variants of push and pop directives. The bare
3920 /// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
3921 /// namespace, since it always applies attributes to the most recently pushed
3922 /// group, regardless of namespace.
3923 /// \code
3924 ///  #pragma clang attribute namespace.push (attribute, subject-set)
3925 ///  #pragma clang attribute namespace.push
3926 ///  #pragma clang attribute namespace.pop
3927 /// \endcode
3928 ///
3929 /// The subject-set clause defines the set of declarations which receive the
3930 /// attribute. Its exact syntax is described in the LanguageExtensions document
3931 /// in Clang's documentation.
3932 ///
3933 /// This directive instructs the compiler to begin/finish applying the specified
3934 /// attribute to the set of attribute-specific declarations in the active range
3935 /// of the pragma.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)3936 void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
3937                                           PragmaIntroducer Introducer,
3938                                           Token &FirstToken) {
3939   Token Tok;
3940   PP.Lex(Tok);
3941   auto *Info = new (PP.getPreprocessorAllocator())
3942       PragmaAttributeInfo(AttributesForPragmaAttribute);
3943 
3944   // Parse the optional namespace followed by a period.
3945   if (Tok.is(tok::identifier)) {
3946     IdentifierInfo *II = Tok.getIdentifierInfo();
3947     if (!II->isStr("push") && !II->isStr("pop")) {
3948       Info->Namespace = II;
3949       PP.Lex(Tok);
3950 
3951       if (!Tok.is(tok::period)) {
3952         PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
3953             << II;
3954         return;
3955       }
3956       PP.Lex(Tok);
3957     }
3958   }
3959 
3960   if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
3961     PP.Diag(Tok.getLocation(),
3962             diag::err_pragma_attribute_expected_push_pop_paren);
3963     return;
3964   }
3965 
3966   // Determine what action this pragma clang attribute represents.
3967   if (Tok.is(tok::l_paren)) {
3968     if (Info->Namespace) {
3969       PP.Diag(Tok.getLocation(),
3970               diag::err_pragma_attribute_namespace_on_attribute);
3971       PP.Diag(Tok.getLocation(),
3972               diag::note_pragma_attribute_namespace_on_attribute);
3973       return;
3974     }
3975     Info->Action = PragmaAttributeInfo::Attribute;
3976   } else {
3977     const IdentifierInfo *II = Tok.getIdentifierInfo();
3978     if (II->isStr("push"))
3979       Info->Action = PragmaAttributeInfo::Push;
3980     else if (II->isStr("pop"))
3981       Info->Action = PragmaAttributeInfo::Pop;
3982     else {
3983       PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
3984           << PP.getSpelling(Tok);
3985       return;
3986     }
3987 
3988     PP.Lex(Tok);
3989   }
3990 
3991   // Parse the actual attribute.
3992   if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
3993       Info->Action == PragmaAttributeInfo::Attribute) {
3994     if (Tok.isNot(tok::l_paren)) {
3995       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3996       return;
3997     }
3998     PP.Lex(Tok);
3999 
4000     // Lex the attribute tokens.
4001     SmallVector<Token, 16> AttributeTokens;
4002     int OpenParens = 1;
4003     while (Tok.isNot(tok::eod)) {
4004       if (Tok.is(tok::l_paren))
4005         OpenParens++;
4006       else if (Tok.is(tok::r_paren)) {
4007         OpenParens--;
4008         if (OpenParens == 0)
4009           break;
4010       }
4011 
4012       AttributeTokens.push_back(Tok);
4013       PP.Lex(Tok);
4014     }
4015 
4016     if (AttributeTokens.empty()) {
4017       PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
4018       return;
4019     }
4020     if (Tok.isNot(tok::r_paren)) {
4021       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
4022       return;
4023     }
4024     SourceLocation EndLoc = Tok.getLocation();
4025     PP.Lex(Tok);
4026 
4027     // Terminate the attribute for parsing.
4028     Token EOFTok;
4029     EOFTok.startToken();
4030     EOFTok.setKind(tok::eof);
4031     EOFTok.setLocation(EndLoc);
4032     AttributeTokens.push_back(EOFTok);
4033 
4034     markAsReinjectedForRelexing(AttributeTokens);
4035     Info->Tokens =
4036         llvm::ArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
4037   }
4038 
4039   if (Tok.isNot(tok::eod))
4040     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
4041         << "clang attribute";
4042 
4043   // Generate the annotated pragma token.
4044   auto TokenArray = std::make_unique<Token[]>(1);
4045   TokenArray[0].startToken();
4046   TokenArray[0].setKind(tok::annot_pragma_attribute);
4047   TokenArray[0].setLocation(FirstToken.getLocation());
4048   TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
4049   TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
4050   PP.EnterTokenStream(std::move(TokenArray), 1,
4051                       /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
4052 }
4053 
4054 // Handle '#pragma clang max_tokens 12345'.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)4055 void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP,
4056                                               PragmaIntroducer Introducer,
4057                                               Token &Tok) {
4058   PP.Lex(Tok);
4059   if (Tok.is(tok::eod)) {
4060     PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
4061         << "clang max_tokens_here" << /*Expected=*/true << "integer";
4062     return;
4063   }
4064 
4065   SourceLocation Loc = Tok.getLocation();
4066   uint64_t MaxTokens;
4067   if (Tok.isNot(tok::numeric_constant) ||
4068       !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
4069     PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
4070         << "clang max_tokens_here";
4071     return;
4072   }
4073 
4074   if (Tok.isNot(tok::eod)) {
4075     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
4076         << "clang max_tokens_here";
4077     return;
4078   }
4079 
4080   if (PP.getTokenCount() > MaxTokens) {
4081     PP.Diag(Loc, diag::warn_max_tokens)
4082         << PP.getTokenCount() << (unsigned)MaxTokens;
4083   }
4084 }
4085 
4086 // Handle '#pragma clang max_tokens_total 12345'.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)4087 void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP,
4088                                                PragmaIntroducer Introducer,
4089                                                Token &Tok) {
4090   PP.Lex(Tok);
4091   if (Tok.is(tok::eod)) {
4092     PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
4093         << "clang max_tokens_total" << /*Expected=*/true << "integer";
4094     return;
4095   }
4096 
4097   SourceLocation Loc = Tok.getLocation();
4098   uint64_t MaxTokens;
4099   if (Tok.isNot(tok::numeric_constant) ||
4100       !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
4101     PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
4102         << "clang max_tokens_total";
4103     return;
4104   }
4105 
4106   if (Tok.isNot(tok::eod)) {
4107     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
4108         << "clang max_tokens_total";
4109     return;
4110   }
4111 
4112   PP.overrideMaxTokens(MaxTokens, Loc);
4113 }
4114 
4115 // Handle '#pragma clang riscv intrinsic vector'.
4116 //        '#pragma clang riscv intrinsic sifive_vector'.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)4117 void PragmaRISCVHandler::HandlePragma(Preprocessor &PP,
4118                                       PragmaIntroducer Introducer,
4119                                       Token &FirstToken) {
4120   Token Tok;
4121   PP.Lex(Tok);
4122   IdentifierInfo *II = Tok.getIdentifierInfo();
4123 
4124   if (!II || !II->isStr("intrinsic")) {
4125     PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
4126         << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'intrinsic'";
4127     return;
4128   }
4129 
4130   PP.Lex(Tok);
4131   II = Tok.getIdentifierInfo();
4132   if (!II || !(II->isStr("vector") || II->isStr("sifive_vector"))) {
4133     PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
4134         << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true
4135         << "'vector' or 'sifive_vector'";
4136     return;
4137   }
4138 
4139   PP.Lex(Tok);
4140   if (Tok.isNot(tok::eod)) {
4141     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
4142         << "clang riscv intrinsic";
4143     return;
4144   }
4145 
4146   if (II->isStr("vector"))
4147     Actions.DeclareRISCVVBuiltins = true;
4148   else if (II->isStr("sifive_vector"))
4149     Actions.DeclareRISCVSiFiveVectorBuiltins = true;
4150 }
4151