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