Path: blob/main/contrib/llvm-project/clang/lib/Parse/ParsePragma.cpp
35233 views
//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the language specific #pragma handlers.9//10//===----------------------------------------------------------------------===//1112#include "clang/AST/ASTContext.h"13#include "clang/Basic/PragmaKinds.h"14#include "clang/Basic/TargetInfo.h"15#include "clang/Lex/Preprocessor.h"16#include "clang/Lex/Token.h"17#include "clang/Parse/LoopHint.h"18#include "clang/Parse/ParseDiagnostic.h"19#include "clang/Parse/Parser.h"20#include "clang/Parse/RAIIObjectsForParser.h"21#include "clang/Sema/EnterExpressionEvaluationContext.h"22#include "clang/Sema/Scope.h"23#include "clang/Sema/SemaCUDA.h"24#include "clang/Sema/SemaCodeCompletion.h"25#include "clang/Sema/SemaRISCV.h"26#include "llvm/ADT/ArrayRef.h"27#include "llvm/ADT/StringSwitch.h"28#include <optional>29using namespace clang;3031namespace {3233struct PragmaAlignHandler : public PragmaHandler {34explicit PragmaAlignHandler() : PragmaHandler("align") {}35void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,36Token &FirstToken) override;37};3839struct PragmaGCCVisibilityHandler : public PragmaHandler {40explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}41void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,42Token &FirstToken) override;43};4445struct PragmaOptionsHandler : public PragmaHandler {46explicit PragmaOptionsHandler() : PragmaHandler("options") {}47void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,48Token &FirstToken) override;49};5051struct PragmaPackHandler : public PragmaHandler {52explicit PragmaPackHandler() : PragmaHandler("pack") {}53void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,54Token &FirstToken) override;55};5657struct PragmaClangSectionHandler : public PragmaHandler {58explicit PragmaClangSectionHandler(Sema &S)59: PragmaHandler("section"), Actions(S) {}60void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,61Token &FirstToken) override;6263private:64Sema &Actions;65};6667struct PragmaMSStructHandler : public PragmaHandler {68explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}69void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,70Token &FirstToken) override;71};7273struct PragmaUnusedHandler : public PragmaHandler {74PragmaUnusedHandler() : PragmaHandler("unused") {}75void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,76Token &FirstToken) override;77};7879struct PragmaWeakHandler : public PragmaHandler {80explicit PragmaWeakHandler() : PragmaHandler("weak") {}81void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,82Token &FirstToken) override;83};8485struct PragmaRedefineExtnameHandler : public PragmaHandler {86explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}87void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,88Token &FirstToken) override;89};9091struct PragmaOpenCLExtensionHandler : public PragmaHandler {92PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}93void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,94Token &FirstToken) override;95};969798struct PragmaFPContractHandler : public PragmaHandler {99PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}100void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,101Token &FirstToken) override;102};103104// Pragma STDC implementations.105106/// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".107struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {108PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}109110void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,111Token &Tok) override {112Token PragmaName = Tok;113if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {114PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)115<< PragmaName.getIdentifierInfo()->getName();116return;117}118tok::OnOffSwitch OOS;119if (PP.LexOnOffSwitch(OOS))120return;121122MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),1231);124Toks[0].startToken();125Toks[0].setKind(tok::annot_pragma_fenv_access);126Toks[0].setLocation(Tok.getLocation());127Toks[0].setAnnotationEndLoc(Tok.getLocation());128Toks[0].setAnnotationValue(reinterpret_cast<void*>(129static_cast<uintptr_t>(OOS)));130PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,131/*IsReinject=*/false);132}133};134135/// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".136struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {137PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}138139void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,140Token &Tok) override {141tok::OnOffSwitch OOS;142if (PP.LexOnOffSwitch(OOS))143return;144145MutableArrayRef<Token> Toks(146PP.getPreprocessorAllocator().Allocate<Token>(1), 1);147148Toks[0].startToken();149Toks[0].setKind(tok::annot_pragma_cx_limited_range);150Toks[0].setLocation(Tok.getLocation());151Toks[0].setAnnotationEndLoc(Tok.getLocation());152Toks[0].setAnnotationValue(153reinterpret_cast<void *>(static_cast<uintptr_t>(OOS)));154PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,155/*IsReinject=*/false);156}157};158159/// Handler for "\#pragma STDC FENV_ROUND ...".160struct PragmaSTDC_FENV_ROUNDHandler : public PragmaHandler {161PragmaSTDC_FENV_ROUNDHandler() : PragmaHandler("FENV_ROUND") {}162163void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,164Token &Tok) override;165};166167/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".168struct PragmaSTDC_UnknownHandler : public PragmaHandler {169PragmaSTDC_UnknownHandler() = default;170171void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,172Token &UnknownTok) override {173// C99 6.10.6p2, unknown forms are not allowed.174PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);175}176};177178struct PragmaFPHandler : public PragmaHandler {179PragmaFPHandler() : PragmaHandler("fp") {}180void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,181Token &FirstToken) override;182};183184// A pragma handler to be the base of the NoOpenMPHandler and NoOpenACCHandler,185// which are identical other than the name given to them, and the diagnostic186// emitted.187template <diag::kind IgnoredDiag>188struct PragmaNoSupportHandler : public PragmaHandler {189PragmaNoSupportHandler(StringRef Name) : PragmaHandler(Name) {}190void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,191Token &FirstToken) override;192};193194struct PragmaNoOpenMPHandler195: public PragmaNoSupportHandler<diag::warn_pragma_omp_ignored> {196PragmaNoOpenMPHandler() : PragmaNoSupportHandler("omp") {}197};198199struct PragmaNoOpenACCHandler200: public PragmaNoSupportHandler<diag::warn_pragma_acc_ignored> {201PragmaNoOpenACCHandler() : PragmaNoSupportHandler("acc") {}202};203204// A pragma handler to be the base for the OpenMPHandler and OpenACCHandler,205// which are identical other than the tokens used for the start/end of a pragma206// section, and some diagnostics.207template <tok::TokenKind StartTok, tok::TokenKind EndTok,208diag::kind UnexpectedDiag>209struct PragmaSupportHandler : public PragmaHandler {210PragmaSupportHandler(StringRef Name) : PragmaHandler(Name) {}211void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,212Token &FirstToken) override;213};214215struct PragmaOpenMPHandler216: public PragmaSupportHandler<tok::annot_pragma_openmp,217tok::annot_pragma_openmp_end,218diag::err_omp_unexpected_directive> {219PragmaOpenMPHandler() : PragmaSupportHandler("omp") {}220};221222struct PragmaOpenACCHandler223: public PragmaSupportHandler<tok::annot_pragma_openacc,224tok::annot_pragma_openacc_end,225diag::err_acc_unexpected_directive> {226PragmaOpenACCHandler() : PragmaSupportHandler("acc") {}227};228229/// PragmaCommentHandler - "\#pragma comment ...".230struct PragmaCommentHandler : public PragmaHandler {231PragmaCommentHandler(Sema &Actions)232: PragmaHandler("comment"), Actions(Actions) {}233void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,234Token &FirstToken) override;235236private:237Sema &Actions;238};239240struct PragmaDetectMismatchHandler : public PragmaHandler {241PragmaDetectMismatchHandler(Sema &Actions)242: PragmaHandler("detect_mismatch"), Actions(Actions) {}243void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,244Token &FirstToken) override;245246private:247Sema &Actions;248};249250struct PragmaFloatControlHandler : public PragmaHandler {251PragmaFloatControlHandler(Sema &Actions)252: PragmaHandler("float_control") {}253void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,254Token &FirstToken) override;255};256257struct PragmaMSPointersToMembers : public PragmaHandler {258explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}259void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,260Token &FirstToken) override;261};262263struct PragmaMSVtorDisp : public PragmaHandler {264explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}265void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,266Token &FirstToken) override;267};268269struct PragmaMSPragma : public PragmaHandler {270explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}271void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,272Token &FirstToken) override;273};274275/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".276struct PragmaOptimizeHandler : public PragmaHandler {277PragmaOptimizeHandler(Sema &S)278: PragmaHandler("optimize"), Actions(S) {}279void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,280Token &FirstToken) override;281282private:283Sema &Actions;284};285286struct PragmaLoopHintHandler : public PragmaHandler {287PragmaLoopHintHandler() : PragmaHandler("loop") {}288void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,289Token &FirstToken) override;290};291292struct PragmaUnrollHintHandler : public PragmaHandler {293PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}294void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,295Token &FirstToken) override;296};297298struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {299PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}300};301302struct PragmaMSIntrinsicHandler : public PragmaHandler {303PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}304void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,305Token &FirstToken) override;306};307308// "\#pragma fenv_access (on)".309struct PragmaMSFenvAccessHandler : public PragmaHandler {310PragmaMSFenvAccessHandler() : PragmaHandler("fenv_access") {}311void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,312Token &FirstToken) override {313StringRef PragmaName = FirstToken.getIdentifierInfo()->getName();314if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {315PP.Diag(FirstToken.getLocation(), diag::warn_pragma_fp_ignored)316<< PragmaName;317return;318}319320Token Tok;321PP.Lex(Tok);322if (Tok.isNot(tok::l_paren)) {323PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)324<< PragmaName;325return;326}327PP.Lex(Tok); // Consume the l_paren.328if (Tok.isNot(tok::identifier)) {329PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);330return;331}332const IdentifierInfo *II = Tok.getIdentifierInfo();333tok::OnOffSwitch OOS;334if (II->isStr("on")) {335OOS = tok::OOS_ON;336PP.Lex(Tok);337} else if (II->isStr("off")) {338OOS = tok::OOS_OFF;339PP.Lex(Tok);340} else {341PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);342return;343}344if (Tok.isNot(tok::r_paren)) {345PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)346<< PragmaName;347return;348}349PP.Lex(Tok); // Consume the r_paren.350351if (Tok.isNot(tok::eod)) {352PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)353<< PragmaName;354return;355}356357MutableArrayRef<Token> Toks(358PP.getPreprocessorAllocator().Allocate<Token>(1), 1);359Toks[0].startToken();360Toks[0].setKind(tok::annot_pragma_fenv_access_ms);361Toks[0].setLocation(FirstToken.getLocation());362Toks[0].setAnnotationEndLoc(Tok.getLocation());363Toks[0].setAnnotationValue(364reinterpret_cast<void*>(static_cast<uintptr_t>(OOS)));365PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,366/*IsReinject=*/false);367}368};369370struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {371PragmaForceCUDAHostDeviceHandler(Sema &Actions)372: PragmaHandler("force_cuda_host_device"), Actions(Actions) {}373void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,374Token &FirstToken) override;375376private:377Sema &Actions;378};379380/// PragmaAttributeHandler - "\#pragma clang attribute ...".381struct PragmaAttributeHandler : public PragmaHandler {382PragmaAttributeHandler(AttributeFactory &AttrFactory)383: PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}384void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,385Token &FirstToken) override;386387/// A pool of attributes that were parsed in \#pragma clang attribute.388ParsedAttributes AttributesForPragmaAttribute;389};390391struct PragmaMaxTokensHereHandler : public PragmaHandler {392PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {}393void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,394Token &FirstToken) override;395};396397struct PragmaMaxTokensTotalHandler : public PragmaHandler {398PragmaMaxTokensTotalHandler() : PragmaHandler("max_tokens_total") {}399void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,400Token &FirstToken) override;401};402403struct PragmaRISCVHandler : public PragmaHandler {404PragmaRISCVHandler(Sema &Actions)405: PragmaHandler("riscv"), Actions(Actions) {}406void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,407Token &FirstToken) override;408409private:410Sema &Actions;411};412413void markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks) {414for (auto &T : Toks)415T.setFlag(clang::Token::IsReinjected);416}417} // end namespace418419void Parser::initializePragmaHandlers() {420AlignHandler = std::make_unique<PragmaAlignHandler>();421PP.AddPragmaHandler(AlignHandler.get());422423GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>();424PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());425426OptionsHandler = std::make_unique<PragmaOptionsHandler>();427PP.AddPragmaHandler(OptionsHandler.get());428429PackHandler = std::make_unique<PragmaPackHandler>();430PP.AddPragmaHandler(PackHandler.get());431432MSStructHandler = std::make_unique<PragmaMSStructHandler>();433PP.AddPragmaHandler(MSStructHandler.get());434435UnusedHandler = std::make_unique<PragmaUnusedHandler>();436PP.AddPragmaHandler(UnusedHandler.get());437438WeakHandler = std::make_unique<PragmaWeakHandler>();439PP.AddPragmaHandler(WeakHandler.get());440441RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>();442PP.AddPragmaHandler(RedefineExtnameHandler.get());443444FPContractHandler = std::make_unique<PragmaFPContractHandler>();445PP.AddPragmaHandler("STDC", FPContractHandler.get());446447STDCFenvAccessHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();448PP.AddPragmaHandler("STDC", STDCFenvAccessHandler.get());449450STDCFenvRoundHandler = std::make_unique<PragmaSTDC_FENV_ROUNDHandler>();451PP.AddPragmaHandler("STDC", STDCFenvRoundHandler.get());452453STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();454PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());455456STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>();457PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());458459PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions);460PP.AddPragmaHandler("clang", PCSectionHandler.get());461462if (getLangOpts().OpenCL) {463OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>();464PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());465466PP.AddPragmaHandler("OPENCL", FPContractHandler.get());467}468if (getLangOpts().OpenMP)469OpenMPHandler = std::make_unique<PragmaOpenMPHandler>();470else471OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>();472PP.AddPragmaHandler(OpenMPHandler.get());473474if (getLangOpts().OpenACC)475OpenACCHandler = std::make_unique<PragmaOpenACCHandler>();476else477OpenACCHandler = std::make_unique<PragmaNoOpenACCHandler>();478PP.AddPragmaHandler(OpenACCHandler.get());479480if (getLangOpts().MicrosoftExt ||481getTargetInfo().getTriple().isOSBinFormatELF()) {482MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions);483PP.AddPragmaHandler(MSCommentHandler.get());484}485486FloatControlHandler = std::make_unique<PragmaFloatControlHandler>(Actions);487PP.AddPragmaHandler(FloatControlHandler.get());488if (getLangOpts().MicrosoftExt) {489MSDetectMismatchHandler =490std::make_unique<PragmaDetectMismatchHandler>(Actions);491PP.AddPragmaHandler(MSDetectMismatchHandler.get());492MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>();493PP.AddPragmaHandler(MSPointersToMembers.get());494MSVtorDisp = std::make_unique<PragmaMSVtorDisp>();495PP.AddPragmaHandler(MSVtorDisp.get());496MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg");497PP.AddPragmaHandler(MSInitSeg.get());498MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg");499PP.AddPragmaHandler(MSDataSeg.get());500MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg");501PP.AddPragmaHandler(MSBSSSeg.get());502MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg");503PP.AddPragmaHandler(MSConstSeg.get());504MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg");505PP.AddPragmaHandler(MSCodeSeg.get());506MSSection = std::make_unique<PragmaMSPragma>("section");507PP.AddPragmaHandler(MSSection.get());508MSStrictGuardStackCheck =509std::make_unique<PragmaMSPragma>("strict_gs_check");510PP.AddPragmaHandler(MSStrictGuardStackCheck.get());511MSFunction = std::make_unique<PragmaMSPragma>("function");512PP.AddPragmaHandler(MSFunction.get());513MSAllocText = std::make_unique<PragmaMSPragma>("alloc_text");514PP.AddPragmaHandler(MSAllocText.get());515MSOptimize = std::make_unique<PragmaMSPragma>("optimize");516PP.AddPragmaHandler(MSOptimize.get());517MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>();518PP.AddPragmaHandler(MSRuntimeChecks.get());519MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>();520PP.AddPragmaHandler(MSIntrinsic.get());521MSFenvAccess = std::make_unique<PragmaMSFenvAccessHandler>();522PP.AddPragmaHandler(MSFenvAccess.get());523}524525if (getLangOpts().CUDA) {526CUDAForceHostDeviceHandler =527std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);528PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());529}530531OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions);532PP.AddPragmaHandler("clang", OptimizeHandler.get());533534LoopHintHandler = std::make_unique<PragmaLoopHintHandler>();535PP.AddPragmaHandler("clang", LoopHintHandler.get());536537UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll");538PP.AddPragmaHandler(UnrollHintHandler.get());539PP.AddPragmaHandler("GCC", UnrollHintHandler.get());540541NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll");542PP.AddPragmaHandler(NoUnrollHintHandler.get());543PP.AddPragmaHandler("GCC", NoUnrollHintHandler.get());544545UnrollAndJamHintHandler =546std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");547PP.AddPragmaHandler(UnrollAndJamHintHandler.get());548549NoUnrollAndJamHintHandler =550std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");551PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());552553FPHandler = std::make_unique<PragmaFPHandler>();554PP.AddPragmaHandler("clang", FPHandler.get());555556AttributePragmaHandler =557std::make_unique<PragmaAttributeHandler>(AttrFactory);558PP.AddPragmaHandler("clang", AttributePragmaHandler.get());559560MaxTokensHerePragmaHandler = std::make_unique<PragmaMaxTokensHereHandler>();561PP.AddPragmaHandler("clang", MaxTokensHerePragmaHandler.get());562563MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>();564PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get());565566if (getTargetInfo().getTriple().isRISCV()) {567RISCVPragmaHandler = std::make_unique<PragmaRISCVHandler>(Actions);568PP.AddPragmaHandler("clang", RISCVPragmaHandler.get());569}570}571572void Parser::resetPragmaHandlers() {573// Remove the pragma handlers we installed.574PP.RemovePragmaHandler(AlignHandler.get());575AlignHandler.reset();576PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());577GCCVisibilityHandler.reset();578PP.RemovePragmaHandler(OptionsHandler.get());579OptionsHandler.reset();580PP.RemovePragmaHandler(PackHandler.get());581PackHandler.reset();582PP.RemovePragmaHandler(MSStructHandler.get());583MSStructHandler.reset();584PP.RemovePragmaHandler(UnusedHandler.get());585UnusedHandler.reset();586PP.RemovePragmaHandler(WeakHandler.get());587WeakHandler.reset();588PP.RemovePragmaHandler(RedefineExtnameHandler.get());589RedefineExtnameHandler.reset();590591if (getLangOpts().OpenCL) {592PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());593OpenCLExtensionHandler.reset();594PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());595}596PP.RemovePragmaHandler(OpenMPHandler.get());597OpenMPHandler.reset();598599PP.RemovePragmaHandler(OpenACCHandler.get());600OpenACCHandler.reset();601602if (getLangOpts().MicrosoftExt ||603getTargetInfo().getTriple().isOSBinFormatELF()) {604PP.RemovePragmaHandler(MSCommentHandler.get());605MSCommentHandler.reset();606}607608PP.RemovePragmaHandler("clang", PCSectionHandler.get());609PCSectionHandler.reset();610611PP.RemovePragmaHandler(FloatControlHandler.get());612FloatControlHandler.reset();613if (getLangOpts().MicrosoftExt) {614PP.RemovePragmaHandler(MSDetectMismatchHandler.get());615MSDetectMismatchHandler.reset();616PP.RemovePragmaHandler(MSPointersToMembers.get());617MSPointersToMembers.reset();618PP.RemovePragmaHandler(MSVtorDisp.get());619MSVtorDisp.reset();620PP.RemovePragmaHandler(MSInitSeg.get());621MSInitSeg.reset();622PP.RemovePragmaHandler(MSDataSeg.get());623MSDataSeg.reset();624PP.RemovePragmaHandler(MSBSSSeg.get());625MSBSSSeg.reset();626PP.RemovePragmaHandler(MSConstSeg.get());627MSConstSeg.reset();628PP.RemovePragmaHandler(MSCodeSeg.get());629MSCodeSeg.reset();630PP.RemovePragmaHandler(MSSection.get());631MSSection.reset();632PP.RemovePragmaHandler(MSStrictGuardStackCheck.get());633MSStrictGuardStackCheck.reset();634PP.RemovePragmaHandler(MSFunction.get());635MSFunction.reset();636PP.RemovePragmaHandler(MSAllocText.get());637MSAllocText.reset();638PP.RemovePragmaHandler(MSRuntimeChecks.get());639MSRuntimeChecks.reset();640PP.RemovePragmaHandler(MSIntrinsic.get());641MSIntrinsic.reset();642PP.RemovePragmaHandler(MSOptimize.get());643MSOptimize.reset();644PP.RemovePragmaHandler(MSFenvAccess.get());645MSFenvAccess.reset();646}647648if (getLangOpts().CUDA) {649PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());650CUDAForceHostDeviceHandler.reset();651}652653PP.RemovePragmaHandler("STDC", FPContractHandler.get());654FPContractHandler.reset();655656PP.RemovePragmaHandler("STDC", STDCFenvAccessHandler.get());657STDCFenvAccessHandler.reset();658659PP.RemovePragmaHandler("STDC", STDCFenvRoundHandler.get());660STDCFenvRoundHandler.reset();661662PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());663STDCCXLIMITHandler.reset();664665PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());666STDCUnknownHandler.reset();667668PP.RemovePragmaHandler("clang", OptimizeHandler.get());669OptimizeHandler.reset();670671PP.RemovePragmaHandler("clang", LoopHintHandler.get());672LoopHintHandler.reset();673674PP.RemovePragmaHandler(UnrollHintHandler.get());675PP.RemovePragmaHandler("GCC", UnrollHintHandler.get());676UnrollHintHandler.reset();677678PP.RemovePragmaHandler(NoUnrollHintHandler.get());679PP.RemovePragmaHandler("GCC", NoUnrollHintHandler.get());680NoUnrollHintHandler.reset();681682PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());683UnrollAndJamHintHandler.reset();684685PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());686NoUnrollAndJamHintHandler.reset();687688PP.RemovePragmaHandler("clang", FPHandler.get());689FPHandler.reset();690691PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());692AttributePragmaHandler.reset();693694PP.RemovePragmaHandler("clang", MaxTokensHerePragmaHandler.get());695MaxTokensHerePragmaHandler.reset();696697PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get());698MaxTokensTotalPragmaHandler.reset();699700if (getTargetInfo().getTriple().isRISCV()) {701PP.RemovePragmaHandler("clang", RISCVPragmaHandler.get());702RISCVPragmaHandler.reset();703}704}705706/// Handle the annotation token produced for #pragma unused(...)707///708/// Each annot_pragma_unused is followed by the argument token so e.g.709/// "#pragma unused(x,y)" becomes:710/// annot_pragma_unused 'x' annot_pragma_unused 'y'711void Parser::HandlePragmaUnused() {712assert(Tok.is(tok::annot_pragma_unused));713SourceLocation UnusedLoc = ConsumeAnnotationToken();714Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);715ConsumeToken(); // The argument token.716}717718void Parser::HandlePragmaVisibility() {719assert(Tok.is(tok::annot_pragma_vis));720const IdentifierInfo *VisType =721static_cast<IdentifierInfo *>(Tok.getAnnotationValue());722SourceLocation VisLoc = ConsumeAnnotationToken();723Actions.ActOnPragmaVisibility(VisType, VisLoc);724}725726void Parser::HandlePragmaPack() {727assert(Tok.is(tok::annot_pragma_pack));728Sema::PragmaPackInfo *Info =729static_cast<Sema::PragmaPackInfo *>(Tok.getAnnotationValue());730SourceLocation PragmaLoc = Tok.getLocation();731ExprResult Alignment;732if (Info->Alignment.is(tok::numeric_constant)) {733Alignment = Actions.ActOnNumericConstant(Info->Alignment);734if (Alignment.isInvalid()) {735ConsumeAnnotationToken();736return;737}738}739Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,740Alignment.get());741// Consume the token after processing the pragma to enable pragma-specific742// #include warnings.743ConsumeAnnotationToken();744}745746void Parser::HandlePragmaMSStruct() {747assert(Tok.is(tok::annot_pragma_msstruct));748PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(749reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));750Actions.ActOnPragmaMSStruct(Kind);751ConsumeAnnotationToken();752}753754void Parser::HandlePragmaAlign() {755assert(Tok.is(tok::annot_pragma_align));756Sema::PragmaOptionsAlignKind Kind =757static_cast<Sema::PragmaOptionsAlignKind>(758reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));759Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());760// Consume the token after processing the pragma to enable pragma-specific761// #include warnings.762ConsumeAnnotationToken();763}764765void Parser::HandlePragmaDump() {766assert(Tok.is(tok::annot_pragma_dump));767ConsumeAnnotationToken();768if (Tok.is(tok::eod)) {769PP.Diag(Tok, diag::warn_pragma_debug_missing_argument) << "dump";770} else if (NextToken().is(tok::eod)) {771if (Tok.isNot(tok::identifier)) {772PP.Diag(Tok, diag::warn_pragma_debug_unexpected_argument);773ConsumeAnyToken();774ExpectAndConsume(tok::eod);775return;776}777IdentifierInfo *II = Tok.getIdentifierInfo();778Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);779ConsumeToken();780} else {781SourceLocation StartLoc = Tok.getLocation();782EnterExpressionEvaluationContext Ctx(783Actions, Sema::ExpressionEvaluationContext::Unevaluated);784ExprResult E = ParseExpression();785if (!E.isUsable() || E.get()->containsErrors()) {786// Diagnostics were emitted during parsing. No action needed.787} else if (E.get()->getDependence() != ExprDependence::None) {788PP.Diag(StartLoc, diag::warn_pragma_debug_dependent_argument)789<< E.get()->isTypeDependent()790<< SourceRange(StartLoc, Tok.getLocation());791} else {792Actions.ActOnPragmaDump(E.get());793}794SkipUntil(tok::eod, StopBeforeMatch);795}796ExpectAndConsume(tok::eod);797}798799void Parser::HandlePragmaWeak() {800assert(Tok.is(tok::annot_pragma_weak));801SourceLocation PragmaLoc = ConsumeAnnotationToken();802Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,803Tok.getLocation());804ConsumeToken(); // The weak name.805}806807void Parser::HandlePragmaWeakAlias() {808assert(Tok.is(tok::annot_pragma_weakalias));809SourceLocation PragmaLoc = ConsumeAnnotationToken();810IdentifierInfo *WeakName = Tok.getIdentifierInfo();811SourceLocation WeakNameLoc = Tok.getLocation();812ConsumeToken();813IdentifierInfo *AliasName = Tok.getIdentifierInfo();814SourceLocation AliasNameLoc = Tok.getLocation();815ConsumeToken();816Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,817WeakNameLoc, AliasNameLoc);818819}820821void Parser::HandlePragmaRedefineExtname() {822assert(Tok.is(tok::annot_pragma_redefine_extname));823SourceLocation RedefLoc = ConsumeAnnotationToken();824IdentifierInfo *RedefName = Tok.getIdentifierInfo();825SourceLocation RedefNameLoc = Tok.getLocation();826ConsumeToken();827IdentifierInfo *AliasName = Tok.getIdentifierInfo();828SourceLocation AliasNameLoc = Tok.getLocation();829ConsumeToken();830Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,831RedefNameLoc, AliasNameLoc);832}833834void Parser::HandlePragmaFPContract() {835assert(Tok.is(tok::annot_pragma_fp_contract));836tok::OnOffSwitch OOS =837static_cast<tok::OnOffSwitch>(838reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));839840LangOptions::FPModeKind FPC;841switch (OOS) {842case tok::OOS_ON:843FPC = LangOptions::FPM_On;844break;845case tok::OOS_OFF:846FPC = LangOptions::FPM_Off;847break;848case tok::OOS_DEFAULT:849// According to ISO C99 standard chapter 7.3.4, the default value850// for the pragma is ``off'. '-fcomplex-arithmetic=basic',851// '-fcx-limited-range', '-fcx-fortran-rules' and852// '-fcomplex-arithmetic=improved' control the default value of these853// pragmas.854FPC = getLangOpts().getDefaultFPContractMode();855break;856}857858SourceLocation PragmaLoc = ConsumeAnnotationToken();859Actions.ActOnPragmaFPContract(PragmaLoc, FPC);860}861862void Parser::HandlePragmaFloatControl() {863assert(Tok.is(tok::annot_pragma_float_control));864865// The value that is held on the PragmaFloatControlStack encodes866// the PragmaFloatControl kind and the MSStackAction kind867// into a single 32-bit word. The MsStackAction is the high 16 bits868// and the FloatControl is the lower 16 bits. Use shift and bit-and869// to decode the parts.870uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());871Sema::PragmaMsStackAction Action =872static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);873PragmaFloatControlKind Kind = PragmaFloatControlKind(Value & 0xFFFF);874SourceLocation PragmaLoc = ConsumeAnnotationToken();875Actions.ActOnPragmaFloatControl(PragmaLoc, Action, Kind);876}877878void Parser::HandlePragmaFEnvAccess() {879assert(Tok.is(tok::annot_pragma_fenv_access) ||880Tok.is(tok::annot_pragma_fenv_access_ms));881tok::OnOffSwitch OOS =882static_cast<tok::OnOffSwitch>(883reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));884885bool IsEnabled;886switch (OOS) {887case tok::OOS_ON:888IsEnabled = true;889break;890case tok::OOS_OFF:891IsEnabled = false;892break;893case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.894IsEnabled = false;895break;896}897898SourceLocation PragmaLoc = ConsumeAnnotationToken();899Actions.ActOnPragmaFEnvAccess(PragmaLoc, IsEnabled);900}901902void Parser::HandlePragmaFEnvRound() {903assert(Tok.is(tok::annot_pragma_fenv_round));904auto RM = static_cast<llvm::RoundingMode>(905reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));906907SourceLocation PragmaLoc = ConsumeAnnotationToken();908Actions.ActOnPragmaFEnvRound(PragmaLoc, RM);909}910911void Parser::HandlePragmaCXLimitedRange() {912assert(Tok.is(tok::annot_pragma_cx_limited_range));913tok::OnOffSwitch OOS = static_cast<tok::OnOffSwitch>(914reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));915916LangOptions::ComplexRangeKind Range;917switch (OOS) {918case tok::OOS_ON:919Range = LangOptions::CX_Basic;920break;921case tok::OOS_OFF:922Range = LangOptions::CX_Full;923break;924case tok::OOS_DEFAULT:925// According to ISO C99 standard chapter 7.3.4, the default value926// for the pragma is ``off'. -fcomplex-arithmetic controls the default value927// of these pragmas.928Range = getLangOpts().getComplexRange();929break;930}931932SourceLocation PragmaLoc = ConsumeAnnotationToken();933Actions.ActOnPragmaCXLimitedRange(PragmaLoc, Range);934}935936StmtResult Parser::HandlePragmaCaptured()937{938assert(Tok.is(tok::annot_pragma_captured));939ConsumeAnnotationToken();940941if (Tok.isNot(tok::l_brace)) {942PP.Diag(Tok, diag::err_expected) << tok::l_brace;943return StmtError();944}945946SourceLocation Loc = Tok.getLocation();947948ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |949Scope::CompoundStmtScope);950Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,951/*NumParams=*/1);952953StmtResult R = ParseCompoundStatement();954CapturedRegionScope.Exit();955956if (R.isInvalid()) {957Actions.ActOnCapturedRegionError();958return StmtError();959}960961return Actions.ActOnCapturedRegionEnd(R.get());962}963964namespace {965enum OpenCLExtState : char {966Disable, Enable, Begin, End967};968typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;969}970971void Parser::HandlePragmaOpenCLExtension() {972assert(Tok.is(tok::annot_pragma_opencl_extension));973OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());974auto State = Data->second;975auto Ident = Data->first;976SourceLocation NameLoc = Tok.getLocation();977ConsumeAnnotationToken();978979auto &Opt = Actions.getOpenCLOptions();980auto Name = Ident->getName();981// OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,982// overriding all previously issued extension directives, but only if the983// behavior is set to disable."984if (Name == "all") {985if (State == Disable)986Opt.disableAll();987else988PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;989} else if (State == Begin) {990if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) {991Opt.support(Name);992// FIXME: Default behavior of the extension pragma is not defined.993// Therefore, it should never be added by default.994Opt.acceptsPragma(Name);995}996} else if (State == End) {997// There is no behavior for this directive. We only accept this for998// backward compatibility.999} else if (!Opt.isKnown(Name) || !Opt.isWithPragma(Name))1000PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;1001else if (Opt.isSupportedExtension(Name, getLangOpts()))1002Opt.enable(Name, State == Enable);1003else if (Opt.isSupportedCoreOrOptionalCore(Name, getLangOpts()))1004PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;1005else1006PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;1007}10081009void Parser::HandlePragmaMSPointersToMembers() {1010assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));1011LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =1012static_cast<LangOptions::PragmaMSPointersToMembersKind>(1013reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));1014SourceLocation PragmaLoc = ConsumeAnnotationToken();1015Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);1016}10171018void Parser::HandlePragmaMSVtorDisp() {1019assert(Tok.is(tok::annot_pragma_ms_vtordisp));1020uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());1021Sema::PragmaMsStackAction Action =1022static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);1023MSVtorDispMode Mode = MSVtorDispMode(Value & 0xFFFF);1024SourceLocation PragmaLoc = ConsumeAnnotationToken();1025Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);1026}10271028void Parser::HandlePragmaMSPragma() {1029assert(Tok.is(tok::annot_pragma_ms_pragma));1030// Grab the tokens out of the annotation and enter them into the stream.1031auto TheTokens =1032(std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();1033PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true,1034/*IsReinject=*/true);1035SourceLocation PragmaLocation = ConsumeAnnotationToken();1036assert(Tok.isAnyIdentifier());1037StringRef PragmaName = Tok.getIdentifierInfo()->getName();1038PP.Lex(Tok); // pragma kind10391040// Figure out which #pragma we're dealing with. The switch has no default1041// because lex shouldn't emit the annotation token for unrecognized pragmas.1042typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);1043PragmaHandler Handler =1044llvm::StringSwitch<PragmaHandler>(PragmaName)1045.Case("data_seg", &Parser::HandlePragmaMSSegment)1046.Case("bss_seg", &Parser::HandlePragmaMSSegment)1047.Case("const_seg", &Parser::HandlePragmaMSSegment)1048.Case("code_seg", &Parser::HandlePragmaMSSegment)1049.Case("section", &Parser::HandlePragmaMSSection)1050.Case("init_seg", &Parser::HandlePragmaMSInitSeg)1051.Case("strict_gs_check", &Parser::HandlePragmaMSStrictGuardStackCheck)1052.Case("function", &Parser::HandlePragmaMSFunction)1053.Case("alloc_text", &Parser::HandlePragmaMSAllocText)1054.Case("optimize", &Parser::HandlePragmaMSOptimize);10551056if (!(this->*Handler)(PragmaName, PragmaLocation)) {1057// Pragma handling failed, and has been diagnosed. Slurp up the tokens1058// until eof (really end of line) to prevent follow-on errors.1059while (Tok.isNot(tok::eof))1060PP.Lex(Tok);1061PP.Lex(Tok);1062}1063}10641065bool Parser::HandlePragmaMSSection(StringRef PragmaName,1066SourceLocation PragmaLocation) {1067if (Tok.isNot(tok::l_paren)) {1068PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;1069return false;1070}1071PP.Lex(Tok); // (1072// Parsing code for pragma section1073if (Tok.isNot(tok::string_literal)) {1074PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)1075<< PragmaName;1076return false;1077}1078ExprResult StringResult = ParseStringLiteralExpression();1079if (StringResult.isInvalid())1080return false; // Already diagnosed.1081StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());1082if (SegmentName->getCharByteWidth() != 1) {1083PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)1084<< PragmaName;1085return false;1086}1087int SectionFlags = ASTContext::PSF_Read;1088bool SectionFlagsAreDefault = true;1089while (Tok.is(tok::comma)) {1090PP.Lex(Tok); // ,1091// Ignore "long" and "short".1092// They are undocumented, but widely used, section attributes which appear1093// to do nothing.1094if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {1095PP.Lex(Tok); // long/short1096continue;1097}10981099if (!Tok.isAnyIdentifier()) {1100PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)1101<< PragmaName;1102return false;1103}1104ASTContext::PragmaSectionFlag Flag =1105llvm::StringSwitch<ASTContext::PragmaSectionFlag>(1106Tok.getIdentifierInfo()->getName())1107.Case("read", ASTContext::PSF_Read)1108.Case("write", ASTContext::PSF_Write)1109.Case("execute", ASTContext::PSF_Execute)1110.Case("shared", ASTContext::PSF_Invalid)1111.Case("nopage", ASTContext::PSF_Invalid)1112.Case("nocache", ASTContext::PSF_Invalid)1113.Case("discard", ASTContext::PSF_Invalid)1114.Case("remove", ASTContext::PSF_Invalid)1115.Default(ASTContext::PSF_None);1116if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {1117PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None1118? diag::warn_pragma_invalid_specific_action1119: diag::warn_pragma_unsupported_action)1120<< PragmaName << Tok.getIdentifierInfo()->getName();1121return false;1122}1123SectionFlags |= Flag;1124SectionFlagsAreDefault = false;1125PP.Lex(Tok); // Identifier1126}1127// If no section attributes are specified, the section will be marked as1128// read/write.1129if (SectionFlagsAreDefault)1130SectionFlags |= ASTContext::PSF_Write;1131if (Tok.isNot(tok::r_paren)) {1132PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;1133return false;1134}1135PP.Lex(Tok); // )1136if (Tok.isNot(tok::eof)) {1137PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)1138<< PragmaName;1139return false;1140}1141PP.Lex(Tok); // eof1142Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);1143return true;1144}11451146bool Parser::HandlePragmaMSSegment(StringRef PragmaName,1147SourceLocation PragmaLocation) {1148if (Tok.isNot(tok::l_paren)) {1149PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;1150return false;1151}1152PP.Lex(Tok); // (1153Sema::PragmaMsStackAction Action = Sema::PSK_Reset;1154StringRef SlotLabel;1155if (Tok.isAnyIdentifier()) {1156StringRef PushPop = Tok.getIdentifierInfo()->getName();1157if (PushPop == "push")1158Action = Sema::PSK_Push;1159else if (PushPop == "pop")1160Action = Sema::PSK_Pop;1161else {1162PP.Diag(PragmaLocation,1163diag::warn_pragma_expected_section_push_pop_or_name)1164<< PragmaName;1165return false;1166}1167if (Action != Sema::PSK_Reset) {1168PP.Lex(Tok); // push | pop1169if (Tok.is(tok::comma)) {1170PP.Lex(Tok); // ,1171// If we've got a comma, we either need a label or a string.1172if (Tok.isAnyIdentifier()) {1173SlotLabel = Tok.getIdentifierInfo()->getName();1174PP.Lex(Tok); // identifier1175if (Tok.is(tok::comma))1176PP.Lex(Tok);1177else if (Tok.isNot(tok::r_paren)) {1178PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)1179<< PragmaName;1180return false;1181}1182}1183} else if (Tok.isNot(tok::r_paren)) {1184PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;1185return false;1186}1187}1188}1189// Grab the string literal for our section name.1190StringLiteral *SegmentName = nullptr;1191if (Tok.isNot(tok::r_paren)) {1192if (Tok.isNot(tok::string_literal)) {1193unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?1194diag::warn_pragma_expected_section_name :1195diag::warn_pragma_expected_section_label_or_name :1196diag::warn_pragma_expected_section_push_pop_or_name;1197PP.Diag(PragmaLocation, DiagID) << PragmaName;1198return false;1199}1200ExprResult StringResult = ParseStringLiteralExpression();1201if (StringResult.isInvalid())1202return false; // Already diagnosed.1203SegmentName = cast<StringLiteral>(StringResult.get());1204if (SegmentName->getCharByteWidth() != 1) {1205PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)1206<< PragmaName;1207return false;1208}1209// Setting section "" has no effect1210if (SegmentName->getLength())1211Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);1212}1213if (Tok.isNot(tok::r_paren)) {1214PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;1215return false;1216}1217PP.Lex(Tok); // )1218if (Tok.isNot(tok::eof)) {1219PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)1220<< PragmaName;1221return false;1222}1223PP.Lex(Tok); // eof1224Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,1225SegmentName, PragmaName);1226return true;1227}12281229// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )1230bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,1231SourceLocation PragmaLocation) {1232if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {1233PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);1234return false;1235}12361237if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,1238PragmaName))1239return false;12401241// Parse either the known section names or the string section name.1242StringLiteral *SegmentName = nullptr;1243if (Tok.isAnyIdentifier()) {1244auto *II = Tok.getIdentifierInfo();1245StringRef Section = llvm::StringSwitch<StringRef>(II->getName())1246.Case("compiler", "\".CRT$XCC\"")1247.Case("lib", "\".CRT$XCL\"")1248.Case("user", "\".CRT$XCU\"")1249.Default("");12501251if (!Section.empty()) {1252// Pretend the user wrote the appropriate string literal here.1253Token Toks[1];1254Toks[0].startToken();1255Toks[0].setKind(tok::string_literal);1256Toks[0].setLocation(Tok.getLocation());1257Toks[0].setLiteralData(Section.data());1258Toks[0].setLength(Section.size());1259SegmentName =1260cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());1261PP.Lex(Tok);1262}1263} else if (Tok.is(tok::string_literal)) {1264ExprResult StringResult = ParseStringLiteralExpression();1265if (StringResult.isInvalid())1266return false;1267SegmentName = cast<StringLiteral>(StringResult.get());1268if (SegmentName->getCharByteWidth() != 1) {1269PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)1270<< PragmaName;1271return false;1272}1273// FIXME: Add support for the '[, func-name]' part of the pragma.1274}12751276if (!SegmentName) {1277PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;1278return false;1279}12801281if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,1282PragmaName) ||1283ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,1284PragmaName))1285return false;12861287Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);1288return true;1289}12901291// #pragma strict_gs_check(pop)1292// #pragma strict_gs_check(push, "on" | "off")1293// #pragma strict_gs_check("on" | "off")1294bool Parser::HandlePragmaMSStrictGuardStackCheck(1295StringRef PragmaName, SourceLocation PragmaLocation) {1296if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,1297PragmaName))1298return false;12991300Sema::PragmaMsStackAction Action = Sema::PSK_Set;1301if (Tok.is(tok::identifier)) {1302StringRef PushPop = Tok.getIdentifierInfo()->getName();1303if (PushPop == "push") {1304PP.Lex(Tok);1305Action = Sema::PSK_Push;1306if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_punc,1307PragmaName))1308return false;1309} else if (PushPop == "pop") {1310PP.Lex(Tok);1311Action = Sema::PSK_Pop;1312}1313}13141315bool Value = false;1316if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {1317const IdentifierInfo *II = Tok.getIdentifierInfo();1318if (II && II->isStr("off")) {1319PP.Lex(Tok);1320Value = false;1321} else if (II && II->isStr("on")) {1322PP.Lex(Tok);1323Value = true;1324} else {1325PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)1326<< PragmaName;1327return false;1328}1329}13301331// Finish the pragma: ')' $1332if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,1333PragmaName))1334return false;13351336if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,1337PragmaName))1338return false;13391340Actions.ActOnPragmaMSStrictGuardStackCheck(PragmaLocation, Action, Value);1341return true;1342}13431344bool Parser::HandlePragmaMSAllocText(StringRef PragmaName,1345SourceLocation PragmaLocation) {1346Token FirstTok = Tok;1347if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,1348PragmaName))1349return false;13501351StringRef Section;1352if (Tok.is(tok::string_literal)) {1353ExprResult StringResult = ParseStringLiteralExpression();1354if (StringResult.isInvalid())1355return false; // Already diagnosed.1356StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());1357if (SegmentName->getCharByteWidth() != 1) {1358PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)1359<< PragmaName;1360return false;1361}1362Section = SegmentName->getString();1363} else if (Tok.is(tok::identifier)) {1364Section = Tok.getIdentifierInfo()->getName();1365PP.Lex(Tok);1366} else {1367PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)1368<< PragmaName;1369return false;1370}13711372if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,1373PragmaName))1374return false;13751376SmallVector<std::tuple<IdentifierInfo *, SourceLocation>> Functions;1377while (true) {1378if (Tok.isNot(tok::identifier)) {1379PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)1380<< PragmaName;1381return false;1382}13831384IdentifierInfo *II = Tok.getIdentifierInfo();1385Functions.emplace_back(II, Tok.getLocation());13861387PP.Lex(Tok);1388if (Tok.isNot(tok::comma))1389break;1390PP.Lex(Tok);1391}13921393if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,1394PragmaName) ||1395ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,1396PragmaName))1397return false;13981399Actions.ActOnPragmaMSAllocText(FirstTok.getLocation(), Section, Functions);1400return true;1401}14021403static std::string PragmaLoopHintString(Token PragmaName, Token Option) {1404StringRef Str = PragmaName.getIdentifierInfo()->getName();1405std::string ClangLoopStr("clang loop ");1406if (Str == "loop" && Option.getIdentifierInfo())1407ClangLoopStr += Option.getIdentifierInfo()->getName();1408return std::string(llvm::StringSwitch<StringRef>(Str)1409.Case("loop", ClangLoopStr)1410.Case("unroll_and_jam", Str)1411.Case("unroll", Str)1412.Default(""));1413}14141415bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {1416assert(Tok.is(tok::annot_pragma_loop_hint));1417PragmaLoopHintInfo *Info =1418static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());14191420IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();1421Hint.PragmaNameLoc = IdentifierLoc::create(1422Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);14231424// It is possible that the loop hint has no option identifier, such as1425// #pragma unroll(4).1426IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)1427? Info->Option.getIdentifierInfo()1428: nullptr;1429Hint.OptionLoc = IdentifierLoc::create(1430Actions.Context, Info->Option.getLocation(), OptionInfo);14311432llvm::ArrayRef<Token> Toks = Info->Toks;14331434// Return a valid hint if pragma unroll or nounroll were specified1435// without an argument.1436auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName())1437.Cases("unroll", "nounroll", "unroll_and_jam",1438"nounroll_and_jam", true)1439.Default(false);14401441if (Toks.empty() && IsLoopHint) {1442ConsumeAnnotationToken();1443Hint.Range = Info->PragmaName.getLocation();1444return true;1445}14461447// The constant expression is always followed by an eof token, which increases1448// the TokSize by 1.1449assert(!Toks.empty() &&1450"PragmaLoopHintInfo::Toks must contain at least one token.");14511452// If no option is specified the argument is assumed to be a constant expr.1453bool OptionUnroll = false;1454bool OptionUnrollAndJam = false;1455bool OptionDistribute = false;1456bool OptionPipelineDisabled = false;1457bool StateOption = false;1458if (OptionInfo) { // Pragma Unroll does not specify an option.1459OptionUnroll = OptionInfo->isStr("unroll");1460OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");1461OptionDistribute = OptionInfo->isStr("distribute");1462OptionPipelineDisabled = OptionInfo->isStr("pipeline");1463StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())1464.Case("vectorize", true)1465.Case("interleave", true)1466.Case("vectorize_predicate", true)1467.Default(false) ||1468OptionUnroll || OptionUnrollAndJam || OptionDistribute ||1469OptionPipelineDisabled;1470}14711472bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam &&1473!OptionDistribute && !OptionPipelineDisabled;1474// Verify loop hint has an argument.1475if (Toks[0].is(tok::eof)) {1476ConsumeAnnotationToken();1477Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)1478<< /*StateArgument=*/StateOption1479<< /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)1480<< /*AssumeSafetyKeyword=*/AssumeSafetyArg;1481return false;1482}14831484// Validate the argument.1485if (StateOption) {1486ConsumeAnnotationToken();1487SourceLocation StateLoc = Toks[0].getLocation();1488IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();14891490bool Valid = StateInfo &&1491llvm::StringSwitch<bool>(StateInfo->getName())1492.Case("disable", true)1493.Case("enable", !OptionPipelineDisabled)1494.Case("full", OptionUnroll || OptionUnrollAndJam)1495.Case("assume_safety", AssumeSafetyArg)1496.Default(false);1497if (!Valid) {1498if (OptionPipelineDisabled) {1499Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);1500} else {1501Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)1502<< /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)1503<< /*AssumeSafetyKeyword=*/AssumeSafetyArg;1504}1505return false;1506}1507if (Toks.size() > 2)1508Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)1509<< PragmaLoopHintString(Info->PragmaName, Info->Option);1510Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);1511} else if (OptionInfo && OptionInfo->getName() == "vectorize_width") {1512PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,1513/*IsReinject=*/false);1514ConsumeAnnotationToken();15151516SourceLocation StateLoc = Toks[0].getLocation();1517IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();1518StringRef IsScalableStr = StateInfo ? StateInfo->getName() : "";15191520// Look for vectorize_width(fixed|scalable)1521if (IsScalableStr == "scalable" || IsScalableStr == "fixed") {1522PP.Lex(Tok); // Identifier15231524if (Toks.size() > 2) {1525Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)1526<< PragmaLoopHintString(Info->PragmaName, Info->Option);1527while (Tok.isNot(tok::eof))1528ConsumeAnyToken();1529}15301531Hint.StateLoc =1532IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);15331534ConsumeToken(); // Consume the constant expression eof terminator.1535} else {1536// Enter constant expression including eof terminator into token stream.1537ExprResult R = ParseConstantExpression();15381539if (R.isInvalid() && !Tok.is(tok::comma))1540Diag(Toks[0].getLocation(),1541diag::note_pragma_loop_invalid_vectorize_option);15421543bool Arg2Error = false;1544if (Tok.is(tok::comma)) {1545PP.Lex(Tok); // ,15461547StateInfo = Tok.getIdentifierInfo();1548IsScalableStr = StateInfo->getName();15491550if (IsScalableStr != "scalable" && IsScalableStr != "fixed") {1551Diag(Tok.getLocation(),1552diag::err_pragma_loop_invalid_vectorize_option);1553Arg2Error = true;1554} else1555Hint.StateLoc =1556IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);15571558PP.Lex(Tok); // Identifier1559}15601561// Tokens following an error in an ill-formed constant expression will1562// remain in the token stream and must be removed.1563if (Tok.isNot(tok::eof)) {1564Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)1565<< PragmaLoopHintString(Info->PragmaName, Info->Option);1566while (Tok.isNot(tok::eof))1567ConsumeAnyToken();1568}15691570ConsumeToken(); // Consume the constant expression eof terminator.15711572if (Arg2Error || R.isInvalid() ||1573Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation(),1574/*AllowZero=*/false))1575return false;15761577// Argument is a constant expression with an integer type.1578Hint.ValueExpr = R.get();1579}1580} else {1581// Enter constant expression including eof terminator into token stream.1582PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,1583/*IsReinject=*/false);1584ConsumeAnnotationToken();1585ExprResult R = ParseConstantExpression();15861587// Tokens following an error in an ill-formed constant expression will1588// remain in the token stream and must be removed.1589if (Tok.isNot(tok::eof)) {1590Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)1591<< PragmaLoopHintString(Info->PragmaName, Info->Option);1592while (Tok.isNot(tok::eof))1593ConsumeAnyToken();1594}15951596ConsumeToken(); // Consume the constant expression eof terminator.15971598if (R.isInvalid() ||1599Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation(),1600/*AllowZero=*/true))1601return false;16021603// Argument is a constant expression with an integer type.1604Hint.ValueExpr = R.get();1605}16061607Hint.Range = SourceRange(Info->PragmaName.getLocation(),1608Info->Toks.back().getLocation());1609return true;1610}16111612namespace {1613struct PragmaAttributeInfo {1614enum ActionType { Push, Pop, Attribute };1615ParsedAttributes &Attributes;1616ActionType Action;1617const IdentifierInfo *Namespace = nullptr;1618ArrayRef<Token> Tokens;16191620PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}1621};16221623#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"16241625} // end anonymous namespace16261627static StringRef getIdentifier(const Token &Tok) {1628if (Tok.is(tok::identifier))1629return Tok.getIdentifierInfo()->getName();1630const char *S = tok::getKeywordSpelling(Tok.getKind());1631if (!S)1632return "";1633return S;1634}16351636static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {1637using namespace attr;1638switch (Rule) {1639#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \1640case Value: \1641return IsAbstract;1642#include "clang/Basic/AttrSubMatchRulesList.inc"1643}1644llvm_unreachable("Invalid attribute subject match rule");1645return false;1646}16471648static void diagnoseExpectedAttributeSubjectSubRule(1649Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,1650SourceLocation SubRuleLoc) {1651auto Diagnostic =1652PRef.Diag(SubRuleLoc,1653diag::err_pragma_attribute_expected_subject_sub_identifier)1654<< PrimaryRuleName;1655if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))1656Diagnostic << /*SubRulesSupported=*/1 << SubRules;1657else1658Diagnostic << /*SubRulesSupported=*/0;1659}16601661static void diagnoseUnknownAttributeSubjectSubRule(1662Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,1663StringRef SubRuleName, SourceLocation SubRuleLoc) {16641665auto Diagnostic =1666PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)1667<< SubRuleName << PrimaryRuleName;1668if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))1669Diagnostic << /*SubRulesSupported=*/1 << SubRules;1670else1671Diagnostic << /*SubRulesSupported=*/0;1672}16731674bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(1675attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,1676SourceLocation &LastMatchRuleEndLoc) {1677bool IsAny = false;1678BalancedDelimiterTracker AnyParens(*this, tok::l_paren);1679if (getIdentifier(Tok) == "any") {1680AnyLoc = ConsumeToken();1681IsAny = true;1682if (AnyParens.expectAndConsume())1683return true;1684}16851686do {1687// Parse the subject matcher rule.1688StringRef Name = getIdentifier(Tok);1689if (Name.empty()) {1690Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);1691return true;1692}1693std::pair<std::optional<attr::SubjectMatchRule>,1694std::optional<attr::SubjectMatchRule> (*)(StringRef, bool)>1695Rule = isAttributeSubjectMatchRule(Name);1696if (!Rule.first) {1697Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;1698return true;1699}1700attr::SubjectMatchRule PrimaryRule = *Rule.first;1701SourceLocation RuleLoc = ConsumeToken();17021703BalancedDelimiterTracker Parens(*this, tok::l_paren);1704if (isAbstractAttrMatcherRule(PrimaryRule)) {1705if (Parens.expectAndConsume())1706return true;1707} else if (Parens.consumeOpen()) {1708if (!SubjectMatchRules1709.insert(1710std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))1711.second)1712Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)1713<< Name1714<< FixItHint::CreateRemoval(SourceRange(1715RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));1716LastMatchRuleEndLoc = RuleLoc;1717continue;1718}17191720// Parse the sub-rules.1721StringRef SubRuleName = getIdentifier(Tok);1722if (SubRuleName.empty()) {1723diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,1724Tok.getLocation());1725return true;1726}1727attr::SubjectMatchRule SubRule;1728if (SubRuleName == "unless") {1729SourceLocation SubRuleLoc = ConsumeToken();1730BalancedDelimiterTracker Parens(*this, tok::l_paren);1731if (Parens.expectAndConsume())1732return true;1733SubRuleName = getIdentifier(Tok);1734if (SubRuleName.empty()) {1735diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,1736SubRuleLoc);1737return true;1738}1739auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);1740if (!SubRuleOrNone) {1741std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";1742diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,1743SubRuleUnlessName, SubRuleLoc);1744return true;1745}1746SubRule = *SubRuleOrNone;1747ConsumeToken();1748if (Parens.consumeClose())1749return true;1750} else {1751auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);1752if (!SubRuleOrNone) {1753diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,1754SubRuleName, Tok.getLocation());1755return true;1756}1757SubRule = *SubRuleOrNone;1758ConsumeToken();1759}1760SourceLocation RuleEndLoc = Tok.getLocation();1761LastMatchRuleEndLoc = RuleEndLoc;1762if (Parens.consumeClose())1763return true;1764if (!SubjectMatchRules1765.insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))1766.second) {1767Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)1768<< attr::getSubjectMatchRuleSpelling(SubRule)1769<< FixItHint::CreateRemoval(SourceRange(1770RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));1771continue;1772}1773} while (IsAny && TryConsumeToken(tok::comma));17741775if (IsAny)1776if (AnyParens.consumeClose())1777return true;17781779return false;1780}17811782namespace {17831784/// Describes the stage at which attribute subject rule parsing was interrupted.1785enum class MissingAttributeSubjectRulesRecoveryPoint {1786Comma,1787ApplyTo,1788Equals,1789Any,1790None,1791};17921793MissingAttributeSubjectRulesRecoveryPoint1794getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {1795if (const auto *II = Tok.getIdentifierInfo()) {1796if (II->isStr("apply_to"))1797return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;1798if (II->isStr("any"))1799return MissingAttributeSubjectRulesRecoveryPoint::Any;1800}1801if (Tok.is(tok::equal))1802return MissingAttributeSubjectRulesRecoveryPoint::Equals;1803return MissingAttributeSubjectRulesRecoveryPoint::None;1804}18051806/// Creates a diagnostic for the attribute subject rule parsing diagnostic that1807/// suggests the possible attribute subject rules in a fix-it together with1808/// any other missing tokens.1809DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(1810unsigned DiagID, ParsedAttributes &Attrs,1811MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {1812SourceLocation Loc = PRef.getEndOfPreviousToken();1813if (Loc.isInvalid())1814Loc = PRef.getCurToken().getLocation();1815auto Diagnostic = PRef.Diag(Loc, DiagID);1816std::string FixIt;1817MissingAttributeSubjectRulesRecoveryPoint EndPoint =1818getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());1819if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)1820FixIt = ", ";1821if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&1822EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)1823FixIt += "apply_to";1824if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&1825EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)1826FixIt += " = ";1827SourceRange FixItRange(Loc);1828if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {1829// Gather the subject match rules that are supported by the attribute.1830// Add all the possible rules initially.1831llvm::BitVector IsMatchRuleAvailable(attr::SubjectMatchRule_Last + 1, true);1832// Remove the ones that are not supported by any of the attributes.1833for (const ParsedAttr &Attribute : Attrs) {1834SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> MatchRules;1835Attribute.getMatchRules(PRef.getLangOpts(), MatchRules);1836llvm::BitVector IsSupported(attr::SubjectMatchRule_Last + 1);1837for (const auto &Rule : MatchRules) {1838// Ensure that the missing rule is reported in the fix-it only when it's1839// supported in the current language mode.1840if (!Rule.second)1841continue;1842IsSupported[Rule.first] = true;1843}1844IsMatchRuleAvailable &= IsSupported;1845}1846if (IsMatchRuleAvailable.count() == 0) {1847// FIXME: We can emit a "fix-it" with a subject list placeholder when1848// placeholders will be supported by the fix-its.1849return Diagnostic;1850}1851FixIt += "any(";1852bool NeedsComma = false;1853for (unsigned I = 0; I <= attr::SubjectMatchRule_Last; I++) {1854if (!IsMatchRuleAvailable[I])1855continue;1856if (NeedsComma)1857FixIt += ", ";1858else1859NeedsComma = true;1860FixIt += attr::getSubjectMatchRuleSpelling(1861static_cast<attr::SubjectMatchRule>(I));1862}1863FixIt += ")";1864// Check if we need to remove the range1865PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);1866FixItRange.setEnd(PRef.getCurToken().getLocation());1867}1868if (FixItRange.getBegin() == FixItRange.getEnd())1869Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);1870else1871Diagnostic << FixItHint::CreateReplacement(1872CharSourceRange::getCharRange(FixItRange), FixIt);1873return Diagnostic;1874}18751876} // end anonymous namespace18771878void Parser::HandlePragmaAttribute() {1879assert(Tok.is(tok::annot_pragma_attribute) &&1880"Expected #pragma attribute annotation token");1881SourceLocation PragmaLoc = Tok.getLocation();1882auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());1883if (Info->Action == PragmaAttributeInfo::Pop) {1884ConsumeAnnotationToken();1885Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);1886return;1887}1888// Parse the actual attribute with its arguments.1889assert((Info->Action == PragmaAttributeInfo::Push ||1890Info->Action == PragmaAttributeInfo::Attribute) &&1891"Unexpected #pragma attribute command");18921893if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {1894ConsumeAnnotationToken();1895Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);1896return;1897}18981899PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false,1900/*IsReinject=*/false);1901ConsumeAnnotationToken();19021903ParsedAttributes &Attrs = Info->Attributes;1904Attrs.clearListOnly();19051906auto SkipToEnd = [this]() {1907SkipUntil(tok::eof, StopBeforeMatch);1908ConsumeToken();1909};19101911if ((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) ||1912Tok.isRegularKeywordAttribute()) {1913// Parse the CXX11 style attribute.1914ParseCXX11AttributeSpecifier(Attrs);1915} else if (Tok.is(tok::kw___attribute)) {1916ConsumeToken();1917if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,1918"attribute"))1919return SkipToEnd();1920if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))1921return SkipToEnd();19221923// FIXME: The practical usefulness of completion here is limited because1924// we only get here if the line has balanced parens.1925if (Tok.is(tok::code_completion)) {1926cutOffParsing();1927// FIXME: suppress completion of unsupported attributes?1928Actions.CodeCompletion().CodeCompleteAttribute(1929AttributeCommonInfo::Syntax::AS_GNU);1930return SkipToEnd();1931}19321933// Parse the comma-separated list of attributes.1934do {1935if (Tok.isNot(tok::identifier)) {1936Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);1937SkipToEnd();1938return;1939}1940IdentifierInfo *AttrName = Tok.getIdentifierInfo();1941SourceLocation AttrNameLoc = ConsumeToken();19421943if (Tok.isNot(tok::l_paren))1944Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,1945ParsedAttr::Form::GNU());1946else1947ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,1948/*ScopeName=*/nullptr,1949/*ScopeLoc=*/SourceLocation(),1950ParsedAttr::Form::GNU(),1951/*Declarator=*/nullptr);1952} while (TryConsumeToken(tok::comma));19531954if (ExpectAndConsume(tok::r_paren))1955return SkipToEnd();1956if (ExpectAndConsume(tok::r_paren))1957return SkipToEnd();1958} else if (Tok.is(tok::kw___declspec)) {1959ParseMicrosoftDeclSpecs(Attrs);1960} else {1961Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);1962if (Tok.getIdentifierInfo()) {1963// If we suspect that this is an attribute suggest the use of1964// '__attribute__'.1965if (ParsedAttr::getParsedKind(1966Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,1967ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) {1968SourceLocation InsertStartLoc = Tok.getLocation();1969ConsumeToken();1970if (Tok.is(tok::l_paren)) {1971ConsumeAnyToken();1972SkipUntil(tok::r_paren, StopBeforeMatch);1973if (Tok.isNot(tok::r_paren))1974return SkipToEnd();1975}1976Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)1977<< FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")1978<< FixItHint::CreateInsertion(Tok.getEndLoc(), "))");1979}1980}1981SkipToEnd();1982return;1983}19841985if (Attrs.empty() || Attrs.begin()->isInvalid()) {1986SkipToEnd();1987return;1988}19891990for (const ParsedAttr &Attribute : Attrs) {1991if (!Attribute.isSupportedByPragmaAttribute()) {1992Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)1993<< Attribute;1994SkipToEnd();1995return;1996}1997}19981999// Parse the subject-list.2000if (!TryConsumeToken(tok::comma)) {2001createExpectedAttributeSubjectRulesTokenDiagnostic(2002diag::err_expected, Attrs,2003MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)2004<< tok::comma;2005SkipToEnd();2006return;2007}20082009if (Tok.isNot(tok::identifier)) {2010createExpectedAttributeSubjectRulesTokenDiagnostic(2011diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,2012MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);2013SkipToEnd();2014return;2015}2016const IdentifierInfo *II = Tok.getIdentifierInfo();2017if (!II->isStr("apply_to")) {2018createExpectedAttributeSubjectRulesTokenDiagnostic(2019diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,2020MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);2021SkipToEnd();2022return;2023}2024ConsumeToken();20252026if (!TryConsumeToken(tok::equal)) {2027createExpectedAttributeSubjectRulesTokenDiagnostic(2028diag::err_expected, Attrs,2029MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)2030<< tok::equal;2031SkipToEnd();2032return;2033}20342035attr::ParsedSubjectMatchRuleSet SubjectMatchRules;2036SourceLocation AnyLoc, LastMatchRuleEndLoc;2037if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,2038LastMatchRuleEndLoc)) {2039SkipToEnd();2040return;2041}20422043// Tokens following an ill-formed attribute will remain in the token stream2044// and must be removed.2045if (Tok.isNot(tok::eof)) {2046Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);2047SkipToEnd();2048return;2049}20502051// Consume the eof terminator token.2052ConsumeToken();20532054// Handle a mixed push/attribute by desurging to a push, then an attribute.2055if (Info->Action == PragmaAttributeInfo::Push)2056Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);20572058for (ParsedAttr &Attribute : Attrs) {2059Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,2060SubjectMatchRules);2061}2062}20632064// #pragma GCC visibility comes in two variants:2065// 'push' '(' [visibility] ')'2066// 'pop'2067void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,2068PragmaIntroducer Introducer,2069Token &VisTok) {2070SourceLocation VisLoc = VisTok.getLocation();20712072Token Tok;2073PP.LexUnexpandedToken(Tok);20742075const IdentifierInfo *PushPop = Tok.getIdentifierInfo();20762077const IdentifierInfo *VisType;2078if (PushPop && PushPop->isStr("pop")) {2079VisType = nullptr;2080} else if (PushPop && PushPop->isStr("push")) {2081PP.LexUnexpandedToken(Tok);2082if (Tok.isNot(tok::l_paren)) {2083PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)2084<< "visibility";2085return;2086}2087PP.LexUnexpandedToken(Tok);2088VisType = Tok.getIdentifierInfo();2089if (!VisType) {2090PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)2091<< "visibility";2092return;2093}2094PP.LexUnexpandedToken(Tok);2095if (Tok.isNot(tok::r_paren)) {2096PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)2097<< "visibility";2098return;2099}2100} else {2101PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)2102<< "visibility";2103return;2104}2105SourceLocation EndLoc = Tok.getLocation();2106PP.LexUnexpandedToken(Tok);2107if (Tok.isNot(tok::eod)) {2108PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)2109<< "visibility";2110return;2111}21122113auto Toks = std::make_unique<Token[]>(1);2114Toks[0].startToken();2115Toks[0].setKind(tok::annot_pragma_vis);2116Toks[0].setLocation(VisLoc);2117Toks[0].setAnnotationEndLoc(EndLoc);2118Toks[0].setAnnotationValue(2119const_cast<void *>(static_cast<const void *>(VisType)));2120PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true,2121/*IsReinject=*/false);2122}21232124// #pragma pack(...) comes in the following delicious flavors:2125// pack '(' [integer] ')'2126// pack '(' 'show' ')'2127// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'2128void PragmaPackHandler::HandlePragma(Preprocessor &PP,2129PragmaIntroducer Introducer,2130Token &PackTok) {2131SourceLocation PackLoc = PackTok.getLocation();21322133Token Tok;2134PP.Lex(Tok);2135if (Tok.isNot(tok::l_paren)) {2136PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";2137return;2138}21392140Sema::PragmaMsStackAction Action = Sema::PSK_Reset;2141StringRef SlotLabel;2142Token Alignment;2143Alignment.startToken();2144PP.Lex(Tok);2145if (Tok.is(tok::numeric_constant)) {2146Alignment = Tok;21472148PP.Lex(Tok);21492150// In MSVC/gcc, #pragma pack(4) sets the alignment without affecting2151// the push/pop stack.2152// In Apple gcc/XL, #pragma pack(4) is equivalent to #pragma pack(push, 4)2153Action = (PP.getLangOpts().ApplePragmaPack || PP.getLangOpts().XLPragmaPack)2154? Sema::PSK_Push_Set2155: Sema::PSK_Set;2156} else if (Tok.is(tok::identifier)) {2157const IdentifierInfo *II = Tok.getIdentifierInfo();2158if (II->isStr("show")) {2159Action = Sema::PSK_Show;2160PP.Lex(Tok);2161} else {2162if (II->isStr("push")) {2163Action = Sema::PSK_Push;2164} else if (II->isStr("pop")) {2165Action = Sema::PSK_Pop;2166} else {2167PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";2168return;2169}2170PP.Lex(Tok);21712172if (Tok.is(tok::comma)) {2173PP.Lex(Tok);21742175if (Tok.is(tok::numeric_constant)) {2176Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);2177Alignment = Tok;21782179PP.Lex(Tok);2180} else if (Tok.is(tok::identifier)) {2181SlotLabel = Tok.getIdentifierInfo()->getName();2182PP.Lex(Tok);21832184if (Tok.is(tok::comma)) {2185PP.Lex(Tok);21862187if (Tok.isNot(tok::numeric_constant)) {2188PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);2189return;2190}21912192Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);2193Alignment = Tok;21942195PP.Lex(Tok);2196}2197} else {2198PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);2199return;2200}2201}2202}2203} else if (PP.getLangOpts().ApplePragmaPack ||2204PP.getLangOpts().XLPragmaPack) {2205// In MSVC/gcc, #pragma pack() resets the alignment without affecting2206// the push/pop stack.2207// In Apple gcc and IBM XL, #pragma pack() is equivalent to #pragma2208// pack(pop).2209Action = Sema::PSK_Pop;2210}22112212if (Tok.isNot(tok::r_paren)) {2213PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";2214return;2215}22162217SourceLocation RParenLoc = Tok.getLocation();2218PP.Lex(Tok);2219if (Tok.isNot(tok::eod)) {2220PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";2221return;2222}22232224Sema::PragmaPackInfo *Info =2225PP.getPreprocessorAllocator().Allocate<Sema::PragmaPackInfo>(1);2226Info->Action = Action;2227Info->SlotLabel = SlotLabel;2228Info->Alignment = Alignment;22292230MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),22311);2232Toks[0].startToken();2233Toks[0].setKind(tok::annot_pragma_pack);2234Toks[0].setLocation(PackLoc);2235Toks[0].setAnnotationEndLoc(RParenLoc);2236Toks[0].setAnnotationValue(static_cast<void*>(Info));2237PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,2238/*IsReinject=*/false);2239}22402241// #pragma ms_struct on2242// #pragma ms_struct off2243void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,2244PragmaIntroducer Introducer,2245Token &MSStructTok) {2246PragmaMSStructKind Kind = PMSST_OFF;22472248Token Tok;2249PP.Lex(Tok);2250if (Tok.isNot(tok::identifier)) {2251PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);2252return;2253}2254SourceLocation EndLoc = Tok.getLocation();2255const IdentifierInfo *II = Tok.getIdentifierInfo();2256if (II->isStr("on")) {2257Kind = PMSST_ON;2258PP.Lex(Tok);2259}2260else if (II->isStr("off") || II->isStr("reset"))2261PP.Lex(Tok);2262else {2263PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);2264return;2265}22662267if (Tok.isNot(tok::eod)) {2268PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)2269<< "ms_struct";2270return;2271}22722273MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),22741);2275Toks[0].startToken();2276Toks[0].setKind(tok::annot_pragma_msstruct);2277Toks[0].setLocation(MSStructTok.getLocation());2278Toks[0].setAnnotationEndLoc(EndLoc);2279Toks[0].setAnnotationValue(reinterpret_cast<void*>(2280static_cast<uintptr_t>(Kind)));2281PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,2282/*IsReinject=*/false);2283}22842285// #pragma clang section bss="abc" data="" rodata="def" text="" relro=""2286void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,2287PragmaIntroducer Introducer,2288Token &FirstToken) {22892290Token Tok;2291auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;22922293PP.Lex(Tok); // eat 'section'2294while (Tok.isNot(tok::eod)) {2295if (Tok.isNot(tok::identifier)) {2296PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";2297return;2298}22992300const IdentifierInfo *SecType = Tok.getIdentifierInfo();2301if (SecType->isStr("bss"))2302SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;2303else if (SecType->isStr("data"))2304SecKind = Sema::PragmaClangSectionKind::PCSK_Data;2305else if (SecType->isStr("rodata"))2306SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;2307else if (SecType->isStr("relro"))2308SecKind = Sema::PragmaClangSectionKind::PCSK_Relro;2309else if (SecType->isStr("text"))2310SecKind = Sema::PragmaClangSectionKind::PCSK_Text;2311else {2312PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";2313return;2314}23152316SourceLocation PragmaLocation = Tok.getLocation();2317PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']2318if (Tok.isNot(tok::equal)) {2319PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;2320return;2321}23222323std::string SecName;2324if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))2325return;23262327Actions.ActOnPragmaClangSection(2328PragmaLocation,2329(SecName.size() ? Sema::PragmaClangSectionAction::PCSA_Set2330: Sema::PragmaClangSectionAction::PCSA_Clear),2331SecKind, SecName);2332}2333}23342335// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}2336// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}2337// #pragma 'align' '(' {'native','natural','mac68k','power','reset'} ')'2338static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,2339bool IsOptions) {2340Token Tok;23412342if (IsOptions) {2343PP.Lex(Tok);2344if (Tok.isNot(tok::identifier) ||2345!Tok.getIdentifierInfo()->isStr("align")) {2346PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);2347return;2348}2349}23502351PP.Lex(Tok);2352if (PP.getLangOpts().XLPragmaPack) {2353if (Tok.isNot(tok::l_paren)) {2354PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "align";2355return;2356}2357} else if (Tok.isNot(tok::equal)) {2358PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)2359<< IsOptions;2360return;2361}23622363PP.Lex(Tok);2364if (Tok.isNot(tok::identifier)) {2365PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)2366<< (IsOptions ? "options" : "align");2367return;2368}23692370Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;2371const IdentifierInfo *II = Tok.getIdentifierInfo();2372if (II->isStr("native"))2373Kind = Sema::POAK_Native;2374else if (II->isStr("natural"))2375Kind = Sema::POAK_Natural;2376else if (II->isStr("packed"))2377Kind = Sema::POAK_Packed;2378else if (II->isStr("power"))2379Kind = Sema::POAK_Power;2380else if (II->isStr("mac68k"))2381Kind = Sema::POAK_Mac68k;2382else if (II->isStr("reset"))2383Kind = Sema::POAK_Reset;2384else {2385PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)2386<< IsOptions;2387return;2388}23892390if (PP.getLangOpts().XLPragmaPack) {2391PP.Lex(Tok);2392if (Tok.isNot(tok::r_paren)) {2393PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "align";2394return;2395}2396}23972398SourceLocation EndLoc = Tok.getLocation();2399PP.Lex(Tok);2400if (Tok.isNot(tok::eod)) {2401PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)2402<< (IsOptions ? "options" : "align");2403return;2404}24052406MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),24071);2408Toks[0].startToken();2409Toks[0].setKind(tok::annot_pragma_align);2410Toks[0].setLocation(FirstTok.getLocation());2411Toks[0].setAnnotationEndLoc(EndLoc);2412Toks[0].setAnnotationValue(reinterpret_cast<void*>(2413static_cast<uintptr_t>(Kind)));2414PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,2415/*IsReinject=*/false);2416}24172418void PragmaAlignHandler::HandlePragma(Preprocessor &PP,2419PragmaIntroducer Introducer,2420Token &AlignTok) {2421ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);2422}24232424void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,2425PragmaIntroducer Introducer,2426Token &OptionsTok) {2427ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);2428}24292430// #pragma unused(identifier)2431void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,2432PragmaIntroducer Introducer,2433Token &UnusedTok) {2434// FIXME: Should we be expanding macros here? My guess is no.2435SourceLocation UnusedLoc = UnusedTok.getLocation();24362437// Lex the left '('.2438Token Tok;2439PP.Lex(Tok);2440if (Tok.isNot(tok::l_paren)) {2441PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";2442return;2443}24442445// Lex the declaration reference(s).2446SmallVector<Token, 5> Identifiers;2447SourceLocation RParenLoc;2448bool LexID = true;24492450while (true) {2451PP.Lex(Tok);24522453if (LexID) {2454if (Tok.is(tok::identifier)) {2455Identifiers.push_back(Tok);2456LexID = false;2457continue;2458}24592460// Illegal token!2461PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);2462return;2463}24642465// We are execting a ')' or a ','.2466if (Tok.is(tok::comma)) {2467LexID = true;2468continue;2469}24702471if (Tok.is(tok::r_paren)) {2472RParenLoc = Tok.getLocation();2473break;2474}24752476// Illegal token!2477PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";2478return;2479}24802481PP.Lex(Tok);2482if (Tok.isNot(tok::eod)) {2483PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<2484"unused";2485return;2486}24872488// Verify that we have a location for the right parenthesis.2489assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");2490assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");24912492// For each identifier token, insert into the token stream a2493// annot_pragma_unused token followed by the identifier token.2494// This allows us to cache a "#pragma unused" that occurs inside an inline2495// C++ member function.24962497MutableArrayRef<Token> Toks(2498PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),24992 * Identifiers.size());2500for (unsigned i=0; i != Identifiers.size(); i++) {2501Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];2502pragmaUnusedTok.startToken();2503pragmaUnusedTok.setKind(tok::annot_pragma_unused);2504pragmaUnusedTok.setLocation(UnusedLoc);2505idTok = Identifiers[i];2506}2507PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,2508/*IsReinject=*/false);2509}25102511// #pragma weak identifier2512// #pragma weak identifier '=' identifier2513void PragmaWeakHandler::HandlePragma(Preprocessor &PP,2514PragmaIntroducer Introducer,2515Token &WeakTok) {2516SourceLocation WeakLoc = WeakTok.getLocation();25172518Token Tok;2519PP.Lex(Tok);2520if (Tok.isNot(tok::identifier)) {2521PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";2522return;2523}25242525Token WeakName = Tok;2526bool HasAlias = false;2527Token AliasName;25282529PP.Lex(Tok);2530if (Tok.is(tok::equal)) {2531HasAlias = true;2532PP.Lex(Tok);2533if (Tok.isNot(tok::identifier)) {2534PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)2535<< "weak";2536return;2537}2538AliasName = Tok;2539PP.Lex(Tok);2540}25412542if (Tok.isNot(tok::eod)) {2543PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";2544return;2545}25462547if (HasAlias) {2548MutableArrayRef<Token> Toks(2549PP.getPreprocessorAllocator().Allocate<Token>(3), 3);2550Token &pragmaUnusedTok = Toks[0];2551pragmaUnusedTok.startToken();2552pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);2553pragmaUnusedTok.setLocation(WeakLoc);2554pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());2555Toks[1] = WeakName;2556Toks[2] = AliasName;2557PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,2558/*IsReinject=*/false);2559} else {2560MutableArrayRef<Token> Toks(2561PP.getPreprocessorAllocator().Allocate<Token>(2), 2);2562Token &pragmaUnusedTok = Toks[0];2563pragmaUnusedTok.startToken();2564pragmaUnusedTok.setKind(tok::annot_pragma_weak);2565pragmaUnusedTok.setLocation(WeakLoc);2566pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);2567Toks[1] = WeakName;2568PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,2569/*IsReinject=*/false);2570}2571}25722573// #pragma redefine_extname identifier identifier2574void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,2575PragmaIntroducer Introducer,2576Token &RedefToken) {2577SourceLocation RedefLoc = RedefToken.getLocation();25782579Token Tok;2580PP.Lex(Tok);2581if (Tok.isNot(tok::identifier)) {2582PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<2583"redefine_extname";2584return;2585}25862587Token RedefName = Tok;2588PP.Lex(Tok);25892590if (Tok.isNot(tok::identifier)) {2591PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)2592<< "redefine_extname";2593return;2594}25952596Token AliasName = Tok;2597PP.Lex(Tok);25982599if (Tok.isNot(tok::eod)) {2600PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<2601"redefine_extname";2602return;2603}26042605MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),26063);2607Token &pragmaRedefTok = Toks[0];2608pragmaRedefTok.startToken();2609pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);2610pragmaRedefTok.setLocation(RedefLoc);2611pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());2612Toks[1] = RedefName;2613Toks[2] = AliasName;2614PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,2615/*IsReinject=*/false);2616}26172618void PragmaFPContractHandler::HandlePragma(Preprocessor &PP,2619PragmaIntroducer Introducer,2620Token &Tok) {2621tok::OnOffSwitch OOS;2622if (PP.LexOnOffSwitch(OOS))2623return;26242625MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),26261);2627Toks[0].startToken();2628Toks[0].setKind(tok::annot_pragma_fp_contract);2629Toks[0].setLocation(Tok.getLocation());2630Toks[0].setAnnotationEndLoc(Tok.getLocation());2631Toks[0].setAnnotationValue(reinterpret_cast<void*>(2632static_cast<uintptr_t>(OOS)));2633PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,2634/*IsReinject=*/false);2635}26362637void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,2638PragmaIntroducer Introducer,2639Token &Tok) {2640PP.LexUnexpandedToken(Tok);2641if (Tok.isNot(tok::identifier)) {2642PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<2643"OPENCL";2644return;2645}2646IdentifierInfo *Ext = Tok.getIdentifierInfo();2647SourceLocation NameLoc = Tok.getLocation();26482649PP.Lex(Tok);2650if (Tok.isNot(tok::colon)) {2651PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;2652return;2653}26542655PP.Lex(Tok);2656if (Tok.isNot(tok::identifier)) {2657PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;2658return;2659}2660IdentifierInfo *Pred = Tok.getIdentifierInfo();26612662OpenCLExtState State;2663if (Pred->isStr("enable")) {2664State = Enable;2665} else if (Pred->isStr("disable")) {2666State = Disable;2667} else if (Pred->isStr("begin"))2668State = Begin;2669else if (Pred->isStr("end"))2670State = End;2671else {2672PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)2673<< Ext->isStr("all");2674return;2675}2676SourceLocation StateLoc = Tok.getLocation();26772678PP.Lex(Tok);2679if (Tok.isNot(tok::eod)) {2680PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<2681"OPENCL EXTENSION";2682return;2683}26842685auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);2686Info->first = Ext;2687Info->second = State;2688MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),26891);2690Toks[0].startToken();2691Toks[0].setKind(tok::annot_pragma_opencl_extension);2692Toks[0].setLocation(NameLoc);2693Toks[0].setAnnotationValue(static_cast<void*>(Info));2694Toks[0].setAnnotationEndLoc(StateLoc);2695PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,2696/*IsReinject=*/false);26972698if (PP.getPPCallbacks())2699PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,2700StateLoc, State);2701}27022703/// Handle '#pragma omp ...' when OpenMP is disabled and '#pragma acc ...' when2704/// OpenACC is disabled.2705template <diag::kind IgnoredDiag>2706void PragmaNoSupportHandler<IgnoredDiag>::HandlePragma(2707Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstTok) {2708if (!PP.getDiagnostics().isIgnored(IgnoredDiag, FirstTok.getLocation())) {2709PP.Diag(FirstTok, IgnoredDiag);2710PP.getDiagnostics().setSeverity(IgnoredDiag, diag::Severity::Ignored,2711SourceLocation());2712}2713PP.DiscardUntilEndOfDirective();2714}27152716/// Handle '#pragma omp ...' when OpenMP is enabled, and handle '#pragma acc...'2717/// when OpenACC is enabled.2718template <tok::TokenKind StartTok, tok::TokenKind EndTok,2719diag::kind UnexpectedDiag>2720void PragmaSupportHandler<StartTok, EndTok, UnexpectedDiag>::HandlePragma(2721Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstTok) {2722SmallVector<Token, 16> Pragma;2723Token Tok;2724Tok.startToken();2725Tok.setKind(StartTok);2726Tok.setLocation(Introducer.Loc);27272728while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {2729Pragma.push_back(Tok);2730PP.Lex(Tok);2731if (Tok.is(StartTok)) {2732PP.Diag(Tok, UnexpectedDiag) << 0;2733unsigned InnerPragmaCnt = 1;2734while (InnerPragmaCnt != 0) {2735PP.Lex(Tok);2736if (Tok.is(StartTok))2737++InnerPragmaCnt;2738else if (Tok.is(EndTok))2739--InnerPragmaCnt;2740}2741PP.Lex(Tok);2742}2743}2744SourceLocation EodLoc = Tok.getLocation();2745Tok.startToken();2746Tok.setKind(EndTok);2747Tok.setLocation(EodLoc);2748Pragma.push_back(Tok);27492750auto Toks = std::make_unique<Token[]>(Pragma.size());2751std::copy(Pragma.begin(), Pragma.end(), Toks.get());2752PP.EnterTokenStream(std::move(Toks), Pragma.size(),2753/*DisableMacroExpansion=*/false, /*IsReinject=*/false);2754}27552756/// Handle '#pragma pointers_to_members'2757// The grammar for this pragma is as follows:2758//2759// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'2760//2761// #pragma pointers_to_members '(' 'best_case' ')'2762// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'2763// #pragma pointers_to_members '(' inheritance-model ')'2764void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,2765PragmaIntroducer Introducer,2766Token &Tok) {2767SourceLocation PointersToMembersLoc = Tok.getLocation();2768PP.Lex(Tok);2769if (Tok.isNot(tok::l_paren)) {2770PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)2771<< "pointers_to_members";2772return;2773}2774PP.Lex(Tok);2775const IdentifierInfo *Arg = Tok.getIdentifierInfo();2776if (!Arg) {2777PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)2778<< "pointers_to_members";2779return;2780}2781PP.Lex(Tok);27822783LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;2784if (Arg->isStr("best_case")) {2785RepresentationMethod = LangOptions::PPTMK_BestCase;2786} else {2787if (Arg->isStr("full_generality")) {2788if (Tok.is(tok::comma)) {2789PP.Lex(Tok);27902791Arg = Tok.getIdentifierInfo();2792if (!Arg) {2793PP.Diag(Tok.getLocation(),2794diag::err_pragma_pointers_to_members_unknown_kind)2795<< Tok.getKind() << /*OnlyInheritanceModels*/ 0;2796return;2797}2798PP.Lex(Tok);2799} else if (Tok.is(tok::r_paren)) {2800// #pragma pointers_to_members(full_generality) implicitly specifies2801// virtual_inheritance.2802Arg = nullptr;2803RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;2804} else {2805PP.Diag(Tok.getLocation(), diag::err_expected_punc)2806<< "full_generality";2807return;2808}2809}28102811if (Arg) {2812if (Arg->isStr("single_inheritance")) {2813RepresentationMethod =2814LangOptions::PPTMK_FullGeneralitySingleInheritance;2815} else if (Arg->isStr("multiple_inheritance")) {2816RepresentationMethod =2817LangOptions::PPTMK_FullGeneralityMultipleInheritance;2818} else if (Arg->isStr("virtual_inheritance")) {2819RepresentationMethod =2820LangOptions::PPTMK_FullGeneralityVirtualInheritance;2821} else {2822PP.Diag(Tok.getLocation(),2823diag::err_pragma_pointers_to_members_unknown_kind)2824<< Arg << /*HasPointerDeclaration*/ 1;2825return;2826}2827}2828}28292830if (Tok.isNot(tok::r_paren)) {2831PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)2832<< (Arg ? Arg->getName() : "full_generality");2833return;2834}28352836SourceLocation EndLoc = Tok.getLocation();2837PP.Lex(Tok);2838if (Tok.isNot(tok::eod)) {2839PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)2840<< "pointers_to_members";2841return;2842}28432844Token AnnotTok;2845AnnotTok.startToken();2846AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);2847AnnotTok.setLocation(PointersToMembersLoc);2848AnnotTok.setAnnotationEndLoc(EndLoc);2849AnnotTok.setAnnotationValue(2850reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));2851PP.EnterToken(AnnotTok, /*IsReinject=*/true);2852}28532854/// Handle '#pragma vtordisp'2855// The grammar for this pragma is as follows:2856//2857// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )2858//2859// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'2860// #pragma vtordisp '(' 'pop' ')'2861// #pragma vtordisp '(' ')'2862void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,2863PragmaIntroducer Introducer, Token &Tok) {2864SourceLocation VtorDispLoc = Tok.getLocation();2865PP.Lex(Tok);2866if (Tok.isNot(tok::l_paren)) {2867PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";2868return;2869}2870PP.Lex(Tok);28712872Sema::PragmaMsStackAction Action = Sema::PSK_Set;2873const IdentifierInfo *II = Tok.getIdentifierInfo();2874if (II) {2875if (II->isStr("push")) {2876// #pragma vtordisp(push, mode)2877PP.Lex(Tok);2878if (Tok.isNot(tok::comma)) {2879PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";2880return;2881}2882PP.Lex(Tok);2883Action = Sema::PSK_Push_Set;2884// not push, could be on/off2885} else if (II->isStr("pop")) {2886// #pragma vtordisp(pop)2887PP.Lex(Tok);2888Action = Sema::PSK_Pop;2889}2890// not push or pop, could be on/off2891} else {2892if (Tok.is(tok::r_paren)) {2893// #pragma vtordisp()2894Action = Sema::PSK_Reset;2895}2896}289728982899uint64_t Value = 0;2900if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {2901const IdentifierInfo *II = Tok.getIdentifierInfo();2902if (II && II->isStr("off")) {2903PP.Lex(Tok);2904Value = 0;2905} else if (II && II->isStr("on")) {2906PP.Lex(Tok);2907Value = 1;2908} else if (Tok.is(tok::numeric_constant) &&2909PP.parseSimpleIntegerLiteral(Tok, Value)) {2910if (Value > 2) {2911PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)2912<< 0 << 2 << "vtordisp";2913return;2914}2915} else {2916PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)2917<< "vtordisp";2918return;2919}2920}29212922// Finish the pragma: ')' $2923if (Tok.isNot(tok::r_paren)) {2924PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";2925return;2926}2927SourceLocation EndLoc = Tok.getLocation();2928PP.Lex(Tok);2929if (Tok.isNot(tok::eod)) {2930PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)2931<< "vtordisp";2932return;2933}29342935// Enter the annotation.2936Token AnnotTok;2937AnnotTok.startToken();2938AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);2939AnnotTok.setLocation(VtorDispLoc);2940AnnotTok.setAnnotationEndLoc(EndLoc);2941AnnotTok.setAnnotationValue(reinterpret_cast<void *>(2942static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));2943PP.EnterToken(AnnotTok, /*IsReinject=*/false);2944}29452946/// Handle all MS pragmas. Simply forwards the tokens after inserting2947/// an annotation token.2948void PragmaMSPragma::HandlePragma(Preprocessor &PP,2949PragmaIntroducer Introducer, Token &Tok) {2950Token EoF, AnnotTok;2951EoF.startToken();2952EoF.setKind(tok::eof);2953AnnotTok.startToken();2954AnnotTok.setKind(tok::annot_pragma_ms_pragma);2955AnnotTok.setLocation(Tok.getLocation());2956AnnotTok.setAnnotationEndLoc(Tok.getLocation());2957SmallVector<Token, 8> TokenVector;2958// Suck up all of the tokens before the eod.2959for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {2960TokenVector.push_back(Tok);2961AnnotTok.setAnnotationEndLoc(Tok.getLocation());2962}2963// Add a sentinel EoF token to the end of the list.2964TokenVector.push_back(EoF);2965// We must allocate this array with new because EnterTokenStream is going to2966// delete it later.2967markAsReinjectedForRelexing(TokenVector);2968auto TokenArray = std::make_unique<Token[]>(TokenVector.size());2969std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());2970auto Value = new (PP.getPreprocessorAllocator())2971std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),2972TokenVector.size());2973AnnotTok.setAnnotationValue(Value);2974PP.EnterToken(AnnotTok, /*IsReinject*/ false);2975}29762977/// Handle the \#pragma float_control extension.2978///2979/// The syntax is:2980/// \code2981/// #pragma float_control(keyword[, setting] [,push])2982/// \endcode2983/// Where 'keyword' and 'setting' are identifiers.2984// 'keyword' can be: precise, except, push, pop2985// 'setting' can be: on, off2986/// The optional arguments 'setting' and 'push' are supported only2987/// when the keyword is 'precise' or 'except'.2988void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP,2989PragmaIntroducer Introducer,2990Token &Tok) {2991Sema::PragmaMsStackAction Action = Sema::PSK_Set;2992SourceLocation FloatControlLoc = Tok.getLocation();2993Token PragmaName = Tok;2994if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {2995PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)2996<< PragmaName.getIdentifierInfo()->getName();2997return;2998}2999PP.Lex(Tok);3000if (Tok.isNot(tok::l_paren)) {3001PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren;3002return;3003}30043005// Read the identifier.3006PP.Lex(Tok);3007if (Tok.isNot(tok::identifier)) {3008PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);3009return;3010}30113012// Verify that this is one of the float control options.3013IdentifierInfo *II = Tok.getIdentifierInfo();3014PragmaFloatControlKind Kind =3015llvm::StringSwitch<PragmaFloatControlKind>(II->getName())3016.Case("precise", PFC_Precise)3017.Case("except", PFC_Except)3018.Case("push", PFC_Push)3019.Case("pop", PFC_Pop)3020.Default(PFC_Unknown);3021PP.Lex(Tok); // the identifier3022if (Kind == PFC_Unknown) {3023PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);3024return;3025} else if (Kind == PFC_Push || Kind == PFC_Pop) {3026if (Tok.isNot(tok::r_paren)) {3027PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);3028return;3029}3030PP.Lex(Tok); // Eat the r_paren3031Action = (Kind == PFC_Pop) ? Sema::PSK_Pop : Sema::PSK_Push;3032} else {3033if (Tok.is(tok::r_paren))3034// Selecting Precise or Except3035PP.Lex(Tok); // the r_paren3036else if (Tok.isNot(tok::comma)) {3037PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);3038return;3039} else {3040PP.Lex(Tok); // ,3041if (!Tok.isAnyIdentifier()) {3042PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);3043return;3044}3045StringRef PushOnOff = Tok.getIdentifierInfo()->getName();3046if (PushOnOff == "on")3047// Kind is set correctly3048;3049else if (PushOnOff == "off") {3050if (Kind == PFC_Precise)3051Kind = PFC_NoPrecise;3052if (Kind == PFC_Except)3053Kind = PFC_NoExcept;3054} else if (PushOnOff == "push") {3055Action = Sema::PSK_Push_Set;3056} else {3057PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);3058return;3059}3060PP.Lex(Tok); // the identifier3061if (Tok.is(tok::comma)) {3062PP.Lex(Tok); // ,3063if (!Tok.isAnyIdentifier()) {3064PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);3065return;3066}3067StringRef ExpectedPush = Tok.getIdentifierInfo()->getName();3068if (ExpectedPush == "push") {3069Action = Sema::PSK_Push_Set;3070} else {3071PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);3072return;3073}3074PP.Lex(Tok); // the push identifier3075}3076if (Tok.isNot(tok::r_paren)) {3077PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);3078return;3079}3080PP.Lex(Tok); // the r_paren3081}3082}3083SourceLocation EndLoc = Tok.getLocation();3084if (Tok.isNot(tok::eod)) {3085PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)3086<< "float_control";3087return;3088}30893090// Note: there is no accomodation for PP callback for this pragma.30913092// Enter the annotation.3093auto TokenArray = std::make_unique<Token[]>(1);3094TokenArray[0].startToken();3095TokenArray[0].setKind(tok::annot_pragma_float_control);3096TokenArray[0].setLocation(FloatControlLoc);3097TokenArray[0].setAnnotationEndLoc(EndLoc);3098// Create an encoding of Action and Value by shifting the Action into3099// the high 16 bits then union with the Kind.3100TokenArray[0].setAnnotationValue(reinterpret_cast<void *>(3101static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF))));3102PP.EnterTokenStream(std::move(TokenArray), 1,3103/*DisableMacroExpansion=*/false, /*IsReinject=*/false);3104}31053106/// Handle the Microsoft \#pragma detect_mismatch extension.3107///3108/// The syntax is:3109/// \code3110/// #pragma detect_mismatch("name", "value")3111/// \endcode3112/// Where 'name' and 'value' are quoted strings. The values are embedded in3113/// the object file and passed along to the linker. If the linker detects a3114/// mismatch in the object file's values for the given name, a LNK2038 error3115/// is emitted. See MSDN for more details.3116void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,3117PragmaIntroducer Introducer,3118Token &Tok) {3119SourceLocation DetectMismatchLoc = Tok.getLocation();3120PP.Lex(Tok);3121if (Tok.isNot(tok::l_paren)) {3122PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;3123return;3124}31253126// Read the name to embed, which must be a string literal.3127std::string NameString;3128if (!PP.LexStringLiteral(Tok, NameString,3129"pragma detect_mismatch",3130/*AllowMacroExpansion=*/true))3131return;31323133// Read the comma followed by a second string literal.3134std::string ValueString;3135if (Tok.isNot(tok::comma)) {3136PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);3137return;3138}31393140if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",3141/*AllowMacroExpansion=*/true))3142return;31433144if (Tok.isNot(tok::r_paren)) {3145PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;3146return;3147}3148PP.Lex(Tok); // Eat the r_paren.31493150if (Tok.isNot(tok::eod)) {3151PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);3152return;3153}31543155// If the pragma is lexically sound, notify any interested PPCallbacks.3156if (PP.getPPCallbacks())3157PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,3158ValueString);31593160Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);3161}31623163/// Handle the microsoft \#pragma comment extension.3164///3165/// The syntax is:3166/// \code3167/// #pragma comment(linker, "foo")3168/// \endcode3169/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.3170/// "foo" is a string, which is fully macro expanded, and permits string3171/// concatenation, embedded escape characters etc. See MSDN for more details.3172void PragmaCommentHandler::HandlePragma(Preprocessor &PP,3173PragmaIntroducer Introducer,3174Token &Tok) {3175SourceLocation CommentLoc = Tok.getLocation();3176PP.Lex(Tok);3177if (Tok.isNot(tok::l_paren)) {3178PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);3179return;3180}31813182// Read the identifier.3183PP.Lex(Tok);3184if (Tok.isNot(tok::identifier)) {3185PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);3186return;3187}31883189// Verify that this is one of the 5 explicitly listed options.3190IdentifierInfo *II = Tok.getIdentifierInfo();3191PragmaMSCommentKind Kind =3192llvm::StringSwitch<PragmaMSCommentKind>(II->getName())3193.Case("linker", PCK_Linker)3194.Case("lib", PCK_Lib)3195.Case("compiler", PCK_Compiler)3196.Case("exestr", PCK_ExeStr)3197.Case("user", PCK_User)3198.Default(PCK_Unknown);3199if (Kind == PCK_Unknown) {3200PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);3201return;3202}32033204if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {3205PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)3206<< II->getName();3207return;3208}32093210// Read the optional string if present.3211PP.Lex(Tok);3212std::string ArgumentString;3213if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,3214"pragma comment",3215/*AllowMacroExpansion=*/true))3216return;32173218// FIXME: warn that 'exestr' is deprecated.3219// FIXME: If the kind is "compiler" warn if the string is present (it is3220// ignored).3221// The MSDN docs say that "lib" and "linker" require a string and have a short3222// list of linker options they support, but in practice MSVC doesn't3223// issue a diagnostic. Therefore neither does clang.32243225if (Tok.isNot(tok::r_paren)) {3226PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);3227return;3228}3229PP.Lex(Tok); // eat the r_paren.32303231if (Tok.isNot(tok::eod)) {3232PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);3233return;3234}32353236// If the pragma is lexically sound, notify any interested PPCallbacks.3237if (PP.getPPCallbacks())3238PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);32393240Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);3241}32423243// #pragma clang optimize off3244// #pragma clang optimize on3245void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,3246PragmaIntroducer Introducer,3247Token &FirstToken) {3248Token Tok;3249PP.Lex(Tok);3250if (Tok.is(tok::eod)) {3251PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)3252<< "clang optimize" << /*Expected=*/true << "'on' or 'off'";3253return;3254}3255if (Tok.isNot(tok::identifier)) {3256PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)3257<< PP.getSpelling(Tok);3258return;3259}3260const IdentifierInfo *II = Tok.getIdentifierInfo();3261// The only accepted values are 'on' or 'off'.3262bool IsOn = false;3263if (II->isStr("on")) {3264IsOn = true;3265} else if (!II->isStr("off")) {3266PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)3267<< PP.getSpelling(Tok);3268return;3269}3270PP.Lex(Tok);32713272if (Tok.isNot(tok::eod)) {3273PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)3274<< PP.getSpelling(Tok);3275return;3276}32773278Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());3279}32803281namespace {3282/// Used as the annotation value for tok::annot_pragma_fp.3283struct TokFPAnnotValue {3284enum FlagValues { On, Off, Fast };32853286std::optional<LangOptions::FPModeKind> ContractValue;3287std::optional<LangOptions::FPModeKind> ReassociateValue;3288std::optional<LangOptions::FPModeKind> ReciprocalValue;3289std::optional<LangOptions::FPExceptionModeKind> ExceptionsValue;3290std::optional<LangOptions::FPEvalMethodKind> EvalMethodValue;3291};3292} // end anonymous namespace32933294void PragmaFPHandler::HandlePragma(Preprocessor &PP,3295PragmaIntroducer Introducer, Token &Tok) {3296// fp3297Token PragmaName = Tok;3298SmallVector<Token, 1> TokenList;32993300PP.Lex(Tok);3301if (Tok.isNot(tok::identifier)) {3302PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)3303<< /*MissingOption=*/true << "";3304return;3305}33063307auto *AnnotValue = new (PP.getPreprocessorAllocator()) TokFPAnnotValue;3308while (Tok.is(tok::identifier)) {3309IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();33103311auto FlagKind =3312llvm::StringSwitch<std::optional<PragmaFPKind>>(OptionInfo->getName())3313.Case("contract", PFK_Contract)3314.Case("reassociate", PFK_Reassociate)3315.Case("exceptions", PFK_Exceptions)3316.Case("eval_method", PFK_EvalMethod)3317.Case("reciprocal", PFK_Reciprocal)3318.Default(std::nullopt);3319if (!FlagKind) {3320PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)3321<< /*MissingOption=*/false << OptionInfo;3322return;3323}3324PP.Lex(Tok);33253326// Read '('3327if (Tok.isNot(tok::l_paren)) {3328PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;3329return;3330}3331PP.Lex(Tok);3332bool isEvalMethodDouble =3333Tok.is(tok::kw_double) && FlagKind == PFK_EvalMethod;33343335// Don't diagnose if we have an eval_metod pragma with "double" kind.3336if (Tok.isNot(tok::identifier) && !isEvalMethodDouble) {3337PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)3338<< PP.getSpelling(Tok) << OptionInfo->getName()3339<< static_cast<int>(*FlagKind);3340return;3341}3342const IdentifierInfo *II = Tok.getIdentifierInfo();33433344if (FlagKind == PFK_Contract) {3345AnnotValue->ContractValue =3346llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(3347II->getName())3348.Case("on", LangOptions::FPModeKind::FPM_On)3349.Case("off", LangOptions::FPModeKind::FPM_Off)3350.Case("fast", LangOptions::FPModeKind::FPM_Fast)3351.Default(std::nullopt);3352if (!AnnotValue->ContractValue) {3353PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)3354<< PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;3355return;3356}3357} else if (FlagKind == PFK_Reassociate || FlagKind == PFK_Reciprocal) {3358auto &Value = FlagKind == PFK_Reassociate ? AnnotValue->ReassociateValue3359: AnnotValue->ReciprocalValue;3360Value = llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(3361II->getName())3362.Case("on", LangOptions::FPModeKind::FPM_On)3363.Case("off", LangOptions::FPModeKind::FPM_Off)3364.Default(std::nullopt);3365if (!Value) {3366PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)3367<< PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;3368return;3369}3370} else if (FlagKind == PFK_Exceptions) {3371AnnotValue->ExceptionsValue =3372llvm::StringSwitch<std::optional<LangOptions::FPExceptionModeKind>>(3373II->getName())3374.Case("ignore", LangOptions::FPE_Ignore)3375.Case("maytrap", LangOptions::FPE_MayTrap)3376.Case("strict", LangOptions::FPE_Strict)3377.Default(std::nullopt);3378if (!AnnotValue->ExceptionsValue) {3379PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)3380<< PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;3381return;3382}3383} else if (FlagKind == PFK_EvalMethod) {3384AnnotValue->EvalMethodValue =3385llvm::StringSwitch<std::optional<LangOptions::FPEvalMethodKind>>(3386II->getName())3387.Case("source", LangOptions::FPEvalMethodKind::FEM_Source)3388.Case("double", LangOptions::FPEvalMethodKind::FEM_Double)3389.Case("extended", LangOptions::FPEvalMethodKind::FEM_Extended)3390.Default(std::nullopt);3391if (!AnnotValue->EvalMethodValue) {3392PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)3393<< PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;3394return;3395}3396}3397PP.Lex(Tok);33983399// Read ')'3400if (Tok.isNot(tok::r_paren)) {3401PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;3402return;3403}3404PP.Lex(Tok);3405}34063407if (Tok.isNot(tok::eod)) {3408PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)3409<< "clang fp";3410return;3411}34123413Token FPTok;3414FPTok.startToken();3415FPTok.setKind(tok::annot_pragma_fp);3416FPTok.setLocation(PragmaName.getLocation());3417FPTok.setAnnotationEndLoc(PragmaName.getLocation());3418FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));3419TokenList.push_back(FPTok);34203421auto TokenArray = std::make_unique<Token[]>(TokenList.size());3422std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());34233424PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),3425/*DisableMacroExpansion=*/false, /*IsReinject=*/false);3426}34273428void PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor &PP,3429PragmaIntroducer Introducer,3430Token &Tok) {3431Token PragmaName = Tok;3432SmallVector<Token, 1> TokenList;3433if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {3434PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)3435<< PragmaName.getIdentifierInfo()->getName();3436return;3437}34383439PP.Lex(Tok);3440if (Tok.isNot(tok::identifier)) {3441PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)3442<< PragmaName.getIdentifierInfo()->getName();3443return;3444}3445IdentifierInfo *II = Tok.getIdentifierInfo();34463447auto RM =3448llvm::StringSwitch<llvm::RoundingMode>(II->getName())3449.Case("FE_TOWARDZERO", llvm::RoundingMode::TowardZero)3450.Case("FE_TONEAREST", llvm::RoundingMode::NearestTiesToEven)3451.Case("FE_UPWARD", llvm::RoundingMode::TowardPositive)3452.Case("FE_DOWNWARD", llvm::RoundingMode::TowardNegative)3453.Case("FE_TONEARESTFROMZERO", llvm::RoundingMode::NearestTiesToAway)3454.Case("FE_DYNAMIC", llvm::RoundingMode::Dynamic)3455.Default(llvm::RoundingMode::Invalid);3456if (RM == llvm::RoundingMode::Invalid) {3457PP.Diag(Tok.getLocation(), diag::warn_stdc_unknown_rounding_mode);3458return;3459}3460PP.Lex(Tok);34613462if (Tok.isNot(tok::eod)) {3463PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)3464<< "STDC FENV_ROUND";3465return;3466}34673468// Until the pragma is fully implemented, issue a warning.3469PP.Diag(Tok.getLocation(), diag::warn_stdc_fenv_round_not_supported);34703471MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),34721);3473Toks[0].startToken();3474Toks[0].setKind(tok::annot_pragma_fenv_round);3475Toks[0].setLocation(Tok.getLocation());3476Toks[0].setAnnotationEndLoc(Tok.getLocation());3477Toks[0].setAnnotationValue(3478reinterpret_cast<void *>(static_cast<uintptr_t>(RM)));3479PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,3480/*IsReinject=*/false);3481}34823483void Parser::HandlePragmaFP() {3484assert(Tok.is(tok::annot_pragma_fp));3485auto *AnnotValue =3486reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());34873488if (AnnotValue->ReassociateValue)3489Actions.ActOnPragmaFPValueChangingOption(3490Tok.getLocation(), PFK_Reassociate,3491*AnnotValue->ReassociateValue == LangOptions::FPModeKind::FPM_On);34923493if (AnnotValue->ReciprocalValue)3494Actions.ActOnPragmaFPValueChangingOption(3495Tok.getLocation(), PFK_Reciprocal,3496*AnnotValue->ReciprocalValue == LangOptions::FPModeKind::FPM_On);34973498if (AnnotValue->ContractValue)3499Actions.ActOnPragmaFPContract(Tok.getLocation(),3500*AnnotValue->ContractValue);3501if (AnnotValue->ExceptionsValue)3502Actions.ActOnPragmaFPExceptions(Tok.getLocation(),3503*AnnotValue->ExceptionsValue);3504if (AnnotValue->EvalMethodValue)3505Actions.ActOnPragmaFPEvalMethod(Tok.getLocation(),3506*AnnotValue->EvalMethodValue);3507ConsumeAnnotationToken();3508}35093510/// Parses loop or unroll pragma hint value and fills in Info.3511static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,3512Token Option, bool ValueInParens,3513PragmaLoopHintInfo &Info) {3514SmallVector<Token, 1> ValueList;3515int OpenParens = ValueInParens ? 1 : 0;3516// Read constant expression.3517while (Tok.isNot(tok::eod)) {3518if (Tok.is(tok::l_paren))3519OpenParens++;3520else if (Tok.is(tok::r_paren)) {3521OpenParens--;3522if (OpenParens == 0 && ValueInParens)3523break;3524}35253526ValueList.push_back(Tok);3527PP.Lex(Tok);3528}35293530if (ValueInParens) {3531// Read ')'3532if (Tok.isNot(tok::r_paren)) {3533PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;3534return true;3535}3536PP.Lex(Tok);3537}35383539Token EOFTok;3540EOFTok.startToken();3541EOFTok.setKind(tok::eof);3542EOFTok.setLocation(Tok.getLocation());3543ValueList.push_back(EOFTok); // Terminates expression for parsing.35443545markAsReinjectedForRelexing(ValueList);3546Info.Toks = llvm::ArrayRef(ValueList).copy(PP.getPreprocessorAllocator());35473548Info.PragmaName = PragmaName;3549Info.Option = Option;3550return false;3551}35523553/// Handle the \#pragma clang loop directive.3554/// #pragma clang 'loop' loop-hints3555///3556/// loop-hints:3557/// loop-hint loop-hints[opt]3558///3559/// loop-hint:3560/// 'vectorize' '(' loop-hint-keyword ')'3561/// 'interleave' '(' loop-hint-keyword ')'3562/// 'unroll' '(' unroll-hint-keyword ')'3563/// 'vectorize_predicate' '(' loop-hint-keyword ')'3564/// 'vectorize_width' '(' loop-hint-value ')'3565/// 'interleave_count' '(' loop-hint-value ')'3566/// 'unroll_count' '(' loop-hint-value ')'3567/// 'pipeline' '(' disable ')'3568/// 'pipeline_initiation_interval' '(' loop-hint-value ')'3569///3570/// loop-hint-keyword:3571/// 'enable'3572/// 'disable'3573/// 'assume_safety'3574///3575/// unroll-hint-keyword:3576/// 'enable'3577/// 'disable'3578/// 'full'3579///3580/// loop-hint-value:3581/// constant-expression3582///3583/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to3584/// try vectorizing the instructions of the loop it precedes. Specifying3585/// interleave(enable) or interleave_count(_value_) instructs llvm to try3586/// interleaving multiple iterations of the loop it precedes. The width of the3587/// vector instructions is specified by vectorize_width() and the number of3588/// interleaved loop iterations is specified by interleave_count(). Specifying a3589/// value of 1 effectively disables vectorization/interleaving, even if it is3590/// possible and profitable, and 0 is invalid. The loop vectorizer currently3591/// only works on inner loops.3592///3593/// The unroll and unroll_count directives control the concatenation3594/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop3595/// completely if the trip count is known at compile time and unroll partially3596/// if the trip count is not known. Specifying unroll(full) is similar to3597/// unroll(enable) but will unroll the loop only if the trip count is known at3598/// compile time. Specifying unroll(disable) disables unrolling for the3599/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the3600/// loop the number of times indicated by the value.3601void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,3602PragmaIntroducer Introducer,3603Token &Tok) {3604// Incoming token is "loop" from "#pragma clang loop".3605Token PragmaName = Tok;3606SmallVector<Token, 1> TokenList;36073608// Lex the optimization option and verify it is an identifier.3609PP.Lex(Tok);3610if (Tok.isNot(tok::identifier)) {3611PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)3612<< /*MissingOption=*/true << "";3613return;3614}36153616while (Tok.is(tok::identifier)) {3617Token Option = Tok;3618IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();36193620bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())3621.Case("vectorize", true)3622.Case("interleave", true)3623.Case("unroll", true)3624.Case("distribute", true)3625.Case("vectorize_predicate", true)3626.Case("vectorize_width", true)3627.Case("interleave_count", true)3628.Case("unroll_count", true)3629.Case("pipeline", true)3630.Case("pipeline_initiation_interval", true)3631.Default(false);3632if (!OptionValid) {3633PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)3634<< /*MissingOption=*/false << OptionInfo;3635return;3636}3637PP.Lex(Tok);36383639// Read '('3640if (Tok.isNot(tok::l_paren)) {3641PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;3642return;3643}3644PP.Lex(Tok);36453646auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;3647if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,3648*Info))3649return;36503651// Generate the loop hint token.3652Token LoopHintTok;3653LoopHintTok.startToken();3654LoopHintTok.setKind(tok::annot_pragma_loop_hint);3655LoopHintTok.setLocation(Introducer.Loc);3656LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());3657LoopHintTok.setAnnotationValue(static_cast<void *>(Info));3658TokenList.push_back(LoopHintTok);3659}36603661if (Tok.isNot(tok::eod)) {3662PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)3663<< "clang loop";3664return;3665}36663667auto TokenArray = std::make_unique<Token[]>(TokenList.size());3668std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());36693670PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),3671/*DisableMacroExpansion=*/false, /*IsReinject=*/false);3672}36733674/// Handle the loop unroll optimization pragmas.3675/// #pragma unroll3676/// #pragma unroll unroll-hint-value3677/// #pragma unroll '(' unroll-hint-value ')'3678/// #pragma nounroll3679/// #pragma unroll_and_jam3680/// #pragma unroll_and_jam unroll-hint-value3681/// #pragma unroll_and_jam '(' unroll-hint-value ')'3682/// #pragma nounroll_and_jam3683///3684/// unroll-hint-value:3685/// constant-expression3686///3687/// Loop unrolling hints can be specified with '#pragma unroll' or3688/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally3689/// contained in parentheses. With no argument the directive instructs llvm to3690/// try to unroll the loop completely. A positive integer argument can be3691/// specified to indicate the number of times the loop should be unrolled. To3692/// maximize compatibility with other compilers the unroll count argument can be3693/// specified with or without parentheses. Specifying, '#pragma nounroll'3694/// disables unrolling of the loop.3695void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,3696PragmaIntroducer Introducer,3697Token &Tok) {3698// Incoming token is "unroll" for "#pragma unroll", or "nounroll" for3699// "#pragma nounroll".3700Token PragmaName = Tok;3701PP.Lex(Tok);3702auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;3703if (Tok.is(tok::eod)) {3704// nounroll or unroll pragma without an argument.3705Info->PragmaName = PragmaName;3706Info->Option.startToken();3707} else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||3708PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {3709PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)3710<< PragmaName.getIdentifierInfo()->getName();3711return;3712} else {3713// Unroll pragma with an argument: "#pragma unroll N" or3714// "#pragma unroll(N)".3715// Read '(' if it exists.3716bool ValueInParens = Tok.is(tok::l_paren);3717if (ValueInParens)3718PP.Lex(Tok);37193720Token Option;3721Option.startToken();3722if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))3723return;37243725// In CUDA, the argument to '#pragma unroll' should not be contained in3726// parentheses.3727if (PP.getLangOpts().CUDA && ValueInParens)3728PP.Diag(Info->Toks[0].getLocation(),3729diag::warn_pragma_unroll_cuda_value_in_parens);37303731if (Tok.isNot(tok::eod)) {3732PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)3733<< "unroll";3734return;3735}3736}37373738// Generate the hint token.3739auto TokenArray = std::make_unique<Token[]>(1);3740TokenArray[0].startToken();3741TokenArray[0].setKind(tok::annot_pragma_loop_hint);3742TokenArray[0].setLocation(Introducer.Loc);3743TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());3744TokenArray[0].setAnnotationValue(static_cast<void *>(Info));3745PP.EnterTokenStream(std::move(TokenArray), 1,3746/*DisableMacroExpansion=*/false, /*IsReinject=*/false);3747}37483749/// Handle the Microsoft \#pragma intrinsic extension.3750///3751/// The syntax is:3752/// \code3753/// #pragma intrinsic(memset)3754/// #pragma intrinsic(strlen, memcpy)3755/// \endcode3756///3757/// Pragma intrisic tells the compiler to use a builtin version of the3758/// function. Clang does it anyway, so the pragma doesn't really do anything.3759/// Anyway, we emit a warning if the function specified in \#pragma intrinsic3760/// isn't an intrinsic in clang and suggest to include intrin.h.3761void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,3762PragmaIntroducer Introducer,3763Token &Tok) {3764PP.Lex(Tok);37653766if (Tok.isNot(tok::l_paren)) {3767PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)3768<< "intrinsic";3769return;3770}3771PP.Lex(Tok);37723773bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");37743775while (Tok.is(tok::identifier)) {3776IdentifierInfo *II = Tok.getIdentifierInfo();3777if (!II->getBuiltinID())3778PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)3779<< II << SuggestIntrinH;37803781PP.Lex(Tok);3782if (Tok.isNot(tok::comma))3783break;3784PP.Lex(Tok);3785}37863787if (Tok.isNot(tok::r_paren)) {3788PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)3789<< "intrinsic";3790return;3791}3792PP.Lex(Tok);37933794if (Tok.isNot(tok::eod))3795PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)3796<< "intrinsic";3797}37983799bool Parser::HandlePragmaMSFunction(StringRef PragmaName,3800SourceLocation PragmaLocation) {3801Token FirstTok = Tok;38023803if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,3804PragmaName))3805return false;38063807bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");38083809llvm::SmallVector<StringRef> NoBuiltins;3810while (Tok.is(tok::identifier)) {3811IdentifierInfo *II = Tok.getIdentifierInfo();3812if (!II->getBuiltinID())3813PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)3814<< II << SuggestIntrinH;3815else3816NoBuiltins.emplace_back(II->getName());38173818PP.Lex(Tok);3819if (Tok.isNot(tok::comma))3820break;3821PP.Lex(Tok); // ,3822}38233824if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,3825PragmaName) ||3826ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,3827PragmaName))3828return false;38293830Actions.ActOnPragmaMSFunction(FirstTok.getLocation(), NoBuiltins);3831return true;3832}38333834// #pragma optimize("gsty", on|off)3835bool Parser::HandlePragmaMSOptimize(StringRef PragmaName,3836SourceLocation PragmaLocation) {3837Token FirstTok = Tok;3838if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,3839PragmaName))3840return false;38413842if (Tok.isNot(tok::string_literal)) {3843PP.Diag(PragmaLocation, diag::warn_pragma_expected_string) << PragmaName;3844return false;3845}3846ExprResult StringResult = ParseStringLiteralExpression();3847if (StringResult.isInvalid())3848return false; // Already diagnosed.3849StringLiteral *OptimizationList = cast<StringLiteral>(StringResult.get());3850if (OptimizationList->getCharByteWidth() != 1) {3851PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)3852<< PragmaName;3853return false;3854}38553856if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,3857PragmaName))3858return false;38593860if (Tok.is(tok::eof) || Tok.is(tok::r_paren)) {3861PP.Diag(PragmaLocation, diag::warn_pragma_missing_argument)3862<< PragmaName << /*Expected=*/true << "'on' or 'off'";3863return false;3864}3865IdentifierInfo *II = Tok.getIdentifierInfo();3866if (!II || (!II->isStr("on") && !II->isStr("off"))) {3867PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)3868<< PP.getSpelling(Tok) << PragmaName << /*Expected=*/true3869<< "'on' or 'off'";3870return false;3871}3872bool IsOn = II->isStr("on");3873PP.Lex(Tok);38743875if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,3876PragmaName))3877return false;38783879// TODO: Add support for "sgty"3880if (!OptimizationList->getString().empty()) {3881PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)3882<< OptimizationList->getString() << PragmaName << /*Expected=*/true3883<< "\"\"";3884return false;3885}38863887if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,3888PragmaName))3889return false;38903891Actions.ActOnPragmaMSOptimize(FirstTok.getLocation(), IsOn);3892return true;3893}38943895void PragmaForceCUDAHostDeviceHandler::HandlePragma(3896Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) {3897Token FirstTok = Tok;38983899PP.Lex(Tok);3900IdentifierInfo *Info = Tok.getIdentifierInfo();3901if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {3902PP.Diag(FirstTok.getLocation(),3903diag::warn_pragma_force_cuda_host_device_bad_arg);3904return;3905}39063907if (Info->isStr("begin"))3908Actions.CUDA().PushForceHostDevice();3909else if (!Actions.CUDA().PopForceHostDevice())3910PP.Diag(FirstTok.getLocation(),3911diag::err_pragma_cannot_end_force_cuda_host_device);39123913PP.Lex(Tok);3914if (!Tok.is(tok::eod))3915PP.Diag(FirstTok.getLocation(),3916diag::warn_pragma_force_cuda_host_device_bad_arg);3917}39183919/// Handle the #pragma clang attribute directive.3920///3921/// The syntax is:3922/// \code3923/// #pragma clang attribute push (attribute, subject-set)3924/// #pragma clang attribute push3925/// #pragma clang attribute (attribute, subject-set)3926/// #pragma clang attribute pop3927/// \endcode3928///3929/// There are also 'namespace' variants of push and pop directives. The bare3930/// '#pragma clang attribute (attribute, subject-set)' version doesn't require a3931/// namespace, since it always applies attributes to the most recently pushed3932/// group, regardless of namespace.3933/// \code3934/// #pragma clang attribute namespace.push (attribute, subject-set)3935/// #pragma clang attribute namespace.push3936/// #pragma clang attribute namespace.pop3937/// \endcode3938///3939/// The subject-set clause defines the set of declarations which receive the3940/// attribute. Its exact syntax is described in the LanguageExtensions document3941/// in Clang's documentation.3942///3943/// This directive instructs the compiler to begin/finish applying the specified3944/// attribute to the set of attribute-specific declarations in the active range3945/// of the pragma.3946void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,3947PragmaIntroducer Introducer,3948Token &FirstToken) {3949Token Tok;3950PP.Lex(Tok);3951auto *Info = new (PP.getPreprocessorAllocator())3952PragmaAttributeInfo(AttributesForPragmaAttribute);39533954// Parse the optional namespace followed by a period.3955if (Tok.is(tok::identifier)) {3956IdentifierInfo *II = Tok.getIdentifierInfo();3957if (!II->isStr("push") && !II->isStr("pop")) {3958Info->Namespace = II;3959PP.Lex(Tok);39603961if (!Tok.is(tok::period)) {3962PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)3963<< II;3964return;3965}3966PP.Lex(Tok);3967}3968}39693970if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {3971PP.Diag(Tok.getLocation(),3972diag::err_pragma_attribute_expected_push_pop_paren);3973return;3974}39753976// Determine what action this pragma clang attribute represents.3977if (Tok.is(tok::l_paren)) {3978if (Info->Namespace) {3979PP.Diag(Tok.getLocation(),3980diag::err_pragma_attribute_namespace_on_attribute);3981PP.Diag(Tok.getLocation(),3982diag::note_pragma_attribute_namespace_on_attribute);3983return;3984}3985Info->Action = PragmaAttributeInfo::Attribute;3986} else {3987const IdentifierInfo *II = Tok.getIdentifierInfo();3988if (II->isStr("push"))3989Info->Action = PragmaAttributeInfo::Push;3990else if (II->isStr("pop"))3991Info->Action = PragmaAttributeInfo::Pop;3992else {3993PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)3994<< PP.getSpelling(Tok);3995return;3996}39973998PP.Lex(Tok);3999}40004001// Parse the actual attribute.4002if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||4003Info->Action == PragmaAttributeInfo::Attribute) {4004if (Tok.isNot(tok::l_paren)) {4005PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;4006return;4007}4008PP.Lex(Tok);40094010// Lex the attribute tokens.4011SmallVector<Token, 16> AttributeTokens;4012int OpenParens = 1;4013while (Tok.isNot(tok::eod)) {4014if (Tok.is(tok::l_paren))4015OpenParens++;4016else if (Tok.is(tok::r_paren)) {4017OpenParens--;4018if (OpenParens == 0)4019break;4020}40214022AttributeTokens.push_back(Tok);4023PP.Lex(Tok);4024}40254026if (AttributeTokens.empty()) {4027PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);4028return;4029}4030if (Tok.isNot(tok::r_paren)) {4031PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;4032return;4033}4034SourceLocation EndLoc = Tok.getLocation();4035PP.Lex(Tok);40364037// Terminate the attribute for parsing.4038Token EOFTok;4039EOFTok.startToken();4040EOFTok.setKind(tok::eof);4041EOFTok.setLocation(EndLoc);4042AttributeTokens.push_back(EOFTok);40434044markAsReinjectedForRelexing(AttributeTokens);4045Info->Tokens =4046llvm::ArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());4047}40484049if (Tok.isNot(tok::eod))4050PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)4051<< "clang attribute";40524053// Generate the annotated pragma token.4054auto TokenArray = std::make_unique<Token[]>(1);4055TokenArray[0].startToken();4056TokenArray[0].setKind(tok::annot_pragma_attribute);4057TokenArray[0].setLocation(FirstToken.getLocation());4058TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());4059TokenArray[0].setAnnotationValue(static_cast<void *>(Info));4060PP.EnterTokenStream(std::move(TokenArray), 1,4061/*DisableMacroExpansion=*/false, /*IsReinject=*/false);4062}40634064// Handle '#pragma clang max_tokens 12345'.4065void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP,4066PragmaIntroducer Introducer,4067Token &Tok) {4068PP.Lex(Tok);4069if (Tok.is(tok::eod)) {4070PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)4071<< "clang max_tokens_here" << /*Expected=*/true << "integer";4072return;4073}40744075SourceLocation Loc = Tok.getLocation();4076uint64_t MaxTokens;4077if (Tok.isNot(tok::numeric_constant) ||4078!PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {4079PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)4080<< "clang max_tokens_here";4081return;4082}40834084if (Tok.isNot(tok::eod)) {4085PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)4086<< "clang max_tokens_here";4087return;4088}40894090if (PP.getTokenCount() > MaxTokens) {4091PP.Diag(Loc, diag::warn_max_tokens)4092<< PP.getTokenCount() << (unsigned)MaxTokens;4093}4094}40954096// Handle '#pragma clang max_tokens_total 12345'.4097void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP,4098PragmaIntroducer Introducer,4099Token &Tok) {4100PP.Lex(Tok);4101if (Tok.is(tok::eod)) {4102PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)4103<< "clang max_tokens_total" << /*Expected=*/true << "integer";4104return;4105}41064107SourceLocation Loc = Tok.getLocation();4108uint64_t MaxTokens;4109if (Tok.isNot(tok::numeric_constant) ||4110!PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {4111PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)4112<< "clang max_tokens_total";4113return;4114}41154116if (Tok.isNot(tok::eod)) {4117PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)4118<< "clang max_tokens_total";4119return;4120}41214122PP.overrideMaxTokens(MaxTokens, Loc);4123}41244125// Handle '#pragma clang riscv intrinsic vector'.4126// '#pragma clang riscv intrinsic sifive_vector'.4127void PragmaRISCVHandler::HandlePragma(Preprocessor &PP,4128PragmaIntroducer Introducer,4129Token &FirstToken) {4130Token Tok;4131PP.Lex(Tok);4132IdentifierInfo *II = Tok.getIdentifierInfo();41334134if (!II || !II->isStr("intrinsic")) {4135PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)4136<< PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'intrinsic'";4137return;4138}41394140PP.Lex(Tok);4141II = Tok.getIdentifierInfo();4142if (!II || !(II->isStr("vector") || II->isStr("sifive_vector"))) {4143PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)4144<< PP.getSpelling(Tok) << "riscv" << /*Expected=*/true4145<< "'vector' or 'sifive_vector'";4146return;4147}41484149PP.Lex(Tok);4150if (Tok.isNot(tok::eod)) {4151PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)4152<< "clang riscv intrinsic";4153return;4154}41554156if (II->isStr("vector"))4157Actions.RISCV().DeclareRVVBuiltins = true;4158else if (II->isStr("sifive_vector"))4159Actions.RISCV().DeclareSiFiveVectorBuiltins = true;4160}416141624163