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