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