brintos

brintos / llvm-project-archived public Read only

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