brintos

brintos / llvm-project-archived public Read only

0
0
Text · 57.5 KiB · 7729c11 Raw
1578 lines · cpp
1//===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===//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 semantic analysis for non-trivial attributes and10// pragmas.11//12//===----------------------------------------------------------------------===//13 14#include "clang/AST/ASTConsumer.h"15#include "clang/AST/Attr.h"16#include "clang/AST/DeclCXX.h"17#include "clang/AST/Expr.h"18#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h"19#include "clang/Basic/TargetInfo.h"20#include "clang/Lex/Preprocessor.h"21#include "clang/Sema/Lookup.h"22#include <optional>23using namespace clang;24 25//===----------------------------------------------------------------------===//26// Pragma 'pack' and 'options align'27//===----------------------------------------------------------------------===//28 29Sema::PragmaStackSentinelRAII::PragmaStackSentinelRAII(Sema &S,30                                                       StringRef SlotLabel,31                                                       bool ShouldAct)32    : S(S), SlotLabel(SlotLabel), ShouldAct(ShouldAct) {33  if (ShouldAct) {34    S.VtorDispStack.SentinelAction(PSK_Push, SlotLabel);35    S.DataSegStack.SentinelAction(PSK_Push, SlotLabel);36    S.BSSSegStack.SentinelAction(PSK_Push, SlotLabel);37    S.ConstSegStack.SentinelAction(PSK_Push, SlotLabel);38    S.CodeSegStack.SentinelAction(PSK_Push, SlotLabel);39    S.StrictGuardStackCheckStack.SentinelAction(PSK_Push, SlotLabel);40  }41}42 43Sema::PragmaStackSentinelRAII::~PragmaStackSentinelRAII() {44  if (ShouldAct) {45    S.VtorDispStack.SentinelAction(PSK_Pop, SlotLabel);46    S.DataSegStack.SentinelAction(PSK_Pop, SlotLabel);47    S.BSSSegStack.SentinelAction(PSK_Pop, SlotLabel);48    S.ConstSegStack.SentinelAction(PSK_Pop, SlotLabel);49    S.CodeSegStack.SentinelAction(PSK_Pop, SlotLabel);50    S.StrictGuardStackCheckStack.SentinelAction(PSK_Pop, SlotLabel);51  }52}53 54void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {55  AlignPackInfo InfoVal = AlignPackStack.CurrentValue;56  AlignPackInfo::Mode M = InfoVal.getAlignMode();57  bool IsPackSet = InfoVal.IsPackSet();58  bool IsXLPragma = getLangOpts().XLPragmaPack;59 60  // If we are not under mac68k/natural alignment mode and also there is no pack61  // value, we don't need any attributes.62  if (!IsPackSet && M != AlignPackInfo::Mac68k && M != AlignPackInfo::Natural)63    return;64 65  if (M == AlignPackInfo::Mac68k && (IsXLPragma || InfoVal.IsAlignAttr())) {66    RD->addAttr(AlignMac68kAttr::CreateImplicit(Context));67  } else if (IsPackSet) {68    // Check to see if we need a max field alignment attribute.69    RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit(70        Context, InfoVal.getPackNumber() * 8));71  }72 73  if (IsXLPragma && M == AlignPackInfo::Natural)74    RD->addAttr(AlignNaturalAttr::CreateImplicit(Context));75 76  if (AlignPackIncludeStack.empty())77    return;78  // The #pragma align/pack affected a record in an included file, so Clang79  // should warn when that pragma was written in a file that included the80  // included file.81  for (auto &AlignPackedInclude : llvm::reverse(AlignPackIncludeStack)) {82    if (AlignPackedInclude.CurrentPragmaLocation !=83        AlignPackStack.CurrentPragmaLocation)84      break;85    if (AlignPackedInclude.HasNonDefaultValue)86      AlignPackedInclude.ShouldWarnOnInclude = true;87  }88}89 90void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {91  if (MSStructPragmaOn)92    RD->addAttr(MSStructAttr::CreateImplicit(Context));93 94  // FIXME: We should merge AddAlignmentAttributesForRecord with95  // AddMsStructLayoutForRecord into AddPragmaAttributesForRecord, which takes96  // all active pragmas and applies them as attributes to class definitions.97  if (VtorDispStack.CurrentValue != getLangOpts().getVtorDispMode())98    RD->addAttr(MSVtorDispAttr::CreateImplicit(99        Context, unsigned(VtorDispStack.CurrentValue)));100}101 102template <typename Attribute>103static void addGslOwnerPointerAttributeIfNotExisting(ASTContext &Context,104                                                     CXXRecordDecl *Record) {105  if (Record->hasAttr<OwnerAttr>() || Record->hasAttr<PointerAttr>())106    return;107 108  for (Decl *Redecl : Record->redecls())109    Redecl->addAttr(Attribute::CreateImplicit(Context, /*DerefType=*/nullptr));110}111 112void Sema::inferGslPointerAttribute(NamedDecl *ND,113                                    CXXRecordDecl *UnderlyingRecord) {114  if (!UnderlyingRecord)115    return;116 117  const auto *Parent = dyn_cast<CXXRecordDecl>(ND->getDeclContext());118  if (!Parent)119    return;120 121  static const llvm::StringSet<> Containers{122      "array",123      "basic_string",124      "deque",125      "forward_list",126      "vector",127      "list",128      "map",129      "multiset",130      "multimap",131      "priority_queue",132      "queue",133      "set",134      "stack",135      "unordered_set",136      "unordered_map",137      "unordered_multiset",138      "unordered_multimap",139  };140 141  static const llvm::StringSet<> Iterators{"iterator", "const_iterator",142                                           "reverse_iterator",143                                           "const_reverse_iterator"};144 145  if (Parent->isInStdNamespace() && Iterators.count(ND->getName()) &&146      Containers.count(Parent->getName()))147    addGslOwnerPointerAttributeIfNotExisting<PointerAttr>(Context,148                                                          UnderlyingRecord);149}150 151void Sema::inferGslPointerAttribute(TypedefNameDecl *TD) {152 153  QualType Canonical = TD->getUnderlyingType().getCanonicalType();154 155  CXXRecordDecl *RD = Canonical->getAsCXXRecordDecl();156  if (!RD) {157    if (auto *TST =158            dyn_cast<TemplateSpecializationType>(Canonical.getTypePtr())) {159 160      if (const auto *TD = TST->getTemplateName().getAsTemplateDecl())161        RD = dyn_cast_or_null<CXXRecordDecl>(TD->getTemplatedDecl());162    }163  }164 165  inferGslPointerAttribute(TD, RD);166}167 168void Sema::inferGslOwnerPointerAttribute(CXXRecordDecl *Record) {169  static const llvm::StringSet<> StdOwners{170      "any",171      "array",172      "basic_regex",173      "basic_string",174      "deque",175      "forward_list",176      "vector",177      "list",178      "map",179      "multiset",180      "multimap",181      "optional",182      "priority_queue",183      "queue",184      "set",185      "stack",186      "unique_ptr",187      "unordered_set",188      "unordered_map",189      "unordered_multiset",190      "unordered_multimap",191      "variant",192  };193  static const llvm::StringSet<> StdPointers{194      "basic_string_view",195      "reference_wrapper",196      "regex_iterator",197      "span",198  };199 200  if (!Record->getIdentifier())201    return;202 203  // Handle classes that directly appear in std namespace.204  if (Record->isInStdNamespace()) {205    if (Record->hasAttr<OwnerAttr>() || Record->hasAttr<PointerAttr>())206      return;207 208    if (StdOwners.count(Record->getName()))209      addGslOwnerPointerAttributeIfNotExisting<OwnerAttr>(Context, Record);210    else if (StdPointers.count(Record->getName()))211      addGslOwnerPointerAttributeIfNotExisting<PointerAttr>(Context, Record);212 213    return;214  }215 216  // Handle nested classes that could be a gsl::Pointer.217  inferGslPointerAttribute(Record, Record);218}219 220void Sema::inferLifetimeBoundAttribute(FunctionDecl *FD) {221  if (FD->getNumParams() == 0)222    return;223  // Skip void returning functions (except constructors). This can occur in224  // cases like 'as_const'.225  if (!isa<CXXConstructorDecl>(FD) && FD->getReturnType()->isVoidType())226    return;227 228  if (unsigned BuiltinID = FD->getBuiltinID()) {229    // Add lifetime attribute to std::move, std::fowrard et al.230    switch (BuiltinID) {231    case Builtin::BIaddressof:232    case Builtin::BI__addressof:233    case Builtin::BI__builtin_addressof:234    case Builtin::BIas_const:235    case Builtin::BIforward:236    case Builtin::BIforward_like:237    case Builtin::BImove:238    case Builtin::BImove_if_noexcept:239      if (ParmVarDecl *P = FD->getParamDecl(0u);240          !P->hasAttr<LifetimeBoundAttr>())241        P->addAttr(242            LifetimeBoundAttr::CreateImplicit(Context, FD->getLocation()));243      break;244    default:245      break;246    }247    return;248  }249  if (auto *CMD = dyn_cast<CXXMethodDecl>(FD)) {250    const auto *CRD = CMD->getParent();251    if (!CRD->isInStdNamespace() || !CRD->getIdentifier())252      return;253 254    if (isa<CXXConstructorDecl>(CMD)) {255      auto *Param = CMD->getParamDecl(0);256      if (Param->hasAttr<LifetimeBoundAttr>())257        return;258      if (CRD->getName() == "basic_string_view" &&259          Param->getType()->isPointerType()) {260        // construct from a char array pointed by a pointer.261        //   basic_string_view(const CharT* s);262        //   basic_string_view(const CharT* s, size_type count);263        Param->addAttr(264            LifetimeBoundAttr::CreateImplicit(Context, FD->getLocation()));265      } else if (CRD->getName() == "span") {266        // construct from a reference of array.267        //   span(std::type_identity_t<element_type> (&arr)[N]);268        const auto *LRT = Param->getType()->getAs<LValueReferenceType>();269        if (LRT && LRT->getPointeeType().IgnoreParens()->isArrayType())270          Param->addAttr(271              LifetimeBoundAttr::CreateImplicit(Context, FD->getLocation()));272      }273    }274  }275}276 277void Sema::inferLifetimeCaptureByAttribute(FunctionDecl *FD) {278  auto *MD = dyn_cast_if_present<CXXMethodDecl>(FD);279  if (!MD || !MD->getParent()->isInStdNamespace())280    return;281  auto Annotate = [this](const FunctionDecl *MD) {282    // Do not infer if any parameter is explicitly annotated.283    for (ParmVarDecl *PVD : MD->parameters())284      if (PVD->hasAttr<LifetimeCaptureByAttr>())285        return;286    for (ParmVarDecl *PVD : MD->parameters()) {287      // Methods in standard containers that capture values typically accept288      // reference-type parameters, e.g., `void push_back(const T& value)`.289      // We only apply the lifetime_capture_by attribute to parameters of290      // pointer-like reference types (`const T&`, `T&&`).291      if (PVD->getType()->isReferenceType() &&292          lifetimes::isGslPointerType(PVD->getType().getNonReferenceType())) {293        int CaptureByThis[] = {LifetimeCaptureByAttr::This};294        PVD->addAttr(295            LifetimeCaptureByAttr::CreateImplicit(Context, CaptureByThis, 1));296      }297    }298  };299 300  if (!MD->getIdentifier()) {301    static const llvm::StringSet<> MapLikeContainer{302        "map",303        "multimap",304        "unordered_map",305        "unordered_multimap",306    };307    // Infer for the map's operator []:308    //    std::map<string_view, ...> m;309    //    m[ReturnString(..)] = ...; // !dangling references in m.310    if (MD->getOverloadedOperator() == OO_Subscript &&311        MapLikeContainer.contains(MD->getParent()->getName()))312      Annotate(MD);313    return;314  }315  static const llvm::StringSet<> CapturingMethods{316      "insert", "insert_or_assign", "push", "push_front", "push_back"};317  if (!CapturingMethods.contains(MD->getName()))318    return;319  Annotate(MD);320}321 322void Sema::inferNullableClassAttribute(CXXRecordDecl *CRD) {323  static const llvm::StringSet<> Nullable{324      "auto_ptr",         "shared_ptr", "unique_ptr",         "exception_ptr",325      "coroutine_handle", "function",   "move_only_function",326  };327 328  if (CRD->isInStdNamespace() && Nullable.count(CRD->getName()) &&329      !CRD->hasAttr<TypeNullableAttr>())330    for (Decl *Redecl : CRD->redecls())331      Redecl->addAttr(TypeNullableAttr::CreateImplicit(Context));332}333 334void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,335                                   SourceLocation PragmaLoc) {336  PragmaMsStackAction Action = Sema::PSK_Reset;337  AlignPackInfo::Mode ModeVal = AlignPackInfo::Native;338 339  switch (Kind) {340    // For most of the platforms we support, native and natural are the same.341    // With XL, native is the same as power, natural means something else.342  case PragmaOptionsAlignKind::Native:343  case PragmaOptionsAlignKind::Power:344    Action = Sema::PSK_Push_Set;345    break;346  case PragmaOptionsAlignKind::Natural:347    Action = Sema::PSK_Push_Set;348    ModeVal = AlignPackInfo::Natural;349    break;350 351    // Note that '#pragma options align=packed' is not equivalent to attribute352    // packed, it has a different precedence relative to attribute aligned.353  case PragmaOptionsAlignKind::Packed:354    Action = Sema::PSK_Push_Set;355    ModeVal = AlignPackInfo::Packed;356    break;357 358  case PragmaOptionsAlignKind::Mac68k:359    // Check if the target supports this.360    if (!this->Context.getTargetInfo().hasAlignMac68kSupport()) {361      Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);362      return;363    }364    Action = Sema::PSK_Push_Set;365    ModeVal = AlignPackInfo::Mac68k;366    break;367  case PragmaOptionsAlignKind::Reset:368    // Reset just pops the top of the stack, or resets the current alignment to369    // default.370    Action = Sema::PSK_Pop;371    if (AlignPackStack.Stack.empty()) {372      if (AlignPackStack.CurrentValue.getAlignMode() != AlignPackInfo::Native ||373          AlignPackStack.CurrentValue.IsPackAttr()) {374        Action = Sema::PSK_Reset;375      } else {376        Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)377            << "stack empty";378        return;379      }380    }381    break;382  }383 384  AlignPackInfo Info(ModeVal, getLangOpts().XLPragmaPack);385 386  AlignPackStack.Act(PragmaLoc, Action, StringRef(), Info);387}388 389void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc,390                                   PragmaClangSectionAction Action,391                                   PragmaClangSectionKind SecKind,392                                   StringRef SecName) {393  PragmaClangSection *CSec;394  int SectionFlags = ASTContext::PSF_Read;395  switch (SecKind) {396    case PragmaClangSectionKind::BSS:397      CSec = &PragmaClangBSSSection;398      SectionFlags |= ASTContext::PSF_Write | ASTContext::PSF_ZeroInit;399      break;400    case PragmaClangSectionKind::Data:401      CSec = &PragmaClangDataSection;402      SectionFlags |= ASTContext::PSF_Write;403      break;404    case PragmaClangSectionKind::Rodata:405      CSec = &PragmaClangRodataSection;406      break;407    case PragmaClangSectionKind::Relro:408      CSec = &PragmaClangRelroSection;409      break;410    case PragmaClangSectionKind::Text:411      CSec = &PragmaClangTextSection;412      SectionFlags |= ASTContext::PSF_Execute;413      break;414    default:415      llvm_unreachable("invalid clang section kind");416  }417 418  if (Action == PragmaClangSectionAction::Clear) {419    CSec->Valid = false;420    return;421  }422 423  if (llvm::Error E = isValidSectionSpecifier(SecName)) {424    Diag(PragmaLoc, diag::err_pragma_section_invalid_for_target)425        << toString(std::move(E));426    CSec->Valid = false;427    return;428  }429 430  if (UnifySection(SecName, SectionFlags, PragmaLoc))431    return;432 433  CSec->Valid = true;434  CSec->SectionName = std::string(SecName);435  CSec->PragmaLocation = PragmaLoc;436}437 438void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,439                           StringRef SlotLabel, Expr *Alignment) {440  bool IsXLPragma = getLangOpts().XLPragmaPack;441  // XL pragma pack does not support identifier syntax.442  if (IsXLPragma && !SlotLabel.empty()) {443    Diag(PragmaLoc, diag::err_pragma_pack_identifer_not_supported);444    return;445  }446 447  const AlignPackInfo CurVal = AlignPackStack.CurrentValue;448 449  // If specified then alignment must be a "small" power of two.450  unsigned AlignmentVal = 0;451  AlignPackInfo::Mode ModeVal = CurVal.getAlignMode();452 453  if (Alignment) {454    std::optional<llvm::APSInt> Val;455    Val = Alignment->getIntegerConstantExpr(Context);456 457    // pack(0) is like pack(), which just works out since that is what458    // we use 0 for in PackAttr.459    if (Alignment->isTypeDependent() || !Val ||460        !(*Val == 0 || Val->isPowerOf2()) || Val->getZExtValue() > 16) {461      Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);462      return; // Ignore463    }464 465    if (IsXLPragma && *Val == 0) {466      // pack(0) does not work out with XL.467      Diag(PragmaLoc, diag::err_pragma_pack_invalid_alignment);468      return; // Ignore469    }470 471    AlignmentVal = (unsigned)Val->getZExtValue();472  }473 474  if (Action == Sema::PSK_Show) {475    // Show the current alignment, making sure to show the right value476    // for the default.477    // FIXME: This should come from the target.478    AlignmentVal = CurVal.IsPackSet() ? CurVal.getPackNumber() : 8;479    if (ModeVal == AlignPackInfo::Mac68k &&480        (IsXLPragma || CurVal.IsAlignAttr()))481      Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";482    else483      Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;484  }485 486  // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:487  // "#pragma pack(pop, identifier, n) is undefined"488  if (Action & Sema::PSK_Pop) {489    if (Alignment && !SlotLabel.empty())490      Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifier_and_alignment);491    if (AlignPackStack.Stack.empty()) {492      assert(CurVal.getAlignMode() == AlignPackInfo::Native &&493             "Empty pack stack can only be at Native alignment mode.");494      Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "pack" << "stack empty";495    }496  }497 498  AlignPackInfo Info(ModeVal, AlignmentVal, IsXLPragma);499 500  AlignPackStack.Act(PragmaLoc, Action, SlotLabel, Info);501}502 503bool Sema::ConstantFoldAttrArgs(const AttributeCommonInfo &CI,504                                MutableArrayRef<Expr *> Args) {505  llvm::SmallVector<PartialDiagnosticAt, 8> Notes;506  for (unsigned Idx = 0; Idx < Args.size(); Idx++) {507    Expr *&E = Args.begin()[Idx];508    assert(E && "error are handled before");509    if (E->isValueDependent() || E->isTypeDependent())510      continue;511 512    // FIXME: Use DefaultFunctionArrayLValueConversion() in place of the logic513    // that adds implicit casts here.514    if (E->getType()->isArrayType())515      E = ImpCastExprToType(E, Context.getPointerType(E->getType()),516                            clang::CK_ArrayToPointerDecay)517              .get();518    if (E->getType()->isFunctionType())519      E = ImplicitCastExpr::Create(Context,520                                   Context.getPointerType(E->getType()),521                                   clang::CK_FunctionToPointerDecay, E, nullptr,522                                   VK_PRValue, FPOptionsOverride());523    if (E->isLValue())524      E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(),525                                   clang::CK_LValueToRValue, E, nullptr,526                                   VK_PRValue, FPOptionsOverride());527 528    Expr::EvalResult Eval;529    Notes.clear();530    Eval.Diag = &Notes;531 532    bool Result = E->EvaluateAsConstantExpr(Eval, Context);533 534    /// Result means the expression can be folded to a constant.535    /// Note.empty() means the expression is a valid constant expression in the536    /// current language mode.537    if (!Result || !Notes.empty()) {538      Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type)539          << CI << (Idx + 1) << AANT_ArgumentConstantExpr;540      for (auto &Note : Notes)541        Diag(Note.first, Note.second);542      return false;543    }544    E = ConstantExpr::Create(Context, E, Eval.Val);545  }546 547  return true;548}549 550void Sema::DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind,551                                             SourceLocation IncludeLoc) {552  if (Kind == PragmaAlignPackDiagnoseKind::NonDefaultStateAtInclude) {553    SourceLocation PrevLocation = AlignPackStack.CurrentPragmaLocation;554    // Warn about non-default alignment at #includes (without redundant555    // warnings for the same directive in nested includes).556    // The warning is delayed until the end of the file to avoid warnings557    // for files that don't have any records that are affected by the modified558    // alignment.559    bool HasNonDefaultValue =560        AlignPackStack.hasValue() &&561        (AlignPackIncludeStack.empty() ||562         AlignPackIncludeStack.back().CurrentPragmaLocation != PrevLocation);563    AlignPackIncludeStack.push_back(564        {AlignPackStack.CurrentValue,565         AlignPackStack.hasValue() ? PrevLocation : SourceLocation(),566         HasNonDefaultValue, /*ShouldWarnOnInclude*/ false});567    return;568  }569 570  assert(Kind == PragmaAlignPackDiagnoseKind::ChangedStateAtExit &&571         "invalid kind");572  AlignPackIncludeState PrevAlignPackState =573      AlignPackIncludeStack.pop_back_val();574  // FIXME: AlignPackStack may contain both #pragma align and #pragma pack575  // information, diagnostics below might not be accurate if we have mixed576  // pragmas.577  if (PrevAlignPackState.ShouldWarnOnInclude) {578    // Emit the delayed non-default alignment at #include warning.579    Diag(IncludeLoc, diag::warn_pragma_pack_non_default_at_include);580    Diag(PrevAlignPackState.CurrentPragmaLocation, diag::note_pragma_pack_here);581  }582  // Warn about modified alignment after #includes.583  if (PrevAlignPackState.CurrentValue != AlignPackStack.CurrentValue) {584    Diag(IncludeLoc, diag::warn_pragma_pack_modified_after_include);585    Diag(AlignPackStack.CurrentPragmaLocation, diag::note_pragma_pack_here);586  }587}588 589void Sema::DiagnoseUnterminatedPragmaAlignPack() {590  if (AlignPackStack.Stack.empty())591    return;592  bool IsInnermost = true;593 594  // FIXME: AlignPackStack may contain both #pragma align and #pragma pack595  // information, diagnostics below might not be accurate if we have mixed596  // pragmas.597  for (const auto &StackSlot : llvm::reverse(AlignPackStack.Stack)) {598    Diag(StackSlot.PragmaPushLocation, diag::warn_pragma_pack_no_pop_eof);599    // The user might have already reset the alignment, so suggest replacing600    // the reset with a pop.601    if (IsInnermost &&602        AlignPackStack.CurrentValue == AlignPackStack.DefaultValue) {603      auto DB = Diag(AlignPackStack.CurrentPragmaLocation,604                     diag::note_pragma_pack_pop_instead_reset);605      SourceLocation FixItLoc =606          Lexer::findLocationAfterToken(AlignPackStack.CurrentPragmaLocation,607                                        tok::l_paren, SourceMgr, LangOpts,608                                        /*SkipTrailing=*/false);609      if (FixItLoc.isValid())610        DB << FixItHint::CreateInsertion(FixItLoc, "pop");611    }612    IsInnermost = false;613  }614}615 616void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {617  MSStructPragmaOn = (Kind == PMSST_ON);618}619 620void Sema::ActOnPragmaMSComment(SourceLocation CommentLoc,621                                PragmaMSCommentKind Kind, StringRef Arg) {622  auto *PCD = PragmaCommentDecl::Create(623      Context, Context.getTranslationUnitDecl(), CommentLoc, Kind, Arg);624  Context.getTranslationUnitDecl()->addDecl(PCD);625  Consumer.HandleTopLevelDecl(DeclGroupRef(PCD));626}627 628void Sema::ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,629                                     StringRef Value) {630  auto *PDMD = PragmaDetectMismatchDecl::Create(631      Context, Context.getTranslationUnitDecl(), Loc, Name, Value);632  Context.getTranslationUnitDecl()->addDecl(PDMD);633  Consumer.HandleTopLevelDecl(DeclGroupRef(PDMD));634}635 636void Sema::ActOnPragmaFPEvalMethod(SourceLocation Loc,637                                   LangOptions::FPEvalMethodKind Value) {638  FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();639  switch (Value) {640  default:641    llvm_unreachable("invalid pragma eval_method kind");642  case LangOptions::FEM_Source:643    NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Source);644    break;645  case LangOptions::FEM_Double:646    NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Double);647    break;648  case LangOptions::FEM_Extended:649    NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Extended);650    break;651  }652  if (getLangOpts().ApproxFunc)653    Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context) << 0 << 0;654  if (getLangOpts().AllowFPReassoc)655    Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context) << 0 << 1;656  if (getLangOpts().AllowRecip)657    Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context) << 0 << 2;658  FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);659  CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());660  PP.setCurrentFPEvalMethod(Loc, Value);661}662 663void Sema::ActOnPragmaFloatControl(SourceLocation Loc,664                                   PragmaMsStackAction Action,665                                   PragmaFloatControlKind Value) {666  FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();667  if ((Action == PSK_Push_Set || Action == PSK_Push || Action == PSK_Pop) &&668      !CurContext->getRedeclContext()->isFileContext()) {669    // Push and pop can only occur at file or namespace scope, or within a670    // language linkage declaration.671    Diag(Loc, diag::err_pragma_fc_pp_scope);672    return;673  }674  switch (Value) {675  default:676    llvm_unreachable("invalid pragma float_control kind");677  case PFC_Precise:678    NewFPFeatures.setFPPreciseEnabled(true);679    FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures);680    break;681  case PFC_NoPrecise:682    if (CurFPFeatures.getExceptionMode() == LangOptions::FPE_Strict)683      Diag(Loc, diag::err_pragma_fc_noprecise_requires_noexcept);684    else if (CurFPFeatures.getAllowFEnvAccess())685      Diag(Loc, diag::err_pragma_fc_noprecise_requires_nofenv);686    else687      NewFPFeatures.setFPPreciseEnabled(false);688    FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures);689    break;690  case PFC_Except:691    if (!isPreciseFPEnabled())692      Diag(Loc, diag::err_pragma_fc_except_requires_precise);693    else694      NewFPFeatures.setSpecifiedExceptionModeOverride(LangOptions::FPE_Strict);695    FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures);696    break;697  case PFC_NoExcept:698    NewFPFeatures.setSpecifiedExceptionModeOverride(LangOptions::FPE_Ignore);699    FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures);700    break;701  case PFC_Push:702    FpPragmaStack.Act(Loc, Sema::PSK_Push_Set, StringRef(), NewFPFeatures);703    break;704  case PFC_Pop:705    if (FpPragmaStack.Stack.empty()) {706      Diag(Loc, diag::warn_pragma_pop_failed) << "float_control"707                                              << "stack empty";708      return;709    }710    FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures);711    NewFPFeatures = FpPragmaStack.CurrentValue;712    break;713  }714  CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());715}716 717void Sema::ActOnPragmaMSPointersToMembers(718    LangOptions::PragmaMSPointersToMembersKind RepresentationMethod,719    SourceLocation PragmaLoc) {720  MSPointerToMemberRepresentationMethod = RepresentationMethod;721  ImplicitMSInheritanceAttrLoc = PragmaLoc;722}723 724void Sema::ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,725                                 SourceLocation PragmaLoc,726                                 MSVtorDispMode Mode) {727  if (Action & PSK_Pop && VtorDispStack.Stack.empty())728    Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "vtordisp"729                                                  << "stack empty";730  VtorDispStack.Act(PragmaLoc, Action, StringRef(), Mode);731}732 733template <>734void Sema::PragmaStack<Sema::AlignPackInfo>::Act(SourceLocation PragmaLocation,735                                                 PragmaMsStackAction Action,736                                                 llvm::StringRef StackSlotLabel,737                                                 AlignPackInfo Value) {738  if (Action == PSK_Reset) {739    CurrentValue = DefaultValue;740    CurrentPragmaLocation = PragmaLocation;741    return;742  }743  if (Action & PSK_Push)744    Stack.emplace_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation,745                            PragmaLocation));746  else if (Action & PSK_Pop) {747    if (!StackSlotLabel.empty()) {748      // If we've got a label, try to find it and jump there.749      auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) {750        return x.StackSlotLabel == StackSlotLabel;751      });752      // We found the label, so pop from there.753      if (I != Stack.rend()) {754        CurrentValue = I->Value;755        CurrentPragmaLocation = I->PragmaLocation;756        Stack.erase(std::prev(I.base()), Stack.end());757      }758    } else if (Value.IsXLStack() && Value.IsAlignAttr() &&759               CurrentValue.IsPackAttr()) {760      // XL '#pragma align(reset)' would pop the stack until761      // a current in effect pragma align is popped.762      auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) {763        return x.Value.IsAlignAttr();764      });765      // If we found pragma align so pop from there.766      if (I != Stack.rend()) {767        Stack.erase(std::prev(I.base()), Stack.end());768        if (Stack.empty()) {769          CurrentValue = DefaultValue;770          CurrentPragmaLocation = PragmaLocation;771        } else {772          CurrentValue = Stack.back().Value;773          CurrentPragmaLocation = Stack.back().PragmaLocation;774          Stack.pop_back();775        }776      }777    } else if (!Stack.empty()) {778      // xl '#pragma align' sets the baseline, and `#pragma pack` cannot pop779      // over the baseline.780      if (Value.IsXLStack() && Value.IsPackAttr() && CurrentValue.IsAlignAttr())781        return;782 783      // We don't have a label, just pop the last entry.784      CurrentValue = Stack.back().Value;785      CurrentPragmaLocation = Stack.back().PragmaLocation;786      Stack.pop_back();787    }788  }789  if (Action & PSK_Set) {790    CurrentValue = Value;791    CurrentPragmaLocation = PragmaLocation;792  }793}794 795bool Sema::UnifySection(StringRef SectionName, int SectionFlags,796                        NamedDecl *Decl) {797  SourceLocation PragmaLocation;798  if (auto A = Decl->getAttr<SectionAttr>())799    if (A->isImplicit())800      PragmaLocation = A->getLocation();801  auto [SectionIt, Inserted] = Context.SectionInfos.try_emplace(802      SectionName, Decl, PragmaLocation, SectionFlags);803  if (Inserted)804    return false;805  // A pre-declared section takes precedence w/o diagnostic.806  const auto &Section = SectionIt->second;807  if (Section.SectionFlags == SectionFlags ||808      ((SectionFlags & ASTContext::PSF_Implicit) &&809       !(Section.SectionFlags & ASTContext::PSF_Implicit)))810    return false;811  Diag(Decl->getLocation(), diag::err_section_conflict) << Decl << Section;812  if (Section.Decl)813    Diag(Section.Decl->getLocation(), diag::note_declared_at)814        << Section.Decl->getName();815  if (PragmaLocation.isValid())816    Diag(PragmaLocation, diag::note_pragma_entered_here);817  if (Section.PragmaSectionLocation.isValid())818    Diag(Section.PragmaSectionLocation, diag::note_pragma_entered_here);819  return true;820}821 822bool Sema::UnifySection(StringRef SectionName,823                        int SectionFlags,824                        SourceLocation PragmaSectionLocation) {825  auto SectionIt = Context.SectionInfos.find(SectionName);826  if (SectionIt != Context.SectionInfos.end()) {827    const auto &Section = SectionIt->second;828    if (Section.SectionFlags == SectionFlags)829      return false;830    if (!(Section.SectionFlags & ASTContext::PSF_Implicit)) {831      Diag(PragmaSectionLocation, diag::err_section_conflict)832          << "this" << Section;833      if (Section.Decl)834        Diag(Section.Decl->getLocation(), diag::note_declared_at)835            << Section.Decl->getName();836      if (Section.PragmaSectionLocation.isValid())837        Diag(Section.PragmaSectionLocation, diag::note_pragma_entered_here);838      return true;839    }840  }841  Context.SectionInfos[SectionName] =842      ASTContext::SectionInfo(nullptr, PragmaSectionLocation, SectionFlags);843  return false;844}845 846/// Called on well formed \#pragma bss_seg().847void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation,848                            PragmaMsStackAction Action,849                            llvm::StringRef StackSlotLabel,850                            StringLiteral *SegmentName,851                            llvm::StringRef PragmaName) {852  PragmaStack<StringLiteral *> *Stack =853    llvm::StringSwitch<PragmaStack<StringLiteral *> *>(PragmaName)854        .Case("data_seg", &DataSegStack)855        .Case("bss_seg", &BSSSegStack)856        .Case("const_seg", &ConstSegStack)857        .Case("code_seg", &CodeSegStack);858  if (Action & PSK_Pop && Stack->Stack.empty())859    Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName860        << "stack empty";861  if (SegmentName) {862    if (!checkSectionName(SegmentName->getBeginLoc(), SegmentName->getString()))863      return;864 865    if (SegmentName->getString() == ".drectve" &&866        Context.getTargetInfo().getCXXABI().isMicrosoft())867      Diag(PragmaLocation, diag::warn_attribute_section_drectve) << PragmaName;868  }869 870  Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName);871}872 873/// Called on well formed \#pragma strict_gs_check().874void Sema::ActOnPragmaMSStrictGuardStackCheck(SourceLocation PragmaLocation,875                                              PragmaMsStackAction Action,876                                              bool Value) {877  if (Action & PSK_Pop && StrictGuardStackCheckStack.Stack.empty())878    Diag(PragmaLocation, diag::warn_pragma_pop_failed) << "strict_gs_check"879                                                       << "stack empty";880 881  StrictGuardStackCheckStack.Act(PragmaLocation, Action, StringRef(), Value);882}883 884/// Called on well formed \#pragma bss_seg().885void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation,886                                int SectionFlags, StringLiteral *SegmentName) {887  UnifySection(SegmentName->getString(), SectionFlags, PragmaLocation);888}889 890void Sema::ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,891                                StringLiteral *SegmentName) {892  // There's no stack to maintain, so we just have a current section.  When we893  // see the default section, reset our current section back to null so we stop894  // tacking on unnecessary attributes.895  CurInitSeg = SegmentName->getString() == ".CRT$XCU" ? nullptr : SegmentName;896  CurInitSegLoc = PragmaLocation;897}898 899void Sema::ActOnPragmaMSAllocText(900    SourceLocation PragmaLocation, StringRef Section,901    const SmallVector<std::tuple<IdentifierInfo *, SourceLocation>>902        &Functions) {903  if (!CurContext->getRedeclContext()->isFileContext()) {904    Diag(PragmaLocation, diag::err_pragma_expected_file_scope) << "alloc_text";905    return;906  }907 908  for (auto &Function : Functions) {909    IdentifierInfo *II;910    SourceLocation Loc;911    std::tie(II, Loc) = Function;912 913    DeclarationName DN(II);914    NamedDecl *ND = LookupSingleName(TUScope, DN, Loc, LookupOrdinaryName);915    if (!ND) {916      Diag(Loc, diag::err_undeclared_use) << II->getName();917      return;918    }919 920    auto *FD = dyn_cast<FunctionDecl>(ND->getCanonicalDecl());921    if (!FD) {922      Diag(Loc, diag::err_pragma_alloc_text_not_function);923      return;924    }925 926    if (getLangOpts().CPlusPlus && !FD->isInExternCContext()) {927      Diag(Loc, diag::err_pragma_alloc_text_c_linkage);928      return;929    }930 931    FunctionToSectionMap[II->getName()] = std::make_tuple(Section, Loc);932  }933}934 935void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,936                             SourceLocation PragmaLoc) {937 938  IdentifierInfo *Name = IdTok.getIdentifierInfo();939  LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);940  LookupName(Lookup, curScope, /*AllowBuiltinCreation=*/true);941 942  if (Lookup.empty()) {943    Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)944      << Name << SourceRange(IdTok.getLocation());945    return;946  }947 948  VarDecl *VD = Lookup.getAsSingle<VarDecl>();949  if (!VD) {950    Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg)951      << Name << SourceRange(IdTok.getLocation());952    return;953  }954 955  // Warn if this was used before being marked unused.956  if (VD->isUsed())957    Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;958 959  VD->addAttr(UnusedAttr::CreateImplicit(Context, IdTok.getLocation(),960                                         UnusedAttr::GNU_unused));961}962 963namespace {964 965std::optional<attr::SubjectMatchRule>966getParentAttrMatcherRule(attr::SubjectMatchRule Rule) {967  using namespace attr;968  switch (Rule) {969  default:970    return std::nullopt;971#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract)972#define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated)    \973  case Value:                                                                  \974    return Parent;975#include "clang/Basic/AttrSubMatchRulesList.inc"976  }977}978 979bool isNegatedAttrMatcherSubRule(attr::SubjectMatchRule Rule) {980  using namespace attr;981  switch (Rule) {982  default:983    return false;984#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract)985#define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated)    \986  case Value:                                                                  \987    return IsNegated;988#include "clang/Basic/AttrSubMatchRulesList.inc"989  }990}991 992CharSourceRange replacementRangeForListElement(const Sema &S,993                                               SourceRange Range) {994  // Make sure that the ',' is removed as well.995  SourceLocation AfterCommaLoc = Lexer::findLocationAfterToken(996      Range.getEnd(), tok::comma, S.getSourceManager(), S.getLangOpts(),997      /*SkipTrailingWhitespaceAndNewLine=*/false);998  if (AfterCommaLoc.isValid())999    return CharSourceRange::getCharRange(Range.getBegin(), AfterCommaLoc);1000  else1001    return CharSourceRange::getTokenRange(Range);1002}1003 1004std::string1005attrMatcherRuleListToString(ArrayRef<attr::SubjectMatchRule> Rules) {1006  std::string Result;1007  llvm::raw_string_ostream OS(Result);1008  for (const auto &I : llvm::enumerate(Rules)) {1009    if (I.index())1010      OS << (I.index() == Rules.size() - 1 ? ", and " : ", ");1011    OS << "'" << attr::getSubjectMatchRuleSpelling(I.value()) << "'";1012  }1013  return Result;1014}1015 1016} // end anonymous namespace1017 1018void Sema::ActOnPragmaAttributeAttribute(1019    ParsedAttr &Attribute, SourceLocation PragmaLoc,1020    attr::ParsedSubjectMatchRuleSet Rules) {1021  Attribute.setIsPragmaClangAttribute();1022  SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules;1023  // Gather the subject match rules that are supported by the attribute.1024  SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4>1025      StrictSubjectMatchRuleSet;1026  Attribute.getMatchRules(LangOpts, StrictSubjectMatchRuleSet);1027 1028  // Figure out which subject matching rules are valid.1029  if (StrictSubjectMatchRuleSet.empty()) {1030    // Check for contradicting match rules. Contradicting match rules are1031    // either:1032    //  - a top-level rule and one of its sub-rules. E.g. variable and1033    //    variable(is_parameter).1034    //  - a sub-rule and a sibling that's negated. E.g.1035    //    variable(is_thread_local) and variable(unless(is_parameter))1036    llvm::SmallDenseMap<int, std::pair<int, SourceRange>, 2>1037        RulesToFirstSpecifiedNegatedSubRule;1038    for (const auto &Rule : Rules) {1039      attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first);1040      std::optional<attr::SubjectMatchRule> ParentRule =1041          getParentAttrMatcherRule(MatchRule);1042      if (!ParentRule)1043        continue;1044      auto It = Rules.find(*ParentRule);1045      if (It != Rules.end()) {1046        // A sub-rule contradicts a parent rule.1047        Diag(Rule.second.getBegin(),1048             diag::err_pragma_attribute_matcher_subrule_contradicts_rule)1049            << attr::getSubjectMatchRuleSpelling(MatchRule)1050            << attr::getSubjectMatchRuleSpelling(*ParentRule) << It->second1051            << FixItHint::CreateRemoval(1052                   replacementRangeForListElement(*this, Rule.second));1053        // Keep going without removing this rule as it won't change the set of1054        // declarations that receive the attribute.1055        continue;1056      }1057      if (isNegatedAttrMatcherSubRule(MatchRule))1058        RulesToFirstSpecifiedNegatedSubRule.insert(1059            std::make_pair(*ParentRule, Rule));1060    }1061    bool IgnoreNegatedSubRules = false;1062    for (const auto &Rule : Rules) {1063      attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first);1064      std::optional<attr::SubjectMatchRule> ParentRule =1065          getParentAttrMatcherRule(MatchRule);1066      if (!ParentRule)1067        continue;1068      auto It = RulesToFirstSpecifiedNegatedSubRule.find(*ParentRule);1069      if (It != RulesToFirstSpecifiedNegatedSubRule.end() &&1070          It->second != Rule) {1071        // Negated sub-rule contradicts another sub-rule.1072        Diag(1073            It->second.second.getBegin(),1074            diag::1075                err_pragma_attribute_matcher_negated_subrule_contradicts_subrule)1076            << attr::getSubjectMatchRuleSpelling(1077                   attr::SubjectMatchRule(It->second.first))1078            << attr::getSubjectMatchRuleSpelling(MatchRule) << Rule.second1079            << FixItHint::CreateRemoval(1080                   replacementRangeForListElement(*this, It->second.second));1081        // Keep going but ignore all of the negated sub-rules.1082        IgnoreNegatedSubRules = true;1083        RulesToFirstSpecifiedNegatedSubRule.erase(It);1084      }1085    }1086 1087    if (!IgnoreNegatedSubRules) {1088      for (const auto &Rule : Rules)1089        SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first));1090    } else {1091      for (const auto &Rule : Rules) {1092        if (!isNegatedAttrMatcherSubRule(attr::SubjectMatchRule(Rule.first)))1093          SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first));1094      }1095    }1096    Rules.clear();1097  } else {1098    // Each rule in Rules must be a strict subset of the attribute's1099    // SubjectMatch rules.  I.e. we're allowed to use1100    // `apply_to=variables(is_global)` on an attrubute with SubjectList<[Var]>,1101    // but should not allow `apply_to=variables` on an attribute which has1102    // `SubjectList<[GlobalVar]>`.1103    for (const auto &StrictRule : StrictSubjectMatchRuleSet) {1104      // First, check for exact match.1105      if (Rules.erase(StrictRule.first)) {1106        // Add the rule to the set of attribute receivers only if it's supported1107        // in the current language mode.1108        if (StrictRule.second)1109          SubjectMatchRules.push_back(StrictRule.first);1110      }1111    }1112    // Check remaining rules for subset matches.1113    auto RulesToCheck = Rules;1114    for (const auto &Rule : RulesToCheck) {1115      attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first);1116      if (auto ParentRule = getParentAttrMatcherRule(MatchRule)) {1117        if (llvm::any_of(StrictSubjectMatchRuleSet,1118                         [ParentRule](const auto &StrictRule) {1119                           return StrictRule.first == *ParentRule &&1120                                  StrictRule.second; // IsEnabled1121                         })) {1122          SubjectMatchRules.push_back(MatchRule);1123          Rules.erase(MatchRule);1124        }1125      }1126    }1127  }1128 1129  if (!Rules.empty()) {1130    auto Diagnostic =1131        Diag(PragmaLoc, diag::err_pragma_attribute_invalid_matchers)1132        << Attribute;1133    SmallVector<attr::SubjectMatchRule, 2> ExtraRules;1134    for (const auto &Rule : Rules) {1135      ExtraRules.push_back(attr::SubjectMatchRule(Rule.first));1136      Diagnostic << FixItHint::CreateRemoval(1137          replacementRangeForListElement(*this, Rule.second));1138    }1139    Diagnostic << attrMatcherRuleListToString(ExtraRules);1140  }1141 1142  if (PragmaAttributeStack.empty()) {1143    Diag(PragmaLoc, diag::err_pragma_attr_attr_no_push);1144    return;1145  }1146 1147  PragmaAttributeStack.back().Entries.push_back(1148      {PragmaLoc, &Attribute, std::move(SubjectMatchRules), /*IsUsed=*/false});1149}1150 1151void Sema::ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc,1152                                         const IdentifierInfo *Namespace) {1153  PragmaAttributeStack.emplace_back();1154  PragmaAttributeStack.back().Loc = PragmaLoc;1155  PragmaAttributeStack.back().Namespace = Namespace;1156}1157 1158void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc,1159                                   const IdentifierInfo *Namespace) {1160  if (PragmaAttributeStack.empty()) {1161    Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch) << 1;1162    return;1163  }1164 1165  // Dig back through the stack trying to find the most recently pushed group1166  // that in Namespace. Note that this works fine if no namespace is present,1167  // think of push/pops without namespaces as having an implicit "nullptr"1168  // namespace.1169  for (size_t Index = PragmaAttributeStack.size(); Index;) {1170    --Index;1171    if (PragmaAttributeStack[Index].Namespace == Namespace) {1172      for (const PragmaAttributeEntry &Entry :1173           PragmaAttributeStack[Index].Entries) {1174        if (!Entry.IsUsed) {1175          assert(Entry.Attribute && "Expected an attribute");1176          Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused)1177              << *Entry.Attribute;1178          Diag(PragmaLoc, diag::note_pragma_attribute_region_ends_here);1179        }1180      }1181      PragmaAttributeStack.erase(PragmaAttributeStack.begin() + Index);1182      return;1183    }1184  }1185 1186  if (Namespace)1187    Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch)1188        << 0 << Namespace->getName();1189  else1190    Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch) << 1;1191}1192 1193void Sema::AddPragmaAttributes(Scope *S, Decl *D) {1194  if (PragmaAttributeStack.empty())1195    return;1196 1197  if (const auto *P = dyn_cast<ParmVarDecl>(D))1198    if (P->getType()->isVoidType())1199      return;1200 1201  for (auto &Group : PragmaAttributeStack) {1202    for (auto &Entry : Group.Entries) {1203      ParsedAttr *Attribute = Entry.Attribute;1204      assert(Attribute && "Expected an attribute");1205      assert(Attribute->isPragmaClangAttribute() &&1206             "expected #pragma clang attribute");1207 1208      // Ensure that the attribute can be applied to the given declaration.1209      bool Applies = false;1210      for (const auto &Rule : Entry.MatchRules) {1211        if (Attribute->appliesToDecl(D, Rule)) {1212          Applies = true;1213          break;1214        }1215      }1216      if (!Applies)1217        continue;1218      Entry.IsUsed = true;1219      PragmaAttributeCurrentTargetDecl = D;1220      ParsedAttributesView Attrs;1221      Attrs.addAtEnd(Attribute);1222      ProcessDeclAttributeList(S, D, Attrs);1223      PragmaAttributeCurrentTargetDecl = nullptr;1224    }1225  }1226}1227 1228void Sema::PrintPragmaAttributeInstantiationPoint(1229    InstantiationContextDiagFuncRef DiagFunc) {1230  assert(PragmaAttributeCurrentTargetDecl && "Expected an active declaration");1231  DiagFunc(PragmaAttributeCurrentTargetDecl->getBeginLoc(),1232           PDiag(diag::note_pragma_attribute_applied_decl_here));1233}1234 1235void Sema::DiagnosePrecisionLossInComplexDivision() {1236  for (auto &[Type, Num] : ExcessPrecisionNotSatisfied) {1237    assert(LocationOfExcessPrecisionNotSatisfied.isValid() &&1238           "expected a valid source location");1239    Diag(LocationOfExcessPrecisionNotSatisfied,1240         diag::warn_excess_precision_not_supported)1241        << static_cast<bool>(Num);1242  }1243}1244 1245void Sema::DiagnoseUnterminatedPragmaAttribute() {1246  if (PragmaAttributeStack.empty())1247    return;1248  Diag(PragmaAttributeStack.back().Loc, diag::err_pragma_attribute_no_pop_eof);1249}1250 1251void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) {1252  if(On)1253    OptimizeOffPragmaLocation = SourceLocation();1254  else1255    OptimizeOffPragmaLocation = PragmaLoc;1256}1257 1258void Sema::ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn) {1259  if (!CurContext->getRedeclContext()->isFileContext()) {1260    Diag(Loc, diag::err_pragma_expected_file_scope) << "optimize";1261    return;1262  }1263 1264  MSPragmaOptimizeIsOn = IsOn;1265}1266 1267void Sema::ActOnPragmaMSFunction(1268    SourceLocation Loc, const llvm::SmallVectorImpl<StringRef> &NoBuiltins) {1269  if (!CurContext->getRedeclContext()->isFileContext()) {1270    Diag(Loc, diag::err_pragma_expected_file_scope) << "function";1271    return;1272  }1273 1274  MSFunctionNoBuiltins.insert_range(NoBuiltins);1275}1276 1277void Sema::AddRangeBasedOptnone(FunctionDecl *FD) {1278  // In the future, check other pragmas if they're implemented (e.g. pragma1279  // optimize 0 will probably map to this functionality too).1280  if(OptimizeOffPragmaLocation.isValid())1281    AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation);1282}1283 1284void Sema::AddSectionMSAllocText(FunctionDecl *FD) {1285  if (!FD->getIdentifier())1286    return;1287 1288  StringRef Name = FD->getName();1289  auto It = FunctionToSectionMap.find(Name);1290  if (It != FunctionToSectionMap.end()) {1291    StringRef Section;1292    SourceLocation Loc;1293    std::tie(Section, Loc) = It->second;1294 1295    if (!FD->hasAttr<SectionAttr>())1296      FD->addAttr(SectionAttr::CreateImplicit(Context, Section));1297  }1298}1299 1300void Sema::ModifyFnAttributesMSPragmaOptimize(FunctionDecl *FD) {1301  // Don't modify the function attributes if it's "on". "on" resets the1302  // optimizations to the ones listed on the command line1303  if (!MSPragmaOptimizeIsOn)1304    AddOptnoneAttributeIfNoConflicts(FD, FD->getBeginLoc());1305}1306 1307void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD,1308                                            SourceLocation Loc) {1309  // Don't add a conflicting attribute. No diagnostic is needed.1310  if (FD->hasAttr<MinSizeAttr>() || FD->hasAttr<AlwaysInlineAttr>())1311    return;1312 1313  // Add attributes only if required. Optnone requires noinline as well, but if1314  // either is already present then don't bother adding them.1315  if (!FD->hasAttr<OptimizeNoneAttr>())1316    FD->addAttr(OptimizeNoneAttr::CreateImplicit(Context, Loc));1317  if (!FD->hasAttr<NoInlineAttr>())1318    FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc));1319}1320 1321void Sema::AddImplicitMSFunctionNoBuiltinAttr(FunctionDecl *FD) {1322  if (FD->isDeleted() || FD->isDefaulted())1323    return;1324  SmallVector<StringRef> V(MSFunctionNoBuiltins.begin(),1325                           MSFunctionNoBuiltins.end());1326  if (!MSFunctionNoBuiltins.empty())1327    FD->addAttr(NoBuiltinAttr::CreateImplicit(Context, V.data(), V.size()));1328}1329 1330typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;1331enum : unsigned { NoVisibility = ~0U };1332 1333void Sema::AddPushedVisibilityAttribute(Decl *D) {1334  if (!VisContext)1335    return;1336 1337  NamedDecl *ND = dyn_cast<NamedDecl>(D);1338  if (ND && ND->getExplicitVisibility(NamedDecl::VisibilityForValue))1339    return;1340 1341  VisStack *Stack = static_cast<VisStack*>(VisContext);1342  unsigned rawType = Stack->back().first;1343  if (rawType == NoVisibility) return;1344 1345  VisibilityAttr::VisibilityType type1346    = (VisibilityAttr::VisibilityType) rawType;1347  SourceLocation loc = Stack->back().second;1348 1349  D->addAttr(VisibilityAttr::CreateImplicit(Context, type, loc));1350}1351 1352void Sema::FreeVisContext() {1353  delete static_cast<VisStack*>(VisContext);1354  VisContext = nullptr;1355}1356 1357static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) {1358  // Put visibility on stack.1359  if (!S.VisContext)1360    S.VisContext = new VisStack;1361 1362  VisStack *Stack = static_cast<VisStack*>(S.VisContext);1363  Stack->push_back(std::make_pair(type, loc));1364}1365 1366void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType,1367                                 SourceLocation PragmaLoc) {1368  if (VisType) {1369    // Compute visibility to use.1370    VisibilityAttr::VisibilityType T;1371    if (!VisibilityAttr::ConvertStrToVisibilityType(VisType->getName(), T)) {1372      Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << VisType;1373      return;1374    }1375    PushPragmaVisibility(*this, T, PragmaLoc);1376  } else {1377    PopPragmaVisibility(false, PragmaLoc);1378  }1379}1380 1381void Sema::ActOnPragmaFPContract(SourceLocation Loc,1382                                 LangOptions::FPModeKind FPC) {1383  FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();1384  switch (FPC) {1385  case LangOptions::FPM_On:1386    NewFPFeatures.setAllowFPContractWithinStatement();1387    break;1388  case LangOptions::FPM_Fast:1389  case LangOptions::FPM_FastHonorPragmas:1390    NewFPFeatures.setAllowFPContractAcrossStatement();1391    break;1392  case LangOptions::FPM_Off:1393    NewFPFeatures.setDisallowFPContract();1394    break;1395  }1396  FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(), NewFPFeatures);1397  CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());1398}1399 1400void Sema::ActOnPragmaFPValueChangingOption(SourceLocation Loc,1401                                            PragmaFPKind Kind, bool IsEnabled) {1402  if (IsEnabled) {1403    // For value unsafe context, combining this pragma with eval method1404    // setting is not recommended. See comment in function FixupInvocation#506.1405    int Reason = -1;1406    if (getLangOpts().getFPEvalMethod() != LangOptions::FEM_UnsetOnCommandLine)1407      // Eval method set using the option 'ffp-eval-method'.1408      Reason = 1;1409    if (PP.getLastFPEvalPragmaLocation().isValid())1410      // Eval method set using the '#pragma clang fp eval_method'.1411      // We could have both an option and a pragma used to the set the eval1412      // method. The pragma overrides the option in the command line. The Reason1413      // of the diagnostic is overriden too.1414      Reason = 0;1415    if (Reason != -1)1416      Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context)1417          << Reason << (Kind == PFK_Reassociate ? 4 : 5);1418  }1419 1420  FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();1421  switch (Kind) {1422  case PFK_Reassociate:1423    NewFPFeatures.setAllowFPReassociateOverride(IsEnabled);1424    break;1425  case PFK_Reciprocal:1426    NewFPFeatures.setAllowReciprocalOverride(IsEnabled);1427    break;1428  default:1429    llvm_unreachable("unhandled value changing pragma fp");1430  }1431 1432  FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);1433  CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());1434}1435 1436void Sema::ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode FPR) {1437  FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();1438  NewFPFeatures.setConstRoundingModeOverride(FPR);1439  FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);1440  CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());1441}1442 1443void Sema::setExceptionMode(SourceLocation Loc,1444                            LangOptions::FPExceptionModeKind FPE) {1445  FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();1446  NewFPFeatures.setSpecifiedExceptionModeOverride(FPE);1447  FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);1448  CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());1449}1450 1451void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) {1452  FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();1453  if (IsEnabled) {1454    // Verify Microsoft restriction:1455    // You can't enable fenv_access unless precise semantics are enabled.1456    // Precise semantics can be enabled either by the float_control1457    // pragma, or by using the /fp:precise or /fp:strict compiler options1458    if (!isPreciseFPEnabled())1459      Diag(Loc, diag::err_pragma_fenv_requires_precise);1460  }1461  NewFPFeatures.setAllowFEnvAccessOverride(IsEnabled);1462  NewFPFeatures.setRoundingMathOverride(IsEnabled);1463  FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);1464  CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());1465}1466 1467void Sema::ActOnPragmaCXLimitedRange(SourceLocation Loc,1468                                     LangOptions::ComplexRangeKind Range) {1469  FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();1470  NewFPFeatures.setComplexRangeOverride(Range);1471  FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);1472  CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());1473}1474 1475void Sema::ActOnPragmaFPExceptions(SourceLocation Loc,1476                                   LangOptions::FPExceptionModeKind FPE) {1477  setExceptionMode(Loc, FPE);1478}1479 1480void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,1481                                       SourceLocation Loc) {1482  // Visibility calculations will consider the namespace's visibility.1483  // Here we just want to note that we're in a visibility context1484  // which overrides any enclosing #pragma context, but doesn't itself1485  // contribute visibility.1486  PushPragmaVisibility(*this, NoVisibility, Loc);1487}1488 1489void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) {1490  if (!VisContext) {1491    Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);1492    return;1493  }1494 1495  // Pop visibility from stack1496  VisStack *Stack = static_cast<VisStack*>(VisContext);1497 1498  const std::pair<unsigned, SourceLocation> *Back = &Stack->back();1499  bool StartsWithPragma = Back->first != NoVisibility;1500  if (StartsWithPragma && IsNamespaceEnd) {1501    Diag(Back->second, diag::err_pragma_push_visibility_mismatch);1502    Diag(EndLoc, diag::note_surrounding_namespace_ends_here);1503 1504    // For better error recovery, eat all pushes inside the namespace.1505    do {1506      Stack->pop_back();1507      Back = &Stack->back();1508      StartsWithPragma = Back->first != NoVisibility;1509    } while (StartsWithPragma);1510  } else if (!StartsWithPragma && !IsNamespaceEnd) {1511    Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);1512    Diag(Back->second, diag::note_surrounding_namespace_starts_here);1513    return;1514  }1515 1516  Stack->pop_back();1517  // To simplify the implementation, never keep around an empty stack.1518  if (Stack->empty())1519    FreeVisContext();1520}1521 1522template <typename Ty>1523static bool checkCommonAttributeFeatures(Sema &S, const Ty *Node,1524                                         const ParsedAttr &A,1525                                         bool SkipArgCountCheck) {1526  // Several attributes carry different semantics than the parsing requires, so1527  // those are opted out of the common argument checks.1528  //1529  // We also bail on unknown and ignored attributes because those are handled1530  // as part of the target-specific handling logic.1531  if (A.getKind() == ParsedAttr::UnknownAttribute)1532    return false;1533  // Check whether the attribute requires specific language extensions to be1534  // enabled.1535  if (!A.diagnoseLangOpts(S))1536    return true;1537  // Check whether the attribute appertains to the given subject.1538  if (!A.diagnoseAppertainsTo(S, Node))1539    return true;1540  // Check whether the attribute is mutually exclusive with other attributes1541  // that have already been applied to the declaration.1542  if (!A.diagnoseMutualExclusion(S, Node))1543    return true;1544  // Check whether the attribute exists in the target architecture.1545  if (S.CheckAttrTarget(A))1546    return true;1547 1548  if (A.hasCustomParsing())1549    return false;1550 1551  if (!SkipArgCountCheck) {1552    if (A.getMinArgs() == A.getMaxArgs()) {1553      // If there are no optional arguments, then checking for the argument1554      // count is trivial.1555      if (!A.checkExactlyNumArgs(S, A.getMinArgs()))1556        return true;1557    } else {1558      // There are optional arguments, so checking is slightly more involved.1559      if (A.getMinArgs() && !A.checkAtLeastNumArgs(S, A.getMinArgs()))1560        return true;1561      else if (!A.hasVariadicArg() && A.getMaxArgs() &&1562               !A.checkAtMostNumArgs(S, A.getMaxArgs()))1563        return true;1564    }1565  }1566 1567  return false;1568}1569 1570bool Sema::checkCommonAttributeFeatures(const Decl *D, const ParsedAttr &A,1571                                        bool SkipArgCountCheck) {1572  return ::checkCommonAttributeFeatures(*this, D, A, SkipArgCountCheck);1573}1574bool Sema::checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A,1575                                        bool SkipArgCountCheck) {1576  return ::checkCommonAttributeFeatures(*this, S, A, SkipArgCountCheck);1577}1578