xref: /freebsd-src/contrib/llvm-project/clang/lib/Parse/ParsePragma.cpp (revision 62987288060ff68c817b7056815aa9fb8ba8ecd7)
10b57cec5SDimitry Andric //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the language specific #pragma handlers.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
140b57cec5SDimitry Andric #include "clang/Basic/PragmaKinds.h"
150b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
160b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h"
17fe6060f1SDimitry Andric #include "clang/Lex/Token.h"
180b57cec5SDimitry Andric #include "clang/Parse/LoopHint.h"
190b57cec5SDimitry Andric #include "clang/Parse/ParseDiagnostic.h"
200b57cec5SDimitry Andric #include "clang/Parse/Parser.h"
210b57cec5SDimitry Andric #include "clang/Parse/RAIIObjectsForParser.h"
2206c3fb27SDimitry Andric #include "clang/Sema/EnterExpressionEvaluationContext.h"
230b57cec5SDimitry Andric #include "clang/Sema/Scope.h"
24*0fca6ea1SDimitry Andric #include "clang/Sema/SemaCUDA.h"
25*0fca6ea1SDimitry Andric #include "clang/Sema/SemaCodeCompletion.h"
26*0fca6ea1SDimitry Andric #include "clang/Sema/SemaRISCV.h"
27fe6060f1SDimitry Andric #include "llvm/ADT/ArrayRef.h"
280b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
29bdd1243dSDimitry Andric #include <optional>
300b57cec5SDimitry Andric using namespace clang;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric namespace {
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric struct PragmaAlignHandler : public PragmaHandler {
350b57cec5SDimitry Andric   explicit PragmaAlignHandler() : PragmaHandler("align") {}
360b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
370b57cec5SDimitry Andric                     Token &FirstToken) override;
380b57cec5SDimitry Andric };
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric struct PragmaGCCVisibilityHandler : public PragmaHandler {
410b57cec5SDimitry Andric   explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
420b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
430b57cec5SDimitry Andric                     Token &FirstToken) override;
440b57cec5SDimitry Andric };
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric struct PragmaOptionsHandler : public PragmaHandler {
470b57cec5SDimitry Andric   explicit PragmaOptionsHandler() : PragmaHandler("options") {}
480b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
490b57cec5SDimitry Andric                     Token &FirstToken) override;
500b57cec5SDimitry Andric };
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric struct PragmaPackHandler : public PragmaHandler {
530b57cec5SDimitry Andric   explicit PragmaPackHandler() : PragmaHandler("pack") {}
540b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
550b57cec5SDimitry Andric                     Token &FirstToken) override;
560b57cec5SDimitry Andric };
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric struct PragmaClangSectionHandler : public PragmaHandler {
590b57cec5SDimitry Andric   explicit PragmaClangSectionHandler(Sema &S)
600b57cec5SDimitry Andric              : PragmaHandler("section"), Actions(S) {}
610b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
620b57cec5SDimitry Andric                     Token &FirstToken) override;
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric private:
650b57cec5SDimitry Andric   Sema &Actions;
660b57cec5SDimitry Andric };
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric struct PragmaMSStructHandler : public PragmaHandler {
690b57cec5SDimitry Andric   explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
700b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
710b57cec5SDimitry Andric                     Token &FirstToken) override;
720b57cec5SDimitry Andric };
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric struct PragmaUnusedHandler : public PragmaHandler {
750b57cec5SDimitry Andric   PragmaUnusedHandler() : PragmaHandler("unused") {}
760b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
770b57cec5SDimitry Andric                     Token &FirstToken) override;
780b57cec5SDimitry Andric };
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric struct PragmaWeakHandler : public PragmaHandler {
810b57cec5SDimitry Andric   explicit PragmaWeakHandler() : PragmaHandler("weak") {}
820b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
830b57cec5SDimitry Andric                     Token &FirstToken) override;
840b57cec5SDimitry Andric };
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric struct PragmaRedefineExtnameHandler : public PragmaHandler {
870b57cec5SDimitry Andric   explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
880b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
890b57cec5SDimitry Andric                     Token &FirstToken) override;
900b57cec5SDimitry Andric };
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric struct PragmaOpenCLExtensionHandler : public PragmaHandler {
930b57cec5SDimitry Andric   PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
940b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
950b57cec5SDimitry Andric                     Token &FirstToken) override;
960b57cec5SDimitry Andric };
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric struct PragmaFPContractHandler : public PragmaHandler {
1000b57cec5SDimitry Andric   PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
1010b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
1020b57cec5SDimitry Andric                     Token &FirstToken) override;
1030b57cec5SDimitry Andric };
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric // Pragma STDC implementations.
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric /// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
1080b57cec5SDimitry Andric struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
1090b57cec5SDimitry Andric   PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
1120b57cec5SDimitry Andric                     Token &Tok) override {
113e8d8bef9SDimitry Andric     Token PragmaName = Tok;
114e8d8bef9SDimitry Andric     if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
115e8d8bef9SDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
116e8d8bef9SDimitry Andric           << PragmaName.getIdentifierInfo()->getName();
117e8d8bef9SDimitry Andric       return;
118e8d8bef9SDimitry Andric     }
1190b57cec5SDimitry Andric     tok::OnOffSwitch OOS;
1200b57cec5SDimitry Andric     if (PP.LexOnOffSwitch(OOS))
1210b57cec5SDimitry Andric      return;
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric     MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1240b57cec5SDimitry Andric                                 1);
1250b57cec5SDimitry Andric     Toks[0].startToken();
1260b57cec5SDimitry Andric     Toks[0].setKind(tok::annot_pragma_fenv_access);
1270b57cec5SDimitry Andric     Toks[0].setLocation(Tok.getLocation());
1280b57cec5SDimitry Andric     Toks[0].setAnnotationEndLoc(Tok.getLocation());
1290b57cec5SDimitry Andric     Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1300b57cec5SDimitry Andric                                static_cast<uintptr_t>(OOS)));
1310b57cec5SDimitry Andric     PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1320b57cec5SDimitry Andric                         /*IsReinject=*/false);
1330b57cec5SDimitry Andric   }
1340b57cec5SDimitry Andric };
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric /// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
1370b57cec5SDimitry Andric struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
1380b57cec5SDimitry Andric   PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
1410b57cec5SDimitry Andric                     Token &Tok) override {
1420b57cec5SDimitry Andric     tok::OnOffSwitch OOS;
1435f757f3fSDimitry Andric     if (PP.LexOnOffSwitch(OOS))
1445f757f3fSDimitry Andric       return;
1455f757f3fSDimitry Andric 
1465f757f3fSDimitry Andric     MutableArrayRef<Token> Toks(
1475f757f3fSDimitry Andric         PP.getPreprocessorAllocator().Allocate<Token>(1), 1);
1485f757f3fSDimitry Andric 
1495f757f3fSDimitry Andric     Toks[0].startToken();
1505f757f3fSDimitry Andric     Toks[0].setKind(tok::annot_pragma_cx_limited_range);
1515f757f3fSDimitry Andric     Toks[0].setLocation(Tok.getLocation());
1525f757f3fSDimitry Andric     Toks[0].setAnnotationEndLoc(Tok.getLocation());
1535f757f3fSDimitry Andric     Toks[0].setAnnotationValue(
1545f757f3fSDimitry Andric         reinterpret_cast<void *>(static_cast<uintptr_t>(OOS)));
1555f757f3fSDimitry Andric     PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1565f757f3fSDimitry Andric                         /*IsReinject=*/false);
1570b57cec5SDimitry Andric   }
1580b57cec5SDimitry Andric };
1590b57cec5SDimitry Andric 
160e8d8bef9SDimitry Andric /// Handler for "\#pragma STDC FENV_ROUND ...".
161e8d8bef9SDimitry Andric struct PragmaSTDC_FENV_ROUNDHandler : public PragmaHandler {
162e8d8bef9SDimitry Andric   PragmaSTDC_FENV_ROUNDHandler() : PragmaHandler("FENV_ROUND") {}
163e8d8bef9SDimitry Andric 
164e8d8bef9SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
165e8d8bef9SDimitry Andric                     Token &Tok) override;
166e8d8bef9SDimitry Andric };
167e8d8bef9SDimitry Andric 
1680b57cec5SDimitry Andric /// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
1690b57cec5SDimitry Andric struct PragmaSTDC_UnknownHandler : public PragmaHandler {
1700b57cec5SDimitry Andric   PragmaSTDC_UnknownHandler() = default;
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
1730b57cec5SDimitry Andric                     Token &UnknownTok) override {
1740b57cec5SDimitry Andric     // C99 6.10.6p2, unknown forms are not allowed.
1750b57cec5SDimitry Andric     PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
1760b57cec5SDimitry Andric   }
1770b57cec5SDimitry Andric };
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric struct PragmaFPHandler : public PragmaHandler {
1800b57cec5SDimitry Andric   PragmaFPHandler() : PragmaHandler("fp") {}
1810b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
1820b57cec5SDimitry Andric                     Token &FirstToken) override;
1830b57cec5SDimitry Andric };
1840b57cec5SDimitry Andric 
1855f757f3fSDimitry Andric // A pragma handler to be the base of the NoOpenMPHandler and NoOpenACCHandler,
1865f757f3fSDimitry Andric // which are identical other than the name given to them, and the diagnostic
1875f757f3fSDimitry Andric // emitted.
1885f757f3fSDimitry Andric template <diag::kind IgnoredDiag>
1895f757f3fSDimitry Andric struct PragmaNoSupportHandler : public PragmaHandler {
1905f757f3fSDimitry Andric   PragmaNoSupportHandler(StringRef Name) : PragmaHandler(Name) {}
1910b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
1920b57cec5SDimitry Andric                     Token &FirstToken) override;
1930b57cec5SDimitry Andric };
1940b57cec5SDimitry Andric 
1955f757f3fSDimitry Andric struct PragmaNoOpenMPHandler
1965f757f3fSDimitry Andric     : public PragmaNoSupportHandler<diag::warn_pragma_omp_ignored> {
1975f757f3fSDimitry Andric   PragmaNoOpenMPHandler() : PragmaNoSupportHandler("omp") {}
1985f757f3fSDimitry Andric };
1995f757f3fSDimitry Andric 
2005f757f3fSDimitry Andric struct PragmaNoOpenACCHandler
2015f757f3fSDimitry Andric     : public PragmaNoSupportHandler<diag::warn_pragma_acc_ignored> {
2025f757f3fSDimitry Andric   PragmaNoOpenACCHandler() : PragmaNoSupportHandler("acc") {}
2035f757f3fSDimitry Andric };
2045f757f3fSDimitry Andric 
2055f757f3fSDimitry Andric // A pragma handler to be the base for the OpenMPHandler and OpenACCHandler,
2065f757f3fSDimitry Andric // which are identical other than the tokens used for the start/end of a pragma
2075f757f3fSDimitry Andric // section, and some diagnostics.
2085f757f3fSDimitry Andric template <tok::TokenKind StartTok, tok::TokenKind EndTok,
2095f757f3fSDimitry Andric           diag::kind UnexpectedDiag>
2105f757f3fSDimitry Andric struct PragmaSupportHandler : public PragmaHandler {
2115f757f3fSDimitry Andric   PragmaSupportHandler(StringRef Name) : PragmaHandler(Name) {}
2120b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
2130b57cec5SDimitry Andric                     Token &FirstToken) override;
2140b57cec5SDimitry Andric };
2150b57cec5SDimitry Andric 
2165f757f3fSDimitry Andric struct PragmaOpenMPHandler
2175f757f3fSDimitry Andric     : public PragmaSupportHandler<tok::annot_pragma_openmp,
2185f757f3fSDimitry Andric                                   tok::annot_pragma_openmp_end,
2195f757f3fSDimitry Andric                                   diag::err_omp_unexpected_directive> {
2205f757f3fSDimitry Andric   PragmaOpenMPHandler() : PragmaSupportHandler("omp") {}
2215f757f3fSDimitry Andric };
2225f757f3fSDimitry Andric 
2235f757f3fSDimitry Andric struct PragmaOpenACCHandler
2245f757f3fSDimitry Andric     : public PragmaSupportHandler<tok::annot_pragma_openacc,
2255f757f3fSDimitry Andric                                   tok::annot_pragma_openacc_end,
2265f757f3fSDimitry Andric                                   diag::err_acc_unexpected_directive> {
2275f757f3fSDimitry Andric   PragmaOpenACCHandler() : PragmaSupportHandler("acc") {}
2285f757f3fSDimitry Andric };
2295f757f3fSDimitry Andric 
2300b57cec5SDimitry Andric /// PragmaCommentHandler - "\#pragma comment ...".
2310b57cec5SDimitry Andric struct PragmaCommentHandler : public PragmaHandler {
2320b57cec5SDimitry Andric   PragmaCommentHandler(Sema &Actions)
2330b57cec5SDimitry Andric     : PragmaHandler("comment"), Actions(Actions) {}
2340b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
2350b57cec5SDimitry Andric                     Token &FirstToken) override;
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric private:
2380b57cec5SDimitry Andric   Sema &Actions;
2390b57cec5SDimitry Andric };
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric struct PragmaDetectMismatchHandler : public PragmaHandler {
2420b57cec5SDimitry Andric   PragmaDetectMismatchHandler(Sema &Actions)
2430b57cec5SDimitry Andric     : PragmaHandler("detect_mismatch"), Actions(Actions) {}
2440b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
2450b57cec5SDimitry Andric                     Token &FirstToken) override;
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric private:
2480b57cec5SDimitry Andric   Sema &Actions;
2490b57cec5SDimitry Andric };
2500b57cec5SDimitry Andric 
2515ffd83dbSDimitry Andric struct PragmaFloatControlHandler : public PragmaHandler {
2525ffd83dbSDimitry Andric   PragmaFloatControlHandler(Sema &Actions)
2535ffd83dbSDimitry Andric       : PragmaHandler("float_control") {}
2545ffd83dbSDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
2555ffd83dbSDimitry Andric                     Token &FirstToken) override;
2565ffd83dbSDimitry Andric };
2575ffd83dbSDimitry Andric 
2580b57cec5SDimitry Andric struct PragmaMSPointersToMembers : public PragmaHandler {
2590b57cec5SDimitry Andric   explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
2600b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
2610b57cec5SDimitry Andric                     Token &FirstToken) override;
2620b57cec5SDimitry Andric };
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric struct PragmaMSVtorDisp : public PragmaHandler {
2650b57cec5SDimitry Andric   explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
2660b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
2670b57cec5SDimitry Andric                     Token &FirstToken) override;
2680b57cec5SDimitry Andric };
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric struct PragmaMSPragma : public PragmaHandler {
2710b57cec5SDimitry Andric   explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
2720b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
2730b57cec5SDimitry Andric                     Token &FirstToken) override;
2740b57cec5SDimitry Andric };
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric /// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
2770b57cec5SDimitry Andric struct PragmaOptimizeHandler : public PragmaHandler {
2780b57cec5SDimitry Andric   PragmaOptimizeHandler(Sema &S)
2790b57cec5SDimitry Andric     : PragmaHandler("optimize"), Actions(S) {}
2800b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
2810b57cec5SDimitry Andric                     Token &FirstToken) override;
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric private:
2840b57cec5SDimitry Andric   Sema &Actions;
2850b57cec5SDimitry Andric };
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric struct PragmaLoopHintHandler : public PragmaHandler {
2880b57cec5SDimitry Andric   PragmaLoopHintHandler() : PragmaHandler("loop") {}
2890b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
2900b57cec5SDimitry Andric                     Token &FirstToken) override;
2910b57cec5SDimitry Andric };
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric struct PragmaUnrollHintHandler : public PragmaHandler {
2940b57cec5SDimitry Andric   PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
2950b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
2960b57cec5SDimitry Andric                     Token &FirstToken) override;
2970b57cec5SDimitry Andric };
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
3000b57cec5SDimitry Andric   PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
3010b57cec5SDimitry Andric };
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric struct PragmaMSIntrinsicHandler : public PragmaHandler {
3040b57cec5SDimitry Andric   PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
3050b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
3060b57cec5SDimitry Andric                     Token &FirstToken) override;
3070b57cec5SDimitry Andric };
3080b57cec5SDimitry Andric 
309349cc55cSDimitry Andric // "\#pragma fenv_access (on)".
310349cc55cSDimitry Andric struct PragmaMSFenvAccessHandler : public PragmaHandler {
311349cc55cSDimitry Andric   PragmaMSFenvAccessHandler() : PragmaHandler("fenv_access") {}
312349cc55cSDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
313349cc55cSDimitry Andric                     Token &FirstToken) override {
314349cc55cSDimitry Andric     StringRef PragmaName = FirstToken.getIdentifierInfo()->getName();
315349cc55cSDimitry Andric     if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
316349cc55cSDimitry Andric       PP.Diag(FirstToken.getLocation(), diag::warn_pragma_fp_ignored)
317349cc55cSDimitry Andric           << PragmaName;
318349cc55cSDimitry Andric       return;
319349cc55cSDimitry Andric     }
320349cc55cSDimitry Andric 
321349cc55cSDimitry Andric     Token Tok;
322349cc55cSDimitry Andric     PP.Lex(Tok);
323349cc55cSDimitry Andric     if (Tok.isNot(tok::l_paren)) {
324349cc55cSDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
325349cc55cSDimitry Andric           << PragmaName;
326349cc55cSDimitry Andric       return;
327349cc55cSDimitry Andric     }
328349cc55cSDimitry Andric     PP.Lex(Tok); // Consume the l_paren.
329349cc55cSDimitry Andric     if (Tok.isNot(tok::identifier)) {
330349cc55cSDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
331349cc55cSDimitry Andric       return;
332349cc55cSDimitry Andric     }
333349cc55cSDimitry Andric     const IdentifierInfo *II = Tok.getIdentifierInfo();
334349cc55cSDimitry Andric     tok::OnOffSwitch OOS;
335349cc55cSDimitry Andric     if (II->isStr("on")) {
336349cc55cSDimitry Andric       OOS = tok::OOS_ON;
337349cc55cSDimitry Andric       PP.Lex(Tok);
338349cc55cSDimitry Andric     } else if (II->isStr("off")) {
339349cc55cSDimitry Andric       OOS = tok::OOS_OFF;
340349cc55cSDimitry Andric       PP.Lex(Tok);
341349cc55cSDimitry Andric     } else {
342349cc55cSDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
343349cc55cSDimitry Andric       return;
344349cc55cSDimitry Andric     }
345349cc55cSDimitry Andric     if (Tok.isNot(tok::r_paren)) {
346349cc55cSDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
347349cc55cSDimitry Andric           << PragmaName;
348349cc55cSDimitry Andric       return;
349349cc55cSDimitry Andric     }
350349cc55cSDimitry Andric     PP.Lex(Tok); // Consume the r_paren.
351349cc55cSDimitry Andric 
352349cc55cSDimitry Andric     if (Tok.isNot(tok::eod)) {
353349cc55cSDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
354349cc55cSDimitry Andric           << PragmaName;
355349cc55cSDimitry Andric       return;
356349cc55cSDimitry Andric     }
357349cc55cSDimitry Andric 
358349cc55cSDimitry Andric     MutableArrayRef<Token> Toks(
359349cc55cSDimitry Andric         PP.getPreprocessorAllocator().Allocate<Token>(1), 1);
360349cc55cSDimitry Andric     Toks[0].startToken();
361349cc55cSDimitry Andric     Toks[0].setKind(tok::annot_pragma_fenv_access_ms);
362349cc55cSDimitry Andric     Toks[0].setLocation(FirstToken.getLocation());
363349cc55cSDimitry Andric     Toks[0].setAnnotationEndLoc(Tok.getLocation());
364349cc55cSDimitry Andric     Toks[0].setAnnotationValue(
365349cc55cSDimitry Andric         reinterpret_cast<void*>(static_cast<uintptr_t>(OOS)));
366349cc55cSDimitry Andric     PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
367349cc55cSDimitry Andric                         /*IsReinject=*/false);
368349cc55cSDimitry Andric   }
369349cc55cSDimitry Andric };
370349cc55cSDimitry Andric 
3710b57cec5SDimitry Andric struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
3720b57cec5SDimitry Andric   PragmaForceCUDAHostDeviceHandler(Sema &Actions)
3730b57cec5SDimitry Andric       : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
3740b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
3750b57cec5SDimitry Andric                     Token &FirstToken) override;
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric private:
3780b57cec5SDimitry Andric   Sema &Actions;
3790b57cec5SDimitry Andric };
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric /// PragmaAttributeHandler - "\#pragma clang attribute ...".
3820b57cec5SDimitry Andric struct PragmaAttributeHandler : public PragmaHandler {
3830b57cec5SDimitry Andric   PragmaAttributeHandler(AttributeFactory &AttrFactory)
3840b57cec5SDimitry Andric       : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
3850b57cec5SDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
3860b57cec5SDimitry Andric                     Token &FirstToken) override;
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric   /// A pool of attributes that were parsed in \#pragma clang attribute.
3890b57cec5SDimitry Andric   ParsedAttributes AttributesForPragmaAttribute;
3900b57cec5SDimitry Andric };
3910b57cec5SDimitry Andric 
3925ffd83dbSDimitry Andric struct PragmaMaxTokensHereHandler : public PragmaHandler {
3935ffd83dbSDimitry Andric   PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {}
3945ffd83dbSDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
3955ffd83dbSDimitry Andric                     Token &FirstToken) override;
3965ffd83dbSDimitry Andric };
3975ffd83dbSDimitry Andric 
3985ffd83dbSDimitry Andric struct PragmaMaxTokensTotalHandler : public PragmaHandler {
3995ffd83dbSDimitry Andric   PragmaMaxTokensTotalHandler() : PragmaHandler("max_tokens_total") {}
4005ffd83dbSDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
4015ffd83dbSDimitry Andric                     Token &FirstToken) override;
4025ffd83dbSDimitry Andric };
4035ffd83dbSDimitry Andric 
404972a253aSDimitry Andric struct PragmaRISCVHandler : public PragmaHandler {
405972a253aSDimitry Andric   PragmaRISCVHandler(Sema &Actions)
406972a253aSDimitry Andric       : PragmaHandler("riscv"), Actions(Actions) {}
407972a253aSDimitry Andric   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
408972a253aSDimitry Andric                     Token &FirstToken) override;
409972a253aSDimitry Andric 
410972a253aSDimitry Andric private:
411972a253aSDimitry Andric   Sema &Actions;
412972a253aSDimitry Andric };
413972a253aSDimitry Andric 
414fe6060f1SDimitry Andric void markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks) {
415fe6060f1SDimitry Andric   for (auto &T : Toks)
416fe6060f1SDimitry Andric     T.setFlag(clang::Token::IsReinjected);
417fe6060f1SDimitry Andric }
4180b57cec5SDimitry Andric }  // end namespace
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric void Parser::initializePragmaHandlers() {
421a7dea167SDimitry Andric   AlignHandler = std::make_unique<PragmaAlignHandler>();
4220b57cec5SDimitry Andric   PP.AddPragmaHandler(AlignHandler.get());
4230b57cec5SDimitry Andric 
424a7dea167SDimitry Andric   GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>();
4250b57cec5SDimitry Andric   PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
4260b57cec5SDimitry Andric 
427a7dea167SDimitry Andric   OptionsHandler = std::make_unique<PragmaOptionsHandler>();
4280b57cec5SDimitry Andric   PP.AddPragmaHandler(OptionsHandler.get());
4290b57cec5SDimitry Andric 
430a7dea167SDimitry Andric   PackHandler = std::make_unique<PragmaPackHandler>();
4310b57cec5SDimitry Andric   PP.AddPragmaHandler(PackHandler.get());
4320b57cec5SDimitry Andric 
433a7dea167SDimitry Andric   MSStructHandler = std::make_unique<PragmaMSStructHandler>();
4340b57cec5SDimitry Andric   PP.AddPragmaHandler(MSStructHandler.get());
4350b57cec5SDimitry Andric 
436a7dea167SDimitry Andric   UnusedHandler = std::make_unique<PragmaUnusedHandler>();
4370b57cec5SDimitry Andric   PP.AddPragmaHandler(UnusedHandler.get());
4380b57cec5SDimitry Andric 
439a7dea167SDimitry Andric   WeakHandler = std::make_unique<PragmaWeakHandler>();
4400b57cec5SDimitry Andric   PP.AddPragmaHandler(WeakHandler.get());
4410b57cec5SDimitry Andric 
442a7dea167SDimitry Andric   RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>();
4430b57cec5SDimitry Andric   PP.AddPragmaHandler(RedefineExtnameHandler.get());
4440b57cec5SDimitry Andric 
445a7dea167SDimitry Andric   FPContractHandler = std::make_unique<PragmaFPContractHandler>();
4460b57cec5SDimitry Andric   PP.AddPragmaHandler("STDC", FPContractHandler.get());
4470b57cec5SDimitry Andric 
448e8d8bef9SDimitry Andric   STDCFenvAccessHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
449e8d8bef9SDimitry Andric   PP.AddPragmaHandler("STDC", STDCFenvAccessHandler.get());
450e8d8bef9SDimitry Andric 
451e8d8bef9SDimitry Andric   STDCFenvRoundHandler = std::make_unique<PragmaSTDC_FENV_ROUNDHandler>();
452e8d8bef9SDimitry Andric   PP.AddPragmaHandler("STDC", STDCFenvRoundHandler.get());
4530b57cec5SDimitry Andric 
454a7dea167SDimitry Andric   STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
4550b57cec5SDimitry Andric   PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
4560b57cec5SDimitry Andric 
457a7dea167SDimitry Andric   STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>();
4580b57cec5SDimitry Andric   PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
4590b57cec5SDimitry Andric 
460a7dea167SDimitry Andric   PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions);
4610b57cec5SDimitry Andric   PP.AddPragmaHandler("clang", PCSectionHandler.get());
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric   if (getLangOpts().OpenCL) {
464a7dea167SDimitry Andric     OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>();
4650b57cec5SDimitry Andric     PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric     PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
4680b57cec5SDimitry Andric   }
4690b57cec5SDimitry Andric   if (getLangOpts().OpenMP)
470a7dea167SDimitry Andric     OpenMPHandler = std::make_unique<PragmaOpenMPHandler>();
4710b57cec5SDimitry Andric   else
472a7dea167SDimitry Andric     OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>();
4730b57cec5SDimitry Andric   PP.AddPragmaHandler(OpenMPHandler.get());
4740b57cec5SDimitry Andric 
4755f757f3fSDimitry Andric   if (getLangOpts().OpenACC)
4765f757f3fSDimitry Andric     OpenACCHandler = std::make_unique<PragmaOpenACCHandler>();
4775f757f3fSDimitry Andric   else
4785f757f3fSDimitry Andric     OpenACCHandler = std::make_unique<PragmaNoOpenACCHandler>();
4795f757f3fSDimitry Andric   PP.AddPragmaHandler(OpenACCHandler.get());
4805f757f3fSDimitry Andric 
4810b57cec5SDimitry Andric   if (getLangOpts().MicrosoftExt ||
4820b57cec5SDimitry Andric       getTargetInfo().getTriple().isOSBinFormatELF()) {
483a7dea167SDimitry Andric     MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions);
4840b57cec5SDimitry Andric     PP.AddPragmaHandler(MSCommentHandler.get());
4850b57cec5SDimitry Andric   }
4860b57cec5SDimitry Andric 
4875ffd83dbSDimitry Andric   FloatControlHandler = std::make_unique<PragmaFloatControlHandler>(Actions);
4885ffd83dbSDimitry Andric   PP.AddPragmaHandler(FloatControlHandler.get());
4890b57cec5SDimitry Andric   if (getLangOpts().MicrosoftExt) {
4900b57cec5SDimitry Andric     MSDetectMismatchHandler =
491a7dea167SDimitry Andric         std::make_unique<PragmaDetectMismatchHandler>(Actions);
4920b57cec5SDimitry Andric     PP.AddPragmaHandler(MSDetectMismatchHandler.get());
493a7dea167SDimitry Andric     MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>();
4940b57cec5SDimitry Andric     PP.AddPragmaHandler(MSPointersToMembers.get());
495a7dea167SDimitry Andric     MSVtorDisp = std::make_unique<PragmaMSVtorDisp>();
4960b57cec5SDimitry Andric     PP.AddPragmaHandler(MSVtorDisp.get());
497a7dea167SDimitry Andric     MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg");
4980b57cec5SDimitry Andric     PP.AddPragmaHandler(MSInitSeg.get());
499a7dea167SDimitry Andric     MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg");
5000b57cec5SDimitry Andric     PP.AddPragmaHandler(MSDataSeg.get());
501a7dea167SDimitry Andric     MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg");
5020b57cec5SDimitry Andric     PP.AddPragmaHandler(MSBSSSeg.get());
503a7dea167SDimitry Andric     MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg");
5040b57cec5SDimitry Andric     PP.AddPragmaHandler(MSConstSeg.get());
505a7dea167SDimitry Andric     MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg");
5060b57cec5SDimitry Andric     PP.AddPragmaHandler(MSCodeSeg.get());
507a7dea167SDimitry Andric     MSSection = std::make_unique<PragmaMSPragma>("section");
5080b57cec5SDimitry Andric     PP.AddPragmaHandler(MSSection.get());
509bdd1243dSDimitry Andric     MSStrictGuardStackCheck =
510bdd1243dSDimitry Andric         std::make_unique<PragmaMSPragma>("strict_gs_check");
511bdd1243dSDimitry Andric     PP.AddPragmaHandler(MSStrictGuardStackCheck.get());
51281ad6265SDimitry Andric     MSFunction = std::make_unique<PragmaMSPragma>("function");
51381ad6265SDimitry Andric     PP.AddPragmaHandler(MSFunction.get());
51481ad6265SDimitry Andric     MSAllocText = std::make_unique<PragmaMSPragma>("alloc_text");
51581ad6265SDimitry Andric     PP.AddPragmaHandler(MSAllocText.get());
51681ad6265SDimitry Andric     MSOptimize = std::make_unique<PragmaMSPragma>("optimize");
51781ad6265SDimitry Andric     PP.AddPragmaHandler(MSOptimize.get());
518a7dea167SDimitry Andric     MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>();
5190b57cec5SDimitry Andric     PP.AddPragmaHandler(MSRuntimeChecks.get());
520a7dea167SDimitry Andric     MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>();
5210b57cec5SDimitry Andric     PP.AddPragmaHandler(MSIntrinsic.get());
522349cc55cSDimitry Andric     MSFenvAccess = std::make_unique<PragmaMSFenvAccessHandler>();
523349cc55cSDimitry Andric     PP.AddPragmaHandler(MSFenvAccess.get());
5240b57cec5SDimitry Andric   }
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric   if (getLangOpts().CUDA) {
5270b57cec5SDimitry Andric     CUDAForceHostDeviceHandler =
528a7dea167SDimitry Andric         std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
5290b57cec5SDimitry Andric     PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
5300b57cec5SDimitry Andric   }
5310b57cec5SDimitry Andric 
532a7dea167SDimitry Andric   OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions);
5330b57cec5SDimitry Andric   PP.AddPragmaHandler("clang", OptimizeHandler.get());
5340b57cec5SDimitry Andric 
535a7dea167SDimitry Andric   LoopHintHandler = std::make_unique<PragmaLoopHintHandler>();
5360b57cec5SDimitry Andric   PP.AddPragmaHandler("clang", LoopHintHandler.get());
5370b57cec5SDimitry Andric 
538a7dea167SDimitry Andric   UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll");
5390b57cec5SDimitry Andric   PP.AddPragmaHandler(UnrollHintHandler.get());
540fe6060f1SDimitry Andric   PP.AddPragmaHandler("GCC", UnrollHintHandler.get());
5410b57cec5SDimitry Andric 
542a7dea167SDimitry Andric   NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll");
5430b57cec5SDimitry Andric   PP.AddPragmaHandler(NoUnrollHintHandler.get());
544fe6060f1SDimitry Andric   PP.AddPragmaHandler("GCC", NoUnrollHintHandler.get());
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric   UnrollAndJamHintHandler =
547a7dea167SDimitry Andric       std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
5480b57cec5SDimitry Andric   PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric   NoUnrollAndJamHintHandler =
551a7dea167SDimitry Andric       std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
5520b57cec5SDimitry Andric   PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
5530b57cec5SDimitry Andric 
554a7dea167SDimitry Andric   FPHandler = std::make_unique<PragmaFPHandler>();
5550b57cec5SDimitry Andric   PP.AddPragmaHandler("clang", FPHandler.get());
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric   AttributePragmaHandler =
558a7dea167SDimitry Andric       std::make_unique<PragmaAttributeHandler>(AttrFactory);
5590b57cec5SDimitry Andric   PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
5605ffd83dbSDimitry Andric 
5615ffd83dbSDimitry Andric   MaxTokensHerePragmaHandler = std::make_unique<PragmaMaxTokensHereHandler>();
5625ffd83dbSDimitry Andric   PP.AddPragmaHandler("clang", MaxTokensHerePragmaHandler.get());
5635ffd83dbSDimitry Andric 
5645ffd83dbSDimitry Andric   MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>();
5655ffd83dbSDimitry Andric   PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
566972a253aSDimitry Andric 
567972a253aSDimitry Andric   if (getTargetInfo().getTriple().isRISCV()) {
568972a253aSDimitry Andric     RISCVPragmaHandler = std::make_unique<PragmaRISCVHandler>(Actions);
569972a253aSDimitry Andric     PP.AddPragmaHandler("clang", RISCVPragmaHandler.get());
570972a253aSDimitry Andric   }
5710b57cec5SDimitry Andric }
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric void Parser::resetPragmaHandlers() {
5740b57cec5SDimitry Andric   // Remove the pragma handlers we installed.
5750b57cec5SDimitry Andric   PP.RemovePragmaHandler(AlignHandler.get());
5760b57cec5SDimitry Andric   AlignHandler.reset();
5770b57cec5SDimitry Andric   PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
5780b57cec5SDimitry Andric   GCCVisibilityHandler.reset();
5790b57cec5SDimitry Andric   PP.RemovePragmaHandler(OptionsHandler.get());
5800b57cec5SDimitry Andric   OptionsHandler.reset();
5810b57cec5SDimitry Andric   PP.RemovePragmaHandler(PackHandler.get());
5820b57cec5SDimitry Andric   PackHandler.reset();
5830b57cec5SDimitry Andric   PP.RemovePragmaHandler(MSStructHandler.get());
5840b57cec5SDimitry Andric   MSStructHandler.reset();
5850b57cec5SDimitry Andric   PP.RemovePragmaHandler(UnusedHandler.get());
5860b57cec5SDimitry Andric   UnusedHandler.reset();
5870b57cec5SDimitry Andric   PP.RemovePragmaHandler(WeakHandler.get());
5880b57cec5SDimitry Andric   WeakHandler.reset();
5890b57cec5SDimitry Andric   PP.RemovePragmaHandler(RedefineExtnameHandler.get());
5900b57cec5SDimitry Andric   RedefineExtnameHandler.reset();
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric   if (getLangOpts().OpenCL) {
5930b57cec5SDimitry Andric     PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
5940b57cec5SDimitry Andric     OpenCLExtensionHandler.reset();
5950b57cec5SDimitry Andric     PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
5960b57cec5SDimitry Andric   }
5970b57cec5SDimitry Andric   PP.RemovePragmaHandler(OpenMPHandler.get());
5980b57cec5SDimitry Andric   OpenMPHandler.reset();
5990b57cec5SDimitry Andric 
6005f757f3fSDimitry Andric   PP.RemovePragmaHandler(OpenACCHandler.get());
6015f757f3fSDimitry Andric   OpenACCHandler.reset();
6025f757f3fSDimitry Andric 
6030b57cec5SDimitry Andric   if (getLangOpts().MicrosoftExt ||
6040b57cec5SDimitry Andric       getTargetInfo().getTriple().isOSBinFormatELF()) {
6050b57cec5SDimitry Andric     PP.RemovePragmaHandler(MSCommentHandler.get());
6060b57cec5SDimitry Andric     MSCommentHandler.reset();
6070b57cec5SDimitry Andric   }
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric   PP.RemovePragmaHandler("clang", PCSectionHandler.get());
6100b57cec5SDimitry Andric   PCSectionHandler.reset();
6110b57cec5SDimitry Andric 
6125ffd83dbSDimitry Andric   PP.RemovePragmaHandler(FloatControlHandler.get());
6135ffd83dbSDimitry Andric   FloatControlHandler.reset();
6140b57cec5SDimitry Andric   if (getLangOpts().MicrosoftExt) {
6150b57cec5SDimitry Andric     PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
6160b57cec5SDimitry Andric     MSDetectMismatchHandler.reset();
6170b57cec5SDimitry Andric     PP.RemovePragmaHandler(MSPointersToMembers.get());
6180b57cec5SDimitry Andric     MSPointersToMembers.reset();
6190b57cec5SDimitry Andric     PP.RemovePragmaHandler(MSVtorDisp.get());
6200b57cec5SDimitry Andric     MSVtorDisp.reset();
6210b57cec5SDimitry Andric     PP.RemovePragmaHandler(MSInitSeg.get());
6220b57cec5SDimitry Andric     MSInitSeg.reset();
6230b57cec5SDimitry Andric     PP.RemovePragmaHandler(MSDataSeg.get());
6240b57cec5SDimitry Andric     MSDataSeg.reset();
6250b57cec5SDimitry Andric     PP.RemovePragmaHandler(MSBSSSeg.get());
6260b57cec5SDimitry Andric     MSBSSSeg.reset();
6270b57cec5SDimitry Andric     PP.RemovePragmaHandler(MSConstSeg.get());
6280b57cec5SDimitry Andric     MSConstSeg.reset();
6290b57cec5SDimitry Andric     PP.RemovePragmaHandler(MSCodeSeg.get());
6300b57cec5SDimitry Andric     MSCodeSeg.reset();
6310b57cec5SDimitry Andric     PP.RemovePragmaHandler(MSSection.get());
6320b57cec5SDimitry Andric     MSSection.reset();
633bdd1243dSDimitry Andric     PP.RemovePragmaHandler(MSStrictGuardStackCheck.get());
634bdd1243dSDimitry Andric     MSStrictGuardStackCheck.reset();
63581ad6265SDimitry Andric     PP.RemovePragmaHandler(MSFunction.get());
63681ad6265SDimitry Andric     MSFunction.reset();
63781ad6265SDimitry Andric     PP.RemovePragmaHandler(MSAllocText.get());
63881ad6265SDimitry Andric     MSAllocText.reset();
6390b57cec5SDimitry Andric     PP.RemovePragmaHandler(MSRuntimeChecks.get());
6400b57cec5SDimitry Andric     MSRuntimeChecks.reset();
6410b57cec5SDimitry Andric     PP.RemovePragmaHandler(MSIntrinsic.get());
6420b57cec5SDimitry Andric     MSIntrinsic.reset();
6430b57cec5SDimitry Andric     PP.RemovePragmaHandler(MSOptimize.get());
6440b57cec5SDimitry Andric     MSOptimize.reset();
645349cc55cSDimitry Andric     PP.RemovePragmaHandler(MSFenvAccess.get());
646349cc55cSDimitry Andric     MSFenvAccess.reset();
6470b57cec5SDimitry Andric   }
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric   if (getLangOpts().CUDA) {
6500b57cec5SDimitry Andric     PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
6510b57cec5SDimitry Andric     CUDAForceHostDeviceHandler.reset();
6520b57cec5SDimitry Andric   }
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric   PP.RemovePragmaHandler("STDC", FPContractHandler.get());
6550b57cec5SDimitry Andric   FPContractHandler.reset();
6560b57cec5SDimitry Andric 
657e8d8bef9SDimitry Andric   PP.RemovePragmaHandler("STDC", STDCFenvAccessHandler.get());
658e8d8bef9SDimitry Andric   STDCFenvAccessHandler.reset();
659e8d8bef9SDimitry Andric 
660e8d8bef9SDimitry Andric   PP.RemovePragmaHandler("STDC", STDCFenvRoundHandler.get());
661e8d8bef9SDimitry Andric   STDCFenvRoundHandler.reset();
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric   PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
6640b57cec5SDimitry Andric   STDCCXLIMITHandler.reset();
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric   PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
6670b57cec5SDimitry Andric   STDCUnknownHandler.reset();
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric   PP.RemovePragmaHandler("clang", OptimizeHandler.get());
6700b57cec5SDimitry Andric   OptimizeHandler.reset();
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric   PP.RemovePragmaHandler("clang", LoopHintHandler.get());
6730b57cec5SDimitry Andric   LoopHintHandler.reset();
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric   PP.RemovePragmaHandler(UnrollHintHandler.get());
676fe6060f1SDimitry Andric   PP.RemovePragmaHandler("GCC", UnrollHintHandler.get());
6770b57cec5SDimitry Andric   UnrollHintHandler.reset();
6780b57cec5SDimitry Andric 
6790b57cec5SDimitry Andric   PP.RemovePragmaHandler(NoUnrollHintHandler.get());
680fe6060f1SDimitry Andric   PP.RemovePragmaHandler("GCC", NoUnrollHintHandler.get());
6810b57cec5SDimitry Andric   NoUnrollHintHandler.reset();
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric   PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
6840b57cec5SDimitry Andric   UnrollAndJamHintHandler.reset();
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric   PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
6870b57cec5SDimitry Andric   NoUnrollAndJamHintHandler.reset();
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric   PP.RemovePragmaHandler("clang", FPHandler.get());
6900b57cec5SDimitry Andric   FPHandler.reset();
6910b57cec5SDimitry Andric 
6920b57cec5SDimitry Andric   PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
6930b57cec5SDimitry Andric   AttributePragmaHandler.reset();
6945ffd83dbSDimitry Andric 
6955ffd83dbSDimitry Andric   PP.RemovePragmaHandler("clang", MaxTokensHerePragmaHandler.get());
6965ffd83dbSDimitry Andric   MaxTokensHerePragmaHandler.reset();
6975ffd83dbSDimitry Andric 
6985ffd83dbSDimitry Andric   PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
6995ffd83dbSDimitry Andric   MaxTokensTotalPragmaHandler.reset();
700972a253aSDimitry Andric 
701972a253aSDimitry Andric   if (getTargetInfo().getTriple().isRISCV()) {
702972a253aSDimitry Andric     PP.RemovePragmaHandler("clang", RISCVPragmaHandler.get());
703972a253aSDimitry Andric     RISCVPragmaHandler.reset();
704972a253aSDimitry Andric   }
7050b57cec5SDimitry Andric }
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric /// Handle the annotation token produced for #pragma unused(...)
7080b57cec5SDimitry Andric ///
7090b57cec5SDimitry Andric /// Each annot_pragma_unused is followed by the argument token so e.g.
7100b57cec5SDimitry Andric /// "#pragma unused(x,y)" becomes:
7110b57cec5SDimitry Andric /// annot_pragma_unused 'x' annot_pragma_unused 'y'
7120b57cec5SDimitry Andric void Parser::HandlePragmaUnused() {
7130b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_unused));
7140b57cec5SDimitry Andric   SourceLocation UnusedLoc = ConsumeAnnotationToken();
7150b57cec5SDimitry Andric   Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
7160b57cec5SDimitry Andric   ConsumeToken(); // The argument token.
7170b57cec5SDimitry Andric }
7180b57cec5SDimitry Andric 
7190b57cec5SDimitry Andric void Parser::HandlePragmaVisibility() {
7200b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_vis));
7210b57cec5SDimitry Andric   const IdentifierInfo *VisType =
7220b57cec5SDimitry Andric     static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
7230b57cec5SDimitry Andric   SourceLocation VisLoc = ConsumeAnnotationToken();
7240b57cec5SDimitry Andric   Actions.ActOnPragmaVisibility(VisType, VisLoc);
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric void Parser::HandlePragmaPack() {
7280b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_pack));
72906c3fb27SDimitry Andric   Sema::PragmaPackInfo *Info =
73006c3fb27SDimitry Andric       static_cast<Sema::PragmaPackInfo *>(Tok.getAnnotationValue());
7310b57cec5SDimitry Andric   SourceLocation PragmaLoc = Tok.getLocation();
7320b57cec5SDimitry Andric   ExprResult Alignment;
7330b57cec5SDimitry Andric   if (Info->Alignment.is(tok::numeric_constant)) {
7340b57cec5SDimitry Andric     Alignment = Actions.ActOnNumericConstant(Info->Alignment);
7350b57cec5SDimitry Andric     if (Alignment.isInvalid()) {
7360b57cec5SDimitry Andric       ConsumeAnnotationToken();
7370b57cec5SDimitry Andric       return;
7380b57cec5SDimitry Andric     }
7390b57cec5SDimitry Andric   }
7400b57cec5SDimitry Andric   Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
7410b57cec5SDimitry Andric                           Alignment.get());
7420b57cec5SDimitry Andric   // Consume the token after processing the pragma to enable pragma-specific
7430b57cec5SDimitry Andric   // #include warnings.
7440b57cec5SDimitry Andric   ConsumeAnnotationToken();
7450b57cec5SDimitry Andric }
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric void Parser::HandlePragmaMSStruct() {
7480b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_msstruct));
7490b57cec5SDimitry Andric   PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
7500b57cec5SDimitry Andric       reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
7510b57cec5SDimitry Andric   Actions.ActOnPragmaMSStruct(Kind);
7520b57cec5SDimitry Andric   ConsumeAnnotationToken();
7530b57cec5SDimitry Andric }
7540b57cec5SDimitry Andric 
7550b57cec5SDimitry Andric void Parser::HandlePragmaAlign() {
7560b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_align));
7570b57cec5SDimitry Andric   Sema::PragmaOptionsAlignKind Kind =
7580b57cec5SDimitry Andric     static_cast<Sema::PragmaOptionsAlignKind>(
7590b57cec5SDimitry Andric     reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
7600b57cec5SDimitry Andric   Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
7610b57cec5SDimitry Andric   // Consume the token after processing the pragma to enable pragma-specific
7620b57cec5SDimitry Andric   // #include warnings.
7630b57cec5SDimitry Andric   ConsumeAnnotationToken();
7640b57cec5SDimitry Andric }
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric void Parser::HandlePragmaDump() {
7670b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_dump));
7680b57cec5SDimitry Andric   ConsumeAnnotationToken();
76906c3fb27SDimitry Andric   if (Tok.is(tok::eod)) {
77006c3fb27SDimitry Andric     PP.Diag(Tok, diag::warn_pragma_debug_missing_argument) << "dump";
77106c3fb27SDimitry Andric   } else if (NextToken().is(tok::eod)) {
77206c3fb27SDimitry Andric     if (Tok.isNot(tok::identifier)) {
77306c3fb27SDimitry Andric       PP.Diag(Tok, diag::warn_pragma_debug_unexpected_argument);
77406c3fb27SDimitry Andric       ConsumeAnyToken();
77506c3fb27SDimitry Andric       ExpectAndConsume(tok::eod);
77606c3fb27SDimitry Andric       return;
77706c3fb27SDimitry Andric     }
77806c3fb27SDimitry Andric     IdentifierInfo *II = Tok.getIdentifierInfo();
77906c3fb27SDimitry Andric     Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
78006c3fb27SDimitry Andric     ConsumeToken();
78106c3fb27SDimitry Andric   } else {
78206c3fb27SDimitry Andric     SourceLocation StartLoc = Tok.getLocation();
78306c3fb27SDimitry Andric     EnterExpressionEvaluationContext Ctx(
78406c3fb27SDimitry Andric       Actions, Sema::ExpressionEvaluationContext::Unevaluated);
78506c3fb27SDimitry Andric     ExprResult E = ParseExpression();
78606c3fb27SDimitry Andric     if (!E.isUsable() || E.get()->containsErrors()) {
78706c3fb27SDimitry Andric       // Diagnostics were emitted during parsing. No action needed.
78806c3fb27SDimitry Andric     } else if (E.get()->getDependence() != ExprDependence::None) {
78906c3fb27SDimitry Andric       PP.Diag(StartLoc, diag::warn_pragma_debug_dependent_argument)
79006c3fb27SDimitry Andric         << E.get()->isTypeDependent()
79106c3fb27SDimitry Andric         << SourceRange(StartLoc, Tok.getLocation());
79206c3fb27SDimitry Andric     } else {
79306c3fb27SDimitry Andric       Actions.ActOnPragmaDump(E.get());
79406c3fb27SDimitry Andric     }
79506c3fb27SDimitry Andric     SkipUntil(tok::eod, StopBeforeMatch);
79606c3fb27SDimitry Andric   }
79706c3fb27SDimitry Andric   ExpectAndConsume(tok::eod);
7980b57cec5SDimitry Andric }
7990b57cec5SDimitry Andric 
8000b57cec5SDimitry Andric void Parser::HandlePragmaWeak() {
8010b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_weak));
8020b57cec5SDimitry Andric   SourceLocation PragmaLoc = ConsumeAnnotationToken();
8030b57cec5SDimitry Andric   Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
8040b57cec5SDimitry Andric                             Tok.getLocation());
8050b57cec5SDimitry Andric   ConsumeToken(); // The weak name.
8060b57cec5SDimitry Andric }
8070b57cec5SDimitry Andric 
8080b57cec5SDimitry Andric void Parser::HandlePragmaWeakAlias() {
8090b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_weakalias));
8100b57cec5SDimitry Andric   SourceLocation PragmaLoc = ConsumeAnnotationToken();
8110b57cec5SDimitry Andric   IdentifierInfo *WeakName = Tok.getIdentifierInfo();
8120b57cec5SDimitry Andric   SourceLocation WeakNameLoc = Tok.getLocation();
8130b57cec5SDimitry Andric   ConsumeToken();
8140b57cec5SDimitry Andric   IdentifierInfo *AliasName = Tok.getIdentifierInfo();
8150b57cec5SDimitry Andric   SourceLocation AliasNameLoc = Tok.getLocation();
8160b57cec5SDimitry Andric   ConsumeToken();
8170b57cec5SDimitry Andric   Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
8180b57cec5SDimitry Andric                                WeakNameLoc, AliasNameLoc);
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric }
8210b57cec5SDimitry Andric 
8220b57cec5SDimitry Andric void Parser::HandlePragmaRedefineExtname() {
8230b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_redefine_extname));
8240b57cec5SDimitry Andric   SourceLocation RedefLoc = ConsumeAnnotationToken();
8250b57cec5SDimitry Andric   IdentifierInfo *RedefName = Tok.getIdentifierInfo();
8260b57cec5SDimitry Andric   SourceLocation RedefNameLoc = Tok.getLocation();
8270b57cec5SDimitry Andric   ConsumeToken();
8280b57cec5SDimitry Andric   IdentifierInfo *AliasName = Tok.getIdentifierInfo();
8290b57cec5SDimitry Andric   SourceLocation AliasNameLoc = Tok.getLocation();
8300b57cec5SDimitry Andric   ConsumeToken();
8310b57cec5SDimitry Andric   Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
8320b57cec5SDimitry Andric                                      RedefNameLoc, AliasNameLoc);
8330b57cec5SDimitry Andric }
8340b57cec5SDimitry Andric 
8350b57cec5SDimitry Andric void Parser::HandlePragmaFPContract() {
8360b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_fp_contract));
8370b57cec5SDimitry Andric   tok::OnOffSwitch OOS =
8380b57cec5SDimitry Andric     static_cast<tok::OnOffSwitch>(
8390b57cec5SDimitry Andric     reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
8400b57cec5SDimitry Andric 
8415ffd83dbSDimitry Andric   LangOptions::FPModeKind FPC;
8420b57cec5SDimitry Andric   switch (OOS) {
8430b57cec5SDimitry Andric   case tok::OOS_ON:
8445ffd83dbSDimitry Andric     FPC = LangOptions::FPM_On;
8450b57cec5SDimitry Andric     break;
8460b57cec5SDimitry Andric   case tok::OOS_OFF:
8475ffd83dbSDimitry Andric     FPC = LangOptions::FPM_Off;
8480b57cec5SDimitry Andric     break;
8490b57cec5SDimitry Andric   case tok::OOS_DEFAULT:
850*0fca6ea1SDimitry Andric     // According to ISO C99 standard chapter 7.3.4, the default value
851*0fca6ea1SDimitry Andric     // for the pragma is ``off'. '-fcomplex-arithmetic=basic',
852*0fca6ea1SDimitry Andric     // '-fcx-limited-range', '-fcx-fortran-rules' and
853*0fca6ea1SDimitry Andric     // '-fcomplex-arithmetic=improved' control the default value of these
854*0fca6ea1SDimitry Andric     // pragmas.
8550b57cec5SDimitry Andric     FPC = getLangOpts().getDefaultFPContractMode();
8560b57cec5SDimitry Andric     break;
8570b57cec5SDimitry Andric   }
8580b57cec5SDimitry Andric 
8595ffd83dbSDimitry Andric   SourceLocation PragmaLoc = ConsumeAnnotationToken();
8605ffd83dbSDimitry Andric   Actions.ActOnPragmaFPContract(PragmaLoc, FPC);
8615ffd83dbSDimitry Andric }
8625ffd83dbSDimitry Andric 
8635ffd83dbSDimitry Andric void Parser::HandlePragmaFloatControl() {
8645ffd83dbSDimitry Andric   assert(Tok.is(tok::annot_pragma_float_control));
8655ffd83dbSDimitry Andric 
8665ffd83dbSDimitry Andric   // The value that is held on the PragmaFloatControlStack encodes
8675ffd83dbSDimitry Andric   // the PragmaFloatControl kind and the MSStackAction kind
8685ffd83dbSDimitry Andric   // into a single 32-bit word. The MsStackAction is the high 16 bits
8695ffd83dbSDimitry Andric   // and the FloatControl is the lower 16 bits. Use shift and bit-and
8705ffd83dbSDimitry Andric   // to decode the parts.
8715ffd83dbSDimitry Andric   uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
8725ffd83dbSDimitry Andric   Sema::PragmaMsStackAction Action =
8735ffd83dbSDimitry Andric       static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
8745ffd83dbSDimitry Andric   PragmaFloatControlKind Kind = PragmaFloatControlKind(Value & 0xFFFF);
8755ffd83dbSDimitry Andric   SourceLocation PragmaLoc = ConsumeAnnotationToken();
8765ffd83dbSDimitry Andric   Actions.ActOnPragmaFloatControl(PragmaLoc, Action, Kind);
8770b57cec5SDimitry Andric }
8780b57cec5SDimitry Andric 
8790b57cec5SDimitry Andric void Parser::HandlePragmaFEnvAccess() {
880349cc55cSDimitry Andric   assert(Tok.is(tok::annot_pragma_fenv_access) ||
881349cc55cSDimitry Andric          Tok.is(tok::annot_pragma_fenv_access_ms));
8820b57cec5SDimitry Andric   tok::OnOffSwitch OOS =
8830b57cec5SDimitry Andric     static_cast<tok::OnOffSwitch>(
8840b57cec5SDimitry Andric     reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
8850b57cec5SDimitry Andric 
8865ffd83dbSDimitry Andric   bool IsEnabled;
8870b57cec5SDimitry Andric   switch (OOS) {
8880b57cec5SDimitry Andric   case tok::OOS_ON:
8895ffd83dbSDimitry Andric     IsEnabled = true;
8900b57cec5SDimitry Andric     break;
8910b57cec5SDimitry Andric   case tok::OOS_OFF:
8925ffd83dbSDimitry Andric     IsEnabled = false;
8930b57cec5SDimitry Andric     break;
8940b57cec5SDimitry Andric   case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
8955ffd83dbSDimitry Andric     IsEnabled = false;
8960b57cec5SDimitry Andric     break;
8970b57cec5SDimitry Andric   }
8980b57cec5SDimitry Andric 
8995ffd83dbSDimitry Andric   SourceLocation PragmaLoc = ConsumeAnnotationToken();
9005ffd83dbSDimitry Andric   Actions.ActOnPragmaFEnvAccess(PragmaLoc, IsEnabled);
9010b57cec5SDimitry Andric }
9020b57cec5SDimitry Andric 
903e8d8bef9SDimitry Andric void Parser::HandlePragmaFEnvRound() {
904e8d8bef9SDimitry Andric   assert(Tok.is(tok::annot_pragma_fenv_round));
905e8d8bef9SDimitry Andric   auto RM = static_cast<llvm::RoundingMode>(
906e8d8bef9SDimitry Andric       reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
907e8d8bef9SDimitry Andric 
908e8d8bef9SDimitry Andric   SourceLocation PragmaLoc = ConsumeAnnotationToken();
90981ad6265SDimitry Andric   Actions.ActOnPragmaFEnvRound(PragmaLoc, RM);
910e8d8bef9SDimitry Andric }
9110b57cec5SDimitry Andric 
9125f757f3fSDimitry Andric void Parser::HandlePragmaCXLimitedRange() {
9135f757f3fSDimitry Andric   assert(Tok.is(tok::annot_pragma_cx_limited_range));
9145f757f3fSDimitry Andric   tok::OnOffSwitch OOS = static_cast<tok::OnOffSwitch>(
9155f757f3fSDimitry Andric       reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
9165f757f3fSDimitry Andric 
9175f757f3fSDimitry Andric   LangOptions::ComplexRangeKind Range;
9185f757f3fSDimitry Andric   switch (OOS) {
9195f757f3fSDimitry Andric   case tok::OOS_ON:
920*0fca6ea1SDimitry Andric     Range = LangOptions::CX_Basic;
9215f757f3fSDimitry Andric     break;
9225f757f3fSDimitry Andric   case tok::OOS_OFF:
9235f757f3fSDimitry Andric     Range = LangOptions::CX_Full;
9245f757f3fSDimitry Andric     break;
9255f757f3fSDimitry Andric   case tok::OOS_DEFAULT:
9265f757f3fSDimitry Andric     // According to ISO C99 standard chapter 7.3.4, the default value
927*0fca6ea1SDimitry Andric     // for the pragma is ``off'. -fcomplex-arithmetic controls the default value
928*0fca6ea1SDimitry Andric     // of these pragmas.
9295f757f3fSDimitry Andric     Range = getLangOpts().getComplexRange();
9305f757f3fSDimitry Andric     break;
9315f757f3fSDimitry Andric   }
9325f757f3fSDimitry Andric 
9335f757f3fSDimitry Andric   SourceLocation PragmaLoc = ConsumeAnnotationToken();
9345f757f3fSDimitry Andric   Actions.ActOnPragmaCXLimitedRange(PragmaLoc, Range);
9355f757f3fSDimitry Andric }
9365f757f3fSDimitry Andric 
9370b57cec5SDimitry Andric StmtResult Parser::HandlePragmaCaptured()
9380b57cec5SDimitry Andric {
9390b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_captured));
9400b57cec5SDimitry Andric   ConsumeAnnotationToken();
9410b57cec5SDimitry Andric 
9420b57cec5SDimitry Andric   if (Tok.isNot(tok::l_brace)) {
9430b57cec5SDimitry Andric     PP.Diag(Tok, diag::err_expected) << tok::l_brace;
9440b57cec5SDimitry Andric     return StmtError();
9450b57cec5SDimitry Andric   }
9460b57cec5SDimitry Andric 
9470b57cec5SDimitry Andric   SourceLocation Loc = Tok.getLocation();
9480b57cec5SDimitry Andric 
9490b57cec5SDimitry Andric   ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
9500b57cec5SDimitry Andric                                            Scope::CompoundStmtScope);
9510b57cec5SDimitry Andric   Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
9520b57cec5SDimitry Andric                                    /*NumParams=*/1);
9530b57cec5SDimitry Andric 
9540b57cec5SDimitry Andric   StmtResult R = ParseCompoundStatement();
9550b57cec5SDimitry Andric   CapturedRegionScope.Exit();
9560b57cec5SDimitry Andric 
9570b57cec5SDimitry Andric   if (R.isInvalid()) {
9580b57cec5SDimitry Andric     Actions.ActOnCapturedRegionError();
9590b57cec5SDimitry Andric     return StmtError();
9600b57cec5SDimitry Andric   }
9610b57cec5SDimitry Andric 
9620b57cec5SDimitry Andric   return Actions.ActOnCapturedRegionEnd(R.get());
9630b57cec5SDimitry Andric }
9640b57cec5SDimitry Andric 
9650b57cec5SDimitry Andric namespace {
9660b57cec5SDimitry Andric   enum OpenCLExtState : char {
9670b57cec5SDimitry Andric     Disable, Enable, Begin, End
9680b57cec5SDimitry Andric   };
9690b57cec5SDimitry Andric   typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
9700b57cec5SDimitry Andric }
9710b57cec5SDimitry Andric 
9720b57cec5SDimitry Andric void Parser::HandlePragmaOpenCLExtension() {
9730b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_opencl_extension));
9740b57cec5SDimitry Andric   OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
9750b57cec5SDimitry Andric   auto State = Data->second;
9760b57cec5SDimitry Andric   auto Ident = Data->first;
9770b57cec5SDimitry Andric   SourceLocation NameLoc = Tok.getLocation();
9780b57cec5SDimitry Andric   ConsumeAnnotationToken();
9790b57cec5SDimitry Andric 
9800b57cec5SDimitry Andric   auto &Opt = Actions.getOpenCLOptions();
9810b57cec5SDimitry Andric   auto Name = Ident->getName();
9820b57cec5SDimitry Andric   // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
9830b57cec5SDimitry Andric   // overriding all previously issued extension directives, but only if the
9840b57cec5SDimitry Andric   // behavior is set to disable."
9850b57cec5SDimitry Andric   if (Name == "all") {
986fe6060f1SDimitry Andric     if (State == Disable)
9870b57cec5SDimitry Andric       Opt.disableAll();
988fe6060f1SDimitry Andric     else
9890b57cec5SDimitry Andric       PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
9900b57cec5SDimitry Andric   } else if (State == Begin) {
9910b57cec5SDimitry Andric     if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) {
9920b57cec5SDimitry Andric       Opt.support(Name);
993fe6060f1SDimitry Andric       // FIXME: Default behavior of the extension pragma is not defined.
994fe6060f1SDimitry Andric       // Therefore, it should never be added by default.
995fe6060f1SDimitry Andric       Opt.acceptsPragma(Name);
9960b57cec5SDimitry Andric     }
9970b57cec5SDimitry Andric   } else if (State == End) {
998fe6060f1SDimitry Andric     // There is no behavior for this directive. We only accept this for
999fe6060f1SDimitry Andric     // backward compatibility.
1000fe6060f1SDimitry Andric   } else if (!Opt.isKnown(Name) || !Opt.isWithPragma(Name))
10010b57cec5SDimitry Andric     PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
10020b57cec5SDimitry Andric   else if (Opt.isSupportedExtension(Name, getLangOpts()))
10030b57cec5SDimitry Andric     Opt.enable(Name, State == Enable);
1004e8d8bef9SDimitry Andric   else if (Opt.isSupportedCoreOrOptionalCore(Name, getLangOpts()))
10050b57cec5SDimitry Andric     PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
10060b57cec5SDimitry Andric   else
10070b57cec5SDimitry Andric     PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
10080b57cec5SDimitry Andric }
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric void Parser::HandlePragmaMSPointersToMembers() {
10110b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
10120b57cec5SDimitry Andric   LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
10130b57cec5SDimitry Andric       static_cast<LangOptions::PragmaMSPointersToMembersKind>(
10140b57cec5SDimitry Andric           reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
10150b57cec5SDimitry Andric   SourceLocation PragmaLoc = ConsumeAnnotationToken();
10160b57cec5SDimitry Andric   Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
10170b57cec5SDimitry Andric }
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric void Parser::HandlePragmaMSVtorDisp() {
10200b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_ms_vtordisp));
10210b57cec5SDimitry Andric   uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
10220b57cec5SDimitry Andric   Sema::PragmaMsStackAction Action =
10230b57cec5SDimitry Andric       static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
1024480093f4SDimitry Andric   MSVtorDispMode Mode = MSVtorDispMode(Value & 0xFFFF);
10250b57cec5SDimitry Andric   SourceLocation PragmaLoc = ConsumeAnnotationToken();
10260b57cec5SDimitry Andric   Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
10270b57cec5SDimitry Andric }
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric void Parser::HandlePragmaMSPragma() {
10300b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_ms_pragma));
10310b57cec5SDimitry Andric   // Grab the tokens out of the annotation and enter them into the stream.
10320b57cec5SDimitry Andric   auto TheTokens =
10330b57cec5SDimitry Andric       (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
10340b57cec5SDimitry Andric   PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true,
10350b57cec5SDimitry Andric                       /*IsReinject=*/true);
10360b57cec5SDimitry Andric   SourceLocation PragmaLocation = ConsumeAnnotationToken();
10370b57cec5SDimitry Andric   assert(Tok.isAnyIdentifier());
10380b57cec5SDimitry Andric   StringRef PragmaName = Tok.getIdentifierInfo()->getName();
10390b57cec5SDimitry Andric   PP.Lex(Tok); // pragma kind
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric   // Figure out which #pragma we're dealing with.  The switch has no default
10420b57cec5SDimitry Andric   // because lex shouldn't emit the annotation token for unrecognized pragmas.
10430b57cec5SDimitry Andric   typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
104481ad6265SDimitry Andric   PragmaHandler Handler =
104581ad6265SDimitry Andric       llvm::StringSwitch<PragmaHandler>(PragmaName)
10460b57cec5SDimitry Andric           .Case("data_seg", &Parser::HandlePragmaMSSegment)
10470b57cec5SDimitry Andric           .Case("bss_seg", &Parser::HandlePragmaMSSegment)
10480b57cec5SDimitry Andric           .Case("const_seg", &Parser::HandlePragmaMSSegment)
10490b57cec5SDimitry Andric           .Case("code_seg", &Parser::HandlePragmaMSSegment)
10500b57cec5SDimitry Andric           .Case("section", &Parser::HandlePragmaMSSection)
105181ad6265SDimitry Andric           .Case("init_seg", &Parser::HandlePragmaMSInitSeg)
1052bdd1243dSDimitry Andric           .Case("strict_gs_check", &Parser::HandlePragmaMSStrictGuardStackCheck)
105381ad6265SDimitry Andric           .Case("function", &Parser::HandlePragmaMSFunction)
105481ad6265SDimitry Andric           .Case("alloc_text", &Parser::HandlePragmaMSAllocText)
105581ad6265SDimitry Andric           .Case("optimize", &Parser::HandlePragmaMSOptimize);
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric   if (!(this->*Handler)(PragmaName, PragmaLocation)) {
10580b57cec5SDimitry Andric     // Pragma handling failed, and has been diagnosed.  Slurp up the tokens
10590b57cec5SDimitry Andric     // until eof (really end of line) to prevent follow-on errors.
10600b57cec5SDimitry Andric     while (Tok.isNot(tok::eof))
10610b57cec5SDimitry Andric       PP.Lex(Tok);
10620b57cec5SDimitry Andric     PP.Lex(Tok);
10630b57cec5SDimitry Andric   }
10640b57cec5SDimitry Andric }
10650b57cec5SDimitry Andric 
10660b57cec5SDimitry Andric bool Parser::HandlePragmaMSSection(StringRef PragmaName,
10670b57cec5SDimitry Andric                                    SourceLocation PragmaLocation) {
10680b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren)) {
10690b57cec5SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
10700b57cec5SDimitry Andric     return false;
10710b57cec5SDimitry Andric   }
10720b57cec5SDimitry Andric   PP.Lex(Tok); // (
10730b57cec5SDimitry Andric   // Parsing code for pragma section
10740b57cec5SDimitry Andric   if (Tok.isNot(tok::string_literal)) {
10750b57cec5SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
10760b57cec5SDimitry Andric         << PragmaName;
10770b57cec5SDimitry Andric     return false;
10780b57cec5SDimitry Andric   }
10790b57cec5SDimitry Andric   ExprResult StringResult = ParseStringLiteralExpression();
10800b57cec5SDimitry Andric   if (StringResult.isInvalid())
10810b57cec5SDimitry Andric     return false; // Already diagnosed.
10820b57cec5SDimitry Andric   StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
10830b57cec5SDimitry Andric   if (SegmentName->getCharByteWidth() != 1) {
10840b57cec5SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
10850b57cec5SDimitry Andric         << PragmaName;
10860b57cec5SDimitry Andric     return false;
10870b57cec5SDimitry Andric   }
10880b57cec5SDimitry Andric   int SectionFlags = ASTContext::PSF_Read;
10890b57cec5SDimitry Andric   bool SectionFlagsAreDefault = true;
10900b57cec5SDimitry Andric   while (Tok.is(tok::comma)) {
10910b57cec5SDimitry Andric     PP.Lex(Tok); // ,
10920b57cec5SDimitry Andric     // Ignore "long" and "short".
10930b57cec5SDimitry Andric     // They are undocumented, but widely used, section attributes which appear
10940b57cec5SDimitry Andric     // to do nothing.
10950b57cec5SDimitry Andric     if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
10960b57cec5SDimitry Andric       PP.Lex(Tok); // long/short
10970b57cec5SDimitry Andric       continue;
10980b57cec5SDimitry Andric     }
10990b57cec5SDimitry Andric 
11000b57cec5SDimitry Andric     if (!Tok.isAnyIdentifier()) {
11010b57cec5SDimitry Andric       PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
11020b57cec5SDimitry Andric           << PragmaName;
11030b57cec5SDimitry Andric       return false;
11040b57cec5SDimitry Andric     }
11050b57cec5SDimitry Andric     ASTContext::PragmaSectionFlag Flag =
11060b57cec5SDimitry Andric       llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
11070b57cec5SDimitry Andric       Tok.getIdentifierInfo()->getName())
11080b57cec5SDimitry Andric       .Case("read", ASTContext::PSF_Read)
11090b57cec5SDimitry Andric       .Case("write", ASTContext::PSF_Write)
11100b57cec5SDimitry Andric       .Case("execute", ASTContext::PSF_Execute)
11110b57cec5SDimitry Andric       .Case("shared", ASTContext::PSF_Invalid)
11120b57cec5SDimitry Andric       .Case("nopage", ASTContext::PSF_Invalid)
11130b57cec5SDimitry Andric       .Case("nocache", ASTContext::PSF_Invalid)
11140b57cec5SDimitry Andric       .Case("discard", ASTContext::PSF_Invalid)
11150b57cec5SDimitry Andric       .Case("remove", ASTContext::PSF_Invalid)
11160b57cec5SDimitry Andric       .Default(ASTContext::PSF_None);
11170b57cec5SDimitry Andric     if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
11180b57cec5SDimitry Andric       PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
11190b57cec5SDimitry Andric                                   ? diag::warn_pragma_invalid_specific_action
11200b57cec5SDimitry Andric                                   : diag::warn_pragma_unsupported_action)
11210b57cec5SDimitry Andric           << PragmaName << Tok.getIdentifierInfo()->getName();
11220b57cec5SDimitry Andric       return false;
11230b57cec5SDimitry Andric     }
11240b57cec5SDimitry Andric     SectionFlags |= Flag;
11250b57cec5SDimitry Andric     SectionFlagsAreDefault = false;
11260b57cec5SDimitry Andric     PP.Lex(Tok); // Identifier
11270b57cec5SDimitry Andric   }
11280b57cec5SDimitry Andric   // If no section attributes are specified, the section will be marked as
11290b57cec5SDimitry Andric   // read/write.
11300b57cec5SDimitry Andric   if (SectionFlagsAreDefault)
11310b57cec5SDimitry Andric     SectionFlags |= ASTContext::PSF_Write;
11320b57cec5SDimitry Andric   if (Tok.isNot(tok::r_paren)) {
11330b57cec5SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
11340b57cec5SDimitry Andric     return false;
11350b57cec5SDimitry Andric   }
11360b57cec5SDimitry Andric   PP.Lex(Tok); // )
11370b57cec5SDimitry Andric   if (Tok.isNot(tok::eof)) {
11380b57cec5SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
11390b57cec5SDimitry Andric         << PragmaName;
11400b57cec5SDimitry Andric     return false;
11410b57cec5SDimitry Andric   }
11420b57cec5SDimitry Andric   PP.Lex(Tok); // eof
11430b57cec5SDimitry Andric   Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
11440b57cec5SDimitry Andric   return true;
11450b57cec5SDimitry Andric }
11460b57cec5SDimitry Andric 
11470b57cec5SDimitry Andric bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
11480b57cec5SDimitry Andric                                    SourceLocation PragmaLocation) {
11490b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren)) {
11500b57cec5SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
11510b57cec5SDimitry Andric     return false;
11520b57cec5SDimitry Andric   }
11530b57cec5SDimitry Andric   PP.Lex(Tok); // (
11540b57cec5SDimitry Andric   Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
11550b57cec5SDimitry Andric   StringRef SlotLabel;
11560b57cec5SDimitry Andric   if (Tok.isAnyIdentifier()) {
11570b57cec5SDimitry Andric     StringRef PushPop = Tok.getIdentifierInfo()->getName();
11580b57cec5SDimitry Andric     if (PushPop == "push")
11590b57cec5SDimitry Andric       Action = Sema::PSK_Push;
11600b57cec5SDimitry Andric     else if (PushPop == "pop")
11610b57cec5SDimitry Andric       Action = Sema::PSK_Pop;
11620b57cec5SDimitry Andric     else {
11630b57cec5SDimitry Andric       PP.Diag(PragmaLocation,
11640b57cec5SDimitry Andric               diag::warn_pragma_expected_section_push_pop_or_name)
11650b57cec5SDimitry Andric           << PragmaName;
11660b57cec5SDimitry Andric       return false;
11670b57cec5SDimitry Andric     }
11680b57cec5SDimitry Andric     if (Action != Sema::PSK_Reset) {
11690b57cec5SDimitry Andric       PP.Lex(Tok); // push | pop
11700b57cec5SDimitry Andric       if (Tok.is(tok::comma)) {
11710b57cec5SDimitry Andric         PP.Lex(Tok); // ,
11720b57cec5SDimitry Andric         // If we've got a comma, we either need a label or a string.
11730b57cec5SDimitry Andric         if (Tok.isAnyIdentifier()) {
11740b57cec5SDimitry Andric           SlotLabel = Tok.getIdentifierInfo()->getName();
11750b57cec5SDimitry Andric           PP.Lex(Tok); // identifier
11760b57cec5SDimitry Andric           if (Tok.is(tok::comma))
11770b57cec5SDimitry Andric             PP.Lex(Tok);
11780b57cec5SDimitry Andric           else if (Tok.isNot(tok::r_paren)) {
11790b57cec5SDimitry Andric             PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
11800b57cec5SDimitry Andric                 << PragmaName;
11810b57cec5SDimitry Andric             return false;
11820b57cec5SDimitry Andric           }
11830b57cec5SDimitry Andric         }
11840b57cec5SDimitry Andric       } else if (Tok.isNot(tok::r_paren)) {
11850b57cec5SDimitry Andric         PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
11860b57cec5SDimitry Andric         return false;
11870b57cec5SDimitry Andric       }
11880b57cec5SDimitry Andric     }
11890b57cec5SDimitry Andric   }
11900b57cec5SDimitry Andric   // Grab the string literal for our section name.
11910b57cec5SDimitry Andric   StringLiteral *SegmentName = nullptr;
11920b57cec5SDimitry Andric   if (Tok.isNot(tok::r_paren)) {
11930b57cec5SDimitry Andric     if (Tok.isNot(tok::string_literal)) {
11940b57cec5SDimitry Andric       unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
11950b57cec5SDimitry Andric           diag::warn_pragma_expected_section_name :
11960b57cec5SDimitry Andric           diag::warn_pragma_expected_section_label_or_name :
11970b57cec5SDimitry Andric           diag::warn_pragma_expected_section_push_pop_or_name;
11980b57cec5SDimitry Andric       PP.Diag(PragmaLocation, DiagID) << PragmaName;
11990b57cec5SDimitry Andric       return false;
12000b57cec5SDimitry Andric     }
12010b57cec5SDimitry Andric     ExprResult StringResult = ParseStringLiteralExpression();
12020b57cec5SDimitry Andric     if (StringResult.isInvalid())
12030b57cec5SDimitry Andric       return false; // Already diagnosed.
12040b57cec5SDimitry Andric     SegmentName = cast<StringLiteral>(StringResult.get());
12050b57cec5SDimitry Andric     if (SegmentName->getCharByteWidth() != 1) {
12060b57cec5SDimitry Andric       PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
12070b57cec5SDimitry Andric           << PragmaName;
12080b57cec5SDimitry Andric       return false;
12090b57cec5SDimitry Andric     }
12100b57cec5SDimitry Andric     // Setting section "" has no effect
12110b57cec5SDimitry Andric     if (SegmentName->getLength())
12120b57cec5SDimitry Andric       Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
12130b57cec5SDimitry Andric   }
12140b57cec5SDimitry Andric   if (Tok.isNot(tok::r_paren)) {
12150b57cec5SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
12160b57cec5SDimitry Andric     return false;
12170b57cec5SDimitry Andric   }
12180b57cec5SDimitry Andric   PP.Lex(Tok); // )
12190b57cec5SDimitry Andric   if (Tok.isNot(tok::eof)) {
12200b57cec5SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
12210b57cec5SDimitry Andric         << PragmaName;
12220b57cec5SDimitry Andric     return false;
12230b57cec5SDimitry Andric   }
12240b57cec5SDimitry Andric   PP.Lex(Tok); // eof
12250b57cec5SDimitry Andric   Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
12260b57cec5SDimitry Andric                            SegmentName, PragmaName);
12270b57cec5SDimitry Andric   return true;
12280b57cec5SDimitry Andric }
12290b57cec5SDimitry Andric 
12300b57cec5SDimitry Andric // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
12310b57cec5SDimitry Andric bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
12320b57cec5SDimitry Andric                                    SourceLocation PragmaLocation) {
12330b57cec5SDimitry Andric   if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
12340b57cec5SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
12350b57cec5SDimitry Andric     return false;
12360b57cec5SDimitry Andric   }
12370b57cec5SDimitry Andric 
12380b57cec5SDimitry Andric   if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
12390b57cec5SDimitry Andric                        PragmaName))
12400b57cec5SDimitry Andric     return false;
12410b57cec5SDimitry Andric 
12420b57cec5SDimitry Andric   // Parse either the known section names or the string section name.
12430b57cec5SDimitry Andric   StringLiteral *SegmentName = nullptr;
12440b57cec5SDimitry Andric   if (Tok.isAnyIdentifier()) {
12450b57cec5SDimitry Andric     auto *II = Tok.getIdentifierInfo();
12460b57cec5SDimitry Andric     StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
12470b57cec5SDimitry Andric                             .Case("compiler", "\".CRT$XCC\"")
12480b57cec5SDimitry Andric                             .Case("lib", "\".CRT$XCL\"")
12490b57cec5SDimitry Andric                             .Case("user", "\".CRT$XCU\"")
12500b57cec5SDimitry Andric                             .Default("");
12510b57cec5SDimitry Andric 
12520b57cec5SDimitry Andric     if (!Section.empty()) {
12530b57cec5SDimitry Andric       // Pretend the user wrote the appropriate string literal here.
12540b57cec5SDimitry Andric       Token Toks[1];
12550b57cec5SDimitry Andric       Toks[0].startToken();
12560b57cec5SDimitry Andric       Toks[0].setKind(tok::string_literal);
12570b57cec5SDimitry Andric       Toks[0].setLocation(Tok.getLocation());
12580b57cec5SDimitry Andric       Toks[0].setLiteralData(Section.data());
12590b57cec5SDimitry Andric       Toks[0].setLength(Section.size());
12600b57cec5SDimitry Andric       SegmentName =
12610b57cec5SDimitry Andric           cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
12620b57cec5SDimitry Andric       PP.Lex(Tok);
12630b57cec5SDimitry Andric     }
12640b57cec5SDimitry Andric   } else if (Tok.is(tok::string_literal)) {
12650b57cec5SDimitry Andric     ExprResult StringResult = ParseStringLiteralExpression();
12660b57cec5SDimitry Andric     if (StringResult.isInvalid())
12670b57cec5SDimitry Andric       return false;
12680b57cec5SDimitry Andric     SegmentName = cast<StringLiteral>(StringResult.get());
12690b57cec5SDimitry Andric     if (SegmentName->getCharByteWidth() != 1) {
12700b57cec5SDimitry Andric       PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
12710b57cec5SDimitry Andric           << PragmaName;
12720b57cec5SDimitry Andric       return false;
12730b57cec5SDimitry Andric     }
12740b57cec5SDimitry Andric     // FIXME: Add support for the '[, func-name]' part of the pragma.
12750b57cec5SDimitry Andric   }
12760b57cec5SDimitry Andric 
12770b57cec5SDimitry Andric   if (!SegmentName) {
12780b57cec5SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
12790b57cec5SDimitry Andric     return false;
12800b57cec5SDimitry Andric   }
12810b57cec5SDimitry Andric 
12820b57cec5SDimitry Andric   if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
12830b57cec5SDimitry Andric                        PragmaName) ||
12840b57cec5SDimitry Andric       ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
12850b57cec5SDimitry Andric                        PragmaName))
12860b57cec5SDimitry Andric     return false;
12870b57cec5SDimitry Andric 
12880b57cec5SDimitry Andric   Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
12890b57cec5SDimitry Andric   return true;
12900b57cec5SDimitry Andric }
12910b57cec5SDimitry Andric 
1292bdd1243dSDimitry Andric // #pragma strict_gs_check(pop)
1293bdd1243dSDimitry Andric // #pragma strict_gs_check(push, "on" | "off")
1294bdd1243dSDimitry Andric // #pragma strict_gs_check("on" | "off")
1295bdd1243dSDimitry Andric bool Parser::HandlePragmaMSStrictGuardStackCheck(
1296bdd1243dSDimitry Andric     StringRef PragmaName, SourceLocation PragmaLocation) {
1297bdd1243dSDimitry Andric   if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1298bdd1243dSDimitry Andric                        PragmaName))
1299bdd1243dSDimitry Andric     return false;
1300bdd1243dSDimitry Andric 
1301bdd1243dSDimitry Andric   Sema::PragmaMsStackAction Action = Sema::PSK_Set;
1302bdd1243dSDimitry Andric   if (Tok.is(tok::identifier)) {
1303bdd1243dSDimitry Andric     StringRef PushPop = Tok.getIdentifierInfo()->getName();
1304bdd1243dSDimitry Andric     if (PushPop == "push") {
1305bdd1243dSDimitry Andric       PP.Lex(Tok);
1306bdd1243dSDimitry Andric       Action = Sema::PSK_Push;
1307bdd1243dSDimitry Andric       if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_punc,
1308bdd1243dSDimitry Andric                            PragmaName))
1309bdd1243dSDimitry Andric         return false;
1310bdd1243dSDimitry Andric     } else if (PushPop == "pop") {
1311bdd1243dSDimitry Andric       PP.Lex(Tok);
1312bdd1243dSDimitry Andric       Action = Sema::PSK_Pop;
1313bdd1243dSDimitry Andric     }
1314bdd1243dSDimitry Andric   }
1315bdd1243dSDimitry Andric 
1316bdd1243dSDimitry Andric   bool Value = false;
1317bdd1243dSDimitry Andric   if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
1318bdd1243dSDimitry Andric     const IdentifierInfo *II = Tok.getIdentifierInfo();
1319bdd1243dSDimitry Andric     if (II && II->isStr("off")) {
1320bdd1243dSDimitry Andric       PP.Lex(Tok);
1321bdd1243dSDimitry Andric       Value = false;
1322bdd1243dSDimitry Andric     } else if (II && II->isStr("on")) {
1323bdd1243dSDimitry Andric       PP.Lex(Tok);
1324bdd1243dSDimitry Andric       Value = true;
1325bdd1243dSDimitry Andric     } else {
1326bdd1243dSDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1327bdd1243dSDimitry Andric           << PragmaName;
1328bdd1243dSDimitry Andric       return false;
1329bdd1243dSDimitry Andric     }
1330bdd1243dSDimitry Andric   }
1331bdd1243dSDimitry Andric 
1332bdd1243dSDimitry Andric   // Finish the pragma: ')' $
1333bdd1243dSDimitry Andric   if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1334bdd1243dSDimitry Andric                        PragmaName))
1335bdd1243dSDimitry Andric     return false;
1336bdd1243dSDimitry Andric 
1337bdd1243dSDimitry Andric   if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1338bdd1243dSDimitry Andric                        PragmaName))
1339bdd1243dSDimitry Andric     return false;
1340bdd1243dSDimitry Andric 
1341bdd1243dSDimitry Andric   Actions.ActOnPragmaMSStrictGuardStackCheck(PragmaLocation, Action, Value);
1342bdd1243dSDimitry Andric   return true;
1343bdd1243dSDimitry Andric }
1344bdd1243dSDimitry Andric 
134581ad6265SDimitry Andric bool Parser::HandlePragmaMSAllocText(StringRef PragmaName,
134681ad6265SDimitry Andric                                      SourceLocation PragmaLocation) {
134781ad6265SDimitry Andric   Token FirstTok = Tok;
134881ad6265SDimitry Andric   if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
134981ad6265SDimitry Andric                        PragmaName))
135081ad6265SDimitry Andric     return false;
135181ad6265SDimitry Andric 
135281ad6265SDimitry Andric   StringRef Section;
135381ad6265SDimitry Andric   if (Tok.is(tok::string_literal)) {
135481ad6265SDimitry Andric     ExprResult StringResult = ParseStringLiteralExpression();
135581ad6265SDimitry Andric     if (StringResult.isInvalid())
135681ad6265SDimitry Andric       return false; // Already diagnosed.
135781ad6265SDimitry Andric     StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
135881ad6265SDimitry Andric     if (SegmentName->getCharByteWidth() != 1) {
135981ad6265SDimitry Andric       PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
136081ad6265SDimitry Andric           << PragmaName;
136181ad6265SDimitry Andric       return false;
136281ad6265SDimitry Andric     }
136381ad6265SDimitry Andric     Section = SegmentName->getString();
136481ad6265SDimitry Andric   } else if (Tok.is(tok::identifier)) {
136581ad6265SDimitry Andric     Section = Tok.getIdentifierInfo()->getName();
136681ad6265SDimitry Andric     PP.Lex(Tok);
136781ad6265SDimitry Andric   } else {
136881ad6265SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
136981ad6265SDimitry Andric         << PragmaName;
137081ad6265SDimitry Andric     return false;
137181ad6265SDimitry Andric   }
137281ad6265SDimitry Andric 
137381ad6265SDimitry Andric   if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
137481ad6265SDimitry Andric                        PragmaName))
137581ad6265SDimitry Andric     return false;
137681ad6265SDimitry Andric 
137781ad6265SDimitry Andric   SmallVector<std::tuple<IdentifierInfo *, SourceLocation>> Functions;
137881ad6265SDimitry Andric   while (true) {
137981ad6265SDimitry Andric     if (Tok.isNot(tok::identifier)) {
138081ad6265SDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
138181ad6265SDimitry Andric           << PragmaName;
138281ad6265SDimitry Andric       return false;
138381ad6265SDimitry Andric     }
138481ad6265SDimitry Andric 
138581ad6265SDimitry Andric     IdentifierInfo *II = Tok.getIdentifierInfo();
138681ad6265SDimitry Andric     Functions.emplace_back(II, Tok.getLocation());
138781ad6265SDimitry Andric 
138881ad6265SDimitry Andric     PP.Lex(Tok);
138981ad6265SDimitry Andric     if (Tok.isNot(tok::comma))
139081ad6265SDimitry Andric       break;
139181ad6265SDimitry Andric     PP.Lex(Tok);
139281ad6265SDimitry Andric   }
139381ad6265SDimitry Andric 
139481ad6265SDimitry Andric   if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
139581ad6265SDimitry Andric                        PragmaName) ||
139681ad6265SDimitry Andric       ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
139781ad6265SDimitry Andric                        PragmaName))
139881ad6265SDimitry Andric     return false;
139981ad6265SDimitry Andric 
140081ad6265SDimitry Andric   Actions.ActOnPragmaMSAllocText(FirstTok.getLocation(), Section, Functions);
140181ad6265SDimitry Andric   return true;
140281ad6265SDimitry Andric }
140381ad6265SDimitry Andric 
14040b57cec5SDimitry Andric static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
1405a7dea167SDimitry Andric   StringRef Str = PragmaName.getIdentifierInfo()->getName();
1406bdd1243dSDimitry Andric   std::string ClangLoopStr("clang loop ");
1407bdd1243dSDimitry Andric   if (Str == "loop" && Option.getIdentifierInfo())
1408bdd1243dSDimitry Andric     ClangLoopStr += Option.getIdentifierInfo()->getName();
14095ffd83dbSDimitry Andric   return std::string(llvm::StringSwitch<StringRef>(Str)
1410a7dea167SDimitry Andric                          .Case("loop", ClangLoopStr)
1411a7dea167SDimitry Andric                          .Case("unroll_and_jam", Str)
1412a7dea167SDimitry Andric                          .Case("unroll", Str)
14135ffd83dbSDimitry Andric                          .Default(""));
14140b57cec5SDimitry Andric }
14150b57cec5SDimitry Andric 
14160b57cec5SDimitry Andric bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
14170b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_loop_hint));
14180b57cec5SDimitry Andric   PragmaLoopHintInfo *Info =
14190b57cec5SDimitry Andric       static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
14200b57cec5SDimitry Andric 
14210b57cec5SDimitry Andric   IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
14220b57cec5SDimitry Andric   Hint.PragmaNameLoc = IdentifierLoc::create(
14230b57cec5SDimitry Andric       Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
14240b57cec5SDimitry Andric 
14250b57cec5SDimitry Andric   // It is possible that the loop hint has no option identifier, such as
14260b57cec5SDimitry Andric   // #pragma unroll(4).
14270b57cec5SDimitry Andric   IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
14280b57cec5SDimitry Andric                                    ? Info->Option.getIdentifierInfo()
14290b57cec5SDimitry Andric                                    : nullptr;
14300b57cec5SDimitry Andric   Hint.OptionLoc = IdentifierLoc::create(
14310b57cec5SDimitry Andric       Actions.Context, Info->Option.getLocation(), OptionInfo);
14320b57cec5SDimitry Andric 
14330b57cec5SDimitry Andric   llvm::ArrayRef<Token> Toks = Info->Toks;
14340b57cec5SDimitry Andric 
14350b57cec5SDimitry Andric   // Return a valid hint if pragma unroll or nounroll were specified
14360b57cec5SDimitry Andric   // without an argument.
1437a7dea167SDimitry Andric   auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName())
1438a7dea167SDimitry Andric                         .Cases("unroll", "nounroll", "unroll_and_jam",
1439a7dea167SDimitry Andric                                "nounroll_and_jam", true)
1440a7dea167SDimitry Andric                         .Default(false);
1441a7dea167SDimitry Andric 
1442a7dea167SDimitry Andric   if (Toks.empty() && IsLoopHint) {
14430b57cec5SDimitry Andric     ConsumeAnnotationToken();
14440b57cec5SDimitry Andric     Hint.Range = Info->PragmaName.getLocation();
14450b57cec5SDimitry Andric     return true;
14460b57cec5SDimitry Andric   }
14470b57cec5SDimitry Andric 
14480b57cec5SDimitry Andric   // The constant expression is always followed by an eof token, which increases
14490b57cec5SDimitry Andric   // the TokSize by 1.
14500b57cec5SDimitry Andric   assert(!Toks.empty() &&
14510b57cec5SDimitry Andric          "PragmaLoopHintInfo::Toks must contain at least one token.");
14520b57cec5SDimitry Andric 
14530b57cec5SDimitry Andric   // If no option is specified the argument is assumed to be a constant expr.
14540b57cec5SDimitry Andric   bool OptionUnroll = false;
14550b57cec5SDimitry Andric   bool OptionUnrollAndJam = false;
14560b57cec5SDimitry Andric   bool OptionDistribute = false;
14570b57cec5SDimitry Andric   bool OptionPipelineDisabled = false;
14580b57cec5SDimitry Andric   bool StateOption = false;
14590b57cec5SDimitry Andric   if (OptionInfo) { // Pragma Unroll does not specify an option.
14600b57cec5SDimitry Andric     OptionUnroll = OptionInfo->isStr("unroll");
14610b57cec5SDimitry Andric     OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
14620b57cec5SDimitry Andric     OptionDistribute = OptionInfo->isStr("distribute");
14630b57cec5SDimitry Andric     OptionPipelineDisabled = OptionInfo->isStr("pipeline");
14640b57cec5SDimitry Andric     StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
14650b57cec5SDimitry Andric                       .Case("vectorize", true)
14660b57cec5SDimitry Andric                       .Case("interleave", true)
1467a7dea167SDimitry Andric                       .Case("vectorize_predicate", true)
14680b57cec5SDimitry Andric                       .Default(false) ||
14690b57cec5SDimitry Andric                   OptionUnroll || OptionUnrollAndJam || OptionDistribute ||
14700b57cec5SDimitry Andric                   OptionPipelineDisabled;
14710b57cec5SDimitry Andric   }
14720b57cec5SDimitry Andric 
14730b57cec5SDimitry Andric   bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam &&
14740b57cec5SDimitry Andric                          !OptionDistribute && !OptionPipelineDisabled;
14750b57cec5SDimitry Andric   // Verify loop hint has an argument.
14760b57cec5SDimitry Andric   if (Toks[0].is(tok::eof)) {
14770b57cec5SDimitry Andric     ConsumeAnnotationToken();
14780b57cec5SDimitry Andric     Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
14790b57cec5SDimitry Andric         << /*StateArgument=*/StateOption
14800b57cec5SDimitry Andric         << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
14810b57cec5SDimitry Andric         << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
14820b57cec5SDimitry Andric     return false;
14830b57cec5SDimitry Andric   }
14840b57cec5SDimitry Andric 
14850b57cec5SDimitry Andric   // Validate the argument.
14860b57cec5SDimitry Andric   if (StateOption) {
14870b57cec5SDimitry Andric     ConsumeAnnotationToken();
14880b57cec5SDimitry Andric     SourceLocation StateLoc = Toks[0].getLocation();
14890b57cec5SDimitry Andric     IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
14900b57cec5SDimitry Andric 
14910b57cec5SDimitry Andric     bool Valid = StateInfo &&
14920b57cec5SDimitry Andric                  llvm::StringSwitch<bool>(StateInfo->getName())
14930b57cec5SDimitry Andric                      .Case("disable", true)
14940b57cec5SDimitry Andric                      .Case("enable", !OptionPipelineDisabled)
14950b57cec5SDimitry Andric                      .Case("full", OptionUnroll || OptionUnrollAndJam)
14960b57cec5SDimitry Andric                      .Case("assume_safety", AssumeSafetyArg)
14970b57cec5SDimitry Andric                      .Default(false);
14980b57cec5SDimitry Andric     if (!Valid) {
14990b57cec5SDimitry Andric       if (OptionPipelineDisabled) {
15000b57cec5SDimitry Andric         Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
15010b57cec5SDimitry Andric       } else {
15020b57cec5SDimitry Andric         Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
15030b57cec5SDimitry Andric             << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
15040b57cec5SDimitry Andric             << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
15050b57cec5SDimitry Andric       }
15060b57cec5SDimitry Andric       return false;
15070b57cec5SDimitry Andric     }
15080b57cec5SDimitry Andric     if (Toks.size() > 2)
15090b57cec5SDimitry Andric       Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
15100b57cec5SDimitry Andric           << PragmaLoopHintString(Info->PragmaName, Info->Option);
15110b57cec5SDimitry Andric     Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1512e8d8bef9SDimitry Andric   } else if (OptionInfo && OptionInfo->getName() == "vectorize_width") {
1513e8d8bef9SDimitry Andric     PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1514e8d8bef9SDimitry Andric                         /*IsReinject=*/false);
1515e8d8bef9SDimitry Andric     ConsumeAnnotationToken();
1516e8d8bef9SDimitry Andric 
1517e8d8bef9SDimitry Andric     SourceLocation StateLoc = Toks[0].getLocation();
1518e8d8bef9SDimitry Andric     IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1519e8d8bef9SDimitry Andric     StringRef IsScalableStr = StateInfo ? StateInfo->getName() : "";
1520e8d8bef9SDimitry Andric 
1521e8d8bef9SDimitry Andric     // Look for vectorize_width(fixed|scalable)
1522e8d8bef9SDimitry Andric     if (IsScalableStr == "scalable" || IsScalableStr == "fixed") {
1523e8d8bef9SDimitry Andric       PP.Lex(Tok); // Identifier
1524e8d8bef9SDimitry Andric 
1525e8d8bef9SDimitry Andric       if (Toks.size() > 2) {
1526e8d8bef9SDimitry Andric         Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1527e8d8bef9SDimitry Andric             << PragmaLoopHintString(Info->PragmaName, Info->Option);
1528e8d8bef9SDimitry Andric         while (Tok.isNot(tok::eof))
1529e8d8bef9SDimitry Andric           ConsumeAnyToken();
1530e8d8bef9SDimitry Andric       }
1531e8d8bef9SDimitry Andric 
1532e8d8bef9SDimitry Andric       Hint.StateLoc =
1533e8d8bef9SDimitry Andric           IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1534e8d8bef9SDimitry Andric 
1535e8d8bef9SDimitry Andric       ConsumeToken(); // Consume the constant expression eof terminator.
1536e8d8bef9SDimitry Andric     } else {
1537e8d8bef9SDimitry Andric       // Enter constant expression including eof terminator into token stream.
1538e8d8bef9SDimitry Andric       ExprResult R = ParseConstantExpression();
1539e8d8bef9SDimitry Andric 
1540e8d8bef9SDimitry Andric       if (R.isInvalid() && !Tok.is(tok::comma))
1541e8d8bef9SDimitry Andric         Diag(Toks[0].getLocation(),
1542e8d8bef9SDimitry Andric              diag::note_pragma_loop_invalid_vectorize_option);
1543e8d8bef9SDimitry Andric 
1544e8d8bef9SDimitry Andric       bool Arg2Error = false;
1545e8d8bef9SDimitry Andric       if (Tok.is(tok::comma)) {
1546e8d8bef9SDimitry Andric         PP.Lex(Tok); // ,
1547e8d8bef9SDimitry Andric 
1548e8d8bef9SDimitry Andric         StateInfo = Tok.getIdentifierInfo();
1549e8d8bef9SDimitry Andric         IsScalableStr = StateInfo->getName();
1550e8d8bef9SDimitry Andric 
1551e8d8bef9SDimitry Andric         if (IsScalableStr != "scalable" && IsScalableStr != "fixed") {
1552e8d8bef9SDimitry Andric           Diag(Tok.getLocation(),
1553e8d8bef9SDimitry Andric                diag::err_pragma_loop_invalid_vectorize_option);
1554e8d8bef9SDimitry Andric           Arg2Error = true;
1555e8d8bef9SDimitry Andric         } else
1556e8d8bef9SDimitry Andric           Hint.StateLoc =
1557e8d8bef9SDimitry Andric               IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1558e8d8bef9SDimitry Andric 
1559e8d8bef9SDimitry Andric         PP.Lex(Tok); // Identifier
1560e8d8bef9SDimitry Andric       }
1561e8d8bef9SDimitry Andric 
1562e8d8bef9SDimitry Andric       // Tokens following an error in an ill-formed constant expression will
1563e8d8bef9SDimitry Andric       // remain in the token stream and must be removed.
1564e8d8bef9SDimitry Andric       if (Tok.isNot(tok::eof)) {
1565e8d8bef9SDimitry Andric         Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1566e8d8bef9SDimitry Andric             << PragmaLoopHintString(Info->PragmaName, Info->Option);
1567e8d8bef9SDimitry Andric         while (Tok.isNot(tok::eof))
1568e8d8bef9SDimitry Andric           ConsumeAnyToken();
1569e8d8bef9SDimitry Andric       }
1570e8d8bef9SDimitry Andric 
1571e8d8bef9SDimitry Andric       ConsumeToken(); // Consume the constant expression eof terminator.
1572e8d8bef9SDimitry Andric 
1573e8d8bef9SDimitry Andric       if (Arg2Error || R.isInvalid() ||
1574*0fca6ea1SDimitry Andric           Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation(),
1575*0fca6ea1SDimitry Andric                                     /*AllowZero=*/false))
1576e8d8bef9SDimitry Andric         return false;
1577e8d8bef9SDimitry Andric 
1578e8d8bef9SDimitry Andric       // Argument is a constant expression with an integer type.
1579e8d8bef9SDimitry Andric       Hint.ValueExpr = R.get();
1580e8d8bef9SDimitry Andric     }
15810b57cec5SDimitry Andric   } else {
15820b57cec5SDimitry Andric     // Enter constant expression including eof terminator into token stream.
15830b57cec5SDimitry Andric     PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
15840b57cec5SDimitry Andric                         /*IsReinject=*/false);
15850b57cec5SDimitry Andric     ConsumeAnnotationToken();
15860b57cec5SDimitry Andric     ExprResult R = ParseConstantExpression();
15870b57cec5SDimitry Andric 
15880b57cec5SDimitry Andric     // Tokens following an error in an ill-formed constant expression will
15890b57cec5SDimitry Andric     // remain in the token stream and must be removed.
15900b57cec5SDimitry Andric     if (Tok.isNot(tok::eof)) {
15910b57cec5SDimitry Andric       Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
15920b57cec5SDimitry Andric           << PragmaLoopHintString(Info->PragmaName, Info->Option);
15930b57cec5SDimitry Andric       while (Tok.isNot(tok::eof))
15940b57cec5SDimitry Andric         ConsumeAnyToken();
15950b57cec5SDimitry Andric     }
15960b57cec5SDimitry Andric 
15970b57cec5SDimitry Andric     ConsumeToken(); // Consume the constant expression eof terminator.
15980b57cec5SDimitry Andric 
15990b57cec5SDimitry Andric     if (R.isInvalid() ||
1600*0fca6ea1SDimitry Andric         Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation(),
1601*0fca6ea1SDimitry Andric                                   /*AllowZero=*/true))
16020b57cec5SDimitry Andric       return false;
16030b57cec5SDimitry Andric 
16040b57cec5SDimitry Andric     // Argument is a constant expression with an integer type.
16050b57cec5SDimitry Andric     Hint.ValueExpr = R.get();
16060b57cec5SDimitry Andric   }
16070b57cec5SDimitry Andric 
16080b57cec5SDimitry Andric   Hint.Range = SourceRange(Info->PragmaName.getLocation(),
16090b57cec5SDimitry Andric                            Info->Toks.back().getLocation());
16100b57cec5SDimitry Andric   return true;
16110b57cec5SDimitry Andric }
16120b57cec5SDimitry Andric 
16130b57cec5SDimitry Andric namespace {
16140b57cec5SDimitry Andric struct PragmaAttributeInfo {
16150b57cec5SDimitry Andric   enum ActionType { Push, Pop, Attribute };
16160b57cec5SDimitry Andric   ParsedAttributes &Attributes;
16170b57cec5SDimitry Andric   ActionType Action;
16180b57cec5SDimitry Andric   const IdentifierInfo *Namespace = nullptr;
16190b57cec5SDimitry Andric   ArrayRef<Token> Tokens;
16200b57cec5SDimitry Andric 
16210b57cec5SDimitry Andric   PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
16220b57cec5SDimitry Andric };
16230b57cec5SDimitry Andric 
16240b57cec5SDimitry Andric #include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
16250b57cec5SDimitry Andric 
16260b57cec5SDimitry Andric } // end anonymous namespace
16270b57cec5SDimitry Andric 
16280b57cec5SDimitry Andric static StringRef getIdentifier(const Token &Tok) {
16290b57cec5SDimitry Andric   if (Tok.is(tok::identifier))
16300b57cec5SDimitry Andric     return Tok.getIdentifierInfo()->getName();
16310b57cec5SDimitry Andric   const char *S = tok::getKeywordSpelling(Tok.getKind());
16320b57cec5SDimitry Andric   if (!S)
16330b57cec5SDimitry Andric     return "";
16340b57cec5SDimitry Andric   return S;
16350b57cec5SDimitry Andric }
16360b57cec5SDimitry Andric 
16370b57cec5SDimitry Andric static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
16380b57cec5SDimitry Andric   using namespace attr;
16390b57cec5SDimitry Andric   switch (Rule) {
16400b57cec5SDimitry Andric #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract)                           \
16410b57cec5SDimitry Andric   case Value:                                                                  \
16420b57cec5SDimitry Andric     return IsAbstract;
16430b57cec5SDimitry Andric #include "clang/Basic/AttrSubMatchRulesList.inc"
16440b57cec5SDimitry Andric   }
16450b57cec5SDimitry Andric   llvm_unreachable("Invalid attribute subject match rule");
16460b57cec5SDimitry Andric   return false;
16470b57cec5SDimitry Andric }
16480b57cec5SDimitry Andric 
16490b57cec5SDimitry Andric static void diagnoseExpectedAttributeSubjectSubRule(
16500b57cec5SDimitry Andric     Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
16510b57cec5SDimitry Andric     SourceLocation SubRuleLoc) {
16520b57cec5SDimitry Andric   auto Diagnostic =
16530b57cec5SDimitry Andric       PRef.Diag(SubRuleLoc,
16540b57cec5SDimitry Andric                 diag::err_pragma_attribute_expected_subject_sub_identifier)
16550b57cec5SDimitry Andric       << PrimaryRuleName;
16560b57cec5SDimitry Andric   if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
16570b57cec5SDimitry Andric     Diagnostic << /*SubRulesSupported=*/1 << SubRules;
16580b57cec5SDimitry Andric   else
16590b57cec5SDimitry Andric     Diagnostic << /*SubRulesSupported=*/0;
16600b57cec5SDimitry Andric }
16610b57cec5SDimitry Andric 
16620b57cec5SDimitry Andric static void diagnoseUnknownAttributeSubjectSubRule(
16630b57cec5SDimitry Andric     Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
16640b57cec5SDimitry Andric     StringRef SubRuleName, SourceLocation SubRuleLoc) {
16650b57cec5SDimitry Andric 
16660b57cec5SDimitry Andric   auto Diagnostic =
16670b57cec5SDimitry Andric       PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
16680b57cec5SDimitry Andric       << SubRuleName << PrimaryRuleName;
16690b57cec5SDimitry Andric   if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
16700b57cec5SDimitry Andric     Diagnostic << /*SubRulesSupported=*/1 << SubRules;
16710b57cec5SDimitry Andric   else
16720b57cec5SDimitry Andric     Diagnostic << /*SubRulesSupported=*/0;
16730b57cec5SDimitry Andric }
16740b57cec5SDimitry Andric 
16750b57cec5SDimitry Andric bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
16760b57cec5SDimitry Andric     attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
16770b57cec5SDimitry Andric     SourceLocation &LastMatchRuleEndLoc) {
16780b57cec5SDimitry Andric   bool IsAny = false;
16790b57cec5SDimitry Andric   BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
16800b57cec5SDimitry Andric   if (getIdentifier(Tok) == "any") {
16810b57cec5SDimitry Andric     AnyLoc = ConsumeToken();
16820b57cec5SDimitry Andric     IsAny = true;
16830b57cec5SDimitry Andric     if (AnyParens.expectAndConsume())
16840b57cec5SDimitry Andric       return true;
16850b57cec5SDimitry Andric   }
16860b57cec5SDimitry Andric 
16870b57cec5SDimitry Andric   do {
16880b57cec5SDimitry Andric     // Parse the subject matcher rule.
16890b57cec5SDimitry Andric     StringRef Name = getIdentifier(Tok);
16900b57cec5SDimitry Andric     if (Name.empty()) {
16910b57cec5SDimitry Andric       Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
16920b57cec5SDimitry Andric       return true;
16930b57cec5SDimitry Andric     }
1694bdd1243dSDimitry Andric     std::pair<std::optional<attr::SubjectMatchRule>,
1695bdd1243dSDimitry Andric               std::optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
16960b57cec5SDimitry Andric         Rule = isAttributeSubjectMatchRule(Name);
16970b57cec5SDimitry Andric     if (!Rule.first) {
16980b57cec5SDimitry Andric       Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
16990b57cec5SDimitry Andric       return true;
17000b57cec5SDimitry Andric     }
17010b57cec5SDimitry Andric     attr::SubjectMatchRule PrimaryRule = *Rule.first;
17020b57cec5SDimitry Andric     SourceLocation RuleLoc = ConsumeToken();
17030b57cec5SDimitry Andric 
17040b57cec5SDimitry Andric     BalancedDelimiterTracker Parens(*this, tok::l_paren);
17050b57cec5SDimitry Andric     if (isAbstractAttrMatcherRule(PrimaryRule)) {
17060b57cec5SDimitry Andric       if (Parens.expectAndConsume())
17070b57cec5SDimitry Andric         return true;
17080b57cec5SDimitry Andric     } else if (Parens.consumeOpen()) {
17090b57cec5SDimitry Andric       if (!SubjectMatchRules
17100b57cec5SDimitry Andric                .insert(
17110b57cec5SDimitry Andric                    std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
17120b57cec5SDimitry Andric                .second)
17130b57cec5SDimitry Andric         Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
17140b57cec5SDimitry Andric             << Name
17150b57cec5SDimitry Andric             << FixItHint::CreateRemoval(SourceRange(
17160b57cec5SDimitry Andric                    RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
17170b57cec5SDimitry Andric       LastMatchRuleEndLoc = RuleLoc;
17180b57cec5SDimitry Andric       continue;
17190b57cec5SDimitry Andric     }
17200b57cec5SDimitry Andric 
17210b57cec5SDimitry Andric     // Parse the sub-rules.
17220b57cec5SDimitry Andric     StringRef SubRuleName = getIdentifier(Tok);
17230b57cec5SDimitry Andric     if (SubRuleName.empty()) {
17240b57cec5SDimitry Andric       diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
17250b57cec5SDimitry Andric                                               Tok.getLocation());
17260b57cec5SDimitry Andric       return true;
17270b57cec5SDimitry Andric     }
17280b57cec5SDimitry Andric     attr::SubjectMatchRule SubRule;
17290b57cec5SDimitry Andric     if (SubRuleName == "unless") {
17300b57cec5SDimitry Andric       SourceLocation SubRuleLoc = ConsumeToken();
17310b57cec5SDimitry Andric       BalancedDelimiterTracker Parens(*this, tok::l_paren);
17320b57cec5SDimitry Andric       if (Parens.expectAndConsume())
17330b57cec5SDimitry Andric         return true;
17340b57cec5SDimitry Andric       SubRuleName = getIdentifier(Tok);
17350b57cec5SDimitry Andric       if (SubRuleName.empty()) {
17360b57cec5SDimitry Andric         diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
17370b57cec5SDimitry Andric                                                 SubRuleLoc);
17380b57cec5SDimitry Andric         return true;
17390b57cec5SDimitry Andric       }
17400b57cec5SDimitry Andric       auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
17410b57cec5SDimitry Andric       if (!SubRuleOrNone) {
17420b57cec5SDimitry Andric         std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
17430b57cec5SDimitry Andric         diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
17440b57cec5SDimitry Andric                                                SubRuleUnlessName, SubRuleLoc);
17450b57cec5SDimitry Andric         return true;
17460b57cec5SDimitry Andric       }
17470b57cec5SDimitry Andric       SubRule = *SubRuleOrNone;
17480b57cec5SDimitry Andric       ConsumeToken();
17490b57cec5SDimitry Andric       if (Parens.consumeClose())
17500b57cec5SDimitry Andric         return true;
17510b57cec5SDimitry Andric     } else {
17520b57cec5SDimitry Andric       auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
17530b57cec5SDimitry Andric       if (!SubRuleOrNone) {
17540b57cec5SDimitry Andric         diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
17550b57cec5SDimitry Andric                                                SubRuleName, Tok.getLocation());
17560b57cec5SDimitry Andric         return true;
17570b57cec5SDimitry Andric       }
17580b57cec5SDimitry Andric       SubRule = *SubRuleOrNone;
17590b57cec5SDimitry Andric       ConsumeToken();
17600b57cec5SDimitry Andric     }
17610b57cec5SDimitry Andric     SourceLocation RuleEndLoc = Tok.getLocation();
17620b57cec5SDimitry Andric     LastMatchRuleEndLoc = RuleEndLoc;
17630b57cec5SDimitry Andric     if (Parens.consumeClose())
17640b57cec5SDimitry Andric       return true;
17650b57cec5SDimitry Andric     if (!SubjectMatchRules
17660b57cec5SDimitry Andric              .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
17670b57cec5SDimitry Andric              .second) {
17680b57cec5SDimitry Andric       Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
17690b57cec5SDimitry Andric           << attr::getSubjectMatchRuleSpelling(SubRule)
17700b57cec5SDimitry Andric           << FixItHint::CreateRemoval(SourceRange(
17710b57cec5SDimitry Andric                  RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
17720b57cec5SDimitry Andric       continue;
17730b57cec5SDimitry Andric     }
17740b57cec5SDimitry Andric   } while (IsAny && TryConsumeToken(tok::comma));
17750b57cec5SDimitry Andric 
17760b57cec5SDimitry Andric   if (IsAny)
17770b57cec5SDimitry Andric     if (AnyParens.consumeClose())
17780b57cec5SDimitry Andric       return true;
17790b57cec5SDimitry Andric 
17800b57cec5SDimitry Andric   return false;
17810b57cec5SDimitry Andric }
17820b57cec5SDimitry Andric 
17830b57cec5SDimitry Andric namespace {
17840b57cec5SDimitry Andric 
17850b57cec5SDimitry Andric /// Describes the stage at which attribute subject rule parsing was interrupted.
17860b57cec5SDimitry Andric enum class MissingAttributeSubjectRulesRecoveryPoint {
17870b57cec5SDimitry Andric   Comma,
17880b57cec5SDimitry Andric   ApplyTo,
17890b57cec5SDimitry Andric   Equals,
17900b57cec5SDimitry Andric   Any,
17910b57cec5SDimitry Andric   None,
17920b57cec5SDimitry Andric };
17930b57cec5SDimitry Andric 
17940b57cec5SDimitry Andric MissingAttributeSubjectRulesRecoveryPoint
17950b57cec5SDimitry Andric getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
17960b57cec5SDimitry Andric   if (const auto *II = Tok.getIdentifierInfo()) {
17970b57cec5SDimitry Andric     if (II->isStr("apply_to"))
17980b57cec5SDimitry Andric       return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
17990b57cec5SDimitry Andric     if (II->isStr("any"))
18000b57cec5SDimitry Andric       return MissingAttributeSubjectRulesRecoveryPoint::Any;
18010b57cec5SDimitry Andric   }
18020b57cec5SDimitry Andric   if (Tok.is(tok::equal))
18030b57cec5SDimitry Andric     return MissingAttributeSubjectRulesRecoveryPoint::Equals;
18040b57cec5SDimitry Andric   return MissingAttributeSubjectRulesRecoveryPoint::None;
18050b57cec5SDimitry Andric }
18060b57cec5SDimitry Andric 
18070b57cec5SDimitry Andric /// Creates a diagnostic for the attribute subject rule parsing diagnostic that
18080b57cec5SDimitry Andric /// suggests the possible attribute subject rules in a fix-it together with
18090b57cec5SDimitry Andric /// any other missing tokens.
18100b57cec5SDimitry Andric DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
181181ad6265SDimitry Andric     unsigned DiagID, ParsedAttributes &Attrs,
18120b57cec5SDimitry Andric     MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
18130b57cec5SDimitry Andric   SourceLocation Loc = PRef.getEndOfPreviousToken();
18140b57cec5SDimitry Andric   if (Loc.isInvalid())
18150b57cec5SDimitry Andric     Loc = PRef.getCurToken().getLocation();
18160b57cec5SDimitry Andric   auto Diagnostic = PRef.Diag(Loc, DiagID);
18170b57cec5SDimitry Andric   std::string FixIt;
18180b57cec5SDimitry Andric   MissingAttributeSubjectRulesRecoveryPoint EndPoint =
18190b57cec5SDimitry Andric       getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
18200b57cec5SDimitry Andric   if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
18210b57cec5SDimitry Andric     FixIt = ", ";
18220b57cec5SDimitry Andric   if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
18230b57cec5SDimitry Andric       EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
18240b57cec5SDimitry Andric     FixIt += "apply_to";
18250b57cec5SDimitry Andric   if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
18260b57cec5SDimitry Andric       EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
18270b57cec5SDimitry Andric     FixIt += " = ";
18280b57cec5SDimitry Andric   SourceRange FixItRange(Loc);
18290b57cec5SDimitry Andric   if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
18300b57cec5SDimitry Andric     // Gather the subject match rules that are supported by the attribute.
183181ad6265SDimitry Andric     // Add all the possible rules initially.
183281ad6265SDimitry Andric     llvm::BitVector IsMatchRuleAvailable(attr::SubjectMatchRule_Last + 1, true);
183381ad6265SDimitry Andric     // Remove the ones that are not supported by any of the attributes.
183481ad6265SDimitry Andric     for (const ParsedAttr &Attribute : Attrs) {
183581ad6265SDimitry Andric       SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> MatchRules;
183681ad6265SDimitry Andric       Attribute.getMatchRules(PRef.getLangOpts(), MatchRules);
183781ad6265SDimitry Andric       llvm::BitVector IsSupported(attr::SubjectMatchRule_Last + 1);
183881ad6265SDimitry Andric       for (const auto &Rule : MatchRules) {
183981ad6265SDimitry Andric         // Ensure that the missing rule is reported in the fix-it only when it's
184081ad6265SDimitry Andric         // supported in the current language mode.
184181ad6265SDimitry Andric         if (!Rule.second)
184281ad6265SDimitry Andric           continue;
184381ad6265SDimitry Andric         IsSupported[Rule.first] = true;
184481ad6265SDimitry Andric       }
184581ad6265SDimitry Andric       IsMatchRuleAvailable &= IsSupported;
184681ad6265SDimitry Andric     }
184781ad6265SDimitry Andric     if (IsMatchRuleAvailable.count() == 0) {
18480b57cec5SDimitry Andric       // FIXME: We can emit a "fix-it" with a subject list placeholder when
18490b57cec5SDimitry Andric       // placeholders will be supported by the fix-its.
18500b57cec5SDimitry Andric       return Diagnostic;
18510b57cec5SDimitry Andric     }
18520b57cec5SDimitry Andric     FixIt += "any(";
18530b57cec5SDimitry Andric     bool NeedsComma = false;
185481ad6265SDimitry Andric     for (unsigned I = 0; I <= attr::SubjectMatchRule_Last; I++) {
185581ad6265SDimitry Andric       if (!IsMatchRuleAvailable[I])
18560b57cec5SDimitry Andric         continue;
18570b57cec5SDimitry Andric       if (NeedsComma)
18580b57cec5SDimitry Andric         FixIt += ", ";
18590b57cec5SDimitry Andric       else
18600b57cec5SDimitry Andric         NeedsComma = true;
186181ad6265SDimitry Andric       FixIt += attr::getSubjectMatchRuleSpelling(
186281ad6265SDimitry Andric           static_cast<attr::SubjectMatchRule>(I));
18630b57cec5SDimitry Andric     }
18640b57cec5SDimitry Andric     FixIt += ")";
18650b57cec5SDimitry Andric     // Check if we need to remove the range
18660b57cec5SDimitry Andric     PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
18670b57cec5SDimitry Andric     FixItRange.setEnd(PRef.getCurToken().getLocation());
18680b57cec5SDimitry Andric   }
18690b57cec5SDimitry Andric   if (FixItRange.getBegin() == FixItRange.getEnd())
18700b57cec5SDimitry Andric     Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
18710b57cec5SDimitry Andric   else
18720b57cec5SDimitry Andric     Diagnostic << FixItHint::CreateReplacement(
18730b57cec5SDimitry Andric         CharSourceRange::getCharRange(FixItRange), FixIt);
18740b57cec5SDimitry Andric   return Diagnostic;
18750b57cec5SDimitry Andric }
18760b57cec5SDimitry Andric 
18770b57cec5SDimitry Andric } // end anonymous namespace
18780b57cec5SDimitry Andric 
18790b57cec5SDimitry Andric void Parser::HandlePragmaAttribute() {
18800b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_attribute) &&
18810b57cec5SDimitry Andric          "Expected #pragma attribute annotation token");
18820b57cec5SDimitry Andric   SourceLocation PragmaLoc = Tok.getLocation();
18830b57cec5SDimitry Andric   auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
18840b57cec5SDimitry Andric   if (Info->Action == PragmaAttributeInfo::Pop) {
18850b57cec5SDimitry Andric     ConsumeAnnotationToken();
18860b57cec5SDimitry Andric     Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
18870b57cec5SDimitry Andric     return;
18880b57cec5SDimitry Andric   }
18890b57cec5SDimitry Andric   // Parse the actual attribute with its arguments.
18900b57cec5SDimitry Andric   assert((Info->Action == PragmaAttributeInfo::Push ||
18910b57cec5SDimitry Andric           Info->Action == PragmaAttributeInfo::Attribute) &&
18920b57cec5SDimitry Andric          "Unexpected #pragma attribute command");
18930b57cec5SDimitry Andric 
18940b57cec5SDimitry Andric   if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
18950b57cec5SDimitry Andric     ConsumeAnnotationToken();
18960b57cec5SDimitry Andric     Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
18970b57cec5SDimitry Andric     return;
18980b57cec5SDimitry Andric   }
18990b57cec5SDimitry Andric 
19000b57cec5SDimitry Andric   PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false,
19010b57cec5SDimitry Andric                       /*IsReinject=*/false);
19020b57cec5SDimitry Andric   ConsumeAnnotationToken();
19030b57cec5SDimitry Andric 
19040b57cec5SDimitry Andric   ParsedAttributes &Attrs = Info->Attributes;
19050b57cec5SDimitry Andric   Attrs.clearListOnly();
19060b57cec5SDimitry Andric 
19070b57cec5SDimitry Andric   auto SkipToEnd = [this]() {
19080b57cec5SDimitry Andric     SkipUntil(tok::eof, StopBeforeMatch);
19090b57cec5SDimitry Andric     ConsumeToken();
19100b57cec5SDimitry Andric   };
19110b57cec5SDimitry Andric 
191206c3fb27SDimitry Andric   if ((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) ||
191306c3fb27SDimitry Andric       Tok.isRegularKeywordAttribute()) {
19140b57cec5SDimitry Andric     // Parse the CXX11 style attribute.
19150b57cec5SDimitry Andric     ParseCXX11AttributeSpecifier(Attrs);
19160b57cec5SDimitry Andric   } else if (Tok.is(tok::kw___attribute)) {
19170b57cec5SDimitry Andric     ConsumeToken();
19180b57cec5SDimitry Andric     if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
19190b57cec5SDimitry Andric                          "attribute"))
19200b57cec5SDimitry Andric       return SkipToEnd();
19210b57cec5SDimitry Andric     if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
19220b57cec5SDimitry Andric       return SkipToEnd();
19230b57cec5SDimitry Andric 
1924349cc55cSDimitry Andric     // FIXME: The practical usefulness of completion here is limited because
1925349cc55cSDimitry Andric     // we only get here if the line has balanced parens.
1926349cc55cSDimitry Andric     if (Tok.is(tok::code_completion)) {
1927349cc55cSDimitry Andric       cutOffParsing();
1928349cc55cSDimitry Andric       // FIXME: suppress completion of unsupported attributes?
1929*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteAttribute(
1930*0fca6ea1SDimitry Andric           AttributeCommonInfo::Syntax::AS_GNU);
1931349cc55cSDimitry Andric       return SkipToEnd();
1932349cc55cSDimitry Andric     }
1933349cc55cSDimitry Andric 
193481ad6265SDimitry Andric     // Parse the comma-separated list of attributes.
193581ad6265SDimitry Andric     do {
19360b57cec5SDimitry Andric       if (Tok.isNot(tok::identifier)) {
19370b57cec5SDimitry Andric         Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
19380b57cec5SDimitry Andric         SkipToEnd();
19390b57cec5SDimitry Andric         return;
19400b57cec5SDimitry Andric       }
19410b57cec5SDimitry Andric       IdentifierInfo *AttrName = Tok.getIdentifierInfo();
19420b57cec5SDimitry Andric       SourceLocation AttrNameLoc = ConsumeToken();
19430b57cec5SDimitry Andric 
19440b57cec5SDimitry Andric       if (Tok.isNot(tok::l_paren))
19450b57cec5SDimitry Andric         Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
194606c3fb27SDimitry Andric                      ParsedAttr::Form::GNU());
19470b57cec5SDimitry Andric       else
19480b57cec5SDimitry Andric         ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
19490b57cec5SDimitry Andric                               /*ScopeName=*/nullptr,
195006c3fb27SDimitry Andric                               /*ScopeLoc=*/SourceLocation(),
195106c3fb27SDimitry Andric                               ParsedAttr::Form::GNU(),
19520b57cec5SDimitry Andric                               /*Declarator=*/nullptr);
195381ad6265SDimitry Andric     } while (TryConsumeToken(tok::comma));
19540b57cec5SDimitry Andric 
19550b57cec5SDimitry Andric     if (ExpectAndConsume(tok::r_paren))
19560b57cec5SDimitry Andric       return SkipToEnd();
19570b57cec5SDimitry Andric     if (ExpectAndConsume(tok::r_paren))
19580b57cec5SDimitry Andric       return SkipToEnd();
19590b57cec5SDimitry Andric   } else if (Tok.is(tok::kw___declspec)) {
19600b57cec5SDimitry Andric     ParseMicrosoftDeclSpecs(Attrs);
19610b57cec5SDimitry Andric   } else {
19620b57cec5SDimitry Andric     Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
19630b57cec5SDimitry Andric     if (Tok.getIdentifierInfo()) {
19640b57cec5SDimitry Andric       // If we suspect that this is an attribute suggest the use of
19650b57cec5SDimitry Andric       // '__attribute__'.
1966a7dea167SDimitry Andric       if (ParsedAttr::getParsedKind(
1967a7dea167SDimitry Andric               Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1968a7dea167SDimitry Andric               ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) {
19690b57cec5SDimitry Andric         SourceLocation InsertStartLoc = Tok.getLocation();
19700b57cec5SDimitry Andric         ConsumeToken();
19710b57cec5SDimitry Andric         if (Tok.is(tok::l_paren)) {
19720b57cec5SDimitry Andric           ConsumeAnyToken();
19730b57cec5SDimitry Andric           SkipUntil(tok::r_paren, StopBeforeMatch);
19740b57cec5SDimitry Andric           if (Tok.isNot(tok::r_paren))
19750b57cec5SDimitry Andric             return SkipToEnd();
19760b57cec5SDimitry Andric         }
19770b57cec5SDimitry Andric         Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
19780b57cec5SDimitry Andric             << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
19790b57cec5SDimitry Andric             << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
19800b57cec5SDimitry Andric       }
19810b57cec5SDimitry Andric     }
19820b57cec5SDimitry Andric     SkipToEnd();
19830b57cec5SDimitry Andric     return;
19840b57cec5SDimitry Andric   }
19850b57cec5SDimitry Andric 
19860b57cec5SDimitry Andric   if (Attrs.empty() || Attrs.begin()->isInvalid()) {
19870b57cec5SDimitry Andric     SkipToEnd();
19880b57cec5SDimitry Andric     return;
19890b57cec5SDimitry Andric   }
19900b57cec5SDimitry Andric 
199181ad6265SDimitry Andric   for (const ParsedAttr &Attribute : Attrs) {
19920b57cec5SDimitry Andric     if (!Attribute.isSupportedByPragmaAttribute()) {
19930b57cec5SDimitry Andric       Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
1994a7dea167SDimitry Andric           << Attribute;
19950b57cec5SDimitry Andric       SkipToEnd();
19960b57cec5SDimitry Andric       return;
19970b57cec5SDimitry Andric     }
199881ad6265SDimitry Andric   }
19990b57cec5SDimitry Andric 
20000b57cec5SDimitry Andric   // Parse the subject-list.
20010b57cec5SDimitry Andric   if (!TryConsumeToken(tok::comma)) {
20020b57cec5SDimitry Andric     createExpectedAttributeSubjectRulesTokenDiagnostic(
200381ad6265SDimitry Andric         diag::err_expected, Attrs,
20040b57cec5SDimitry Andric         MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
20050b57cec5SDimitry Andric         << tok::comma;
20060b57cec5SDimitry Andric     SkipToEnd();
20070b57cec5SDimitry Andric     return;
20080b57cec5SDimitry Andric   }
20090b57cec5SDimitry Andric 
20100b57cec5SDimitry Andric   if (Tok.isNot(tok::identifier)) {
20110b57cec5SDimitry Andric     createExpectedAttributeSubjectRulesTokenDiagnostic(
201281ad6265SDimitry Andric         diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
20130b57cec5SDimitry Andric         MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
20140b57cec5SDimitry Andric     SkipToEnd();
20150b57cec5SDimitry Andric     return;
20160b57cec5SDimitry Andric   }
20170b57cec5SDimitry Andric   const IdentifierInfo *II = Tok.getIdentifierInfo();
20180b57cec5SDimitry Andric   if (!II->isStr("apply_to")) {
20190b57cec5SDimitry Andric     createExpectedAttributeSubjectRulesTokenDiagnostic(
202081ad6265SDimitry Andric         diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
20210b57cec5SDimitry Andric         MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
20220b57cec5SDimitry Andric     SkipToEnd();
20230b57cec5SDimitry Andric     return;
20240b57cec5SDimitry Andric   }
20250b57cec5SDimitry Andric   ConsumeToken();
20260b57cec5SDimitry Andric 
20270b57cec5SDimitry Andric   if (!TryConsumeToken(tok::equal)) {
20280b57cec5SDimitry Andric     createExpectedAttributeSubjectRulesTokenDiagnostic(
202981ad6265SDimitry Andric         diag::err_expected, Attrs,
20300b57cec5SDimitry Andric         MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
20310b57cec5SDimitry Andric         << tok::equal;
20320b57cec5SDimitry Andric     SkipToEnd();
20330b57cec5SDimitry Andric     return;
20340b57cec5SDimitry Andric   }
20350b57cec5SDimitry Andric 
20360b57cec5SDimitry Andric   attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
20370b57cec5SDimitry Andric   SourceLocation AnyLoc, LastMatchRuleEndLoc;
20380b57cec5SDimitry Andric   if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
20390b57cec5SDimitry Andric                                               LastMatchRuleEndLoc)) {
20400b57cec5SDimitry Andric     SkipToEnd();
20410b57cec5SDimitry Andric     return;
20420b57cec5SDimitry Andric   }
20430b57cec5SDimitry Andric 
20440b57cec5SDimitry Andric   // Tokens following an ill-formed attribute will remain in the token stream
20450b57cec5SDimitry Andric   // and must be removed.
20460b57cec5SDimitry Andric   if (Tok.isNot(tok::eof)) {
20470b57cec5SDimitry Andric     Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
20480b57cec5SDimitry Andric     SkipToEnd();
20490b57cec5SDimitry Andric     return;
20500b57cec5SDimitry Andric   }
20510b57cec5SDimitry Andric 
20520b57cec5SDimitry Andric   // Consume the eof terminator token.
20530b57cec5SDimitry Andric   ConsumeToken();
20540b57cec5SDimitry Andric 
20550b57cec5SDimitry Andric   // Handle a mixed push/attribute by desurging to a push, then an attribute.
20560b57cec5SDimitry Andric   if (Info->Action == PragmaAttributeInfo::Push)
20570b57cec5SDimitry Andric     Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
20580b57cec5SDimitry Andric 
205981ad6265SDimitry Andric   for (ParsedAttr &Attribute : Attrs) {
20600b57cec5SDimitry Andric     Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
206181ad6265SDimitry Andric                                           SubjectMatchRules);
206281ad6265SDimitry Andric   }
20630b57cec5SDimitry Andric }
20640b57cec5SDimitry Andric 
20650b57cec5SDimitry Andric // #pragma GCC visibility comes in two variants:
20660b57cec5SDimitry Andric //   'push' '(' [visibility] ')'
20670b57cec5SDimitry Andric //   'pop'
20680b57cec5SDimitry Andric void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
20690b57cec5SDimitry Andric                                               PragmaIntroducer Introducer,
20700b57cec5SDimitry Andric                                               Token &VisTok) {
20710b57cec5SDimitry Andric   SourceLocation VisLoc = VisTok.getLocation();
20720b57cec5SDimitry Andric 
20730b57cec5SDimitry Andric   Token Tok;
20740b57cec5SDimitry Andric   PP.LexUnexpandedToken(Tok);
20750b57cec5SDimitry Andric 
20760b57cec5SDimitry Andric   const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
20770b57cec5SDimitry Andric 
20780b57cec5SDimitry Andric   const IdentifierInfo *VisType;
20790b57cec5SDimitry Andric   if (PushPop && PushPop->isStr("pop")) {
20800b57cec5SDimitry Andric     VisType = nullptr;
20810b57cec5SDimitry Andric   } else if (PushPop && PushPop->isStr("push")) {
20820b57cec5SDimitry Andric     PP.LexUnexpandedToken(Tok);
20830b57cec5SDimitry Andric     if (Tok.isNot(tok::l_paren)) {
20840b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
20850b57cec5SDimitry Andric         << "visibility";
20860b57cec5SDimitry Andric       return;
20870b57cec5SDimitry Andric     }
20880b57cec5SDimitry Andric     PP.LexUnexpandedToken(Tok);
20890b57cec5SDimitry Andric     VisType = Tok.getIdentifierInfo();
20900b57cec5SDimitry Andric     if (!VisType) {
20910b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
20920b57cec5SDimitry Andric         << "visibility";
20930b57cec5SDimitry Andric       return;
20940b57cec5SDimitry Andric     }
20950b57cec5SDimitry Andric     PP.LexUnexpandedToken(Tok);
20960b57cec5SDimitry Andric     if (Tok.isNot(tok::r_paren)) {
20970b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
20980b57cec5SDimitry Andric         << "visibility";
20990b57cec5SDimitry Andric       return;
21000b57cec5SDimitry Andric     }
21010b57cec5SDimitry Andric   } else {
21020b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
21030b57cec5SDimitry Andric       << "visibility";
21040b57cec5SDimitry Andric     return;
21050b57cec5SDimitry Andric   }
21060b57cec5SDimitry Andric   SourceLocation EndLoc = Tok.getLocation();
21070b57cec5SDimitry Andric   PP.LexUnexpandedToken(Tok);
21080b57cec5SDimitry Andric   if (Tok.isNot(tok::eod)) {
21090b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
21100b57cec5SDimitry Andric       << "visibility";
21110b57cec5SDimitry Andric     return;
21120b57cec5SDimitry Andric   }
21130b57cec5SDimitry Andric 
2114a7dea167SDimitry Andric   auto Toks = std::make_unique<Token[]>(1);
21150b57cec5SDimitry Andric   Toks[0].startToken();
21160b57cec5SDimitry Andric   Toks[0].setKind(tok::annot_pragma_vis);
21170b57cec5SDimitry Andric   Toks[0].setLocation(VisLoc);
21180b57cec5SDimitry Andric   Toks[0].setAnnotationEndLoc(EndLoc);
21190b57cec5SDimitry Andric   Toks[0].setAnnotationValue(
21200b57cec5SDimitry Andric       const_cast<void *>(static_cast<const void *>(VisType)));
21210b57cec5SDimitry Andric   PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true,
21220b57cec5SDimitry Andric                       /*IsReinject=*/false);
21230b57cec5SDimitry Andric }
21240b57cec5SDimitry Andric 
21250b57cec5SDimitry Andric // #pragma pack(...) comes in the following delicious flavors:
21260b57cec5SDimitry Andric //   pack '(' [integer] ')'
21270b57cec5SDimitry Andric //   pack '(' 'show' ')'
21280b57cec5SDimitry Andric //   pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
21290b57cec5SDimitry Andric void PragmaPackHandler::HandlePragma(Preprocessor &PP,
21300b57cec5SDimitry Andric                                      PragmaIntroducer Introducer,
21310b57cec5SDimitry Andric                                      Token &PackTok) {
21320b57cec5SDimitry Andric   SourceLocation PackLoc = PackTok.getLocation();
21330b57cec5SDimitry Andric 
21340b57cec5SDimitry Andric   Token Tok;
21350b57cec5SDimitry Andric   PP.Lex(Tok);
21360b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren)) {
21370b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
21380b57cec5SDimitry Andric     return;
21390b57cec5SDimitry Andric   }
21400b57cec5SDimitry Andric 
21410b57cec5SDimitry Andric   Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
21420b57cec5SDimitry Andric   StringRef SlotLabel;
21430b57cec5SDimitry Andric   Token Alignment;
21440b57cec5SDimitry Andric   Alignment.startToken();
21450b57cec5SDimitry Andric   PP.Lex(Tok);
21460b57cec5SDimitry Andric   if (Tok.is(tok::numeric_constant)) {
21470b57cec5SDimitry Andric     Alignment = Tok;
21480b57cec5SDimitry Andric 
21490b57cec5SDimitry Andric     PP.Lex(Tok);
21500b57cec5SDimitry Andric 
21510b57cec5SDimitry Andric     // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
21520b57cec5SDimitry Andric     // the push/pop stack.
2153e8d8bef9SDimitry Andric     // In Apple gcc/XL, #pragma pack(4) is equivalent to #pragma pack(push, 4)
2154e8d8bef9SDimitry Andric     Action = (PP.getLangOpts().ApplePragmaPack || PP.getLangOpts().XLPragmaPack)
2155e8d8bef9SDimitry Andric                  ? Sema::PSK_Push_Set
2156e8d8bef9SDimitry Andric                  : Sema::PSK_Set;
21570b57cec5SDimitry Andric   } else if (Tok.is(tok::identifier)) {
21580b57cec5SDimitry Andric     const IdentifierInfo *II = Tok.getIdentifierInfo();
21590b57cec5SDimitry Andric     if (II->isStr("show")) {
21600b57cec5SDimitry Andric       Action = Sema::PSK_Show;
21610b57cec5SDimitry Andric       PP.Lex(Tok);
21620b57cec5SDimitry Andric     } else {
21630b57cec5SDimitry Andric       if (II->isStr("push")) {
21640b57cec5SDimitry Andric         Action = Sema::PSK_Push;
21650b57cec5SDimitry Andric       } else if (II->isStr("pop")) {
21660b57cec5SDimitry Andric         Action = Sema::PSK_Pop;
21670b57cec5SDimitry Andric       } else {
21680b57cec5SDimitry Andric         PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
21690b57cec5SDimitry Andric         return;
21700b57cec5SDimitry Andric       }
21710b57cec5SDimitry Andric       PP.Lex(Tok);
21720b57cec5SDimitry Andric 
21730b57cec5SDimitry Andric       if (Tok.is(tok::comma)) {
21740b57cec5SDimitry Andric         PP.Lex(Tok);
21750b57cec5SDimitry Andric 
21760b57cec5SDimitry Andric         if (Tok.is(tok::numeric_constant)) {
21770b57cec5SDimitry Andric           Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
21780b57cec5SDimitry Andric           Alignment = Tok;
21790b57cec5SDimitry Andric 
21800b57cec5SDimitry Andric           PP.Lex(Tok);
21810b57cec5SDimitry Andric         } else if (Tok.is(tok::identifier)) {
21820b57cec5SDimitry Andric           SlotLabel = Tok.getIdentifierInfo()->getName();
21830b57cec5SDimitry Andric           PP.Lex(Tok);
21840b57cec5SDimitry Andric 
21850b57cec5SDimitry Andric           if (Tok.is(tok::comma)) {
21860b57cec5SDimitry Andric             PP.Lex(Tok);
21870b57cec5SDimitry Andric 
21880b57cec5SDimitry Andric             if (Tok.isNot(tok::numeric_constant)) {
21890b57cec5SDimitry Andric               PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
21900b57cec5SDimitry Andric               return;
21910b57cec5SDimitry Andric             }
21920b57cec5SDimitry Andric 
21930b57cec5SDimitry Andric             Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
21940b57cec5SDimitry Andric             Alignment = Tok;
21950b57cec5SDimitry Andric 
21960b57cec5SDimitry Andric             PP.Lex(Tok);
21970b57cec5SDimitry Andric           }
21980b57cec5SDimitry Andric         } else {
21990b57cec5SDimitry Andric           PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
22000b57cec5SDimitry Andric           return;
22010b57cec5SDimitry Andric         }
22020b57cec5SDimitry Andric       }
22030b57cec5SDimitry Andric     }
2204e8d8bef9SDimitry Andric   } else if (PP.getLangOpts().ApplePragmaPack ||
2205e8d8bef9SDimitry Andric              PP.getLangOpts().XLPragmaPack) {
22060b57cec5SDimitry Andric     // In MSVC/gcc, #pragma pack() resets the alignment without affecting
22070b57cec5SDimitry Andric     // the push/pop stack.
2208e8d8bef9SDimitry Andric     // In Apple gcc and IBM XL, #pragma pack() is equivalent to #pragma
2209e8d8bef9SDimitry Andric     // pack(pop).
22100b57cec5SDimitry Andric     Action = Sema::PSK_Pop;
22110b57cec5SDimitry Andric   }
22120b57cec5SDimitry Andric 
22130b57cec5SDimitry Andric   if (Tok.isNot(tok::r_paren)) {
22140b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
22150b57cec5SDimitry Andric     return;
22160b57cec5SDimitry Andric   }
22170b57cec5SDimitry Andric 
22180b57cec5SDimitry Andric   SourceLocation RParenLoc = Tok.getLocation();
22190b57cec5SDimitry Andric   PP.Lex(Tok);
22200b57cec5SDimitry Andric   if (Tok.isNot(tok::eod)) {
22210b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
22220b57cec5SDimitry Andric     return;
22230b57cec5SDimitry Andric   }
22240b57cec5SDimitry Andric 
222506c3fb27SDimitry Andric   Sema::PragmaPackInfo *Info =
222606c3fb27SDimitry Andric       PP.getPreprocessorAllocator().Allocate<Sema::PragmaPackInfo>(1);
22270b57cec5SDimitry Andric   Info->Action = Action;
22280b57cec5SDimitry Andric   Info->SlotLabel = SlotLabel;
22290b57cec5SDimitry Andric   Info->Alignment = Alignment;
22300b57cec5SDimitry Andric 
22310b57cec5SDimitry Andric   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
22320b57cec5SDimitry Andric                               1);
22330b57cec5SDimitry Andric   Toks[0].startToken();
22340b57cec5SDimitry Andric   Toks[0].setKind(tok::annot_pragma_pack);
22350b57cec5SDimitry Andric   Toks[0].setLocation(PackLoc);
22360b57cec5SDimitry Andric   Toks[0].setAnnotationEndLoc(RParenLoc);
22370b57cec5SDimitry Andric   Toks[0].setAnnotationValue(static_cast<void*>(Info));
22380b57cec5SDimitry Andric   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
22390b57cec5SDimitry Andric                       /*IsReinject=*/false);
22400b57cec5SDimitry Andric }
22410b57cec5SDimitry Andric 
22420b57cec5SDimitry Andric // #pragma ms_struct on
22430b57cec5SDimitry Andric // #pragma ms_struct off
22440b57cec5SDimitry Andric void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
22450b57cec5SDimitry Andric                                          PragmaIntroducer Introducer,
22460b57cec5SDimitry Andric                                          Token &MSStructTok) {
22470b57cec5SDimitry Andric   PragmaMSStructKind Kind = PMSST_OFF;
22480b57cec5SDimitry Andric 
22490b57cec5SDimitry Andric   Token Tok;
22500b57cec5SDimitry Andric   PP.Lex(Tok);
22510b57cec5SDimitry Andric   if (Tok.isNot(tok::identifier)) {
22520b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
22530b57cec5SDimitry Andric     return;
22540b57cec5SDimitry Andric   }
22550b57cec5SDimitry Andric   SourceLocation EndLoc = Tok.getLocation();
22560b57cec5SDimitry Andric   const IdentifierInfo *II = Tok.getIdentifierInfo();
22570b57cec5SDimitry Andric   if (II->isStr("on")) {
22580b57cec5SDimitry Andric     Kind = PMSST_ON;
22590b57cec5SDimitry Andric     PP.Lex(Tok);
22600b57cec5SDimitry Andric   }
22610b57cec5SDimitry Andric   else if (II->isStr("off") || II->isStr("reset"))
22620b57cec5SDimitry Andric     PP.Lex(Tok);
22630b57cec5SDimitry Andric   else {
22640b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
22650b57cec5SDimitry Andric     return;
22660b57cec5SDimitry Andric   }
22670b57cec5SDimitry Andric 
22680b57cec5SDimitry Andric   if (Tok.isNot(tok::eod)) {
22690b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
22700b57cec5SDimitry Andric       << "ms_struct";
22710b57cec5SDimitry Andric     return;
22720b57cec5SDimitry Andric   }
22730b57cec5SDimitry Andric 
22740b57cec5SDimitry Andric   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
22750b57cec5SDimitry Andric                               1);
22760b57cec5SDimitry Andric   Toks[0].startToken();
22770b57cec5SDimitry Andric   Toks[0].setKind(tok::annot_pragma_msstruct);
22780b57cec5SDimitry Andric   Toks[0].setLocation(MSStructTok.getLocation());
22790b57cec5SDimitry Andric   Toks[0].setAnnotationEndLoc(EndLoc);
22800b57cec5SDimitry Andric   Toks[0].setAnnotationValue(reinterpret_cast<void*>(
22810b57cec5SDimitry Andric                              static_cast<uintptr_t>(Kind)));
22820b57cec5SDimitry Andric   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
22830b57cec5SDimitry Andric                       /*IsReinject=*/false);
22840b57cec5SDimitry Andric }
22850b57cec5SDimitry Andric 
2286a7dea167SDimitry Andric // #pragma clang section bss="abc" data="" rodata="def" text="" relro=""
22870b57cec5SDimitry Andric void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
22880b57cec5SDimitry Andric                                              PragmaIntroducer Introducer,
22890b57cec5SDimitry Andric                                              Token &FirstToken) {
22900b57cec5SDimitry Andric 
22910b57cec5SDimitry Andric   Token Tok;
22920b57cec5SDimitry Andric   auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
22930b57cec5SDimitry Andric 
22940b57cec5SDimitry Andric   PP.Lex(Tok); // eat 'section'
22950b57cec5SDimitry Andric   while (Tok.isNot(tok::eod)) {
22960b57cec5SDimitry Andric     if (Tok.isNot(tok::identifier)) {
22970b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
22980b57cec5SDimitry Andric       return;
22990b57cec5SDimitry Andric     }
23000b57cec5SDimitry Andric 
23010b57cec5SDimitry Andric     const IdentifierInfo *SecType = Tok.getIdentifierInfo();
23020b57cec5SDimitry Andric     if (SecType->isStr("bss"))
23030b57cec5SDimitry Andric       SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
23040b57cec5SDimitry Andric     else if (SecType->isStr("data"))
23050b57cec5SDimitry Andric       SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
23060b57cec5SDimitry Andric     else if (SecType->isStr("rodata"))
23070b57cec5SDimitry Andric       SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
2308a7dea167SDimitry Andric     else if (SecType->isStr("relro"))
2309a7dea167SDimitry Andric       SecKind = Sema::PragmaClangSectionKind::PCSK_Relro;
23100b57cec5SDimitry Andric     else if (SecType->isStr("text"))
23110b57cec5SDimitry Andric       SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
23120b57cec5SDimitry Andric     else {
23130b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
23140b57cec5SDimitry Andric       return;
23150b57cec5SDimitry Andric     }
23160b57cec5SDimitry Andric 
23175ffd83dbSDimitry Andric     SourceLocation PragmaLocation = Tok.getLocation();
23180b57cec5SDimitry Andric     PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
23190b57cec5SDimitry Andric     if (Tok.isNot(tok::equal)) {
23200b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
23210b57cec5SDimitry Andric       return;
23220b57cec5SDimitry Andric     }
23230b57cec5SDimitry Andric 
23240b57cec5SDimitry Andric     std::string SecName;
23250b57cec5SDimitry Andric     if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
23260b57cec5SDimitry Andric       return;
23270b57cec5SDimitry Andric 
23285ffd83dbSDimitry Andric     Actions.ActOnPragmaClangSection(
23295ffd83dbSDimitry Andric         PragmaLocation,
23305ffd83dbSDimitry Andric         (SecName.size() ? Sema::PragmaClangSectionAction::PCSA_Set
23315ffd83dbSDimitry Andric                         : Sema::PragmaClangSectionAction::PCSA_Clear),
23320b57cec5SDimitry Andric         SecKind, SecName);
23330b57cec5SDimitry Andric   }
23340b57cec5SDimitry Andric }
23350b57cec5SDimitry Andric 
23360b57cec5SDimitry Andric // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
23370b57cec5SDimitry Andric // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
2338e8d8bef9SDimitry Andric // #pragma 'align' '(' {'native','natural','mac68k','power','reset'} ')'
23390b57cec5SDimitry Andric static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
23400b57cec5SDimitry Andric                              bool IsOptions) {
23410b57cec5SDimitry Andric   Token Tok;
23420b57cec5SDimitry Andric 
23430b57cec5SDimitry Andric   if (IsOptions) {
23440b57cec5SDimitry Andric     PP.Lex(Tok);
23450b57cec5SDimitry Andric     if (Tok.isNot(tok::identifier) ||
23460b57cec5SDimitry Andric         !Tok.getIdentifierInfo()->isStr("align")) {
23470b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
23480b57cec5SDimitry Andric       return;
23490b57cec5SDimitry Andric     }
23500b57cec5SDimitry Andric   }
23510b57cec5SDimitry Andric 
23520b57cec5SDimitry Andric   PP.Lex(Tok);
2353e8d8bef9SDimitry Andric   if (PP.getLangOpts().XLPragmaPack) {
2354e8d8bef9SDimitry Andric     if (Tok.isNot(tok::l_paren)) {
2355e8d8bef9SDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "align";
2356e8d8bef9SDimitry Andric       return;
2357e8d8bef9SDimitry Andric     }
2358e8d8bef9SDimitry Andric   } else if (Tok.isNot(tok::equal)) {
23590b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
23600b57cec5SDimitry Andric       << IsOptions;
23610b57cec5SDimitry Andric     return;
23620b57cec5SDimitry Andric   }
23630b57cec5SDimitry Andric 
23640b57cec5SDimitry Andric   PP.Lex(Tok);
23650b57cec5SDimitry Andric   if (Tok.isNot(tok::identifier)) {
23660b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
23670b57cec5SDimitry Andric       << (IsOptions ? "options" : "align");
23680b57cec5SDimitry Andric     return;
23690b57cec5SDimitry Andric   }
23700b57cec5SDimitry Andric 
23710b57cec5SDimitry Andric   Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
23720b57cec5SDimitry Andric   const IdentifierInfo *II = Tok.getIdentifierInfo();
23730b57cec5SDimitry Andric   if (II->isStr("native"))
23740b57cec5SDimitry Andric     Kind = Sema::POAK_Native;
23750b57cec5SDimitry Andric   else if (II->isStr("natural"))
23760b57cec5SDimitry Andric     Kind = Sema::POAK_Natural;
23770b57cec5SDimitry Andric   else if (II->isStr("packed"))
23780b57cec5SDimitry Andric     Kind = Sema::POAK_Packed;
23790b57cec5SDimitry Andric   else if (II->isStr("power"))
23800b57cec5SDimitry Andric     Kind = Sema::POAK_Power;
23810b57cec5SDimitry Andric   else if (II->isStr("mac68k"))
23820b57cec5SDimitry Andric     Kind = Sema::POAK_Mac68k;
23830b57cec5SDimitry Andric   else if (II->isStr("reset"))
23840b57cec5SDimitry Andric     Kind = Sema::POAK_Reset;
23850b57cec5SDimitry Andric   else {
23860b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
23870b57cec5SDimitry Andric       << IsOptions;
23880b57cec5SDimitry Andric     return;
23890b57cec5SDimitry Andric   }
23900b57cec5SDimitry Andric 
2391e8d8bef9SDimitry Andric   if (PP.getLangOpts().XLPragmaPack) {
2392e8d8bef9SDimitry Andric     PP.Lex(Tok);
2393e8d8bef9SDimitry Andric     if (Tok.isNot(tok::r_paren)) {
2394e8d8bef9SDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "align";
2395e8d8bef9SDimitry Andric       return;
2396e8d8bef9SDimitry Andric     }
2397e8d8bef9SDimitry Andric   }
2398e8d8bef9SDimitry Andric 
23990b57cec5SDimitry Andric   SourceLocation EndLoc = Tok.getLocation();
24000b57cec5SDimitry Andric   PP.Lex(Tok);
24010b57cec5SDimitry Andric   if (Tok.isNot(tok::eod)) {
24020b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
24030b57cec5SDimitry Andric       << (IsOptions ? "options" : "align");
24040b57cec5SDimitry Andric     return;
24050b57cec5SDimitry Andric   }
24060b57cec5SDimitry Andric 
24070b57cec5SDimitry Andric   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
24080b57cec5SDimitry Andric                               1);
24090b57cec5SDimitry Andric   Toks[0].startToken();
24100b57cec5SDimitry Andric   Toks[0].setKind(tok::annot_pragma_align);
24110b57cec5SDimitry Andric   Toks[0].setLocation(FirstTok.getLocation());
24120b57cec5SDimitry Andric   Toks[0].setAnnotationEndLoc(EndLoc);
24130b57cec5SDimitry Andric   Toks[0].setAnnotationValue(reinterpret_cast<void*>(
24140b57cec5SDimitry Andric                              static_cast<uintptr_t>(Kind)));
24150b57cec5SDimitry Andric   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
24160b57cec5SDimitry Andric                       /*IsReinject=*/false);
24170b57cec5SDimitry Andric }
24180b57cec5SDimitry Andric 
24190b57cec5SDimitry Andric void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
24200b57cec5SDimitry Andric                                       PragmaIntroducer Introducer,
24210b57cec5SDimitry Andric                                       Token &AlignTok) {
24220b57cec5SDimitry Andric   ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
24230b57cec5SDimitry Andric }
24240b57cec5SDimitry Andric 
24250b57cec5SDimitry Andric void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
24260b57cec5SDimitry Andric                                         PragmaIntroducer Introducer,
24270b57cec5SDimitry Andric                                         Token &OptionsTok) {
24280b57cec5SDimitry Andric   ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
24290b57cec5SDimitry Andric }
24300b57cec5SDimitry Andric 
24310b57cec5SDimitry Andric // #pragma unused(identifier)
24320b57cec5SDimitry Andric void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
24330b57cec5SDimitry Andric                                        PragmaIntroducer Introducer,
24340b57cec5SDimitry Andric                                        Token &UnusedTok) {
24350b57cec5SDimitry Andric   // FIXME: Should we be expanding macros here? My guess is no.
24360b57cec5SDimitry Andric   SourceLocation UnusedLoc = UnusedTok.getLocation();
24370b57cec5SDimitry Andric 
24380b57cec5SDimitry Andric   // Lex the left '('.
24390b57cec5SDimitry Andric   Token Tok;
24400b57cec5SDimitry Andric   PP.Lex(Tok);
24410b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren)) {
24420b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
24430b57cec5SDimitry Andric     return;
24440b57cec5SDimitry Andric   }
24450b57cec5SDimitry Andric 
24460b57cec5SDimitry Andric   // Lex the declaration reference(s).
24470b57cec5SDimitry Andric   SmallVector<Token, 5> Identifiers;
24480b57cec5SDimitry Andric   SourceLocation RParenLoc;
24490b57cec5SDimitry Andric   bool LexID = true;
24500b57cec5SDimitry Andric 
24510b57cec5SDimitry Andric   while (true) {
24520b57cec5SDimitry Andric     PP.Lex(Tok);
24530b57cec5SDimitry Andric 
24540b57cec5SDimitry Andric     if (LexID) {
24550b57cec5SDimitry Andric       if (Tok.is(tok::identifier)) {
24560b57cec5SDimitry Andric         Identifiers.push_back(Tok);
24570b57cec5SDimitry Andric         LexID = false;
24580b57cec5SDimitry Andric         continue;
24590b57cec5SDimitry Andric       }
24600b57cec5SDimitry Andric 
24610b57cec5SDimitry Andric       // Illegal token!
24620b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
24630b57cec5SDimitry Andric       return;
24640b57cec5SDimitry Andric     }
24650b57cec5SDimitry Andric 
24660b57cec5SDimitry Andric     // We are execting a ')' or a ','.
24670b57cec5SDimitry Andric     if (Tok.is(tok::comma)) {
24680b57cec5SDimitry Andric       LexID = true;
24690b57cec5SDimitry Andric       continue;
24700b57cec5SDimitry Andric     }
24710b57cec5SDimitry Andric 
24720b57cec5SDimitry Andric     if (Tok.is(tok::r_paren)) {
24730b57cec5SDimitry Andric       RParenLoc = Tok.getLocation();
24740b57cec5SDimitry Andric       break;
24750b57cec5SDimitry Andric     }
24760b57cec5SDimitry Andric 
24770b57cec5SDimitry Andric     // Illegal token!
24780b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
24790b57cec5SDimitry Andric     return;
24800b57cec5SDimitry Andric   }
24810b57cec5SDimitry Andric 
24820b57cec5SDimitry Andric   PP.Lex(Tok);
24830b57cec5SDimitry Andric   if (Tok.isNot(tok::eod)) {
24840b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
24850b57cec5SDimitry Andric         "unused";
24860b57cec5SDimitry Andric     return;
24870b57cec5SDimitry Andric   }
24880b57cec5SDimitry Andric 
24890b57cec5SDimitry Andric   // Verify that we have a location for the right parenthesis.
24900b57cec5SDimitry Andric   assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
24910b57cec5SDimitry Andric   assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
24920b57cec5SDimitry Andric 
24930b57cec5SDimitry Andric   // For each identifier token, insert into the token stream a
24940b57cec5SDimitry Andric   // annot_pragma_unused token followed by the identifier token.
24950b57cec5SDimitry Andric   // This allows us to cache a "#pragma unused" that occurs inside an inline
24960b57cec5SDimitry Andric   // C++ member function.
24970b57cec5SDimitry Andric 
24980b57cec5SDimitry Andric   MutableArrayRef<Token> Toks(
24990b57cec5SDimitry Andric       PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
25000b57cec5SDimitry Andric       2 * Identifiers.size());
25010b57cec5SDimitry Andric   for (unsigned i=0; i != Identifiers.size(); i++) {
25020b57cec5SDimitry Andric     Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
25030b57cec5SDimitry Andric     pragmaUnusedTok.startToken();
25040b57cec5SDimitry Andric     pragmaUnusedTok.setKind(tok::annot_pragma_unused);
25050b57cec5SDimitry Andric     pragmaUnusedTok.setLocation(UnusedLoc);
25060b57cec5SDimitry Andric     idTok = Identifiers[i];
25070b57cec5SDimitry Andric   }
25080b57cec5SDimitry Andric   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
25090b57cec5SDimitry Andric                       /*IsReinject=*/false);
25100b57cec5SDimitry Andric }
25110b57cec5SDimitry Andric 
25120b57cec5SDimitry Andric // #pragma weak identifier
25130b57cec5SDimitry Andric // #pragma weak identifier '=' identifier
25140b57cec5SDimitry Andric void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
25150b57cec5SDimitry Andric                                      PragmaIntroducer Introducer,
25160b57cec5SDimitry Andric                                      Token &WeakTok) {
25170b57cec5SDimitry Andric   SourceLocation WeakLoc = WeakTok.getLocation();
25180b57cec5SDimitry Andric 
25190b57cec5SDimitry Andric   Token Tok;
25200b57cec5SDimitry Andric   PP.Lex(Tok);
25210b57cec5SDimitry Andric   if (Tok.isNot(tok::identifier)) {
25220b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
25230b57cec5SDimitry Andric     return;
25240b57cec5SDimitry Andric   }
25250b57cec5SDimitry Andric 
25260b57cec5SDimitry Andric   Token WeakName = Tok;
25270b57cec5SDimitry Andric   bool HasAlias = false;
25280b57cec5SDimitry Andric   Token AliasName;
25290b57cec5SDimitry Andric 
25300b57cec5SDimitry Andric   PP.Lex(Tok);
25310b57cec5SDimitry Andric   if (Tok.is(tok::equal)) {
25320b57cec5SDimitry Andric     HasAlias = true;
25330b57cec5SDimitry Andric     PP.Lex(Tok);
25340b57cec5SDimitry Andric     if (Tok.isNot(tok::identifier)) {
25350b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
25360b57cec5SDimitry Andric           << "weak";
25370b57cec5SDimitry Andric       return;
25380b57cec5SDimitry Andric     }
25390b57cec5SDimitry Andric     AliasName = Tok;
25400b57cec5SDimitry Andric     PP.Lex(Tok);
25410b57cec5SDimitry Andric   }
25420b57cec5SDimitry Andric 
25430b57cec5SDimitry Andric   if (Tok.isNot(tok::eod)) {
25440b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
25450b57cec5SDimitry Andric     return;
25460b57cec5SDimitry Andric   }
25470b57cec5SDimitry Andric 
25480b57cec5SDimitry Andric   if (HasAlias) {
25490b57cec5SDimitry Andric     MutableArrayRef<Token> Toks(
25500b57cec5SDimitry Andric         PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
25510b57cec5SDimitry Andric     Token &pragmaUnusedTok = Toks[0];
25520b57cec5SDimitry Andric     pragmaUnusedTok.startToken();
25530b57cec5SDimitry Andric     pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
25540b57cec5SDimitry Andric     pragmaUnusedTok.setLocation(WeakLoc);
25550b57cec5SDimitry Andric     pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
25560b57cec5SDimitry Andric     Toks[1] = WeakName;
25570b57cec5SDimitry Andric     Toks[2] = AliasName;
25580b57cec5SDimitry Andric     PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
25590b57cec5SDimitry Andric                         /*IsReinject=*/false);
25600b57cec5SDimitry Andric   } else {
25610b57cec5SDimitry Andric     MutableArrayRef<Token> Toks(
25620b57cec5SDimitry Andric         PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
25630b57cec5SDimitry Andric     Token &pragmaUnusedTok = Toks[0];
25640b57cec5SDimitry Andric     pragmaUnusedTok.startToken();
25650b57cec5SDimitry Andric     pragmaUnusedTok.setKind(tok::annot_pragma_weak);
25660b57cec5SDimitry Andric     pragmaUnusedTok.setLocation(WeakLoc);
25670b57cec5SDimitry Andric     pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
25680b57cec5SDimitry Andric     Toks[1] = WeakName;
25690b57cec5SDimitry Andric     PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
25700b57cec5SDimitry Andric                         /*IsReinject=*/false);
25710b57cec5SDimitry Andric   }
25720b57cec5SDimitry Andric }
25730b57cec5SDimitry Andric 
25740b57cec5SDimitry Andric // #pragma redefine_extname identifier identifier
25750b57cec5SDimitry Andric void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
25760b57cec5SDimitry Andric                                                 PragmaIntroducer Introducer,
25770b57cec5SDimitry Andric                                                 Token &RedefToken) {
25780b57cec5SDimitry Andric   SourceLocation RedefLoc = RedefToken.getLocation();
25790b57cec5SDimitry Andric 
25800b57cec5SDimitry Andric   Token Tok;
25810b57cec5SDimitry Andric   PP.Lex(Tok);
25820b57cec5SDimitry Andric   if (Tok.isNot(tok::identifier)) {
25830b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
25840b57cec5SDimitry Andric       "redefine_extname";
25850b57cec5SDimitry Andric     return;
25860b57cec5SDimitry Andric   }
25870b57cec5SDimitry Andric 
25880b57cec5SDimitry Andric   Token RedefName = Tok;
25890b57cec5SDimitry Andric   PP.Lex(Tok);
25900b57cec5SDimitry Andric 
25910b57cec5SDimitry Andric   if (Tok.isNot(tok::identifier)) {
25920b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
25930b57cec5SDimitry Andric         << "redefine_extname";
25940b57cec5SDimitry Andric     return;
25950b57cec5SDimitry Andric   }
25960b57cec5SDimitry Andric 
25970b57cec5SDimitry Andric   Token AliasName = Tok;
25980b57cec5SDimitry Andric   PP.Lex(Tok);
25990b57cec5SDimitry Andric 
26000b57cec5SDimitry Andric   if (Tok.isNot(tok::eod)) {
26010b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
26020b57cec5SDimitry Andric       "redefine_extname";
26030b57cec5SDimitry Andric     return;
26040b57cec5SDimitry Andric   }
26050b57cec5SDimitry Andric 
26060b57cec5SDimitry Andric   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
26070b57cec5SDimitry Andric                               3);
26080b57cec5SDimitry Andric   Token &pragmaRedefTok = Toks[0];
26090b57cec5SDimitry Andric   pragmaRedefTok.startToken();
26100b57cec5SDimitry Andric   pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
26110b57cec5SDimitry Andric   pragmaRedefTok.setLocation(RedefLoc);
26120b57cec5SDimitry Andric   pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
26130b57cec5SDimitry Andric   Toks[1] = RedefName;
26140b57cec5SDimitry Andric   Toks[2] = AliasName;
26150b57cec5SDimitry Andric   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
26160b57cec5SDimitry Andric                       /*IsReinject=*/false);
26170b57cec5SDimitry Andric }
26180b57cec5SDimitry Andric 
26190b57cec5SDimitry Andric void PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
26200b57cec5SDimitry Andric                                            PragmaIntroducer Introducer,
26210b57cec5SDimitry Andric                                            Token &Tok) {
26220b57cec5SDimitry Andric   tok::OnOffSwitch OOS;
26230b57cec5SDimitry Andric   if (PP.LexOnOffSwitch(OOS))
26240b57cec5SDimitry Andric     return;
26250b57cec5SDimitry Andric 
26260b57cec5SDimitry Andric   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
26270b57cec5SDimitry Andric                               1);
26280b57cec5SDimitry Andric   Toks[0].startToken();
26290b57cec5SDimitry Andric   Toks[0].setKind(tok::annot_pragma_fp_contract);
26300b57cec5SDimitry Andric   Toks[0].setLocation(Tok.getLocation());
26310b57cec5SDimitry Andric   Toks[0].setAnnotationEndLoc(Tok.getLocation());
26320b57cec5SDimitry Andric   Toks[0].setAnnotationValue(reinterpret_cast<void*>(
26330b57cec5SDimitry Andric                              static_cast<uintptr_t>(OOS)));
26340b57cec5SDimitry Andric   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
26350b57cec5SDimitry Andric                       /*IsReinject=*/false);
26360b57cec5SDimitry Andric }
26370b57cec5SDimitry Andric 
26380b57cec5SDimitry Andric void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
26390b57cec5SDimitry Andric                                                 PragmaIntroducer Introducer,
26400b57cec5SDimitry Andric                                                 Token &Tok) {
26410b57cec5SDimitry Andric   PP.LexUnexpandedToken(Tok);
26420b57cec5SDimitry Andric   if (Tok.isNot(tok::identifier)) {
26430b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
26440b57cec5SDimitry Andric       "OPENCL";
26450b57cec5SDimitry Andric     return;
26460b57cec5SDimitry Andric   }
26470b57cec5SDimitry Andric   IdentifierInfo *Ext = Tok.getIdentifierInfo();
26480b57cec5SDimitry Andric   SourceLocation NameLoc = Tok.getLocation();
26490b57cec5SDimitry Andric 
26500b57cec5SDimitry Andric   PP.Lex(Tok);
26510b57cec5SDimitry Andric   if (Tok.isNot(tok::colon)) {
26520b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
26530b57cec5SDimitry Andric     return;
26540b57cec5SDimitry Andric   }
26550b57cec5SDimitry Andric 
26560b57cec5SDimitry Andric   PP.Lex(Tok);
26570b57cec5SDimitry Andric   if (Tok.isNot(tok::identifier)) {
26580b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
26590b57cec5SDimitry Andric     return;
26600b57cec5SDimitry Andric   }
26610b57cec5SDimitry Andric   IdentifierInfo *Pred = Tok.getIdentifierInfo();
26620b57cec5SDimitry Andric 
26630b57cec5SDimitry Andric   OpenCLExtState State;
26640b57cec5SDimitry Andric   if (Pred->isStr("enable")) {
26650b57cec5SDimitry Andric     State = Enable;
26660b57cec5SDimitry Andric   } else if (Pred->isStr("disable")) {
26670b57cec5SDimitry Andric     State = Disable;
26680b57cec5SDimitry Andric   } else if (Pred->isStr("begin"))
26690b57cec5SDimitry Andric     State = Begin;
26700b57cec5SDimitry Andric   else if (Pred->isStr("end"))
26710b57cec5SDimitry Andric     State = End;
26720b57cec5SDimitry Andric   else {
26730b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
26740b57cec5SDimitry Andric       << Ext->isStr("all");
26750b57cec5SDimitry Andric     return;
26760b57cec5SDimitry Andric   }
26770b57cec5SDimitry Andric   SourceLocation StateLoc = Tok.getLocation();
26780b57cec5SDimitry Andric 
26790b57cec5SDimitry Andric   PP.Lex(Tok);
26800b57cec5SDimitry Andric   if (Tok.isNot(tok::eod)) {
26810b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
26820b57cec5SDimitry Andric       "OPENCL EXTENSION";
26830b57cec5SDimitry Andric     return;
26840b57cec5SDimitry Andric   }
26850b57cec5SDimitry Andric 
26860b57cec5SDimitry Andric   auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
26870b57cec5SDimitry Andric   Info->first = Ext;
26880b57cec5SDimitry Andric   Info->second = State;
26890b57cec5SDimitry Andric   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
26900b57cec5SDimitry Andric                               1);
26910b57cec5SDimitry Andric   Toks[0].startToken();
26920b57cec5SDimitry Andric   Toks[0].setKind(tok::annot_pragma_opencl_extension);
26930b57cec5SDimitry Andric   Toks[0].setLocation(NameLoc);
26940b57cec5SDimitry Andric   Toks[0].setAnnotationValue(static_cast<void*>(Info));
26950b57cec5SDimitry Andric   Toks[0].setAnnotationEndLoc(StateLoc);
26960b57cec5SDimitry Andric   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
26970b57cec5SDimitry Andric                       /*IsReinject=*/false);
26980b57cec5SDimitry Andric 
26990b57cec5SDimitry Andric   if (PP.getPPCallbacks())
27000b57cec5SDimitry Andric     PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
27010b57cec5SDimitry Andric                                                StateLoc, State);
27020b57cec5SDimitry Andric }
27030b57cec5SDimitry Andric 
27045f757f3fSDimitry Andric /// Handle '#pragma omp ...' when OpenMP is disabled and '#pragma acc ...' when
27055f757f3fSDimitry Andric /// OpenACC is disabled.
27065f757f3fSDimitry Andric template <diag::kind IgnoredDiag>
27075f757f3fSDimitry Andric void PragmaNoSupportHandler<IgnoredDiag>::HandlePragma(
27085f757f3fSDimitry Andric     Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstTok) {
27095f757f3fSDimitry Andric   if (!PP.getDiagnostics().isIgnored(IgnoredDiag, FirstTok.getLocation())) {
27105f757f3fSDimitry Andric     PP.Diag(FirstTok, IgnoredDiag);
27115f757f3fSDimitry Andric     PP.getDiagnostics().setSeverity(IgnoredDiag, diag::Severity::Ignored,
27125f757f3fSDimitry Andric                                     SourceLocation());
27130b57cec5SDimitry Andric   }
27140b57cec5SDimitry Andric   PP.DiscardUntilEndOfDirective();
27150b57cec5SDimitry Andric }
27160b57cec5SDimitry Andric 
27175f757f3fSDimitry Andric /// Handle '#pragma omp ...' when OpenMP is enabled, and handle '#pragma acc...'
27185f757f3fSDimitry Andric /// when OpenACC is enabled.
27195f757f3fSDimitry Andric template <tok::TokenKind StartTok, tok::TokenKind EndTok,
27205f757f3fSDimitry Andric           diag::kind UnexpectedDiag>
27215f757f3fSDimitry Andric void PragmaSupportHandler<StartTok, EndTok, UnexpectedDiag>::HandlePragma(
27225f757f3fSDimitry Andric     Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstTok) {
27230b57cec5SDimitry Andric   SmallVector<Token, 16> Pragma;
27240b57cec5SDimitry Andric   Token Tok;
27250b57cec5SDimitry Andric   Tok.startToken();
27265f757f3fSDimitry Andric   Tok.setKind(StartTok);
27270b57cec5SDimitry Andric   Tok.setLocation(Introducer.Loc);
27280b57cec5SDimitry Andric 
27290b57cec5SDimitry Andric   while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
27300b57cec5SDimitry Andric     Pragma.push_back(Tok);
27310b57cec5SDimitry Andric     PP.Lex(Tok);
27325f757f3fSDimitry Andric     if (Tok.is(StartTok)) {
27335f757f3fSDimitry Andric       PP.Diag(Tok, UnexpectedDiag) << 0;
27340b57cec5SDimitry Andric       unsigned InnerPragmaCnt = 1;
27350b57cec5SDimitry Andric       while (InnerPragmaCnt != 0) {
27360b57cec5SDimitry Andric         PP.Lex(Tok);
27375f757f3fSDimitry Andric         if (Tok.is(StartTok))
27380b57cec5SDimitry Andric           ++InnerPragmaCnt;
27395f757f3fSDimitry Andric         else if (Tok.is(EndTok))
27400b57cec5SDimitry Andric           --InnerPragmaCnt;
27410b57cec5SDimitry Andric       }
27420b57cec5SDimitry Andric       PP.Lex(Tok);
27430b57cec5SDimitry Andric     }
27440b57cec5SDimitry Andric   }
27450b57cec5SDimitry Andric   SourceLocation EodLoc = Tok.getLocation();
27460b57cec5SDimitry Andric   Tok.startToken();
27475f757f3fSDimitry Andric   Tok.setKind(EndTok);
27480b57cec5SDimitry Andric   Tok.setLocation(EodLoc);
27490b57cec5SDimitry Andric   Pragma.push_back(Tok);
27500b57cec5SDimitry Andric 
2751a7dea167SDimitry Andric   auto Toks = std::make_unique<Token[]>(Pragma.size());
27520b57cec5SDimitry Andric   std::copy(Pragma.begin(), Pragma.end(), Toks.get());
27530b57cec5SDimitry Andric   PP.EnterTokenStream(std::move(Toks), Pragma.size(),
27540b57cec5SDimitry Andric                       /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
27550b57cec5SDimitry Andric }
27560b57cec5SDimitry Andric 
27570b57cec5SDimitry Andric /// Handle '#pragma pointers_to_members'
27580b57cec5SDimitry Andric // The grammar for this pragma is as follows:
27590b57cec5SDimitry Andric //
27600b57cec5SDimitry Andric // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
27610b57cec5SDimitry Andric //
27620b57cec5SDimitry Andric // #pragma pointers_to_members '(' 'best_case' ')'
27630b57cec5SDimitry Andric // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
27640b57cec5SDimitry Andric // #pragma pointers_to_members '(' inheritance-model ')'
27650b57cec5SDimitry Andric void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
27660b57cec5SDimitry Andric                                              PragmaIntroducer Introducer,
27670b57cec5SDimitry Andric                                              Token &Tok) {
27680b57cec5SDimitry Andric   SourceLocation PointersToMembersLoc = Tok.getLocation();
27690b57cec5SDimitry Andric   PP.Lex(Tok);
27700b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren)) {
27710b57cec5SDimitry Andric     PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
27720b57cec5SDimitry Andric       << "pointers_to_members";
27730b57cec5SDimitry Andric     return;
27740b57cec5SDimitry Andric   }
27750b57cec5SDimitry Andric   PP.Lex(Tok);
27760b57cec5SDimitry Andric   const IdentifierInfo *Arg = Tok.getIdentifierInfo();
27770b57cec5SDimitry Andric   if (!Arg) {
27780b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
27790b57cec5SDimitry Andric       << "pointers_to_members";
27800b57cec5SDimitry Andric     return;
27810b57cec5SDimitry Andric   }
27820b57cec5SDimitry Andric   PP.Lex(Tok);
27830b57cec5SDimitry Andric 
27840b57cec5SDimitry Andric   LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
27850b57cec5SDimitry Andric   if (Arg->isStr("best_case")) {
27860b57cec5SDimitry Andric     RepresentationMethod = LangOptions::PPTMK_BestCase;
27870b57cec5SDimitry Andric   } else {
27880b57cec5SDimitry Andric     if (Arg->isStr("full_generality")) {
27890b57cec5SDimitry Andric       if (Tok.is(tok::comma)) {
27900b57cec5SDimitry Andric         PP.Lex(Tok);
27910b57cec5SDimitry Andric 
27920b57cec5SDimitry Andric         Arg = Tok.getIdentifierInfo();
27930b57cec5SDimitry Andric         if (!Arg) {
27940b57cec5SDimitry Andric           PP.Diag(Tok.getLocation(),
27950b57cec5SDimitry Andric                   diag::err_pragma_pointers_to_members_unknown_kind)
27960b57cec5SDimitry Andric               << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
27970b57cec5SDimitry Andric           return;
27980b57cec5SDimitry Andric         }
27990b57cec5SDimitry Andric         PP.Lex(Tok);
28000b57cec5SDimitry Andric       } else if (Tok.is(tok::r_paren)) {
28010b57cec5SDimitry Andric         // #pragma pointers_to_members(full_generality) implicitly specifies
28020b57cec5SDimitry Andric         // virtual_inheritance.
28030b57cec5SDimitry Andric         Arg = nullptr;
28040b57cec5SDimitry Andric         RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
28050b57cec5SDimitry Andric       } else {
28060b57cec5SDimitry Andric         PP.Diag(Tok.getLocation(), diag::err_expected_punc)
28070b57cec5SDimitry Andric             << "full_generality";
28080b57cec5SDimitry Andric         return;
28090b57cec5SDimitry Andric       }
28100b57cec5SDimitry Andric     }
28110b57cec5SDimitry Andric 
28120b57cec5SDimitry Andric     if (Arg) {
28130b57cec5SDimitry Andric       if (Arg->isStr("single_inheritance")) {
28140b57cec5SDimitry Andric         RepresentationMethod =
28150b57cec5SDimitry Andric             LangOptions::PPTMK_FullGeneralitySingleInheritance;
28160b57cec5SDimitry Andric       } else if (Arg->isStr("multiple_inheritance")) {
28170b57cec5SDimitry Andric         RepresentationMethod =
28180b57cec5SDimitry Andric             LangOptions::PPTMK_FullGeneralityMultipleInheritance;
28190b57cec5SDimitry Andric       } else if (Arg->isStr("virtual_inheritance")) {
28200b57cec5SDimitry Andric         RepresentationMethod =
28210b57cec5SDimitry Andric             LangOptions::PPTMK_FullGeneralityVirtualInheritance;
28220b57cec5SDimitry Andric       } else {
28230b57cec5SDimitry Andric         PP.Diag(Tok.getLocation(),
28240b57cec5SDimitry Andric                 diag::err_pragma_pointers_to_members_unknown_kind)
28250b57cec5SDimitry Andric             << Arg << /*HasPointerDeclaration*/ 1;
28260b57cec5SDimitry Andric         return;
28270b57cec5SDimitry Andric       }
28280b57cec5SDimitry Andric     }
28290b57cec5SDimitry Andric   }
28300b57cec5SDimitry Andric 
28310b57cec5SDimitry Andric   if (Tok.isNot(tok::r_paren)) {
28320b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
28330b57cec5SDimitry Andric         << (Arg ? Arg->getName() : "full_generality");
28340b57cec5SDimitry Andric     return;
28350b57cec5SDimitry Andric   }
28360b57cec5SDimitry Andric 
28370b57cec5SDimitry Andric   SourceLocation EndLoc = Tok.getLocation();
28380b57cec5SDimitry Andric   PP.Lex(Tok);
28390b57cec5SDimitry Andric   if (Tok.isNot(tok::eod)) {
28400b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
28410b57cec5SDimitry Andric       << "pointers_to_members";
28420b57cec5SDimitry Andric     return;
28430b57cec5SDimitry Andric   }
28440b57cec5SDimitry Andric 
28450b57cec5SDimitry Andric   Token AnnotTok;
28460b57cec5SDimitry Andric   AnnotTok.startToken();
28470b57cec5SDimitry Andric   AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
28480b57cec5SDimitry Andric   AnnotTok.setLocation(PointersToMembersLoc);
28490b57cec5SDimitry Andric   AnnotTok.setAnnotationEndLoc(EndLoc);
28500b57cec5SDimitry Andric   AnnotTok.setAnnotationValue(
28510b57cec5SDimitry Andric       reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
28520b57cec5SDimitry Andric   PP.EnterToken(AnnotTok, /*IsReinject=*/true);
28530b57cec5SDimitry Andric }
28540b57cec5SDimitry Andric 
28550b57cec5SDimitry Andric /// Handle '#pragma vtordisp'
28560b57cec5SDimitry Andric // The grammar for this pragma is as follows:
28570b57cec5SDimitry Andric //
28580b57cec5SDimitry Andric // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
28590b57cec5SDimitry Andric //
28600b57cec5SDimitry Andric // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
28610b57cec5SDimitry Andric // #pragma vtordisp '(' 'pop' ')'
28620b57cec5SDimitry Andric // #pragma vtordisp '(' ')'
28630b57cec5SDimitry Andric void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
28640b57cec5SDimitry Andric                                     PragmaIntroducer Introducer, Token &Tok) {
28650b57cec5SDimitry Andric   SourceLocation VtorDispLoc = Tok.getLocation();
28660b57cec5SDimitry Andric   PP.Lex(Tok);
28670b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren)) {
28680b57cec5SDimitry Andric     PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
28690b57cec5SDimitry Andric     return;
28700b57cec5SDimitry Andric   }
28710b57cec5SDimitry Andric   PP.Lex(Tok);
28720b57cec5SDimitry Andric 
28730b57cec5SDimitry Andric   Sema::PragmaMsStackAction Action = Sema::PSK_Set;
28740b57cec5SDimitry Andric   const IdentifierInfo *II = Tok.getIdentifierInfo();
28750b57cec5SDimitry Andric   if (II) {
28760b57cec5SDimitry Andric     if (II->isStr("push")) {
28770b57cec5SDimitry Andric       // #pragma vtordisp(push, mode)
28780b57cec5SDimitry Andric       PP.Lex(Tok);
28790b57cec5SDimitry Andric       if (Tok.isNot(tok::comma)) {
28800b57cec5SDimitry Andric         PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
28810b57cec5SDimitry Andric         return;
28820b57cec5SDimitry Andric       }
28830b57cec5SDimitry Andric       PP.Lex(Tok);
28840b57cec5SDimitry Andric       Action = Sema::PSK_Push_Set;
28850b57cec5SDimitry Andric       // not push, could be on/off
28860b57cec5SDimitry Andric     } else if (II->isStr("pop")) {
28870b57cec5SDimitry Andric       // #pragma vtordisp(pop)
28880b57cec5SDimitry Andric       PP.Lex(Tok);
28890b57cec5SDimitry Andric       Action = Sema::PSK_Pop;
28900b57cec5SDimitry Andric     }
28910b57cec5SDimitry Andric     // not push or pop, could be on/off
28920b57cec5SDimitry Andric   } else {
28930b57cec5SDimitry Andric     if (Tok.is(tok::r_paren)) {
28940b57cec5SDimitry Andric       // #pragma vtordisp()
28950b57cec5SDimitry Andric       Action = Sema::PSK_Reset;
28960b57cec5SDimitry Andric     }
28970b57cec5SDimitry Andric   }
28980b57cec5SDimitry Andric 
28990b57cec5SDimitry Andric 
29000b57cec5SDimitry Andric   uint64_t Value = 0;
29010b57cec5SDimitry Andric   if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
29020b57cec5SDimitry Andric     const IdentifierInfo *II = Tok.getIdentifierInfo();
29030b57cec5SDimitry Andric     if (II && II->isStr("off")) {
29040b57cec5SDimitry Andric       PP.Lex(Tok);
29050b57cec5SDimitry Andric       Value = 0;
29060b57cec5SDimitry Andric     } else if (II && II->isStr("on")) {
29070b57cec5SDimitry Andric       PP.Lex(Tok);
29080b57cec5SDimitry Andric       Value = 1;
29090b57cec5SDimitry Andric     } else if (Tok.is(tok::numeric_constant) &&
29100b57cec5SDimitry Andric                PP.parseSimpleIntegerLiteral(Tok, Value)) {
29110b57cec5SDimitry Andric       if (Value > 2) {
29120b57cec5SDimitry Andric         PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
29130b57cec5SDimitry Andric             << 0 << 2 << "vtordisp";
29140b57cec5SDimitry Andric         return;
29150b57cec5SDimitry Andric       }
29160b57cec5SDimitry Andric     } else {
29170b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
29180b57cec5SDimitry Andric           << "vtordisp";
29190b57cec5SDimitry Andric       return;
29200b57cec5SDimitry Andric     }
29210b57cec5SDimitry Andric   }
29220b57cec5SDimitry Andric 
29230b57cec5SDimitry Andric   // Finish the pragma: ')' $
29240b57cec5SDimitry Andric   if (Tok.isNot(tok::r_paren)) {
29250b57cec5SDimitry Andric     PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
29260b57cec5SDimitry Andric     return;
29270b57cec5SDimitry Andric   }
29280b57cec5SDimitry Andric   SourceLocation EndLoc = Tok.getLocation();
29290b57cec5SDimitry Andric   PP.Lex(Tok);
29300b57cec5SDimitry Andric   if (Tok.isNot(tok::eod)) {
29310b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
29320b57cec5SDimitry Andric         << "vtordisp";
29330b57cec5SDimitry Andric     return;
29340b57cec5SDimitry Andric   }
29350b57cec5SDimitry Andric 
29360b57cec5SDimitry Andric   // Enter the annotation.
29370b57cec5SDimitry Andric   Token AnnotTok;
29380b57cec5SDimitry Andric   AnnotTok.startToken();
29390b57cec5SDimitry Andric   AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
29400b57cec5SDimitry Andric   AnnotTok.setLocation(VtorDispLoc);
29410b57cec5SDimitry Andric   AnnotTok.setAnnotationEndLoc(EndLoc);
29420b57cec5SDimitry Andric   AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
29430b57cec5SDimitry Andric       static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
29440b57cec5SDimitry Andric   PP.EnterToken(AnnotTok, /*IsReinject=*/false);
29450b57cec5SDimitry Andric }
29460b57cec5SDimitry Andric 
29470b57cec5SDimitry Andric /// Handle all MS pragmas.  Simply forwards the tokens after inserting
29480b57cec5SDimitry Andric /// an annotation token.
29490b57cec5SDimitry Andric void PragmaMSPragma::HandlePragma(Preprocessor &PP,
29500b57cec5SDimitry Andric                                   PragmaIntroducer Introducer, Token &Tok) {
29510b57cec5SDimitry Andric   Token EoF, AnnotTok;
29520b57cec5SDimitry Andric   EoF.startToken();
29530b57cec5SDimitry Andric   EoF.setKind(tok::eof);
29540b57cec5SDimitry Andric   AnnotTok.startToken();
29550b57cec5SDimitry Andric   AnnotTok.setKind(tok::annot_pragma_ms_pragma);
29560b57cec5SDimitry Andric   AnnotTok.setLocation(Tok.getLocation());
29570b57cec5SDimitry Andric   AnnotTok.setAnnotationEndLoc(Tok.getLocation());
29580b57cec5SDimitry Andric   SmallVector<Token, 8> TokenVector;
29590b57cec5SDimitry Andric   // Suck up all of the tokens before the eod.
29600b57cec5SDimitry Andric   for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
29610b57cec5SDimitry Andric     TokenVector.push_back(Tok);
29620b57cec5SDimitry Andric     AnnotTok.setAnnotationEndLoc(Tok.getLocation());
29630b57cec5SDimitry Andric   }
29640b57cec5SDimitry Andric   // Add a sentinel EoF token to the end of the list.
29650b57cec5SDimitry Andric   TokenVector.push_back(EoF);
29660b57cec5SDimitry Andric   // We must allocate this array with new because EnterTokenStream is going to
29670b57cec5SDimitry Andric   // delete it later.
2968fe6060f1SDimitry Andric   markAsReinjectedForRelexing(TokenVector);
2969a7dea167SDimitry Andric   auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
29700b57cec5SDimitry Andric   std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
29710b57cec5SDimitry Andric   auto Value = new (PP.getPreprocessorAllocator())
29720b57cec5SDimitry Andric       std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
29730b57cec5SDimitry Andric                                                   TokenVector.size());
29740b57cec5SDimitry Andric   AnnotTok.setAnnotationValue(Value);
29750b57cec5SDimitry Andric   PP.EnterToken(AnnotTok, /*IsReinject*/ false);
29760b57cec5SDimitry Andric }
29770b57cec5SDimitry Andric 
29785ffd83dbSDimitry Andric /// Handle the \#pragma float_control extension.
29795ffd83dbSDimitry Andric ///
29805ffd83dbSDimitry Andric /// The syntax is:
29815ffd83dbSDimitry Andric /// \code
29825ffd83dbSDimitry Andric ///   #pragma float_control(keyword[, setting] [,push])
29835ffd83dbSDimitry Andric /// \endcode
29845ffd83dbSDimitry Andric /// Where 'keyword' and 'setting' are identifiers.
29855ffd83dbSDimitry Andric // 'keyword' can be: precise, except, push, pop
29865ffd83dbSDimitry Andric // 'setting' can be: on, off
29875ffd83dbSDimitry Andric /// The optional arguments 'setting' and 'push' are supported only
29885ffd83dbSDimitry Andric /// when the keyword is 'precise' or 'except'.
29895ffd83dbSDimitry Andric void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP,
29905ffd83dbSDimitry Andric                                              PragmaIntroducer Introducer,
29915ffd83dbSDimitry Andric                                              Token &Tok) {
29925ffd83dbSDimitry Andric   Sema::PragmaMsStackAction Action = Sema::PSK_Set;
29935ffd83dbSDimitry Andric   SourceLocation FloatControlLoc = Tok.getLocation();
2994e8d8bef9SDimitry Andric   Token PragmaName = Tok;
2995e8d8bef9SDimitry Andric   if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
2996e8d8bef9SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
2997e8d8bef9SDimitry Andric         << PragmaName.getIdentifierInfo()->getName();
2998e8d8bef9SDimitry Andric     return;
2999e8d8bef9SDimitry Andric   }
30005ffd83dbSDimitry Andric   PP.Lex(Tok);
30015ffd83dbSDimitry Andric   if (Tok.isNot(tok::l_paren)) {
30025ffd83dbSDimitry Andric     PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren;
30035ffd83dbSDimitry Andric     return;
30045ffd83dbSDimitry Andric   }
30055ffd83dbSDimitry Andric 
30065ffd83dbSDimitry Andric   // Read the identifier.
30075ffd83dbSDimitry Andric   PP.Lex(Tok);
30085ffd83dbSDimitry Andric   if (Tok.isNot(tok::identifier)) {
30095ffd83dbSDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
30105ffd83dbSDimitry Andric     return;
30115ffd83dbSDimitry Andric   }
30125ffd83dbSDimitry Andric 
30135ffd83dbSDimitry Andric   // Verify that this is one of the float control options.
30145ffd83dbSDimitry Andric   IdentifierInfo *II = Tok.getIdentifierInfo();
30155ffd83dbSDimitry Andric   PragmaFloatControlKind Kind =
30165ffd83dbSDimitry Andric       llvm::StringSwitch<PragmaFloatControlKind>(II->getName())
30175ffd83dbSDimitry Andric           .Case("precise", PFC_Precise)
30185ffd83dbSDimitry Andric           .Case("except", PFC_Except)
30195ffd83dbSDimitry Andric           .Case("push", PFC_Push)
30205ffd83dbSDimitry Andric           .Case("pop", PFC_Pop)
30215ffd83dbSDimitry Andric           .Default(PFC_Unknown);
30225ffd83dbSDimitry Andric   PP.Lex(Tok); // the identifier
30235ffd83dbSDimitry Andric   if (Kind == PFC_Unknown) {
30245ffd83dbSDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
30255ffd83dbSDimitry Andric     return;
30265ffd83dbSDimitry Andric   } else if (Kind == PFC_Push || Kind == PFC_Pop) {
30275ffd83dbSDimitry Andric     if (Tok.isNot(tok::r_paren)) {
30285ffd83dbSDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
30295ffd83dbSDimitry Andric       return;
30305ffd83dbSDimitry Andric     }
30315ffd83dbSDimitry Andric     PP.Lex(Tok); // Eat the r_paren
30325ffd83dbSDimitry Andric     Action = (Kind == PFC_Pop) ? Sema::PSK_Pop : Sema::PSK_Push;
30335ffd83dbSDimitry Andric   } else {
30345ffd83dbSDimitry Andric     if (Tok.is(tok::r_paren))
30355ffd83dbSDimitry Andric       // Selecting Precise or Except
30365ffd83dbSDimitry Andric       PP.Lex(Tok); // the r_paren
30375ffd83dbSDimitry Andric     else if (Tok.isNot(tok::comma)) {
30385ffd83dbSDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
30395ffd83dbSDimitry Andric       return;
30405ffd83dbSDimitry Andric     } else {
30415ffd83dbSDimitry Andric       PP.Lex(Tok); // ,
30425ffd83dbSDimitry Andric       if (!Tok.isAnyIdentifier()) {
30435ffd83dbSDimitry Andric         PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
30445ffd83dbSDimitry Andric         return;
30455ffd83dbSDimitry Andric       }
30465ffd83dbSDimitry Andric       StringRef PushOnOff = Tok.getIdentifierInfo()->getName();
30475ffd83dbSDimitry Andric       if (PushOnOff == "on")
30485ffd83dbSDimitry Andric         // Kind is set correctly
30495ffd83dbSDimitry Andric         ;
30505ffd83dbSDimitry Andric       else if (PushOnOff == "off") {
30515ffd83dbSDimitry Andric         if (Kind == PFC_Precise)
30525ffd83dbSDimitry Andric           Kind = PFC_NoPrecise;
30535ffd83dbSDimitry Andric         if (Kind == PFC_Except)
30545ffd83dbSDimitry Andric           Kind = PFC_NoExcept;
30555ffd83dbSDimitry Andric       } else if (PushOnOff == "push") {
30565ffd83dbSDimitry Andric         Action = Sema::PSK_Push_Set;
30575ffd83dbSDimitry Andric       } else {
30585ffd83dbSDimitry Andric         PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
30595ffd83dbSDimitry Andric         return;
30605ffd83dbSDimitry Andric       }
30615ffd83dbSDimitry Andric       PP.Lex(Tok); // the identifier
30625ffd83dbSDimitry Andric       if (Tok.is(tok::comma)) {
30635ffd83dbSDimitry Andric         PP.Lex(Tok); // ,
30645ffd83dbSDimitry Andric         if (!Tok.isAnyIdentifier()) {
30655ffd83dbSDimitry Andric           PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
30665ffd83dbSDimitry Andric           return;
30675ffd83dbSDimitry Andric         }
30685ffd83dbSDimitry Andric         StringRef ExpectedPush = Tok.getIdentifierInfo()->getName();
30695ffd83dbSDimitry Andric         if (ExpectedPush == "push") {
30705ffd83dbSDimitry Andric           Action = Sema::PSK_Push_Set;
30715ffd83dbSDimitry Andric         } else {
30725ffd83dbSDimitry Andric           PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
30735ffd83dbSDimitry Andric           return;
30745ffd83dbSDimitry Andric         }
30755ffd83dbSDimitry Andric         PP.Lex(Tok); // the push identifier
30765ffd83dbSDimitry Andric       }
30775ffd83dbSDimitry Andric       if (Tok.isNot(tok::r_paren)) {
30785ffd83dbSDimitry Andric         PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
30795ffd83dbSDimitry Andric         return;
30805ffd83dbSDimitry Andric       }
30815ffd83dbSDimitry Andric       PP.Lex(Tok); // the r_paren
30825ffd83dbSDimitry Andric     }
30835ffd83dbSDimitry Andric   }
30845ffd83dbSDimitry Andric   SourceLocation EndLoc = Tok.getLocation();
30855ffd83dbSDimitry Andric   if (Tok.isNot(tok::eod)) {
30865ffd83dbSDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
30875ffd83dbSDimitry Andric         << "float_control";
30885ffd83dbSDimitry Andric     return;
30895ffd83dbSDimitry Andric   }
30905ffd83dbSDimitry Andric 
30915ffd83dbSDimitry Andric   // Note: there is no accomodation for PP callback for this pragma.
30925ffd83dbSDimitry Andric 
30935ffd83dbSDimitry Andric   // Enter the annotation.
30945ffd83dbSDimitry Andric   auto TokenArray = std::make_unique<Token[]>(1);
30955ffd83dbSDimitry Andric   TokenArray[0].startToken();
30965ffd83dbSDimitry Andric   TokenArray[0].setKind(tok::annot_pragma_float_control);
30975ffd83dbSDimitry Andric   TokenArray[0].setLocation(FloatControlLoc);
30985ffd83dbSDimitry Andric   TokenArray[0].setAnnotationEndLoc(EndLoc);
30995ffd83dbSDimitry Andric   // Create an encoding of Action and Value by shifting the Action into
31005ffd83dbSDimitry Andric   // the high 16 bits then union with the Kind.
31015ffd83dbSDimitry Andric   TokenArray[0].setAnnotationValue(reinterpret_cast<void *>(
31025ffd83dbSDimitry Andric       static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF))));
31035ffd83dbSDimitry Andric   PP.EnterTokenStream(std::move(TokenArray), 1,
31045ffd83dbSDimitry Andric                       /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
31055ffd83dbSDimitry Andric }
31065ffd83dbSDimitry Andric 
31070b57cec5SDimitry Andric /// Handle the Microsoft \#pragma detect_mismatch extension.
31080b57cec5SDimitry Andric ///
31090b57cec5SDimitry Andric /// The syntax is:
31100b57cec5SDimitry Andric /// \code
31110b57cec5SDimitry Andric ///   #pragma detect_mismatch("name", "value")
31120b57cec5SDimitry Andric /// \endcode
31130b57cec5SDimitry Andric /// Where 'name' and 'value' are quoted strings.  The values are embedded in
31140b57cec5SDimitry Andric /// the object file and passed along to the linker.  If the linker detects a
31150b57cec5SDimitry Andric /// mismatch in the object file's values for the given name, a LNK2038 error
31160b57cec5SDimitry Andric /// is emitted.  See MSDN for more details.
31170b57cec5SDimitry Andric void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
31180b57cec5SDimitry Andric                                                PragmaIntroducer Introducer,
31190b57cec5SDimitry Andric                                                Token &Tok) {
31200b57cec5SDimitry Andric   SourceLocation DetectMismatchLoc = Tok.getLocation();
31210b57cec5SDimitry Andric   PP.Lex(Tok);
31220b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren)) {
31230b57cec5SDimitry Andric     PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
31240b57cec5SDimitry Andric     return;
31250b57cec5SDimitry Andric   }
31260b57cec5SDimitry Andric 
31270b57cec5SDimitry Andric   // Read the name to embed, which must be a string literal.
31280b57cec5SDimitry Andric   std::string NameString;
31290b57cec5SDimitry Andric   if (!PP.LexStringLiteral(Tok, NameString,
31300b57cec5SDimitry Andric                            "pragma detect_mismatch",
31310b57cec5SDimitry Andric                            /*AllowMacroExpansion=*/true))
31320b57cec5SDimitry Andric     return;
31330b57cec5SDimitry Andric 
31340b57cec5SDimitry Andric   // Read the comma followed by a second string literal.
31350b57cec5SDimitry Andric   std::string ValueString;
31360b57cec5SDimitry Andric   if (Tok.isNot(tok::comma)) {
31370b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
31380b57cec5SDimitry Andric     return;
31390b57cec5SDimitry Andric   }
31400b57cec5SDimitry Andric 
31410b57cec5SDimitry Andric   if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
31420b57cec5SDimitry Andric                            /*AllowMacroExpansion=*/true))
31430b57cec5SDimitry Andric     return;
31440b57cec5SDimitry Andric 
31450b57cec5SDimitry Andric   if (Tok.isNot(tok::r_paren)) {
31460b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
31470b57cec5SDimitry Andric     return;
31480b57cec5SDimitry Andric   }
31490b57cec5SDimitry Andric   PP.Lex(Tok);  // Eat the r_paren.
31500b57cec5SDimitry Andric 
31510b57cec5SDimitry Andric   if (Tok.isNot(tok::eod)) {
31520b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
31530b57cec5SDimitry Andric     return;
31540b57cec5SDimitry Andric   }
31550b57cec5SDimitry Andric 
31560b57cec5SDimitry Andric   // If the pragma is lexically sound, notify any interested PPCallbacks.
31570b57cec5SDimitry Andric   if (PP.getPPCallbacks())
31580b57cec5SDimitry Andric     PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
31590b57cec5SDimitry Andric                                               ValueString);
31600b57cec5SDimitry Andric 
31610b57cec5SDimitry Andric   Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
31620b57cec5SDimitry Andric }
31630b57cec5SDimitry Andric 
31640b57cec5SDimitry Andric /// Handle the microsoft \#pragma comment extension.
31650b57cec5SDimitry Andric ///
31660b57cec5SDimitry Andric /// The syntax is:
31670b57cec5SDimitry Andric /// \code
31680b57cec5SDimitry Andric ///   #pragma comment(linker, "foo")
31690b57cec5SDimitry Andric /// \endcode
31700b57cec5SDimitry Andric /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
31710b57cec5SDimitry Andric /// "foo" is a string, which is fully macro expanded, and permits string
31720b57cec5SDimitry Andric /// concatenation, embedded escape characters etc.  See MSDN for more details.
31730b57cec5SDimitry Andric void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
31740b57cec5SDimitry Andric                                         PragmaIntroducer Introducer,
31750b57cec5SDimitry Andric                                         Token &Tok) {
31760b57cec5SDimitry Andric   SourceLocation CommentLoc = Tok.getLocation();
31770b57cec5SDimitry Andric   PP.Lex(Tok);
31780b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren)) {
31790b57cec5SDimitry Andric     PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
31800b57cec5SDimitry Andric     return;
31810b57cec5SDimitry Andric   }
31820b57cec5SDimitry Andric 
31830b57cec5SDimitry Andric   // Read the identifier.
31840b57cec5SDimitry Andric   PP.Lex(Tok);
31850b57cec5SDimitry Andric   if (Tok.isNot(tok::identifier)) {
31860b57cec5SDimitry Andric     PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
31870b57cec5SDimitry Andric     return;
31880b57cec5SDimitry Andric   }
31890b57cec5SDimitry Andric 
31905ffd83dbSDimitry Andric   // Verify that this is one of the 5 explicitly listed options.
31910b57cec5SDimitry Andric   IdentifierInfo *II = Tok.getIdentifierInfo();
31920b57cec5SDimitry Andric   PragmaMSCommentKind Kind =
31930b57cec5SDimitry Andric     llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
31940b57cec5SDimitry Andric     .Case("linker",   PCK_Linker)
31950b57cec5SDimitry Andric     .Case("lib",      PCK_Lib)
31960b57cec5SDimitry Andric     .Case("compiler", PCK_Compiler)
31970b57cec5SDimitry Andric     .Case("exestr",   PCK_ExeStr)
31980b57cec5SDimitry Andric     .Case("user",     PCK_User)
31990b57cec5SDimitry Andric     .Default(PCK_Unknown);
32000b57cec5SDimitry Andric   if (Kind == PCK_Unknown) {
32010b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
32020b57cec5SDimitry Andric     return;
32030b57cec5SDimitry Andric   }
32040b57cec5SDimitry Andric 
32050b57cec5SDimitry Andric   if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
32060b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
32070b57cec5SDimitry Andric         << II->getName();
32080b57cec5SDimitry Andric     return;
32090b57cec5SDimitry Andric   }
32100b57cec5SDimitry Andric 
32110b57cec5SDimitry Andric   // Read the optional string if present.
32120b57cec5SDimitry Andric   PP.Lex(Tok);
32130b57cec5SDimitry Andric   std::string ArgumentString;
32140b57cec5SDimitry Andric   if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
32150b57cec5SDimitry Andric                                                  "pragma comment",
32160b57cec5SDimitry Andric                                                  /*AllowMacroExpansion=*/true))
32170b57cec5SDimitry Andric     return;
32180b57cec5SDimitry Andric 
32190b57cec5SDimitry Andric   // FIXME: warn that 'exestr' is deprecated.
32200b57cec5SDimitry Andric   // FIXME: If the kind is "compiler" warn if the string is present (it is
32210b57cec5SDimitry Andric   // ignored).
32220b57cec5SDimitry Andric   // The MSDN docs say that "lib" and "linker" require a string and have a short
32235ffd83dbSDimitry Andric   // list of linker options they support, but in practice MSVC doesn't
32240b57cec5SDimitry Andric   // issue a diagnostic.  Therefore neither does clang.
32250b57cec5SDimitry Andric 
32260b57cec5SDimitry Andric   if (Tok.isNot(tok::r_paren)) {
32270b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
32280b57cec5SDimitry Andric     return;
32290b57cec5SDimitry Andric   }
32300b57cec5SDimitry Andric   PP.Lex(Tok);  // eat the r_paren.
32310b57cec5SDimitry Andric 
32320b57cec5SDimitry Andric   if (Tok.isNot(tok::eod)) {
32330b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
32340b57cec5SDimitry Andric     return;
32350b57cec5SDimitry Andric   }
32360b57cec5SDimitry Andric 
32370b57cec5SDimitry Andric   // If the pragma is lexically sound, notify any interested PPCallbacks.
32380b57cec5SDimitry Andric   if (PP.getPPCallbacks())
32390b57cec5SDimitry Andric     PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
32400b57cec5SDimitry Andric 
32410b57cec5SDimitry Andric   Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
32420b57cec5SDimitry Andric }
32430b57cec5SDimitry Andric 
32440b57cec5SDimitry Andric // #pragma clang optimize off
32450b57cec5SDimitry Andric // #pragma clang optimize on
32460b57cec5SDimitry Andric void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
32470b57cec5SDimitry Andric                                          PragmaIntroducer Introducer,
32480b57cec5SDimitry Andric                                          Token &FirstToken) {
32490b57cec5SDimitry Andric   Token Tok;
32500b57cec5SDimitry Andric   PP.Lex(Tok);
32510b57cec5SDimitry Andric   if (Tok.is(tok::eod)) {
32520b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
32530b57cec5SDimitry Andric         << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
32540b57cec5SDimitry Andric     return;
32550b57cec5SDimitry Andric   }
32560b57cec5SDimitry Andric   if (Tok.isNot(tok::identifier)) {
32570b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
32580b57cec5SDimitry Andric       << PP.getSpelling(Tok);
32590b57cec5SDimitry Andric     return;
32600b57cec5SDimitry Andric   }
32610b57cec5SDimitry Andric   const IdentifierInfo *II = Tok.getIdentifierInfo();
32620b57cec5SDimitry Andric   // The only accepted values are 'on' or 'off'.
32630b57cec5SDimitry Andric   bool IsOn = false;
32640b57cec5SDimitry Andric   if (II->isStr("on")) {
32650b57cec5SDimitry Andric     IsOn = true;
32660b57cec5SDimitry Andric   } else if (!II->isStr("off")) {
32670b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
32680b57cec5SDimitry Andric       << PP.getSpelling(Tok);
32690b57cec5SDimitry Andric     return;
32700b57cec5SDimitry Andric   }
32710b57cec5SDimitry Andric   PP.Lex(Tok);
32720b57cec5SDimitry Andric 
32730b57cec5SDimitry Andric   if (Tok.isNot(tok::eod)) {
32740b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
32750b57cec5SDimitry Andric       << PP.getSpelling(Tok);
32760b57cec5SDimitry Andric     return;
32770b57cec5SDimitry Andric   }
32780b57cec5SDimitry Andric 
32790b57cec5SDimitry Andric   Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
32800b57cec5SDimitry Andric }
32810b57cec5SDimitry Andric 
32820b57cec5SDimitry Andric namespace {
32830b57cec5SDimitry Andric /// Used as the annotation value for tok::annot_pragma_fp.
32840b57cec5SDimitry Andric struct TokFPAnnotValue {
32850b57cec5SDimitry Andric   enum FlagValues { On, Off, Fast };
32860b57cec5SDimitry Andric 
3287bdd1243dSDimitry Andric   std::optional<LangOptions::FPModeKind> ContractValue;
3288bdd1243dSDimitry Andric   std::optional<LangOptions::FPModeKind> ReassociateValue;
32895f757f3fSDimitry Andric   std::optional<LangOptions::FPModeKind> ReciprocalValue;
3290bdd1243dSDimitry Andric   std::optional<LangOptions::FPExceptionModeKind> ExceptionsValue;
3291bdd1243dSDimitry Andric   std::optional<LangOptions::FPEvalMethodKind> EvalMethodValue;
32920b57cec5SDimitry Andric };
32930b57cec5SDimitry Andric } // end anonymous namespace
32940b57cec5SDimitry Andric 
32950b57cec5SDimitry Andric void PragmaFPHandler::HandlePragma(Preprocessor &PP,
32960b57cec5SDimitry Andric                                    PragmaIntroducer Introducer, Token &Tok) {
32970b57cec5SDimitry Andric   // fp
32980b57cec5SDimitry Andric   Token PragmaName = Tok;
32990b57cec5SDimitry Andric   SmallVector<Token, 1> TokenList;
33000b57cec5SDimitry Andric 
33010b57cec5SDimitry Andric   PP.Lex(Tok);
33020b57cec5SDimitry Andric   if (Tok.isNot(tok::identifier)) {
33030b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
33040b57cec5SDimitry Andric         << /*MissingOption=*/true << "";
33050b57cec5SDimitry Andric     return;
33060b57cec5SDimitry Andric   }
33070b57cec5SDimitry Andric 
3308e8d8bef9SDimitry Andric   auto *AnnotValue = new (PP.getPreprocessorAllocator()) TokFPAnnotValue;
33090b57cec5SDimitry Andric   while (Tok.is(tok::identifier)) {
33100b57cec5SDimitry Andric     IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
33110b57cec5SDimitry Andric 
33120b57cec5SDimitry Andric     auto FlagKind =
33135f757f3fSDimitry Andric         llvm::StringSwitch<std::optional<PragmaFPKind>>(OptionInfo->getName())
33145f757f3fSDimitry Andric             .Case("contract", PFK_Contract)
33155f757f3fSDimitry Andric             .Case("reassociate", PFK_Reassociate)
33165f757f3fSDimitry Andric             .Case("exceptions", PFK_Exceptions)
33175f757f3fSDimitry Andric             .Case("eval_method", PFK_EvalMethod)
33185f757f3fSDimitry Andric             .Case("reciprocal", PFK_Reciprocal)
3319bdd1243dSDimitry Andric             .Default(std::nullopt);
33200b57cec5SDimitry Andric     if (!FlagKind) {
33210b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
33220b57cec5SDimitry Andric           << /*MissingOption=*/false << OptionInfo;
33230b57cec5SDimitry Andric       return;
33240b57cec5SDimitry Andric     }
33250b57cec5SDimitry Andric     PP.Lex(Tok);
33260b57cec5SDimitry Andric 
33270b57cec5SDimitry Andric     // Read '('
33280b57cec5SDimitry Andric     if (Tok.isNot(tok::l_paren)) {
33290b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
33300b57cec5SDimitry Andric       return;
33310b57cec5SDimitry Andric     }
33320b57cec5SDimitry Andric     PP.Lex(Tok);
333381ad6265SDimitry Andric     bool isEvalMethodDouble =
33345f757f3fSDimitry Andric         Tok.is(tok::kw_double) && FlagKind == PFK_EvalMethod;
33350b57cec5SDimitry Andric 
333681ad6265SDimitry Andric     // Don't diagnose if we have an eval_metod pragma with "double" kind.
333781ad6265SDimitry Andric     if (Tok.isNot(tok::identifier) && !isEvalMethodDouble) {
33380b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
33395ffd83dbSDimitry Andric           << PP.getSpelling(Tok) << OptionInfo->getName()
3340e8d8bef9SDimitry Andric           << static_cast<int>(*FlagKind);
33410b57cec5SDimitry Andric       return;
33420b57cec5SDimitry Andric     }
33430b57cec5SDimitry Andric     const IdentifierInfo *II = Tok.getIdentifierInfo();
33440b57cec5SDimitry Andric 
33455f757f3fSDimitry Andric     if (FlagKind == PFK_Contract) {
3346e8d8bef9SDimitry Andric       AnnotValue->ContractValue =
3347bdd1243dSDimitry Andric           llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(
33480b57cec5SDimitry Andric               II->getName())
3349e8d8bef9SDimitry Andric               .Case("on", LangOptions::FPModeKind::FPM_On)
3350e8d8bef9SDimitry Andric               .Case("off", LangOptions::FPModeKind::FPM_Off)
3351e8d8bef9SDimitry Andric               .Case("fast", LangOptions::FPModeKind::FPM_Fast)
3352bdd1243dSDimitry Andric               .Default(std::nullopt);
3353e8d8bef9SDimitry Andric       if (!AnnotValue->ContractValue) {
33540b57cec5SDimitry Andric         PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3355e8d8bef9SDimitry Andric             << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
33560b57cec5SDimitry Andric         return;
33570b57cec5SDimitry Andric       }
33585f757f3fSDimitry Andric     } else if (FlagKind == PFK_Reassociate || FlagKind == PFK_Reciprocal) {
33595f757f3fSDimitry Andric       auto &Value = FlagKind == PFK_Reassociate ? AnnotValue->ReassociateValue
33605f757f3fSDimitry Andric                                                 : AnnotValue->ReciprocalValue;
33615f757f3fSDimitry Andric       Value = llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(
3362e8d8bef9SDimitry Andric                   II->getName())
3363e8d8bef9SDimitry Andric                   .Case("on", LangOptions::FPModeKind::FPM_On)
3364e8d8bef9SDimitry Andric                   .Case("off", LangOptions::FPModeKind::FPM_Off)
3365bdd1243dSDimitry Andric                   .Default(std::nullopt);
33665f757f3fSDimitry Andric       if (!Value) {
3367e8d8bef9SDimitry Andric         PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3368e8d8bef9SDimitry Andric             << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3369e8d8bef9SDimitry Andric         return;
3370e8d8bef9SDimitry Andric       }
33715f757f3fSDimitry Andric     } else if (FlagKind == PFK_Exceptions) {
3372e8d8bef9SDimitry Andric       AnnotValue->ExceptionsValue =
3373bdd1243dSDimitry Andric           llvm::StringSwitch<std::optional<LangOptions::FPExceptionModeKind>>(
3374e8d8bef9SDimitry Andric               II->getName())
3375e8d8bef9SDimitry Andric               .Case("ignore", LangOptions::FPE_Ignore)
3376e8d8bef9SDimitry Andric               .Case("maytrap", LangOptions::FPE_MayTrap)
3377e8d8bef9SDimitry Andric               .Case("strict", LangOptions::FPE_Strict)
3378bdd1243dSDimitry Andric               .Default(std::nullopt);
3379e8d8bef9SDimitry Andric       if (!AnnotValue->ExceptionsValue) {
3380e8d8bef9SDimitry Andric         PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3381e8d8bef9SDimitry Andric             << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3382e8d8bef9SDimitry Andric         return;
3383e8d8bef9SDimitry Andric       }
33845f757f3fSDimitry Andric     } else if (FlagKind == PFK_EvalMethod) {
338581ad6265SDimitry Andric       AnnotValue->EvalMethodValue =
3386bdd1243dSDimitry Andric           llvm::StringSwitch<std::optional<LangOptions::FPEvalMethodKind>>(
338781ad6265SDimitry Andric               II->getName())
338881ad6265SDimitry Andric               .Case("source", LangOptions::FPEvalMethodKind::FEM_Source)
338981ad6265SDimitry Andric               .Case("double", LangOptions::FPEvalMethodKind::FEM_Double)
339081ad6265SDimitry Andric               .Case("extended", LangOptions::FPEvalMethodKind::FEM_Extended)
3391bdd1243dSDimitry Andric               .Default(std::nullopt);
339281ad6265SDimitry Andric       if (!AnnotValue->EvalMethodValue) {
339381ad6265SDimitry Andric         PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
339481ad6265SDimitry Andric             << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
339581ad6265SDimitry Andric         return;
339681ad6265SDimitry Andric       }
3397e8d8bef9SDimitry Andric     }
33980b57cec5SDimitry Andric     PP.Lex(Tok);
33990b57cec5SDimitry Andric 
34000b57cec5SDimitry Andric     // Read ')'
34010b57cec5SDimitry Andric     if (Tok.isNot(tok::r_paren)) {
34020b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
34030b57cec5SDimitry Andric       return;
34040b57cec5SDimitry Andric     }
34050b57cec5SDimitry Andric     PP.Lex(Tok);
34060b57cec5SDimitry Andric   }
34070b57cec5SDimitry Andric 
34080b57cec5SDimitry Andric   if (Tok.isNot(tok::eod)) {
34090b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
34100b57cec5SDimitry Andric         << "clang fp";
34110b57cec5SDimitry Andric     return;
34120b57cec5SDimitry Andric   }
34130b57cec5SDimitry Andric 
3414e8d8bef9SDimitry Andric   Token FPTok;
3415e8d8bef9SDimitry Andric   FPTok.startToken();
3416e8d8bef9SDimitry Andric   FPTok.setKind(tok::annot_pragma_fp);
3417e8d8bef9SDimitry Andric   FPTok.setLocation(PragmaName.getLocation());
3418e8d8bef9SDimitry Andric   FPTok.setAnnotationEndLoc(PragmaName.getLocation());
3419e8d8bef9SDimitry Andric   FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
3420e8d8bef9SDimitry Andric   TokenList.push_back(FPTok);
3421e8d8bef9SDimitry Andric 
3422a7dea167SDimitry Andric   auto TokenArray = std::make_unique<Token[]>(TokenList.size());
34230b57cec5SDimitry Andric   std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
34240b57cec5SDimitry Andric 
34250b57cec5SDimitry Andric   PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
34260b57cec5SDimitry Andric                       /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
34270b57cec5SDimitry Andric }
34280b57cec5SDimitry Andric 
3429e8d8bef9SDimitry Andric void PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor &PP,
3430e8d8bef9SDimitry Andric                                                 PragmaIntroducer Introducer,
3431e8d8bef9SDimitry Andric                                                 Token &Tok) {
3432e8d8bef9SDimitry Andric   Token PragmaName = Tok;
3433e8d8bef9SDimitry Andric   SmallVector<Token, 1> TokenList;
3434e8d8bef9SDimitry Andric   if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
3435e8d8bef9SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
3436e8d8bef9SDimitry Andric         << PragmaName.getIdentifierInfo()->getName();
3437e8d8bef9SDimitry Andric     return;
3438e8d8bef9SDimitry Andric   }
3439e8d8bef9SDimitry Andric 
3440e8d8bef9SDimitry Andric   PP.Lex(Tok);
3441e8d8bef9SDimitry Andric   if (Tok.isNot(tok::identifier)) {
3442e8d8bef9SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
3443e8d8bef9SDimitry Andric         << PragmaName.getIdentifierInfo()->getName();
3444e8d8bef9SDimitry Andric     return;
3445e8d8bef9SDimitry Andric   }
3446e8d8bef9SDimitry Andric   IdentifierInfo *II = Tok.getIdentifierInfo();
3447e8d8bef9SDimitry Andric 
3448e8d8bef9SDimitry Andric   auto RM =
3449e8d8bef9SDimitry Andric       llvm::StringSwitch<llvm::RoundingMode>(II->getName())
3450e8d8bef9SDimitry Andric           .Case("FE_TOWARDZERO", llvm::RoundingMode::TowardZero)
3451e8d8bef9SDimitry Andric           .Case("FE_TONEAREST", llvm::RoundingMode::NearestTiesToEven)
3452e8d8bef9SDimitry Andric           .Case("FE_UPWARD", llvm::RoundingMode::TowardPositive)
3453e8d8bef9SDimitry Andric           .Case("FE_DOWNWARD", llvm::RoundingMode::TowardNegative)
3454e8d8bef9SDimitry Andric           .Case("FE_TONEARESTFROMZERO", llvm::RoundingMode::NearestTiesToAway)
3455e8d8bef9SDimitry Andric           .Case("FE_DYNAMIC", llvm::RoundingMode::Dynamic)
3456e8d8bef9SDimitry Andric           .Default(llvm::RoundingMode::Invalid);
3457e8d8bef9SDimitry Andric   if (RM == llvm::RoundingMode::Invalid) {
3458e8d8bef9SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_stdc_unknown_rounding_mode);
3459e8d8bef9SDimitry Andric     return;
3460e8d8bef9SDimitry Andric   }
3461e8d8bef9SDimitry Andric   PP.Lex(Tok);
3462e8d8bef9SDimitry Andric 
3463e8d8bef9SDimitry Andric   if (Tok.isNot(tok::eod)) {
3464e8d8bef9SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3465e8d8bef9SDimitry Andric         << "STDC FENV_ROUND";
3466e8d8bef9SDimitry Andric     return;
3467e8d8bef9SDimitry Andric   }
3468e8d8bef9SDimitry Andric 
3469e8d8bef9SDimitry Andric   // Until the pragma is fully implemented, issue a warning.
3470e8d8bef9SDimitry Andric   PP.Diag(Tok.getLocation(), diag::warn_stdc_fenv_round_not_supported);
3471e8d8bef9SDimitry Andric 
3472e8d8bef9SDimitry Andric   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
3473e8d8bef9SDimitry Andric                               1);
3474e8d8bef9SDimitry Andric   Toks[0].startToken();
3475e8d8bef9SDimitry Andric   Toks[0].setKind(tok::annot_pragma_fenv_round);
3476e8d8bef9SDimitry Andric   Toks[0].setLocation(Tok.getLocation());
3477e8d8bef9SDimitry Andric   Toks[0].setAnnotationEndLoc(Tok.getLocation());
3478e8d8bef9SDimitry Andric   Toks[0].setAnnotationValue(
3479e8d8bef9SDimitry Andric       reinterpret_cast<void *>(static_cast<uintptr_t>(RM)));
3480e8d8bef9SDimitry Andric   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
3481e8d8bef9SDimitry Andric                       /*IsReinject=*/false);
3482e8d8bef9SDimitry Andric }
3483e8d8bef9SDimitry Andric 
34840b57cec5SDimitry Andric void Parser::HandlePragmaFP() {
34850b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_fp));
34860b57cec5SDimitry Andric   auto *AnnotValue =
34870b57cec5SDimitry Andric       reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
34880b57cec5SDimitry Andric 
3489e8d8bef9SDimitry Andric   if (AnnotValue->ReassociateValue)
34905f757f3fSDimitry Andric     Actions.ActOnPragmaFPValueChangingOption(
34915f757f3fSDimitry Andric         Tok.getLocation(), PFK_Reassociate,
34925f757f3fSDimitry Andric         *AnnotValue->ReassociateValue == LangOptions::FPModeKind::FPM_On);
34935f757f3fSDimitry Andric 
34945f757f3fSDimitry Andric   if (AnnotValue->ReciprocalValue)
34955f757f3fSDimitry Andric     Actions.ActOnPragmaFPValueChangingOption(
34965f757f3fSDimitry Andric         Tok.getLocation(), PFK_Reciprocal,
34975f757f3fSDimitry Andric         *AnnotValue->ReciprocalValue == LangOptions::FPModeKind::FPM_On);
34985f757f3fSDimitry Andric 
3499e8d8bef9SDimitry Andric   if (AnnotValue->ContractValue)
3500e8d8bef9SDimitry Andric     Actions.ActOnPragmaFPContract(Tok.getLocation(),
3501e8d8bef9SDimitry Andric                                   *AnnotValue->ContractValue);
3502e8d8bef9SDimitry Andric   if (AnnotValue->ExceptionsValue)
3503e8d8bef9SDimitry Andric     Actions.ActOnPragmaFPExceptions(Tok.getLocation(),
3504e8d8bef9SDimitry Andric                                     *AnnotValue->ExceptionsValue);
350581ad6265SDimitry Andric   if (AnnotValue->EvalMethodValue)
350681ad6265SDimitry Andric     Actions.ActOnPragmaFPEvalMethod(Tok.getLocation(),
350781ad6265SDimitry Andric                                     *AnnotValue->EvalMethodValue);
35080b57cec5SDimitry Andric   ConsumeAnnotationToken();
35090b57cec5SDimitry Andric }
35100b57cec5SDimitry Andric 
35110b57cec5SDimitry Andric /// Parses loop or unroll pragma hint value and fills in Info.
35120b57cec5SDimitry Andric static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
35130b57cec5SDimitry Andric                                Token Option, bool ValueInParens,
35140b57cec5SDimitry Andric                                PragmaLoopHintInfo &Info) {
35150b57cec5SDimitry Andric   SmallVector<Token, 1> ValueList;
35160b57cec5SDimitry Andric   int OpenParens = ValueInParens ? 1 : 0;
35170b57cec5SDimitry Andric   // Read constant expression.
35180b57cec5SDimitry Andric   while (Tok.isNot(tok::eod)) {
35190b57cec5SDimitry Andric     if (Tok.is(tok::l_paren))
35200b57cec5SDimitry Andric       OpenParens++;
35210b57cec5SDimitry Andric     else if (Tok.is(tok::r_paren)) {
35220b57cec5SDimitry Andric       OpenParens--;
35230b57cec5SDimitry Andric       if (OpenParens == 0 && ValueInParens)
35240b57cec5SDimitry Andric         break;
35250b57cec5SDimitry Andric     }
35260b57cec5SDimitry Andric 
35270b57cec5SDimitry Andric     ValueList.push_back(Tok);
35280b57cec5SDimitry Andric     PP.Lex(Tok);
35290b57cec5SDimitry Andric   }
35300b57cec5SDimitry Andric 
35310b57cec5SDimitry Andric   if (ValueInParens) {
35320b57cec5SDimitry Andric     // Read ')'
35330b57cec5SDimitry Andric     if (Tok.isNot(tok::r_paren)) {
35340b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
35350b57cec5SDimitry Andric       return true;
35360b57cec5SDimitry Andric     }
35370b57cec5SDimitry Andric     PP.Lex(Tok);
35380b57cec5SDimitry Andric   }
35390b57cec5SDimitry Andric 
35400b57cec5SDimitry Andric   Token EOFTok;
35410b57cec5SDimitry Andric   EOFTok.startToken();
35420b57cec5SDimitry Andric   EOFTok.setKind(tok::eof);
35430b57cec5SDimitry Andric   EOFTok.setLocation(Tok.getLocation());
35440b57cec5SDimitry Andric   ValueList.push_back(EOFTok); // Terminates expression for parsing.
35450b57cec5SDimitry Andric 
3546fe6060f1SDimitry Andric   markAsReinjectedForRelexing(ValueList);
3547bdd1243dSDimitry Andric   Info.Toks = llvm::ArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
35480b57cec5SDimitry Andric 
35490b57cec5SDimitry Andric   Info.PragmaName = PragmaName;
35500b57cec5SDimitry Andric   Info.Option = Option;
35510b57cec5SDimitry Andric   return false;
35520b57cec5SDimitry Andric }
35530b57cec5SDimitry Andric 
35540b57cec5SDimitry Andric /// Handle the \#pragma clang loop directive.
35550b57cec5SDimitry Andric ///  #pragma clang 'loop' loop-hints
35560b57cec5SDimitry Andric ///
35570b57cec5SDimitry Andric ///  loop-hints:
35580b57cec5SDimitry Andric ///    loop-hint loop-hints[opt]
35590b57cec5SDimitry Andric ///
35600b57cec5SDimitry Andric ///  loop-hint:
35610b57cec5SDimitry Andric ///    'vectorize' '(' loop-hint-keyword ')'
35620b57cec5SDimitry Andric ///    'interleave' '(' loop-hint-keyword ')'
35630b57cec5SDimitry Andric ///    'unroll' '(' unroll-hint-keyword ')'
3564a7dea167SDimitry Andric ///    'vectorize_predicate' '(' loop-hint-keyword ')'
35650b57cec5SDimitry Andric ///    'vectorize_width' '(' loop-hint-value ')'
35660b57cec5SDimitry Andric ///    'interleave_count' '(' loop-hint-value ')'
35670b57cec5SDimitry Andric ///    'unroll_count' '(' loop-hint-value ')'
35680b57cec5SDimitry Andric ///    'pipeline' '(' disable ')'
35690b57cec5SDimitry Andric ///    'pipeline_initiation_interval' '(' loop-hint-value ')'
35700b57cec5SDimitry Andric ///
35710b57cec5SDimitry Andric ///  loop-hint-keyword:
35720b57cec5SDimitry Andric ///    'enable'
35730b57cec5SDimitry Andric ///    'disable'
35740b57cec5SDimitry Andric ///    'assume_safety'
35750b57cec5SDimitry Andric ///
35760b57cec5SDimitry Andric ///  unroll-hint-keyword:
35770b57cec5SDimitry Andric ///    'enable'
35780b57cec5SDimitry Andric ///    'disable'
35790b57cec5SDimitry Andric ///    'full'
35800b57cec5SDimitry Andric ///
35810b57cec5SDimitry Andric ///  loop-hint-value:
35820b57cec5SDimitry Andric ///    constant-expression
35830b57cec5SDimitry Andric ///
35840b57cec5SDimitry Andric /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
35850b57cec5SDimitry Andric /// try vectorizing the instructions of the loop it precedes. Specifying
35860b57cec5SDimitry Andric /// interleave(enable) or interleave_count(_value_) instructs llvm to try
35870b57cec5SDimitry Andric /// interleaving multiple iterations of the loop it precedes. The width of the
35880b57cec5SDimitry Andric /// vector instructions is specified by vectorize_width() and the number of
35890b57cec5SDimitry Andric /// interleaved loop iterations is specified by interleave_count(). Specifying a
35900b57cec5SDimitry Andric /// value of 1 effectively disables vectorization/interleaving, even if it is
35910b57cec5SDimitry Andric /// possible and profitable, and 0 is invalid. The loop vectorizer currently
35920b57cec5SDimitry Andric /// only works on inner loops.
35930b57cec5SDimitry Andric ///
35940b57cec5SDimitry Andric /// The unroll and unroll_count directives control the concatenation
35950b57cec5SDimitry Andric /// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
35960b57cec5SDimitry Andric /// completely if the trip count is known at compile time and unroll partially
35970b57cec5SDimitry Andric /// if the trip count is not known.  Specifying unroll(full) is similar to
35980b57cec5SDimitry Andric /// unroll(enable) but will unroll the loop only if the trip count is known at
35990b57cec5SDimitry Andric /// compile time.  Specifying unroll(disable) disables unrolling for the
36000b57cec5SDimitry Andric /// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
36010b57cec5SDimitry Andric /// loop the number of times indicated by the value.
36020b57cec5SDimitry Andric void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
36030b57cec5SDimitry Andric                                          PragmaIntroducer Introducer,
36040b57cec5SDimitry Andric                                          Token &Tok) {
36050b57cec5SDimitry Andric   // Incoming token is "loop" from "#pragma clang loop".
36060b57cec5SDimitry Andric   Token PragmaName = Tok;
36070b57cec5SDimitry Andric   SmallVector<Token, 1> TokenList;
36080b57cec5SDimitry Andric 
36090b57cec5SDimitry Andric   // Lex the optimization option and verify it is an identifier.
36100b57cec5SDimitry Andric   PP.Lex(Tok);
36110b57cec5SDimitry Andric   if (Tok.isNot(tok::identifier)) {
36120b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
36130b57cec5SDimitry Andric         << /*MissingOption=*/true << "";
36140b57cec5SDimitry Andric     return;
36150b57cec5SDimitry Andric   }
36160b57cec5SDimitry Andric 
36170b57cec5SDimitry Andric   while (Tok.is(tok::identifier)) {
36180b57cec5SDimitry Andric     Token Option = Tok;
36190b57cec5SDimitry Andric     IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
36200b57cec5SDimitry Andric 
36210b57cec5SDimitry Andric     bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
36220b57cec5SDimitry Andric                            .Case("vectorize", true)
36230b57cec5SDimitry Andric                            .Case("interleave", true)
36240b57cec5SDimitry Andric                            .Case("unroll", true)
36250b57cec5SDimitry Andric                            .Case("distribute", true)
3626a7dea167SDimitry Andric                            .Case("vectorize_predicate", true)
36270b57cec5SDimitry Andric                            .Case("vectorize_width", true)
36280b57cec5SDimitry Andric                            .Case("interleave_count", true)
36290b57cec5SDimitry Andric                            .Case("unroll_count", true)
36300b57cec5SDimitry Andric                            .Case("pipeline", true)
36310b57cec5SDimitry Andric                            .Case("pipeline_initiation_interval", true)
36320b57cec5SDimitry Andric                            .Default(false);
36330b57cec5SDimitry Andric     if (!OptionValid) {
36340b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
36350b57cec5SDimitry Andric           << /*MissingOption=*/false << OptionInfo;
36360b57cec5SDimitry Andric       return;
36370b57cec5SDimitry Andric     }
36380b57cec5SDimitry Andric     PP.Lex(Tok);
36390b57cec5SDimitry Andric 
36400b57cec5SDimitry Andric     // Read '('
36410b57cec5SDimitry Andric     if (Tok.isNot(tok::l_paren)) {
36420b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
36430b57cec5SDimitry Andric       return;
36440b57cec5SDimitry Andric     }
36450b57cec5SDimitry Andric     PP.Lex(Tok);
36460b57cec5SDimitry Andric 
36470b57cec5SDimitry Andric     auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
36480b57cec5SDimitry Andric     if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
36490b57cec5SDimitry Andric                            *Info))
36500b57cec5SDimitry Andric       return;
36510b57cec5SDimitry Andric 
36520b57cec5SDimitry Andric     // Generate the loop hint token.
36530b57cec5SDimitry Andric     Token LoopHintTok;
36540b57cec5SDimitry Andric     LoopHintTok.startToken();
36550b57cec5SDimitry Andric     LoopHintTok.setKind(tok::annot_pragma_loop_hint);
36565ffd83dbSDimitry Andric     LoopHintTok.setLocation(Introducer.Loc);
36570b57cec5SDimitry Andric     LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
36580b57cec5SDimitry Andric     LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
36590b57cec5SDimitry Andric     TokenList.push_back(LoopHintTok);
36600b57cec5SDimitry Andric   }
36610b57cec5SDimitry Andric 
36620b57cec5SDimitry Andric   if (Tok.isNot(tok::eod)) {
36630b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
36640b57cec5SDimitry Andric         << "clang loop";
36650b57cec5SDimitry Andric     return;
36660b57cec5SDimitry Andric   }
36670b57cec5SDimitry Andric 
3668a7dea167SDimitry Andric   auto TokenArray = std::make_unique<Token[]>(TokenList.size());
36690b57cec5SDimitry Andric   std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
36700b57cec5SDimitry Andric 
36710b57cec5SDimitry Andric   PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
36720b57cec5SDimitry Andric                       /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
36730b57cec5SDimitry Andric }
36740b57cec5SDimitry Andric 
36750b57cec5SDimitry Andric /// Handle the loop unroll optimization pragmas.
36760b57cec5SDimitry Andric ///  #pragma unroll
36770b57cec5SDimitry Andric ///  #pragma unroll unroll-hint-value
36780b57cec5SDimitry Andric ///  #pragma unroll '(' unroll-hint-value ')'
36790b57cec5SDimitry Andric ///  #pragma nounroll
36800b57cec5SDimitry Andric ///  #pragma unroll_and_jam
36810b57cec5SDimitry Andric ///  #pragma unroll_and_jam unroll-hint-value
36820b57cec5SDimitry Andric ///  #pragma unroll_and_jam '(' unroll-hint-value ')'
36830b57cec5SDimitry Andric ///  #pragma nounroll_and_jam
36840b57cec5SDimitry Andric ///
36850b57cec5SDimitry Andric ///  unroll-hint-value:
36860b57cec5SDimitry Andric ///    constant-expression
36870b57cec5SDimitry Andric ///
36880b57cec5SDimitry Andric /// Loop unrolling hints can be specified with '#pragma unroll' or
36890b57cec5SDimitry Andric /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
36900b57cec5SDimitry Andric /// contained in parentheses. With no argument the directive instructs llvm to
36910b57cec5SDimitry Andric /// try to unroll the loop completely. A positive integer argument can be
36920b57cec5SDimitry Andric /// specified to indicate the number of times the loop should be unrolled.  To
36930b57cec5SDimitry Andric /// maximize compatibility with other compilers the unroll count argument can be
36940b57cec5SDimitry Andric /// specified with or without parentheses.  Specifying, '#pragma nounroll'
36950b57cec5SDimitry Andric /// disables unrolling of the loop.
36960b57cec5SDimitry Andric void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
36970b57cec5SDimitry Andric                                            PragmaIntroducer Introducer,
36980b57cec5SDimitry Andric                                            Token &Tok) {
36990b57cec5SDimitry Andric   // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
37000b57cec5SDimitry Andric   // "#pragma nounroll".
37010b57cec5SDimitry Andric   Token PragmaName = Tok;
37020b57cec5SDimitry Andric   PP.Lex(Tok);
37030b57cec5SDimitry Andric   auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
37040b57cec5SDimitry Andric   if (Tok.is(tok::eod)) {
37050b57cec5SDimitry Andric     // nounroll or unroll pragma without an argument.
37060b57cec5SDimitry Andric     Info->PragmaName = PragmaName;
37070b57cec5SDimitry Andric     Info->Option.startToken();
37080b57cec5SDimitry Andric   } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
37090b57cec5SDimitry Andric              PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
37100b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
37110b57cec5SDimitry Andric         << PragmaName.getIdentifierInfo()->getName();
37120b57cec5SDimitry Andric     return;
37130b57cec5SDimitry Andric   } else {
37140b57cec5SDimitry Andric     // Unroll pragma with an argument: "#pragma unroll N" or
37150b57cec5SDimitry Andric     // "#pragma unroll(N)".
37160b57cec5SDimitry Andric     // Read '(' if it exists.
37170b57cec5SDimitry Andric     bool ValueInParens = Tok.is(tok::l_paren);
37180b57cec5SDimitry Andric     if (ValueInParens)
37190b57cec5SDimitry Andric       PP.Lex(Tok);
37200b57cec5SDimitry Andric 
37210b57cec5SDimitry Andric     Token Option;
37220b57cec5SDimitry Andric     Option.startToken();
37230b57cec5SDimitry Andric     if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
37240b57cec5SDimitry Andric       return;
37250b57cec5SDimitry Andric 
37260b57cec5SDimitry Andric     // In CUDA, the argument to '#pragma unroll' should not be contained in
37270b57cec5SDimitry Andric     // parentheses.
37280b57cec5SDimitry Andric     if (PP.getLangOpts().CUDA && ValueInParens)
37290b57cec5SDimitry Andric       PP.Diag(Info->Toks[0].getLocation(),
37300b57cec5SDimitry Andric               diag::warn_pragma_unroll_cuda_value_in_parens);
37310b57cec5SDimitry Andric 
37320b57cec5SDimitry Andric     if (Tok.isNot(tok::eod)) {
37330b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
37340b57cec5SDimitry Andric           << "unroll";
37350b57cec5SDimitry Andric       return;
37360b57cec5SDimitry Andric     }
37370b57cec5SDimitry Andric   }
37380b57cec5SDimitry Andric 
37390b57cec5SDimitry Andric   // Generate the hint token.
3740a7dea167SDimitry Andric   auto TokenArray = std::make_unique<Token[]>(1);
37410b57cec5SDimitry Andric   TokenArray[0].startToken();
37420b57cec5SDimitry Andric   TokenArray[0].setKind(tok::annot_pragma_loop_hint);
37435ffd83dbSDimitry Andric   TokenArray[0].setLocation(Introducer.Loc);
37440b57cec5SDimitry Andric   TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
37450b57cec5SDimitry Andric   TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
37460b57cec5SDimitry Andric   PP.EnterTokenStream(std::move(TokenArray), 1,
37470b57cec5SDimitry Andric                       /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
37480b57cec5SDimitry Andric }
37490b57cec5SDimitry Andric 
37500b57cec5SDimitry Andric /// Handle the Microsoft \#pragma intrinsic extension.
37510b57cec5SDimitry Andric ///
37520b57cec5SDimitry Andric /// The syntax is:
37530b57cec5SDimitry Andric /// \code
37540b57cec5SDimitry Andric ///  #pragma intrinsic(memset)
37550b57cec5SDimitry Andric ///  #pragma intrinsic(strlen, memcpy)
37560b57cec5SDimitry Andric /// \endcode
37570b57cec5SDimitry Andric ///
37580b57cec5SDimitry Andric /// Pragma intrisic tells the compiler to use a builtin version of the
37590b57cec5SDimitry Andric /// function. Clang does it anyway, so the pragma doesn't really do anything.
37600b57cec5SDimitry Andric /// Anyway, we emit a warning if the function specified in \#pragma intrinsic
37610b57cec5SDimitry Andric /// isn't an intrinsic in clang and suggest to include intrin.h.
37620b57cec5SDimitry Andric void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
37630b57cec5SDimitry Andric                                             PragmaIntroducer Introducer,
37640b57cec5SDimitry Andric                                             Token &Tok) {
37650b57cec5SDimitry Andric   PP.Lex(Tok);
37660b57cec5SDimitry Andric 
37670b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren)) {
37680b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
37690b57cec5SDimitry Andric         << "intrinsic";
37700b57cec5SDimitry Andric     return;
37710b57cec5SDimitry Andric   }
37720b57cec5SDimitry Andric   PP.Lex(Tok);
37730b57cec5SDimitry Andric 
37740b57cec5SDimitry Andric   bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
37750b57cec5SDimitry Andric 
37760b57cec5SDimitry Andric   while (Tok.is(tok::identifier)) {
37770b57cec5SDimitry Andric     IdentifierInfo *II = Tok.getIdentifierInfo();
37780b57cec5SDimitry Andric     if (!II->getBuiltinID())
37790b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
37800b57cec5SDimitry Andric           << II << SuggestIntrinH;
37810b57cec5SDimitry Andric 
37820b57cec5SDimitry Andric     PP.Lex(Tok);
37830b57cec5SDimitry Andric     if (Tok.isNot(tok::comma))
37840b57cec5SDimitry Andric       break;
37850b57cec5SDimitry Andric     PP.Lex(Tok);
37860b57cec5SDimitry Andric   }
37870b57cec5SDimitry Andric 
37880b57cec5SDimitry Andric   if (Tok.isNot(tok::r_paren)) {
37890b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
37900b57cec5SDimitry Andric         << "intrinsic";
37910b57cec5SDimitry Andric     return;
37920b57cec5SDimitry Andric   }
37930b57cec5SDimitry Andric   PP.Lex(Tok);
37940b57cec5SDimitry Andric 
37950b57cec5SDimitry Andric   if (Tok.isNot(tok::eod))
37960b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
37970b57cec5SDimitry Andric         << "intrinsic";
37980b57cec5SDimitry Andric }
37990b57cec5SDimitry Andric 
380081ad6265SDimitry Andric bool Parser::HandlePragmaMSFunction(StringRef PragmaName,
380181ad6265SDimitry Andric                                     SourceLocation PragmaLocation) {
380281ad6265SDimitry Andric   Token FirstTok = Tok;
38030b57cec5SDimitry Andric 
380481ad6265SDimitry Andric   if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
380581ad6265SDimitry Andric                        PragmaName))
380681ad6265SDimitry Andric     return false;
380781ad6265SDimitry Andric 
380881ad6265SDimitry Andric   bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
380981ad6265SDimitry Andric 
381081ad6265SDimitry Andric   llvm::SmallVector<StringRef> NoBuiltins;
381181ad6265SDimitry Andric   while (Tok.is(tok::identifier)) {
381281ad6265SDimitry Andric     IdentifierInfo *II = Tok.getIdentifierInfo();
381381ad6265SDimitry Andric     if (!II->getBuiltinID())
381481ad6265SDimitry Andric       PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
381581ad6265SDimitry Andric           << II << SuggestIntrinH;
381681ad6265SDimitry Andric     else
381781ad6265SDimitry Andric       NoBuiltins.emplace_back(II->getName());
381881ad6265SDimitry Andric 
38190b57cec5SDimitry Andric     PP.Lex(Tok);
382081ad6265SDimitry Andric     if (Tok.isNot(tok::comma))
382181ad6265SDimitry Andric       break;
382281ad6265SDimitry Andric     PP.Lex(Tok); // ,
382381ad6265SDimitry Andric   }
382481ad6265SDimitry Andric 
382581ad6265SDimitry Andric   if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
382681ad6265SDimitry Andric                        PragmaName) ||
382781ad6265SDimitry Andric       ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
382881ad6265SDimitry Andric                        PragmaName))
382981ad6265SDimitry Andric     return false;
383081ad6265SDimitry Andric 
383181ad6265SDimitry Andric   Actions.ActOnPragmaMSFunction(FirstTok.getLocation(), NoBuiltins);
383281ad6265SDimitry Andric   return true;
383381ad6265SDimitry Andric }
383481ad6265SDimitry Andric 
383581ad6265SDimitry Andric // #pragma optimize("gsty", on|off)
383681ad6265SDimitry Andric bool Parser::HandlePragmaMSOptimize(StringRef PragmaName,
383781ad6265SDimitry Andric                                     SourceLocation PragmaLocation) {
383881ad6265SDimitry Andric   Token FirstTok = Tok;
383981ad6265SDimitry Andric   if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
384081ad6265SDimitry Andric                        PragmaName))
384181ad6265SDimitry Andric     return false;
38420b57cec5SDimitry Andric 
38430b57cec5SDimitry Andric   if (Tok.isNot(tok::string_literal)) {
384481ad6265SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_expected_string) << PragmaName;
384581ad6265SDimitry Andric     return false;
38460b57cec5SDimitry Andric   }
384781ad6265SDimitry Andric   ExprResult StringResult = ParseStringLiteralExpression();
384881ad6265SDimitry Andric   if (StringResult.isInvalid())
384981ad6265SDimitry Andric     return false; // Already diagnosed.
385081ad6265SDimitry Andric   StringLiteral *OptimizationList = cast<StringLiteral>(StringResult.get());
385181ad6265SDimitry Andric   if (OptimizationList->getCharByteWidth() != 1) {
385281ad6265SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
385381ad6265SDimitry Andric         << PragmaName;
385481ad6265SDimitry Andric     return false;
38550b57cec5SDimitry Andric   }
38560b57cec5SDimitry Andric 
385781ad6265SDimitry Andric   if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
385881ad6265SDimitry Andric                        PragmaName))
385981ad6265SDimitry Andric     return false;
386081ad6265SDimitry Andric 
386181ad6265SDimitry Andric   if (Tok.is(tok::eof) || Tok.is(tok::r_paren)) {
386281ad6265SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_missing_argument)
386381ad6265SDimitry Andric         << PragmaName << /*Expected=*/true << "'on' or 'off'";
386481ad6265SDimitry Andric     return false;
38650b57cec5SDimitry Andric   }
38660b57cec5SDimitry Andric   IdentifierInfo *II = Tok.getIdentifierInfo();
38670b57cec5SDimitry Andric   if (!II || (!II->isStr("on") && !II->isStr("off"))) {
386881ad6265SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
386981ad6265SDimitry Andric         << PP.getSpelling(Tok) << PragmaName << /*Expected=*/true
38700b57cec5SDimitry Andric         << "'on' or 'off'";
387181ad6265SDimitry Andric     return false;
38720b57cec5SDimitry Andric   }
387381ad6265SDimitry Andric   bool IsOn = II->isStr("on");
38740b57cec5SDimitry Andric   PP.Lex(Tok);
38750b57cec5SDimitry Andric 
387681ad6265SDimitry Andric   if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
387781ad6265SDimitry Andric                        PragmaName))
387881ad6265SDimitry Andric     return false;
38790b57cec5SDimitry Andric 
388081ad6265SDimitry Andric   // TODO: Add support for "sgty"
388181ad6265SDimitry Andric   if (!OptimizationList->getString().empty()) {
388281ad6265SDimitry Andric     PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
388381ad6265SDimitry Andric         << OptimizationList->getString() << PragmaName << /*Expected=*/true
388481ad6265SDimitry Andric         << "\"\"";
388581ad6265SDimitry Andric     return false;
38860b57cec5SDimitry Andric   }
388781ad6265SDimitry Andric 
388881ad6265SDimitry Andric   if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
388981ad6265SDimitry Andric                        PragmaName))
389081ad6265SDimitry Andric     return false;
389181ad6265SDimitry Andric 
389281ad6265SDimitry Andric   Actions.ActOnPragmaMSOptimize(FirstTok.getLocation(), IsOn);
389381ad6265SDimitry Andric   return true;
38940b57cec5SDimitry Andric }
38950b57cec5SDimitry Andric 
38960b57cec5SDimitry Andric void PragmaForceCUDAHostDeviceHandler::HandlePragma(
38970b57cec5SDimitry Andric     Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) {
38980b57cec5SDimitry Andric   Token FirstTok = Tok;
38990b57cec5SDimitry Andric 
39000b57cec5SDimitry Andric   PP.Lex(Tok);
39010b57cec5SDimitry Andric   IdentifierInfo *Info = Tok.getIdentifierInfo();
39020b57cec5SDimitry Andric   if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
39030b57cec5SDimitry Andric     PP.Diag(FirstTok.getLocation(),
39040b57cec5SDimitry Andric             diag::warn_pragma_force_cuda_host_device_bad_arg);
39050b57cec5SDimitry Andric     return;
39060b57cec5SDimitry Andric   }
39070b57cec5SDimitry Andric 
39080b57cec5SDimitry Andric   if (Info->isStr("begin"))
3909*0fca6ea1SDimitry Andric     Actions.CUDA().PushForceHostDevice();
3910*0fca6ea1SDimitry Andric   else if (!Actions.CUDA().PopForceHostDevice())
39110b57cec5SDimitry Andric     PP.Diag(FirstTok.getLocation(),
39120b57cec5SDimitry Andric             diag::err_pragma_cannot_end_force_cuda_host_device);
39130b57cec5SDimitry Andric 
39140b57cec5SDimitry Andric   PP.Lex(Tok);
39150b57cec5SDimitry Andric   if (!Tok.is(tok::eod))
39160b57cec5SDimitry Andric     PP.Diag(FirstTok.getLocation(),
39170b57cec5SDimitry Andric             diag::warn_pragma_force_cuda_host_device_bad_arg);
39180b57cec5SDimitry Andric }
39190b57cec5SDimitry Andric 
39200b57cec5SDimitry Andric /// Handle the #pragma clang attribute directive.
39210b57cec5SDimitry Andric ///
39220b57cec5SDimitry Andric /// The syntax is:
39230b57cec5SDimitry Andric /// \code
39240b57cec5SDimitry Andric ///  #pragma clang attribute push (attribute, subject-set)
39250b57cec5SDimitry Andric ///  #pragma clang attribute push
39260b57cec5SDimitry Andric ///  #pragma clang attribute (attribute, subject-set)
39270b57cec5SDimitry Andric ///  #pragma clang attribute pop
39280b57cec5SDimitry Andric /// \endcode
39290b57cec5SDimitry Andric ///
39300b57cec5SDimitry Andric /// There are also 'namespace' variants of push and pop directives. The bare
39310b57cec5SDimitry Andric /// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
39320b57cec5SDimitry Andric /// namespace, since it always applies attributes to the most recently pushed
39330b57cec5SDimitry Andric /// group, regardless of namespace.
39340b57cec5SDimitry Andric /// \code
39350b57cec5SDimitry Andric ///  #pragma clang attribute namespace.push (attribute, subject-set)
39360b57cec5SDimitry Andric ///  #pragma clang attribute namespace.push
39370b57cec5SDimitry Andric ///  #pragma clang attribute namespace.pop
39380b57cec5SDimitry Andric /// \endcode
39390b57cec5SDimitry Andric ///
39400b57cec5SDimitry Andric /// The subject-set clause defines the set of declarations which receive the
39410b57cec5SDimitry Andric /// attribute. Its exact syntax is described in the LanguageExtensions document
39420b57cec5SDimitry Andric /// in Clang's documentation.
39430b57cec5SDimitry Andric ///
39440b57cec5SDimitry Andric /// This directive instructs the compiler to begin/finish applying the specified
39450b57cec5SDimitry Andric /// attribute to the set of attribute-specific declarations in the active range
39460b57cec5SDimitry Andric /// of the pragma.
39470b57cec5SDimitry Andric void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
39480b57cec5SDimitry Andric                                           PragmaIntroducer Introducer,
39490b57cec5SDimitry Andric                                           Token &FirstToken) {
39500b57cec5SDimitry Andric   Token Tok;
39510b57cec5SDimitry Andric   PP.Lex(Tok);
39520b57cec5SDimitry Andric   auto *Info = new (PP.getPreprocessorAllocator())
39530b57cec5SDimitry Andric       PragmaAttributeInfo(AttributesForPragmaAttribute);
39540b57cec5SDimitry Andric 
39550b57cec5SDimitry Andric   // Parse the optional namespace followed by a period.
39560b57cec5SDimitry Andric   if (Tok.is(tok::identifier)) {
39570b57cec5SDimitry Andric     IdentifierInfo *II = Tok.getIdentifierInfo();
39580b57cec5SDimitry Andric     if (!II->isStr("push") && !II->isStr("pop")) {
39590b57cec5SDimitry Andric       Info->Namespace = II;
39600b57cec5SDimitry Andric       PP.Lex(Tok);
39610b57cec5SDimitry Andric 
39620b57cec5SDimitry Andric       if (!Tok.is(tok::period)) {
39630b57cec5SDimitry Andric         PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
39640b57cec5SDimitry Andric             << II;
39650b57cec5SDimitry Andric         return;
39660b57cec5SDimitry Andric       }
39670b57cec5SDimitry Andric       PP.Lex(Tok);
39680b57cec5SDimitry Andric     }
39690b57cec5SDimitry Andric   }
39700b57cec5SDimitry Andric 
39710b57cec5SDimitry Andric   if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
39720b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(),
39730b57cec5SDimitry Andric             diag::err_pragma_attribute_expected_push_pop_paren);
39740b57cec5SDimitry Andric     return;
39750b57cec5SDimitry Andric   }
39760b57cec5SDimitry Andric 
39770b57cec5SDimitry Andric   // Determine what action this pragma clang attribute represents.
39780b57cec5SDimitry Andric   if (Tok.is(tok::l_paren)) {
39790b57cec5SDimitry Andric     if (Info->Namespace) {
39800b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(),
39810b57cec5SDimitry Andric               diag::err_pragma_attribute_namespace_on_attribute);
39820b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(),
39830b57cec5SDimitry Andric               diag::note_pragma_attribute_namespace_on_attribute);
39840b57cec5SDimitry Andric       return;
39850b57cec5SDimitry Andric     }
39860b57cec5SDimitry Andric     Info->Action = PragmaAttributeInfo::Attribute;
39870b57cec5SDimitry Andric   } else {
39880b57cec5SDimitry Andric     const IdentifierInfo *II = Tok.getIdentifierInfo();
39890b57cec5SDimitry Andric     if (II->isStr("push"))
39900b57cec5SDimitry Andric       Info->Action = PragmaAttributeInfo::Push;
39910b57cec5SDimitry Andric     else if (II->isStr("pop"))
39920b57cec5SDimitry Andric       Info->Action = PragmaAttributeInfo::Pop;
39930b57cec5SDimitry Andric     else {
39940b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
39950b57cec5SDimitry Andric           << PP.getSpelling(Tok);
39960b57cec5SDimitry Andric       return;
39970b57cec5SDimitry Andric     }
39980b57cec5SDimitry Andric 
39990b57cec5SDimitry Andric     PP.Lex(Tok);
40000b57cec5SDimitry Andric   }
40010b57cec5SDimitry Andric 
40020b57cec5SDimitry Andric   // Parse the actual attribute.
40030b57cec5SDimitry Andric   if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
40040b57cec5SDimitry Andric       Info->Action == PragmaAttributeInfo::Attribute) {
40050b57cec5SDimitry Andric     if (Tok.isNot(tok::l_paren)) {
40060b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
40070b57cec5SDimitry Andric       return;
40080b57cec5SDimitry Andric     }
40090b57cec5SDimitry Andric     PP.Lex(Tok);
40100b57cec5SDimitry Andric 
40110b57cec5SDimitry Andric     // Lex the attribute tokens.
40120b57cec5SDimitry Andric     SmallVector<Token, 16> AttributeTokens;
40130b57cec5SDimitry Andric     int OpenParens = 1;
40140b57cec5SDimitry Andric     while (Tok.isNot(tok::eod)) {
40150b57cec5SDimitry Andric       if (Tok.is(tok::l_paren))
40160b57cec5SDimitry Andric         OpenParens++;
40170b57cec5SDimitry Andric       else if (Tok.is(tok::r_paren)) {
40180b57cec5SDimitry Andric         OpenParens--;
40190b57cec5SDimitry Andric         if (OpenParens == 0)
40200b57cec5SDimitry Andric           break;
40210b57cec5SDimitry Andric       }
40220b57cec5SDimitry Andric 
40230b57cec5SDimitry Andric       AttributeTokens.push_back(Tok);
40240b57cec5SDimitry Andric       PP.Lex(Tok);
40250b57cec5SDimitry Andric     }
40260b57cec5SDimitry Andric 
40270b57cec5SDimitry Andric     if (AttributeTokens.empty()) {
40280b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
40290b57cec5SDimitry Andric       return;
40300b57cec5SDimitry Andric     }
40310b57cec5SDimitry Andric     if (Tok.isNot(tok::r_paren)) {
40320b57cec5SDimitry Andric       PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
40330b57cec5SDimitry Andric       return;
40340b57cec5SDimitry Andric     }
40350b57cec5SDimitry Andric     SourceLocation EndLoc = Tok.getLocation();
40360b57cec5SDimitry Andric     PP.Lex(Tok);
40370b57cec5SDimitry Andric 
40380b57cec5SDimitry Andric     // Terminate the attribute for parsing.
40390b57cec5SDimitry Andric     Token EOFTok;
40400b57cec5SDimitry Andric     EOFTok.startToken();
40410b57cec5SDimitry Andric     EOFTok.setKind(tok::eof);
40420b57cec5SDimitry Andric     EOFTok.setLocation(EndLoc);
40430b57cec5SDimitry Andric     AttributeTokens.push_back(EOFTok);
40440b57cec5SDimitry Andric 
4045fe6060f1SDimitry Andric     markAsReinjectedForRelexing(AttributeTokens);
40460b57cec5SDimitry Andric     Info->Tokens =
4047bdd1243dSDimitry Andric         llvm::ArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
40480b57cec5SDimitry Andric   }
40490b57cec5SDimitry Andric 
40500b57cec5SDimitry Andric   if (Tok.isNot(tok::eod))
40510b57cec5SDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
40520b57cec5SDimitry Andric         << "clang attribute";
40530b57cec5SDimitry Andric 
40540b57cec5SDimitry Andric   // Generate the annotated pragma token.
4055a7dea167SDimitry Andric   auto TokenArray = std::make_unique<Token[]>(1);
40560b57cec5SDimitry Andric   TokenArray[0].startToken();
40570b57cec5SDimitry Andric   TokenArray[0].setKind(tok::annot_pragma_attribute);
40580b57cec5SDimitry Andric   TokenArray[0].setLocation(FirstToken.getLocation());
40590b57cec5SDimitry Andric   TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
40600b57cec5SDimitry Andric   TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
40610b57cec5SDimitry Andric   PP.EnterTokenStream(std::move(TokenArray), 1,
40620b57cec5SDimitry Andric                       /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
40630b57cec5SDimitry Andric }
40645ffd83dbSDimitry Andric 
40655ffd83dbSDimitry Andric // Handle '#pragma clang max_tokens 12345'.
40665ffd83dbSDimitry Andric void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP,
40675ffd83dbSDimitry Andric                                               PragmaIntroducer Introducer,
40685ffd83dbSDimitry Andric                                               Token &Tok) {
40695ffd83dbSDimitry Andric   PP.Lex(Tok);
40705ffd83dbSDimitry Andric   if (Tok.is(tok::eod)) {
40715ffd83dbSDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
40725ffd83dbSDimitry Andric         << "clang max_tokens_here" << /*Expected=*/true << "integer";
40735ffd83dbSDimitry Andric     return;
40745ffd83dbSDimitry Andric   }
40755ffd83dbSDimitry Andric 
40765ffd83dbSDimitry Andric   SourceLocation Loc = Tok.getLocation();
40775ffd83dbSDimitry Andric   uint64_t MaxTokens;
40785ffd83dbSDimitry Andric   if (Tok.isNot(tok::numeric_constant) ||
40795ffd83dbSDimitry Andric       !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
40805ffd83dbSDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
40815ffd83dbSDimitry Andric         << "clang max_tokens_here";
40825ffd83dbSDimitry Andric     return;
40835ffd83dbSDimitry Andric   }
40845ffd83dbSDimitry Andric 
40855ffd83dbSDimitry Andric   if (Tok.isNot(tok::eod)) {
40865ffd83dbSDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
40875ffd83dbSDimitry Andric         << "clang max_tokens_here";
40885ffd83dbSDimitry Andric     return;
40895ffd83dbSDimitry Andric   }
40905ffd83dbSDimitry Andric 
40915ffd83dbSDimitry Andric   if (PP.getTokenCount() > MaxTokens) {
40925ffd83dbSDimitry Andric     PP.Diag(Loc, diag::warn_max_tokens)
40935ffd83dbSDimitry Andric         << PP.getTokenCount() << (unsigned)MaxTokens;
40945ffd83dbSDimitry Andric   }
40955ffd83dbSDimitry Andric }
40965ffd83dbSDimitry Andric 
40975ffd83dbSDimitry Andric // Handle '#pragma clang max_tokens_total 12345'.
40985ffd83dbSDimitry Andric void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP,
40995ffd83dbSDimitry Andric                                                PragmaIntroducer Introducer,
41005ffd83dbSDimitry Andric                                                Token &Tok) {
41015ffd83dbSDimitry Andric   PP.Lex(Tok);
41025ffd83dbSDimitry Andric   if (Tok.is(tok::eod)) {
41035ffd83dbSDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
41045ffd83dbSDimitry Andric         << "clang max_tokens_total" << /*Expected=*/true << "integer";
41055ffd83dbSDimitry Andric     return;
41065ffd83dbSDimitry Andric   }
41075ffd83dbSDimitry Andric 
41085ffd83dbSDimitry Andric   SourceLocation Loc = Tok.getLocation();
41095ffd83dbSDimitry Andric   uint64_t MaxTokens;
41105ffd83dbSDimitry Andric   if (Tok.isNot(tok::numeric_constant) ||
41115ffd83dbSDimitry Andric       !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
41125ffd83dbSDimitry Andric     PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
41135ffd83dbSDimitry Andric         << "clang max_tokens_total";
41145ffd83dbSDimitry Andric     return;
41155ffd83dbSDimitry Andric   }
41165ffd83dbSDimitry Andric 
41175ffd83dbSDimitry Andric   if (Tok.isNot(tok::eod)) {
41185ffd83dbSDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
41195ffd83dbSDimitry Andric         << "clang max_tokens_total";
41205ffd83dbSDimitry Andric     return;
41215ffd83dbSDimitry Andric   }
41225ffd83dbSDimitry Andric 
41235ffd83dbSDimitry Andric   PP.overrideMaxTokens(MaxTokens, Loc);
41245ffd83dbSDimitry Andric }
4125972a253aSDimitry Andric 
4126972a253aSDimitry Andric // Handle '#pragma clang riscv intrinsic vector'.
412706c3fb27SDimitry Andric //        '#pragma clang riscv intrinsic sifive_vector'.
4128972a253aSDimitry Andric void PragmaRISCVHandler::HandlePragma(Preprocessor &PP,
4129972a253aSDimitry Andric                                       PragmaIntroducer Introducer,
4130972a253aSDimitry Andric                                       Token &FirstToken) {
4131972a253aSDimitry Andric   Token Tok;
4132972a253aSDimitry Andric   PP.Lex(Tok);
4133972a253aSDimitry Andric   IdentifierInfo *II = Tok.getIdentifierInfo();
4134972a253aSDimitry Andric 
4135972a253aSDimitry Andric   if (!II || !II->isStr("intrinsic")) {
4136972a253aSDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
4137972a253aSDimitry Andric         << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'intrinsic'";
4138972a253aSDimitry Andric     return;
4139972a253aSDimitry Andric   }
4140972a253aSDimitry Andric 
4141972a253aSDimitry Andric   PP.Lex(Tok);
4142972a253aSDimitry Andric   II = Tok.getIdentifierInfo();
414306c3fb27SDimitry Andric   if (!II || !(II->isStr("vector") || II->isStr("sifive_vector"))) {
4144972a253aSDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
414506c3fb27SDimitry Andric         << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true
414606c3fb27SDimitry Andric         << "'vector' or 'sifive_vector'";
4147972a253aSDimitry Andric     return;
4148972a253aSDimitry Andric   }
4149972a253aSDimitry Andric 
4150972a253aSDimitry Andric   PP.Lex(Tok);
4151972a253aSDimitry Andric   if (Tok.isNot(tok::eod)) {
4152972a253aSDimitry Andric     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
4153972a253aSDimitry Andric         << "clang riscv intrinsic";
4154972a253aSDimitry Andric     return;
4155972a253aSDimitry Andric   }
4156972a253aSDimitry Andric 
415706c3fb27SDimitry Andric   if (II->isStr("vector"))
4158*0fca6ea1SDimitry Andric     Actions.RISCV().DeclareRVVBuiltins = true;
415906c3fb27SDimitry Andric   else if (II->isStr("sifive_vector"))
4160*0fca6ea1SDimitry Andric     Actions.RISCV().DeclareSiFiveVectorBuiltins = true;
4161972a253aSDimitry Andric }
4162