10b57cec5SDimitry Andric //===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements semantic analysis for non-trivial attributes and 100b57cec5SDimitry Andric // pragmas. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "clang/AST/ASTConsumer.h" 150b57cec5SDimitry Andric #include "clang/AST/Attr.h" 160b57cec5SDimitry Andric #include "clang/AST/Expr.h" 170b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 180b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h" 190b57cec5SDimitry Andric #include "clang/Sema/Lookup.h" 200b57cec5SDimitry Andric #include "clang/Sema/SemaInternal.h" 21bdd1243dSDimitry Andric #include <optional> 220b57cec5SDimitry Andric using namespace clang; 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 250b57cec5SDimitry Andric // Pragma 'pack' and 'options align' 260b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric Sema::PragmaStackSentinelRAII::PragmaStackSentinelRAII(Sema &S, 290b57cec5SDimitry Andric StringRef SlotLabel, 300b57cec5SDimitry Andric bool ShouldAct) 310b57cec5SDimitry Andric : S(S), SlotLabel(SlotLabel), ShouldAct(ShouldAct) { 320b57cec5SDimitry Andric if (ShouldAct) { 330b57cec5SDimitry Andric S.VtorDispStack.SentinelAction(PSK_Push, SlotLabel); 340b57cec5SDimitry Andric S.DataSegStack.SentinelAction(PSK_Push, SlotLabel); 350b57cec5SDimitry Andric S.BSSSegStack.SentinelAction(PSK_Push, SlotLabel); 360b57cec5SDimitry Andric S.ConstSegStack.SentinelAction(PSK_Push, SlotLabel); 370b57cec5SDimitry Andric S.CodeSegStack.SentinelAction(PSK_Push, SlotLabel); 38bdd1243dSDimitry Andric S.StrictGuardStackCheckStack.SentinelAction(PSK_Push, SlotLabel); 390b57cec5SDimitry Andric } 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric Sema::PragmaStackSentinelRAII::~PragmaStackSentinelRAII() { 430b57cec5SDimitry Andric if (ShouldAct) { 440b57cec5SDimitry Andric S.VtorDispStack.SentinelAction(PSK_Pop, SlotLabel); 450b57cec5SDimitry Andric S.DataSegStack.SentinelAction(PSK_Pop, SlotLabel); 460b57cec5SDimitry Andric S.BSSSegStack.SentinelAction(PSK_Pop, SlotLabel); 470b57cec5SDimitry Andric S.ConstSegStack.SentinelAction(PSK_Pop, SlotLabel); 480b57cec5SDimitry Andric S.CodeSegStack.SentinelAction(PSK_Pop, SlotLabel); 49bdd1243dSDimitry Andric S.StrictGuardStackCheckStack.SentinelAction(PSK_Pop, SlotLabel); 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) { 54e8d8bef9SDimitry Andric AlignPackInfo InfoVal = AlignPackStack.CurrentValue; 55e8d8bef9SDimitry Andric AlignPackInfo::Mode M = InfoVal.getAlignMode(); 56e8d8bef9SDimitry Andric bool IsPackSet = InfoVal.IsPackSet(); 57e8d8bef9SDimitry Andric bool IsXLPragma = getLangOpts().XLPragmaPack; 58e8d8bef9SDimitry Andric 59e8d8bef9SDimitry Andric // If we are not under mac68k/natural alignment mode and also there is no pack 60e8d8bef9SDimitry Andric // value, we don't need any attributes. 61e8d8bef9SDimitry Andric if (!IsPackSet && M != AlignPackInfo::Mac68k && M != AlignPackInfo::Natural) 620b57cec5SDimitry Andric return; 630b57cec5SDimitry Andric 64e8d8bef9SDimitry Andric if (M == AlignPackInfo::Mac68k && (IsXLPragma || InfoVal.IsAlignAttr())) { 650b57cec5SDimitry Andric RD->addAttr(AlignMac68kAttr::CreateImplicit(Context)); 66e8d8bef9SDimitry Andric } else if (IsPackSet) { 67e8d8bef9SDimitry Andric // Check to see if we need a max field alignment attribute. 68e8d8bef9SDimitry Andric RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit( 69e8d8bef9SDimitry Andric Context, InfoVal.getPackNumber() * 8)); 700b57cec5SDimitry Andric } 71e8d8bef9SDimitry Andric 72e8d8bef9SDimitry Andric if (IsXLPragma && M == AlignPackInfo::Natural) 73e8d8bef9SDimitry Andric RD->addAttr(AlignNaturalAttr::CreateImplicit(Context)); 74e8d8bef9SDimitry Andric 75e8d8bef9SDimitry Andric if (AlignPackIncludeStack.empty()) 760b57cec5SDimitry Andric return; 77e8d8bef9SDimitry Andric // The #pragma align/pack affected a record in an included file, so Clang 78e8d8bef9SDimitry Andric // should warn when that pragma was written in a file that included the 79e8d8bef9SDimitry Andric // included file. 80e8d8bef9SDimitry Andric for (auto &AlignPackedInclude : llvm::reverse(AlignPackIncludeStack)) { 81e8d8bef9SDimitry Andric if (AlignPackedInclude.CurrentPragmaLocation != 82e8d8bef9SDimitry Andric AlignPackStack.CurrentPragmaLocation) 830b57cec5SDimitry Andric break; 84e8d8bef9SDimitry Andric if (AlignPackedInclude.HasNonDefaultValue) 85e8d8bef9SDimitry Andric AlignPackedInclude.ShouldWarnOnInclude = true; 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) { 900b57cec5SDimitry Andric if (MSStructPragmaOn) 910b57cec5SDimitry Andric RD->addAttr(MSStructAttr::CreateImplicit(Context)); 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric // FIXME: We should merge AddAlignmentAttributesForRecord with 940b57cec5SDimitry Andric // AddMsStructLayoutForRecord into AddPragmaAttributesForRecord, which takes 950b57cec5SDimitry Andric // all active pragmas and applies them as attributes to class definitions. 96480093f4SDimitry Andric if (VtorDispStack.CurrentValue != getLangOpts().getVtorDispMode()) 97480093f4SDimitry Andric RD->addAttr(MSVtorDispAttr::CreateImplicit( 98480093f4SDimitry Andric Context, unsigned(VtorDispStack.CurrentValue))); 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 101a7dea167SDimitry Andric template <typename Attribute> 102a7dea167SDimitry Andric static void addGslOwnerPointerAttributeIfNotExisting(ASTContext &Context, 103a7dea167SDimitry Andric CXXRecordDecl *Record) { 104a7dea167SDimitry Andric if (Record->hasAttr<OwnerAttr>() || Record->hasAttr<PointerAttr>()) 105a7dea167SDimitry Andric return; 106a7dea167SDimitry Andric 107a7dea167SDimitry Andric for (Decl *Redecl : Record->redecls()) 108a7dea167SDimitry Andric Redecl->addAttr(Attribute::CreateImplicit(Context, /*DerefType=*/nullptr)); 109a7dea167SDimitry Andric } 110a7dea167SDimitry Andric 111a7dea167SDimitry Andric void Sema::inferGslPointerAttribute(NamedDecl *ND, 112a7dea167SDimitry Andric CXXRecordDecl *UnderlyingRecord) { 113a7dea167SDimitry Andric if (!UnderlyingRecord) 114a7dea167SDimitry Andric return; 115a7dea167SDimitry Andric 116a7dea167SDimitry Andric const auto *Parent = dyn_cast<CXXRecordDecl>(ND->getDeclContext()); 117a7dea167SDimitry Andric if (!Parent) 118a7dea167SDimitry Andric return; 119a7dea167SDimitry Andric 120*0fca6ea1SDimitry Andric static const llvm::StringSet<> Containers{ 121a7dea167SDimitry Andric "array", 122a7dea167SDimitry Andric "basic_string", 123a7dea167SDimitry Andric "deque", 124a7dea167SDimitry Andric "forward_list", 125a7dea167SDimitry Andric "vector", 126a7dea167SDimitry Andric "list", 127a7dea167SDimitry Andric "map", 128a7dea167SDimitry Andric "multiset", 129a7dea167SDimitry Andric "multimap", 130a7dea167SDimitry Andric "priority_queue", 131a7dea167SDimitry Andric "queue", 132a7dea167SDimitry Andric "set", 133a7dea167SDimitry Andric "stack", 134a7dea167SDimitry Andric "unordered_set", 135a7dea167SDimitry Andric "unordered_map", 136a7dea167SDimitry Andric "unordered_multiset", 137a7dea167SDimitry Andric "unordered_multimap", 138a7dea167SDimitry Andric }; 139a7dea167SDimitry Andric 140*0fca6ea1SDimitry Andric static const llvm::StringSet<> Iterators{"iterator", "const_iterator", 141a7dea167SDimitry Andric "reverse_iterator", 142a7dea167SDimitry Andric "const_reverse_iterator"}; 143a7dea167SDimitry Andric 144a7dea167SDimitry Andric if (Parent->isInStdNamespace() && Iterators.count(ND->getName()) && 145a7dea167SDimitry Andric Containers.count(Parent->getName())) 146a7dea167SDimitry Andric addGslOwnerPointerAttributeIfNotExisting<PointerAttr>(Context, 147a7dea167SDimitry Andric UnderlyingRecord); 148a7dea167SDimitry Andric } 149a7dea167SDimitry Andric 150a7dea167SDimitry Andric void Sema::inferGslPointerAttribute(TypedefNameDecl *TD) { 151a7dea167SDimitry Andric 152a7dea167SDimitry Andric QualType Canonical = TD->getUnderlyingType().getCanonicalType(); 153a7dea167SDimitry Andric 154a7dea167SDimitry Andric CXXRecordDecl *RD = Canonical->getAsCXXRecordDecl(); 155a7dea167SDimitry Andric if (!RD) { 156a7dea167SDimitry Andric if (auto *TST = 157a7dea167SDimitry Andric dyn_cast<TemplateSpecializationType>(Canonical.getTypePtr())) { 158a7dea167SDimitry Andric 159a7dea167SDimitry Andric RD = dyn_cast_or_null<CXXRecordDecl>( 160a7dea167SDimitry Andric TST->getTemplateName().getAsTemplateDecl()->getTemplatedDecl()); 161a7dea167SDimitry Andric } 162a7dea167SDimitry Andric } 163a7dea167SDimitry Andric 164a7dea167SDimitry Andric inferGslPointerAttribute(TD, RD); 165a7dea167SDimitry Andric } 166a7dea167SDimitry Andric 167a7dea167SDimitry Andric void Sema::inferGslOwnerPointerAttribute(CXXRecordDecl *Record) { 168*0fca6ea1SDimitry Andric static const llvm::StringSet<> StdOwners{ 169a7dea167SDimitry Andric "any", 170a7dea167SDimitry Andric "array", 171a7dea167SDimitry Andric "basic_regex", 172a7dea167SDimitry Andric "basic_string", 173a7dea167SDimitry Andric "deque", 174a7dea167SDimitry Andric "forward_list", 175a7dea167SDimitry Andric "vector", 176a7dea167SDimitry Andric "list", 177a7dea167SDimitry Andric "map", 178a7dea167SDimitry Andric "multiset", 179a7dea167SDimitry Andric "multimap", 180a7dea167SDimitry Andric "optional", 181a7dea167SDimitry Andric "priority_queue", 182a7dea167SDimitry Andric "queue", 183a7dea167SDimitry Andric "set", 184a7dea167SDimitry Andric "stack", 185a7dea167SDimitry Andric "unique_ptr", 186a7dea167SDimitry Andric "unordered_set", 187a7dea167SDimitry Andric "unordered_map", 188a7dea167SDimitry Andric "unordered_multiset", 189a7dea167SDimitry Andric "unordered_multimap", 190a7dea167SDimitry Andric "variant", 191a7dea167SDimitry Andric }; 192*0fca6ea1SDimitry Andric static const llvm::StringSet<> StdPointers{ 193a7dea167SDimitry Andric "basic_string_view", 194a7dea167SDimitry Andric "reference_wrapper", 195a7dea167SDimitry Andric "regex_iterator", 196*0fca6ea1SDimitry Andric "span", 197a7dea167SDimitry Andric }; 198a7dea167SDimitry Andric 199a7dea167SDimitry Andric if (!Record->getIdentifier()) 200a7dea167SDimitry Andric return; 201a7dea167SDimitry Andric 202a7dea167SDimitry Andric // Handle classes that directly appear in std namespace. 203a7dea167SDimitry Andric if (Record->isInStdNamespace()) { 204a7dea167SDimitry Andric if (Record->hasAttr<OwnerAttr>() || Record->hasAttr<PointerAttr>()) 205a7dea167SDimitry Andric return; 206a7dea167SDimitry Andric 207a7dea167SDimitry Andric if (StdOwners.count(Record->getName())) 208a7dea167SDimitry Andric addGslOwnerPointerAttributeIfNotExisting<OwnerAttr>(Context, Record); 209a7dea167SDimitry Andric else if (StdPointers.count(Record->getName())) 210a7dea167SDimitry Andric addGslOwnerPointerAttributeIfNotExisting<PointerAttr>(Context, Record); 211a7dea167SDimitry Andric 212a7dea167SDimitry Andric return; 213a7dea167SDimitry Andric } 214a7dea167SDimitry Andric 215a7dea167SDimitry Andric // Handle nested classes that could be a gsl::Pointer. 216a7dea167SDimitry Andric inferGslPointerAttribute(Record, Record); 217a7dea167SDimitry Andric } 218a7dea167SDimitry Andric 219*0fca6ea1SDimitry Andric void Sema::inferNullableClassAttribute(CXXRecordDecl *CRD) { 220*0fca6ea1SDimitry Andric static const llvm::StringSet<> Nullable{ 221*0fca6ea1SDimitry Andric "auto_ptr", "shared_ptr", "unique_ptr", "exception_ptr", 222*0fca6ea1SDimitry Andric "coroutine_handle", "function", "move_only_function", 223*0fca6ea1SDimitry Andric }; 224*0fca6ea1SDimitry Andric 225*0fca6ea1SDimitry Andric if (CRD->isInStdNamespace() && Nullable.count(CRD->getName()) && 226*0fca6ea1SDimitry Andric !CRD->hasAttr<TypeNullableAttr>()) 227*0fca6ea1SDimitry Andric for (Decl *Redecl : CRD->redecls()) 228*0fca6ea1SDimitry Andric Redecl->addAttr(TypeNullableAttr::CreateImplicit(Context)); 229*0fca6ea1SDimitry Andric } 230*0fca6ea1SDimitry Andric 2310b57cec5SDimitry Andric void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, 2320b57cec5SDimitry Andric SourceLocation PragmaLoc) { 2330b57cec5SDimitry Andric PragmaMsStackAction Action = Sema::PSK_Reset; 234e8d8bef9SDimitry Andric AlignPackInfo::Mode ModeVal = AlignPackInfo::Native; 235e8d8bef9SDimitry Andric 2360b57cec5SDimitry Andric switch (Kind) { 237e8d8bef9SDimitry Andric // For most of the platforms we support, native and natural are the same. 238e8d8bef9SDimitry Andric // With XL, native is the same as power, natural means something else. 2390b57cec5SDimitry Andric case POAK_Native: 2400b57cec5SDimitry Andric case POAK_Power: 241e8d8bef9SDimitry Andric Action = Sema::PSK_Push_Set; 242e8d8bef9SDimitry Andric break; 2430b57cec5SDimitry Andric case POAK_Natural: 2440b57cec5SDimitry Andric Action = Sema::PSK_Push_Set; 245e8d8bef9SDimitry Andric ModeVal = AlignPackInfo::Natural; 2460b57cec5SDimitry Andric break; 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric // Note that '#pragma options align=packed' is not equivalent to attribute 2490b57cec5SDimitry Andric // packed, it has a different precedence relative to attribute aligned. 2500b57cec5SDimitry Andric case POAK_Packed: 2510b57cec5SDimitry Andric Action = Sema::PSK_Push_Set; 252e8d8bef9SDimitry Andric ModeVal = AlignPackInfo::Packed; 2530b57cec5SDimitry Andric break; 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric case POAK_Mac68k: 2560b57cec5SDimitry Andric // Check if the target supports this. 2570b57cec5SDimitry Andric if (!this->Context.getTargetInfo().hasAlignMac68kSupport()) { 2580b57cec5SDimitry Andric Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported); 2590b57cec5SDimitry Andric return; 2600b57cec5SDimitry Andric } 2610b57cec5SDimitry Andric Action = Sema::PSK_Push_Set; 262e8d8bef9SDimitry Andric ModeVal = AlignPackInfo::Mac68k; 2630b57cec5SDimitry Andric break; 2640b57cec5SDimitry Andric case POAK_Reset: 2650b57cec5SDimitry Andric // Reset just pops the top of the stack, or resets the current alignment to 2660b57cec5SDimitry Andric // default. 2670b57cec5SDimitry Andric Action = Sema::PSK_Pop; 268e8d8bef9SDimitry Andric if (AlignPackStack.Stack.empty()) { 269e8d8bef9SDimitry Andric if (AlignPackStack.CurrentValue.getAlignMode() != AlignPackInfo::Native || 270e8d8bef9SDimitry Andric AlignPackStack.CurrentValue.IsPackAttr()) { 2710b57cec5SDimitry Andric Action = Sema::PSK_Reset; 2720b57cec5SDimitry Andric } else { 2730b57cec5SDimitry Andric Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed) 2740b57cec5SDimitry Andric << "stack empty"; 2750b57cec5SDimitry Andric return; 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric break; 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 281e8d8bef9SDimitry Andric AlignPackInfo Info(ModeVal, getLangOpts().XLPragmaPack); 282e8d8bef9SDimitry Andric 283e8d8bef9SDimitry Andric AlignPackStack.Act(PragmaLoc, Action, StringRef(), Info); 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric 286fe6060f1SDimitry Andric void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, 287fe6060f1SDimitry Andric PragmaClangSectionAction Action, 288fe6060f1SDimitry Andric PragmaClangSectionKind SecKind, 289fe6060f1SDimitry Andric StringRef SecName) { 2900b57cec5SDimitry Andric PragmaClangSection *CSec; 2915ffd83dbSDimitry Andric int SectionFlags = ASTContext::PSF_Read; 2920b57cec5SDimitry Andric switch (SecKind) { 2930b57cec5SDimitry Andric case PragmaClangSectionKind::PCSK_BSS: 2940b57cec5SDimitry Andric CSec = &PragmaClangBSSSection; 2955ffd83dbSDimitry Andric SectionFlags |= ASTContext::PSF_Write | ASTContext::PSF_ZeroInit; 2960b57cec5SDimitry Andric break; 2970b57cec5SDimitry Andric case PragmaClangSectionKind::PCSK_Data: 2980b57cec5SDimitry Andric CSec = &PragmaClangDataSection; 2995ffd83dbSDimitry Andric SectionFlags |= ASTContext::PSF_Write; 3000b57cec5SDimitry Andric break; 3010b57cec5SDimitry Andric case PragmaClangSectionKind::PCSK_Rodata: 3020b57cec5SDimitry Andric CSec = &PragmaClangRodataSection; 3030b57cec5SDimitry Andric break; 304a7dea167SDimitry Andric case PragmaClangSectionKind::PCSK_Relro: 305a7dea167SDimitry Andric CSec = &PragmaClangRelroSection; 306a7dea167SDimitry Andric break; 3070b57cec5SDimitry Andric case PragmaClangSectionKind::PCSK_Text: 3080b57cec5SDimitry Andric CSec = &PragmaClangTextSection; 3095ffd83dbSDimitry Andric SectionFlags |= ASTContext::PSF_Execute; 3100b57cec5SDimitry Andric break; 3110b57cec5SDimitry Andric default: 3120b57cec5SDimitry Andric llvm_unreachable("invalid clang section kind"); 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric if (Action == PragmaClangSectionAction::PCSA_Clear) { 3160b57cec5SDimitry Andric CSec->Valid = false; 3170b57cec5SDimitry Andric return; 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric 320fe6060f1SDimitry Andric if (llvm::Error E = isValidSectionSpecifier(SecName)) { 321fe6060f1SDimitry Andric Diag(PragmaLoc, diag::err_pragma_section_invalid_for_target) 322fe6060f1SDimitry Andric << toString(std::move(E)); 323fe6060f1SDimitry Andric CSec->Valid = false; 324fe6060f1SDimitry Andric return; 325fe6060f1SDimitry Andric } 326fe6060f1SDimitry Andric 3275ffd83dbSDimitry Andric if (UnifySection(SecName, SectionFlags, PragmaLoc)) 3285ffd83dbSDimitry Andric return; 3295ffd83dbSDimitry Andric 3300b57cec5SDimitry Andric CSec->Valid = true; 3315ffd83dbSDimitry Andric CSec->SectionName = std::string(SecName); 3320b57cec5SDimitry Andric CSec->PragmaLocation = PragmaLoc; 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action, 3360b57cec5SDimitry Andric StringRef SlotLabel, Expr *alignment) { 337e8d8bef9SDimitry Andric bool IsXLPragma = getLangOpts().XLPragmaPack; 338e8d8bef9SDimitry Andric // XL pragma pack does not support identifier syntax. 339e8d8bef9SDimitry Andric if (IsXLPragma && !SlotLabel.empty()) { 340e8d8bef9SDimitry Andric Diag(PragmaLoc, diag::err_pragma_pack_identifer_not_supported); 341e8d8bef9SDimitry Andric return; 342e8d8bef9SDimitry Andric } 343e8d8bef9SDimitry Andric 344e8d8bef9SDimitry Andric const AlignPackInfo CurVal = AlignPackStack.CurrentValue; 3450b57cec5SDimitry Andric Expr *Alignment = static_cast<Expr *>(alignment); 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric // If specified then alignment must be a "small" power of two. 3480b57cec5SDimitry Andric unsigned AlignmentVal = 0; 349e8d8bef9SDimitry Andric AlignPackInfo::Mode ModeVal = CurVal.getAlignMode(); 350e8d8bef9SDimitry Andric 3510b57cec5SDimitry Andric if (Alignment) { 352bdd1243dSDimitry Andric std::optional<llvm::APSInt> Val; 353e8d8bef9SDimitry Andric Val = Alignment->getIntegerConstantExpr(Context); 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric // pack(0) is like pack(), which just works out since that is what 3560b57cec5SDimitry Andric // we use 0 for in PackAttr. 357349cc55cSDimitry Andric if (Alignment->isTypeDependent() || !Val || 358e8d8bef9SDimitry Andric !(*Val == 0 || Val->isPowerOf2()) || Val->getZExtValue() > 16) { 3590b57cec5SDimitry Andric Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); 3600b57cec5SDimitry Andric return; // Ignore 3610b57cec5SDimitry Andric } 3620b57cec5SDimitry Andric 363e8d8bef9SDimitry Andric if (IsXLPragma && *Val == 0) { 364e8d8bef9SDimitry Andric // pack(0) does not work out with XL. 365e8d8bef9SDimitry Andric Diag(PragmaLoc, diag::err_pragma_pack_invalid_alignment); 366e8d8bef9SDimitry Andric return; // Ignore 3670b57cec5SDimitry Andric } 368e8d8bef9SDimitry Andric 369e8d8bef9SDimitry Andric AlignmentVal = (unsigned)Val->getZExtValue(); 370e8d8bef9SDimitry Andric } 371e8d8bef9SDimitry Andric 3720b57cec5SDimitry Andric if (Action == Sema::PSK_Show) { 3730b57cec5SDimitry Andric // Show the current alignment, making sure to show the right value 3740b57cec5SDimitry Andric // for the default. 3750b57cec5SDimitry Andric // FIXME: This should come from the target. 376e8d8bef9SDimitry Andric AlignmentVal = CurVal.IsPackSet() ? CurVal.getPackNumber() : 8; 377e8d8bef9SDimitry Andric if (ModeVal == AlignPackInfo::Mac68k && 378e8d8bef9SDimitry Andric (IsXLPragma || CurVal.IsAlignAttr())) 3790b57cec5SDimitry Andric Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k"; 3800b57cec5SDimitry Andric else 3810b57cec5SDimitry Andric Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; 3820b57cec5SDimitry Andric } 383e8d8bef9SDimitry Andric 3840b57cec5SDimitry Andric // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack: 3850b57cec5SDimitry Andric // "#pragma pack(pop, identifier, n) is undefined" 3860b57cec5SDimitry Andric if (Action & Sema::PSK_Pop) { 3870b57cec5SDimitry Andric if (Alignment && !SlotLabel.empty()) 3880b57cec5SDimitry Andric Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifier_and_alignment); 389e8d8bef9SDimitry Andric if (AlignPackStack.Stack.empty()) { 390e8d8bef9SDimitry Andric assert(CurVal.getAlignMode() == AlignPackInfo::Native && 391e8d8bef9SDimitry Andric "Empty pack stack can only be at Native alignment mode."); 3920b57cec5SDimitry Andric Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "pack" << "stack empty"; 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric } 3950b57cec5SDimitry Andric 396e8d8bef9SDimitry Andric AlignPackInfo Info(ModeVal, AlignmentVal, IsXLPragma); 397e8d8bef9SDimitry Andric 398e8d8bef9SDimitry Andric AlignPackStack.Act(PragmaLoc, Action, SlotLabel, Info); 399e8d8bef9SDimitry Andric } 400e8d8bef9SDimitry Andric 40181ad6265SDimitry Andric bool Sema::ConstantFoldAttrArgs(const AttributeCommonInfo &CI, 40281ad6265SDimitry Andric MutableArrayRef<Expr *> Args) { 40381ad6265SDimitry Andric llvm::SmallVector<PartialDiagnosticAt, 8> Notes; 40481ad6265SDimitry Andric for (unsigned Idx = 0; Idx < Args.size(); Idx++) { 40581ad6265SDimitry Andric Expr *&E = Args.begin()[Idx]; 40681ad6265SDimitry Andric assert(E && "error are handled before"); 40781ad6265SDimitry Andric if (E->isValueDependent() || E->isTypeDependent()) 40881ad6265SDimitry Andric continue; 40981ad6265SDimitry Andric 41081ad6265SDimitry Andric // FIXME: Use DefaultFunctionArrayLValueConversion() in place of the logic 41181ad6265SDimitry Andric // that adds implicit casts here. 41281ad6265SDimitry Andric if (E->getType()->isArrayType()) 41381ad6265SDimitry Andric E = ImpCastExprToType(E, Context.getPointerType(E->getType()), 41481ad6265SDimitry Andric clang::CK_ArrayToPointerDecay) 41581ad6265SDimitry Andric .get(); 41681ad6265SDimitry Andric if (E->getType()->isFunctionType()) 41781ad6265SDimitry Andric E = ImplicitCastExpr::Create(Context, 41881ad6265SDimitry Andric Context.getPointerType(E->getType()), 41981ad6265SDimitry Andric clang::CK_FunctionToPointerDecay, E, nullptr, 42081ad6265SDimitry Andric VK_PRValue, FPOptionsOverride()); 42181ad6265SDimitry Andric if (E->isLValue()) 42281ad6265SDimitry Andric E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(), 42381ad6265SDimitry Andric clang::CK_LValueToRValue, E, nullptr, 42481ad6265SDimitry Andric VK_PRValue, FPOptionsOverride()); 42581ad6265SDimitry Andric 42681ad6265SDimitry Andric Expr::EvalResult Eval; 42781ad6265SDimitry Andric Notes.clear(); 42881ad6265SDimitry Andric Eval.Diag = &Notes; 42981ad6265SDimitry Andric 43081ad6265SDimitry Andric bool Result = E->EvaluateAsConstantExpr(Eval, Context); 43181ad6265SDimitry Andric 43281ad6265SDimitry Andric /// Result means the expression can be folded to a constant. 43381ad6265SDimitry Andric /// Note.empty() means the expression is a valid constant expression in the 43481ad6265SDimitry Andric /// current language mode. 43581ad6265SDimitry Andric if (!Result || !Notes.empty()) { 43681ad6265SDimitry Andric Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type) 43781ad6265SDimitry Andric << CI << (Idx + 1) << AANT_ArgumentConstantExpr; 43881ad6265SDimitry Andric for (auto &Note : Notes) 43981ad6265SDimitry Andric Diag(Note.first, Note.second); 44081ad6265SDimitry Andric return false; 44181ad6265SDimitry Andric } 44281ad6265SDimitry Andric assert(Eval.Val.hasValue()); 44381ad6265SDimitry Andric E = ConstantExpr::Create(Context, E, Eval.Val); 44481ad6265SDimitry Andric } 44581ad6265SDimitry Andric 44681ad6265SDimitry Andric return true; 44781ad6265SDimitry Andric } 44881ad6265SDimitry Andric 449e8d8bef9SDimitry Andric void Sema::DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind, 4500b57cec5SDimitry Andric SourceLocation IncludeLoc) { 451e8d8bef9SDimitry Andric if (Kind == PragmaAlignPackDiagnoseKind::NonDefaultStateAtInclude) { 452e8d8bef9SDimitry Andric SourceLocation PrevLocation = AlignPackStack.CurrentPragmaLocation; 4530b57cec5SDimitry Andric // Warn about non-default alignment at #includes (without redundant 4540b57cec5SDimitry Andric // warnings for the same directive in nested includes). 4550b57cec5SDimitry Andric // The warning is delayed until the end of the file to avoid warnings 4560b57cec5SDimitry Andric // for files that don't have any records that are affected by the modified 4570b57cec5SDimitry Andric // alignment. 4580b57cec5SDimitry Andric bool HasNonDefaultValue = 459e8d8bef9SDimitry Andric AlignPackStack.hasValue() && 460e8d8bef9SDimitry Andric (AlignPackIncludeStack.empty() || 461e8d8bef9SDimitry Andric AlignPackIncludeStack.back().CurrentPragmaLocation != PrevLocation); 462e8d8bef9SDimitry Andric AlignPackIncludeStack.push_back( 463e8d8bef9SDimitry Andric {AlignPackStack.CurrentValue, 464e8d8bef9SDimitry Andric AlignPackStack.hasValue() ? PrevLocation : SourceLocation(), 4650b57cec5SDimitry Andric HasNonDefaultValue, /*ShouldWarnOnInclude*/ false}); 4660b57cec5SDimitry Andric return; 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 469e8d8bef9SDimitry Andric assert(Kind == PragmaAlignPackDiagnoseKind::ChangedStateAtExit && 470e8d8bef9SDimitry Andric "invalid kind"); 471e8d8bef9SDimitry Andric AlignPackIncludeState PrevAlignPackState = 472e8d8bef9SDimitry Andric AlignPackIncludeStack.pop_back_val(); 473e8d8bef9SDimitry Andric // FIXME: AlignPackStack may contain both #pragma align and #pragma pack 474e8d8bef9SDimitry Andric // information, diagnostics below might not be accurate if we have mixed 475e8d8bef9SDimitry Andric // pragmas. 476e8d8bef9SDimitry Andric if (PrevAlignPackState.ShouldWarnOnInclude) { 4770b57cec5SDimitry Andric // Emit the delayed non-default alignment at #include warning. 4780b57cec5SDimitry Andric Diag(IncludeLoc, diag::warn_pragma_pack_non_default_at_include); 479e8d8bef9SDimitry Andric Diag(PrevAlignPackState.CurrentPragmaLocation, diag::note_pragma_pack_here); 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric // Warn about modified alignment after #includes. 482e8d8bef9SDimitry Andric if (PrevAlignPackState.CurrentValue != AlignPackStack.CurrentValue) { 4830b57cec5SDimitry Andric Diag(IncludeLoc, diag::warn_pragma_pack_modified_after_include); 484e8d8bef9SDimitry Andric Diag(AlignPackStack.CurrentPragmaLocation, diag::note_pragma_pack_here); 4850b57cec5SDimitry Andric } 4860b57cec5SDimitry Andric } 4870b57cec5SDimitry Andric 488e8d8bef9SDimitry Andric void Sema::DiagnoseUnterminatedPragmaAlignPack() { 489e8d8bef9SDimitry Andric if (AlignPackStack.Stack.empty()) 4900b57cec5SDimitry Andric return; 4910b57cec5SDimitry Andric bool IsInnermost = true; 492e8d8bef9SDimitry Andric 493e8d8bef9SDimitry Andric // FIXME: AlignPackStack may contain both #pragma align and #pragma pack 494e8d8bef9SDimitry Andric // information, diagnostics below might not be accurate if we have mixed 495e8d8bef9SDimitry Andric // pragmas. 496e8d8bef9SDimitry Andric for (const auto &StackSlot : llvm::reverse(AlignPackStack.Stack)) { 4970b57cec5SDimitry Andric Diag(StackSlot.PragmaPushLocation, diag::warn_pragma_pack_no_pop_eof); 4980b57cec5SDimitry Andric // The user might have already reset the alignment, so suggest replacing 4990b57cec5SDimitry Andric // the reset with a pop. 500e8d8bef9SDimitry Andric if (IsInnermost && 501e8d8bef9SDimitry Andric AlignPackStack.CurrentValue == AlignPackStack.DefaultValue) { 502e8d8bef9SDimitry Andric auto DB = Diag(AlignPackStack.CurrentPragmaLocation, 5030b57cec5SDimitry Andric diag::note_pragma_pack_pop_instead_reset); 504e8d8bef9SDimitry Andric SourceLocation FixItLoc = 505e8d8bef9SDimitry Andric Lexer::findLocationAfterToken(AlignPackStack.CurrentPragmaLocation, 506e8d8bef9SDimitry Andric tok::l_paren, SourceMgr, LangOpts, 5070b57cec5SDimitry Andric /*SkipTrailing=*/false); 5080b57cec5SDimitry Andric if (FixItLoc.isValid()) 5090b57cec5SDimitry Andric DB << FixItHint::CreateInsertion(FixItLoc, "pop"); 5100b57cec5SDimitry Andric } 5110b57cec5SDimitry Andric IsInnermost = false; 5120b57cec5SDimitry Andric } 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) { 5160b57cec5SDimitry Andric MSStructPragmaOn = (Kind == PMSST_ON); 5170b57cec5SDimitry Andric } 5180b57cec5SDimitry Andric 5190b57cec5SDimitry Andric void Sema::ActOnPragmaMSComment(SourceLocation CommentLoc, 5200b57cec5SDimitry Andric PragmaMSCommentKind Kind, StringRef Arg) { 5210b57cec5SDimitry Andric auto *PCD = PragmaCommentDecl::Create( 5220b57cec5SDimitry Andric Context, Context.getTranslationUnitDecl(), CommentLoc, Kind, Arg); 5230b57cec5SDimitry Andric Context.getTranslationUnitDecl()->addDecl(PCD); 5240b57cec5SDimitry Andric Consumer.HandleTopLevelDecl(DeclGroupRef(PCD)); 5250b57cec5SDimitry Andric } 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric void Sema::ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name, 5280b57cec5SDimitry Andric StringRef Value) { 5290b57cec5SDimitry Andric auto *PDMD = PragmaDetectMismatchDecl::Create( 5300b57cec5SDimitry Andric Context, Context.getTranslationUnitDecl(), Loc, Name, Value); 5310b57cec5SDimitry Andric Context.getTranslationUnitDecl()->addDecl(PDMD); 5320b57cec5SDimitry Andric Consumer.HandleTopLevelDecl(DeclGroupRef(PDMD)); 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric 53581ad6265SDimitry Andric void Sema::ActOnPragmaFPEvalMethod(SourceLocation Loc, 53681ad6265SDimitry Andric LangOptions::FPEvalMethodKind Value) { 53781ad6265SDimitry Andric FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); 53881ad6265SDimitry Andric switch (Value) { 53981ad6265SDimitry Andric default: 54081ad6265SDimitry Andric llvm_unreachable("invalid pragma eval_method kind"); 54181ad6265SDimitry Andric case LangOptions::FEM_Source: 54281ad6265SDimitry Andric NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Source); 54381ad6265SDimitry Andric break; 54481ad6265SDimitry Andric case LangOptions::FEM_Double: 54581ad6265SDimitry Andric NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Double); 54681ad6265SDimitry Andric break; 54781ad6265SDimitry Andric case LangOptions::FEM_Extended: 54881ad6265SDimitry Andric NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Extended); 54981ad6265SDimitry Andric break; 55081ad6265SDimitry Andric } 55181ad6265SDimitry Andric if (getLangOpts().ApproxFunc) 55281ad6265SDimitry Andric Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context) << 0 << 0; 55381ad6265SDimitry Andric if (getLangOpts().AllowFPReassoc) 55481ad6265SDimitry Andric Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context) << 0 << 1; 55581ad6265SDimitry Andric if (getLangOpts().AllowRecip) 55681ad6265SDimitry Andric Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context) << 0 << 2; 55781ad6265SDimitry Andric FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); 55881ad6265SDimitry Andric CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); 55981ad6265SDimitry Andric PP.setCurrentFPEvalMethod(Loc, Value); 56081ad6265SDimitry Andric } 56181ad6265SDimitry Andric 5625ffd83dbSDimitry Andric void Sema::ActOnPragmaFloatControl(SourceLocation Loc, 5635ffd83dbSDimitry Andric PragmaMsStackAction Action, 5645ffd83dbSDimitry Andric PragmaFloatControlKind Value) { 565e8d8bef9SDimitry Andric FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); 5665ffd83dbSDimitry Andric if ((Action == PSK_Push_Set || Action == PSK_Push || Action == PSK_Pop) && 567349cc55cSDimitry Andric !CurContext->getRedeclContext()->isFileContext()) { 568349cc55cSDimitry Andric // Push and pop can only occur at file or namespace scope, or within a 569349cc55cSDimitry Andric // language linkage declaration. 5705ffd83dbSDimitry Andric Diag(Loc, diag::err_pragma_fc_pp_scope); 5715ffd83dbSDimitry Andric return; 5725ffd83dbSDimitry Andric } 5735ffd83dbSDimitry Andric switch (Value) { 5745ffd83dbSDimitry Andric default: 5755ffd83dbSDimitry Andric llvm_unreachable("invalid pragma float_control kind"); 5765ffd83dbSDimitry Andric case PFC_Precise: 5775ffd83dbSDimitry Andric NewFPFeatures.setFPPreciseEnabled(true); 578e8d8bef9SDimitry Andric FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); 5795ffd83dbSDimitry Andric break; 5805ffd83dbSDimitry Andric case PFC_NoPrecise: 58181ad6265SDimitry Andric if (CurFPFeatures.getExceptionMode() == LangOptions::FPE_Strict) 5825ffd83dbSDimitry Andric Diag(Loc, diag::err_pragma_fc_noprecise_requires_noexcept); 5835ffd83dbSDimitry Andric else if (CurFPFeatures.getAllowFEnvAccess()) 5845ffd83dbSDimitry Andric Diag(Loc, diag::err_pragma_fc_noprecise_requires_nofenv); 5855ffd83dbSDimitry Andric else 5865ffd83dbSDimitry Andric NewFPFeatures.setFPPreciseEnabled(false); 587e8d8bef9SDimitry Andric FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); 5885ffd83dbSDimitry Andric break; 5895ffd83dbSDimitry Andric case PFC_Except: 5905ffd83dbSDimitry Andric if (!isPreciseFPEnabled()) 5915ffd83dbSDimitry Andric Diag(Loc, diag::err_pragma_fc_except_requires_precise); 5925ffd83dbSDimitry Andric else 59381ad6265SDimitry Andric NewFPFeatures.setSpecifiedExceptionModeOverride(LangOptions::FPE_Strict); 594e8d8bef9SDimitry Andric FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); 5955ffd83dbSDimitry Andric break; 5965ffd83dbSDimitry Andric case PFC_NoExcept: 59781ad6265SDimitry Andric NewFPFeatures.setSpecifiedExceptionModeOverride(LangOptions::FPE_Ignore); 598e8d8bef9SDimitry Andric FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); 5995ffd83dbSDimitry Andric break; 6005ffd83dbSDimitry Andric case PFC_Push: 601e8d8bef9SDimitry Andric FpPragmaStack.Act(Loc, Sema::PSK_Push_Set, StringRef(), NewFPFeatures); 6025ffd83dbSDimitry Andric break; 6035ffd83dbSDimitry Andric case PFC_Pop: 6045ffd83dbSDimitry Andric if (FpPragmaStack.Stack.empty()) { 6055ffd83dbSDimitry Andric Diag(Loc, diag::warn_pragma_pop_failed) << "float_control" 6065ffd83dbSDimitry Andric << "stack empty"; 6075ffd83dbSDimitry Andric return; 6085ffd83dbSDimitry Andric } 609e8d8bef9SDimitry Andric FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); 610e8d8bef9SDimitry Andric NewFPFeatures = FpPragmaStack.CurrentValue; 6115ffd83dbSDimitry Andric break; 6125ffd83dbSDimitry Andric } 613e8d8bef9SDimitry Andric CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); 6145ffd83dbSDimitry Andric } 6155ffd83dbSDimitry Andric 6160b57cec5SDimitry Andric void Sema::ActOnPragmaMSPointersToMembers( 6170b57cec5SDimitry Andric LangOptions::PragmaMSPointersToMembersKind RepresentationMethod, 6180b57cec5SDimitry Andric SourceLocation PragmaLoc) { 6190b57cec5SDimitry Andric MSPointerToMemberRepresentationMethod = RepresentationMethod; 6200b57cec5SDimitry Andric ImplicitMSInheritanceAttrLoc = PragmaLoc; 6210b57cec5SDimitry Andric } 6220b57cec5SDimitry Andric 6230b57cec5SDimitry Andric void Sema::ActOnPragmaMSVtorDisp(PragmaMsStackAction Action, 6240b57cec5SDimitry Andric SourceLocation PragmaLoc, 625480093f4SDimitry Andric MSVtorDispMode Mode) { 6260b57cec5SDimitry Andric if (Action & PSK_Pop && VtorDispStack.Stack.empty()) 6270b57cec5SDimitry Andric Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "vtordisp" 6280b57cec5SDimitry Andric << "stack empty"; 6290b57cec5SDimitry Andric VtorDispStack.Act(PragmaLoc, Action, StringRef(), Mode); 6300b57cec5SDimitry Andric } 6310b57cec5SDimitry Andric 632e8d8bef9SDimitry Andric template <> 633e8d8bef9SDimitry Andric void Sema::PragmaStack<Sema::AlignPackInfo>::Act(SourceLocation PragmaLocation, 634e8d8bef9SDimitry Andric PragmaMsStackAction Action, 635e8d8bef9SDimitry Andric llvm::StringRef StackSlotLabel, 636e8d8bef9SDimitry Andric AlignPackInfo Value) { 637e8d8bef9SDimitry Andric if (Action == PSK_Reset) { 638e8d8bef9SDimitry Andric CurrentValue = DefaultValue; 639e8d8bef9SDimitry Andric CurrentPragmaLocation = PragmaLocation; 640e8d8bef9SDimitry Andric return; 641e8d8bef9SDimitry Andric } 642e8d8bef9SDimitry Andric if (Action & PSK_Push) 643e8d8bef9SDimitry Andric Stack.emplace_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation, 644e8d8bef9SDimitry Andric PragmaLocation)); 645e8d8bef9SDimitry Andric else if (Action & PSK_Pop) { 646e8d8bef9SDimitry Andric if (!StackSlotLabel.empty()) { 647e8d8bef9SDimitry Andric // If we've got a label, try to find it and jump there. 648e8d8bef9SDimitry Andric auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) { 649e8d8bef9SDimitry Andric return x.StackSlotLabel == StackSlotLabel; 650e8d8bef9SDimitry Andric }); 651e8d8bef9SDimitry Andric // We found the label, so pop from there. 652e8d8bef9SDimitry Andric if (I != Stack.rend()) { 653e8d8bef9SDimitry Andric CurrentValue = I->Value; 654e8d8bef9SDimitry Andric CurrentPragmaLocation = I->PragmaLocation; 655e8d8bef9SDimitry Andric Stack.erase(std::prev(I.base()), Stack.end()); 656e8d8bef9SDimitry Andric } 657e8d8bef9SDimitry Andric } else if (Value.IsXLStack() && Value.IsAlignAttr() && 658e8d8bef9SDimitry Andric CurrentValue.IsPackAttr()) { 659e8d8bef9SDimitry Andric // XL '#pragma align(reset)' would pop the stack until 660e8d8bef9SDimitry Andric // a current in effect pragma align is popped. 661e8d8bef9SDimitry Andric auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) { 662e8d8bef9SDimitry Andric return x.Value.IsAlignAttr(); 663e8d8bef9SDimitry Andric }); 664e8d8bef9SDimitry Andric // If we found pragma align so pop from there. 665e8d8bef9SDimitry Andric if (I != Stack.rend()) { 666e8d8bef9SDimitry Andric Stack.erase(std::prev(I.base()), Stack.end()); 667e8d8bef9SDimitry Andric if (Stack.empty()) { 668e8d8bef9SDimitry Andric CurrentValue = DefaultValue; 669e8d8bef9SDimitry Andric CurrentPragmaLocation = PragmaLocation; 670e8d8bef9SDimitry Andric } else { 671e8d8bef9SDimitry Andric CurrentValue = Stack.back().Value; 672e8d8bef9SDimitry Andric CurrentPragmaLocation = Stack.back().PragmaLocation; 673e8d8bef9SDimitry Andric Stack.pop_back(); 674e8d8bef9SDimitry Andric } 675e8d8bef9SDimitry Andric } 676e8d8bef9SDimitry Andric } else if (!Stack.empty()) { 677e8d8bef9SDimitry Andric // xl '#pragma align' sets the baseline, and `#pragma pack` cannot pop 678e8d8bef9SDimitry Andric // over the baseline. 679e8d8bef9SDimitry Andric if (Value.IsXLStack() && Value.IsPackAttr() && CurrentValue.IsAlignAttr()) 680e8d8bef9SDimitry Andric return; 681e8d8bef9SDimitry Andric 682e8d8bef9SDimitry Andric // We don't have a label, just pop the last entry. 683e8d8bef9SDimitry Andric CurrentValue = Stack.back().Value; 684e8d8bef9SDimitry Andric CurrentPragmaLocation = Stack.back().PragmaLocation; 685e8d8bef9SDimitry Andric Stack.pop_back(); 686e8d8bef9SDimitry Andric } 687e8d8bef9SDimitry Andric } 688e8d8bef9SDimitry Andric if (Action & PSK_Set) { 689e8d8bef9SDimitry Andric CurrentValue = Value; 690e8d8bef9SDimitry Andric CurrentPragmaLocation = PragmaLocation; 691e8d8bef9SDimitry Andric } 692e8d8bef9SDimitry Andric } 693e8d8bef9SDimitry Andric 694e8d8bef9SDimitry Andric bool Sema::UnifySection(StringRef SectionName, int SectionFlags, 695e8d8bef9SDimitry Andric NamedDecl *Decl) { 6965ffd83dbSDimitry Andric SourceLocation PragmaLocation; 6975ffd83dbSDimitry Andric if (auto A = Decl->getAttr<SectionAttr>()) 6985ffd83dbSDimitry Andric if (A->isImplicit()) 6995ffd83dbSDimitry Andric PragmaLocation = A->getLocation(); 7005ffd83dbSDimitry Andric auto SectionIt = Context.SectionInfos.find(SectionName); 7015ffd83dbSDimitry Andric if (SectionIt == Context.SectionInfos.end()) { 7020b57cec5SDimitry Andric Context.SectionInfos[SectionName] = 7035ffd83dbSDimitry Andric ASTContext::SectionInfo(Decl, PragmaLocation, SectionFlags); 7040b57cec5SDimitry Andric return false; 7050b57cec5SDimitry Andric } 7060b57cec5SDimitry Andric // A pre-declared section takes precedence w/o diagnostic. 7075ffd83dbSDimitry Andric const auto &Section = SectionIt->second; 7085ffd83dbSDimitry Andric if (Section.SectionFlags == SectionFlags || 7095ffd83dbSDimitry Andric ((SectionFlags & ASTContext::PSF_Implicit) && 7105ffd83dbSDimitry Andric !(Section.SectionFlags & ASTContext::PSF_Implicit))) 7110b57cec5SDimitry Andric return false; 7125ffd83dbSDimitry Andric Diag(Decl->getLocation(), diag::err_section_conflict) << Decl << Section; 7135ffd83dbSDimitry Andric if (Section.Decl) 7145ffd83dbSDimitry Andric Diag(Section.Decl->getLocation(), diag::note_declared_at) 7155ffd83dbSDimitry Andric << Section.Decl->getName(); 7165ffd83dbSDimitry Andric if (PragmaLocation.isValid()) 7175ffd83dbSDimitry Andric Diag(PragmaLocation, diag::note_pragma_entered_here); 7185ffd83dbSDimitry Andric if (Section.PragmaSectionLocation.isValid()) 7195ffd83dbSDimitry Andric Diag(Section.PragmaSectionLocation, diag::note_pragma_entered_here); 7200b57cec5SDimitry Andric return true; 7210b57cec5SDimitry Andric } 7220b57cec5SDimitry Andric 7230b57cec5SDimitry Andric bool Sema::UnifySection(StringRef SectionName, 7240b57cec5SDimitry Andric int SectionFlags, 7250b57cec5SDimitry Andric SourceLocation PragmaSectionLocation) { 7265ffd83dbSDimitry Andric auto SectionIt = Context.SectionInfos.find(SectionName); 7275ffd83dbSDimitry Andric if (SectionIt != Context.SectionInfos.end()) { 7285ffd83dbSDimitry Andric const auto &Section = SectionIt->second; 7295ffd83dbSDimitry Andric if (Section.SectionFlags == SectionFlags) 7300b57cec5SDimitry Andric return false; 7315ffd83dbSDimitry Andric if (!(Section.SectionFlags & ASTContext::PSF_Implicit)) { 7320b57cec5SDimitry Andric Diag(PragmaSectionLocation, diag::err_section_conflict) 7335ffd83dbSDimitry Andric << "this" << Section; 7345ffd83dbSDimitry Andric if (Section.Decl) 7355ffd83dbSDimitry Andric Diag(Section.Decl->getLocation(), diag::note_declared_at) 7365ffd83dbSDimitry Andric << Section.Decl->getName(); 7375ffd83dbSDimitry Andric if (Section.PragmaSectionLocation.isValid()) 7385ffd83dbSDimitry Andric Diag(Section.PragmaSectionLocation, diag::note_pragma_entered_here); 7390b57cec5SDimitry Andric return true; 7400b57cec5SDimitry Andric } 7410b57cec5SDimitry Andric } 7420b57cec5SDimitry Andric Context.SectionInfos[SectionName] = 7430b57cec5SDimitry Andric ASTContext::SectionInfo(nullptr, PragmaSectionLocation, SectionFlags); 7440b57cec5SDimitry Andric return false; 7450b57cec5SDimitry Andric } 7460b57cec5SDimitry Andric 7470b57cec5SDimitry Andric /// Called on well formed \#pragma bss_seg(). 7480b57cec5SDimitry Andric void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation, 7490b57cec5SDimitry Andric PragmaMsStackAction Action, 7500b57cec5SDimitry Andric llvm::StringRef StackSlotLabel, 7510b57cec5SDimitry Andric StringLiteral *SegmentName, 7520b57cec5SDimitry Andric llvm::StringRef PragmaName) { 7530b57cec5SDimitry Andric PragmaStack<StringLiteral *> *Stack = 7540b57cec5SDimitry Andric llvm::StringSwitch<PragmaStack<StringLiteral *> *>(PragmaName) 7550b57cec5SDimitry Andric .Case("data_seg", &DataSegStack) 7560b57cec5SDimitry Andric .Case("bss_seg", &BSSSegStack) 7570b57cec5SDimitry Andric .Case("const_seg", &ConstSegStack) 7580b57cec5SDimitry Andric .Case("code_seg", &CodeSegStack); 7590b57cec5SDimitry Andric if (Action & PSK_Pop && Stack->Stack.empty()) 7600b57cec5SDimitry Andric Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName 7610b57cec5SDimitry Andric << "stack empty"; 7620b57cec5SDimitry Andric if (SegmentName) { 7630b57cec5SDimitry Andric if (!checkSectionName(SegmentName->getBeginLoc(), SegmentName->getString())) 7640b57cec5SDimitry Andric return; 7650b57cec5SDimitry Andric 7660b57cec5SDimitry Andric if (SegmentName->getString() == ".drectve" && 7670b57cec5SDimitry Andric Context.getTargetInfo().getCXXABI().isMicrosoft()) 7680b57cec5SDimitry Andric Diag(PragmaLocation, diag::warn_attribute_section_drectve) << PragmaName; 7690b57cec5SDimitry Andric } 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName); 7720b57cec5SDimitry Andric } 7730b57cec5SDimitry Andric 774bdd1243dSDimitry Andric /// Called on well formed \#pragma strict_gs_check(). 775bdd1243dSDimitry Andric void Sema::ActOnPragmaMSStrictGuardStackCheck(SourceLocation PragmaLocation, 776bdd1243dSDimitry Andric PragmaMsStackAction Action, 777bdd1243dSDimitry Andric bool Value) { 778bdd1243dSDimitry Andric if (Action & PSK_Pop && StrictGuardStackCheckStack.Stack.empty()) 779bdd1243dSDimitry Andric Diag(PragmaLocation, diag::warn_pragma_pop_failed) << "strict_gs_check" 780bdd1243dSDimitry Andric << "stack empty"; 781bdd1243dSDimitry Andric 782bdd1243dSDimitry Andric StrictGuardStackCheckStack.Act(PragmaLocation, Action, StringRef(), Value); 783bdd1243dSDimitry Andric } 784bdd1243dSDimitry Andric 7850b57cec5SDimitry Andric /// Called on well formed \#pragma bss_seg(). 7860b57cec5SDimitry Andric void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation, 7870b57cec5SDimitry Andric int SectionFlags, StringLiteral *SegmentName) { 7880b57cec5SDimitry Andric UnifySection(SegmentName->getString(), SectionFlags, PragmaLocation); 7890b57cec5SDimitry Andric } 7900b57cec5SDimitry Andric 7910b57cec5SDimitry Andric void Sema::ActOnPragmaMSInitSeg(SourceLocation PragmaLocation, 7920b57cec5SDimitry Andric StringLiteral *SegmentName) { 7930b57cec5SDimitry Andric // There's no stack to maintain, so we just have a current section. When we 7940b57cec5SDimitry Andric // see the default section, reset our current section back to null so we stop 7950b57cec5SDimitry Andric // tacking on unnecessary attributes. 7960b57cec5SDimitry Andric CurInitSeg = SegmentName->getString() == ".CRT$XCU" ? nullptr : SegmentName; 7970b57cec5SDimitry Andric CurInitSegLoc = PragmaLocation; 7980b57cec5SDimitry Andric } 7990b57cec5SDimitry Andric 80081ad6265SDimitry Andric void Sema::ActOnPragmaMSAllocText( 80181ad6265SDimitry Andric SourceLocation PragmaLocation, StringRef Section, 80281ad6265SDimitry Andric const SmallVector<std::tuple<IdentifierInfo *, SourceLocation>> 80381ad6265SDimitry Andric &Functions) { 80481ad6265SDimitry Andric if (!CurContext->getRedeclContext()->isFileContext()) { 80581ad6265SDimitry Andric Diag(PragmaLocation, diag::err_pragma_expected_file_scope) << "alloc_text"; 80681ad6265SDimitry Andric return; 80781ad6265SDimitry Andric } 80881ad6265SDimitry Andric 80981ad6265SDimitry Andric for (auto &Function : Functions) { 81081ad6265SDimitry Andric IdentifierInfo *II; 81181ad6265SDimitry Andric SourceLocation Loc; 81281ad6265SDimitry Andric std::tie(II, Loc) = Function; 81381ad6265SDimitry Andric 81481ad6265SDimitry Andric DeclarationName DN(II); 81581ad6265SDimitry Andric NamedDecl *ND = LookupSingleName(TUScope, DN, Loc, LookupOrdinaryName); 81681ad6265SDimitry Andric if (!ND) { 81781ad6265SDimitry Andric Diag(Loc, diag::err_undeclared_use) << II->getName(); 81881ad6265SDimitry Andric return; 81981ad6265SDimitry Andric } 82081ad6265SDimitry Andric 82181ad6265SDimitry Andric auto *FD = dyn_cast<FunctionDecl>(ND->getCanonicalDecl()); 82281ad6265SDimitry Andric if (!FD) { 82381ad6265SDimitry Andric Diag(Loc, diag::err_pragma_alloc_text_not_function); 82481ad6265SDimitry Andric return; 82581ad6265SDimitry Andric } 82681ad6265SDimitry Andric 82781ad6265SDimitry Andric if (getLangOpts().CPlusPlus && !FD->isInExternCContext()) { 82881ad6265SDimitry Andric Diag(Loc, diag::err_pragma_alloc_text_c_linkage); 82981ad6265SDimitry Andric return; 83081ad6265SDimitry Andric } 83181ad6265SDimitry Andric 83281ad6265SDimitry Andric FunctionToSectionMap[II->getName()] = std::make_tuple(Section, Loc); 83381ad6265SDimitry Andric } 83481ad6265SDimitry Andric } 83581ad6265SDimitry Andric 8360b57cec5SDimitry Andric void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope, 8370b57cec5SDimitry Andric SourceLocation PragmaLoc) { 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric IdentifierInfo *Name = IdTok.getIdentifierInfo(); 8400b57cec5SDimitry Andric LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName); 841*0fca6ea1SDimitry Andric LookupName(Lookup, curScope, /*AllowBuiltinCreation=*/true); 8420b57cec5SDimitry Andric 8430b57cec5SDimitry Andric if (Lookup.empty()) { 8440b57cec5SDimitry Andric Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) 8450b57cec5SDimitry Andric << Name << SourceRange(IdTok.getLocation()); 8460b57cec5SDimitry Andric return; 8470b57cec5SDimitry Andric } 8480b57cec5SDimitry Andric 8490b57cec5SDimitry Andric VarDecl *VD = Lookup.getAsSingle<VarDecl>(); 8500b57cec5SDimitry Andric if (!VD) { 8510b57cec5SDimitry Andric Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg) 8520b57cec5SDimitry Andric << Name << SourceRange(IdTok.getLocation()); 8530b57cec5SDimitry Andric return; 8540b57cec5SDimitry Andric } 8550b57cec5SDimitry Andric 8560b57cec5SDimitry Andric // Warn if this was used before being marked unused. 8570b57cec5SDimitry Andric if (VD->isUsed()) 8580b57cec5SDimitry Andric Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name; 8590b57cec5SDimitry Andric 860a7dea167SDimitry Andric VD->addAttr(UnusedAttr::CreateImplicit(Context, IdTok.getLocation(), 861a7dea167SDimitry Andric UnusedAttr::GNU_unused)); 8620b57cec5SDimitry Andric } 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric namespace { 8650b57cec5SDimitry Andric 866bdd1243dSDimitry Andric std::optional<attr::SubjectMatchRule> 8670b57cec5SDimitry Andric getParentAttrMatcherRule(attr::SubjectMatchRule Rule) { 8680b57cec5SDimitry Andric using namespace attr; 8690b57cec5SDimitry Andric switch (Rule) { 8700b57cec5SDimitry Andric default: 871bdd1243dSDimitry Andric return std::nullopt; 8720b57cec5SDimitry Andric #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) 8730b57cec5SDimitry Andric #define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \ 8740b57cec5SDimitry Andric case Value: \ 8750b57cec5SDimitry Andric return Parent; 8760b57cec5SDimitry Andric #include "clang/Basic/AttrSubMatchRulesList.inc" 8770b57cec5SDimitry Andric } 8780b57cec5SDimitry Andric } 8790b57cec5SDimitry Andric 8800b57cec5SDimitry Andric bool isNegatedAttrMatcherSubRule(attr::SubjectMatchRule Rule) { 8810b57cec5SDimitry Andric using namespace attr; 8820b57cec5SDimitry Andric switch (Rule) { 8830b57cec5SDimitry Andric default: 8840b57cec5SDimitry Andric return false; 8850b57cec5SDimitry Andric #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) 8860b57cec5SDimitry Andric #define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \ 8870b57cec5SDimitry Andric case Value: \ 8880b57cec5SDimitry Andric return IsNegated; 8890b57cec5SDimitry Andric #include "clang/Basic/AttrSubMatchRulesList.inc" 8900b57cec5SDimitry Andric } 8910b57cec5SDimitry Andric } 8920b57cec5SDimitry Andric 8930b57cec5SDimitry Andric CharSourceRange replacementRangeForListElement(const Sema &S, 8940b57cec5SDimitry Andric SourceRange Range) { 8950b57cec5SDimitry Andric // Make sure that the ',' is removed as well. 8960b57cec5SDimitry Andric SourceLocation AfterCommaLoc = Lexer::findLocationAfterToken( 8970b57cec5SDimitry Andric Range.getEnd(), tok::comma, S.getSourceManager(), S.getLangOpts(), 8980b57cec5SDimitry Andric /*SkipTrailingWhitespaceAndNewLine=*/false); 8990b57cec5SDimitry Andric if (AfterCommaLoc.isValid()) 9000b57cec5SDimitry Andric return CharSourceRange::getCharRange(Range.getBegin(), AfterCommaLoc); 9010b57cec5SDimitry Andric else 9020b57cec5SDimitry Andric return CharSourceRange::getTokenRange(Range); 9030b57cec5SDimitry Andric } 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric std::string 9060b57cec5SDimitry Andric attrMatcherRuleListToString(ArrayRef<attr::SubjectMatchRule> Rules) { 9070b57cec5SDimitry Andric std::string Result; 9080b57cec5SDimitry Andric llvm::raw_string_ostream OS(Result); 9090b57cec5SDimitry Andric for (const auto &I : llvm::enumerate(Rules)) { 9100b57cec5SDimitry Andric if (I.index()) 9110b57cec5SDimitry Andric OS << (I.index() == Rules.size() - 1 ? ", and " : ", "); 9120b57cec5SDimitry Andric OS << "'" << attr::getSubjectMatchRuleSpelling(I.value()) << "'"; 9130b57cec5SDimitry Andric } 9140eae32dcSDimitry Andric return Result; 9150b57cec5SDimitry Andric } 9160b57cec5SDimitry Andric 9170b57cec5SDimitry Andric } // end anonymous namespace 9180b57cec5SDimitry Andric 9190b57cec5SDimitry Andric void Sema::ActOnPragmaAttributeAttribute( 9200b57cec5SDimitry Andric ParsedAttr &Attribute, SourceLocation PragmaLoc, 9210b57cec5SDimitry Andric attr::ParsedSubjectMatchRuleSet Rules) { 9220b57cec5SDimitry Andric Attribute.setIsPragmaClangAttribute(); 9230b57cec5SDimitry Andric SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules; 9240b57cec5SDimitry Andric // Gather the subject match rules that are supported by the attribute. 9250b57cec5SDimitry Andric SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> 9260b57cec5SDimitry Andric StrictSubjectMatchRuleSet; 9270b57cec5SDimitry Andric Attribute.getMatchRules(LangOpts, StrictSubjectMatchRuleSet); 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric // Figure out which subject matching rules are valid. 9300b57cec5SDimitry Andric if (StrictSubjectMatchRuleSet.empty()) { 9310b57cec5SDimitry Andric // Check for contradicting match rules. Contradicting match rules are 9320b57cec5SDimitry Andric // either: 9330b57cec5SDimitry Andric // - a top-level rule and one of its sub-rules. E.g. variable and 9340b57cec5SDimitry Andric // variable(is_parameter). 9350b57cec5SDimitry Andric // - a sub-rule and a sibling that's negated. E.g. 9360b57cec5SDimitry Andric // variable(is_thread_local) and variable(unless(is_parameter)) 9370b57cec5SDimitry Andric llvm::SmallDenseMap<int, std::pair<int, SourceRange>, 2> 9380b57cec5SDimitry Andric RulesToFirstSpecifiedNegatedSubRule; 9390b57cec5SDimitry Andric for (const auto &Rule : Rules) { 9400b57cec5SDimitry Andric attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first); 941bdd1243dSDimitry Andric std::optional<attr::SubjectMatchRule> ParentRule = 9420b57cec5SDimitry Andric getParentAttrMatcherRule(MatchRule); 9430b57cec5SDimitry Andric if (!ParentRule) 9440b57cec5SDimitry Andric continue; 9450b57cec5SDimitry Andric auto It = Rules.find(*ParentRule); 9460b57cec5SDimitry Andric if (It != Rules.end()) { 9470b57cec5SDimitry Andric // A sub-rule contradicts a parent rule. 9480b57cec5SDimitry Andric Diag(Rule.second.getBegin(), 9490b57cec5SDimitry Andric diag::err_pragma_attribute_matcher_subrule_contradicts_rule) 9500b57cec5SDimitry Andric << attr::getSubjectMatchRuleSpelling(MatchRule) 9510b57cec5SDimitry Andric << attr::getSubjectMatchRuleSpelling(*ParentRule) << It->second 9520b57cec5SDimitry Andric << FixItHint::CreateRemoval( 9530b57cec5SDimitry Andric replacementRangeForListElement(*this, Rule.second)); 9540b57cec5SDimitry Andric // Keep going without removing this rule as it won't change the set of 9550b57cec5SDimitry Andric // declarations that receive the attribute. 9560b57cec5SDimitry Andric continue; 9570b57cec5SDimitry Andric } 9580b57cec5SDimitry Andric if (isNegatedAttrMatcherSubRule(MatchRule)) 9590b57cec5SDimitry Andric RulesToFirstSpecifiedNegatedSubRule.insert( 9600b57cec5SDimitry Andric std::make_pair(*ParentRule, Rule)); 9610b57cec5SDimitry Andric } 9620b57cec5SDimitry Andric bool IgnoreNegatedSubRules = false; 9630b57cec5SDimitry Andric for (const auto &Rule : Rules) { 9640b57cec5SDimitry Andric attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first); 965bdd1243dSDimitry Andric std::optional<attr::SubjectMatchRule> ParentRule = 9660b57cec5SDimitry Andric getParentAttrMatcherRule(MatchRule); 9670b57cec5SDimitry Andric if (!ParentRule) 9680b57cec5SDimitry Andric continue; 9690b57cec5SDimitry Andric auto It = RulesToFirstSpecifiedNegatedSubRule.find(*ParentRule); 9700b57cec5SDimitry Andric if (It != RulesToFirstSpecifiedNegatedSubRule.end() && 9710b57cec5SDimitry Andric It->second != Rule) { 9720b57cec5SDimitry Andric // Negated sub-rule contradicts another sub-rule. 9730b57cec5SDimitry Andric Diag( 9740b57cec5SDimitry Andric It->second.second.getBegin(), 9750b57cec5SDimitry Andric diag:: 9760b57cec5SDimitry Andric err_pragma_attribute_matcher_negated_subrule_contradicts_subrule) 9770b57cec5SDimitry Andric << attr::getSubjectMatchRuleSpelling( 9780b57cec5SDimitry Andric attr::SubjectMatchRule(It->second.first)) 9790b57cec5SDimitry Andric << attr::getSubjectMatchRuleSpelling(MatchRule) << Rule.second 9800b57cec5SDimitry Andric << FixItHint::CreateRemoval( 9810b57cec5SDimitry Andric replacementRangeForListElement(*this, It->second.second)); 9820b57cec5SDimitry Andric // Keep going but ignore all of the negated sub-rules. 9830b57cec5SDimitry Andric IgnoreNegatedSubRules = true; 9840b57cec5SDimitry Andric RulesToFirstSpecifiedNegatedSubRule.erase(It); 9850b57cec5SDimitry Andric } 9860b57cec5SDimitry Andric } 9870b57cec5SDimitry Andric 9880b57cec5SDimitry Andric if (!IgnoreNegatedSubRules) { 9890b57cec5SDimitry Andric for (const auto &Rule : Rules) 9900b57cec5SDimitry Andric SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first)); 9910b57cec5SDimitry Andric } else { 9920b57cec5SDimitry Andric for (const auto &Rule : Rules) { 9930b57cec5SDimitry Andric if (!isNegatedAttrMatcherSubRule(attr::SubjectMatchRule(Rule.first))) 9940b57cec5SDimitry Andric SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first)); 9950b57cec5SDimitry Andric } 9960b57cec5SDimitry Andric } 9970b57cec5SDimitry Andric Rules.clear(); 9980b57cec5SDimitry Andric } else { 999fe6060f1SDimitry Andric // Each rule in Rules must be a strict subset of the attribute's 1000fe6060f1SDimitry Andric // SubjectMatch rules. I.e. we're allowed to use 1001fe6060f1SDimitry Andric // `apply_to=variables(is_global)` on an attrubute with SubjectList<[Var]>, 1002fe6060f1SDimitry Andric // but should not allow `apply_to=variables` on an attribute which has 1003fe6060f1SDimitry Andric // `SubjectList<[GlobalVar]>`. 1004fe6060f1SDimitry Andric for (const auto &StrictRule : StrictSubjectMatchRuleSet) { 1005fe6060f1SDimitry Andric // First, check for exact match. 1006fe6060f1SDimitry Andric if (Rules.erase(StrictRule.first)) { 10070b57cec5SDimitry Andric // Add the rule to the set of attribute receivers only if it's supported 10080b57cec5SDimitry Andric // in the current language mode. 1009fe6060f1SDimitry Andric if (StrictRule.second) 1010fe6060f1SDimitry Andric SubjectMatchRules.push_back(StrictRule.first); 1011fe6060f1SDimitry Andric } 1012fe6060f1SDimitry Andric } 1013fe6060f1SDimitry Andric // Check remaining rules for subset matches. 1014fe6060f1SDimitry Andric auto RulesToCheck = Rules; 1015fe6060f1SDimitry Andric for (const auto &Rule : RulesToCheck) { 1016fe6060f1SDimitry Andric attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first); 1017fe6060f1SDimitry Andric if (auto ParentRule = getParentAttrMatcherRule(MatchRule)) { 1018fe6060f1SDimitry Andric if (llvm::any_of(StrictSubjectMatchRuleSet, 1019fe6060f1SDimitry Andric [ParentRule](const auto &StrictRule) { 1020fe6060f1SDimitry Andric return StrictRule.first == *ParentRule && 1021fe6060f1SDimitry Andric StrictRule.second; // IsEnabled 1022fe6060f1SDimitry Andric })) { 1023fe6060f1SDimitry Andric SubjectMatchRules.push_back(MatchRule); 1024fe6060f1SDimitry Andric Rules.erase(MatchRule); 1025fe6060f1SDimitry Andric } 10260b57cec5SDimitry Andric } 10270b57cec5SDimitry Andric } 10280b57cec5SDimitry Andric } 10290b57cec5SDimitry Andric 10300b57cec5SDimitry Andric if (!Rules.empty()) { 10310b57cec5SDimitry Andric auto Diagnostic = 10320b57cec5SDimitry Andric Diag(PragmaLoc, diag::err_pragma_attribute_invalid_matchers) 1033a7dea167SDimitry Andric << Attribute; 10340b57cec5SDimitry Andric SmallVector<attr::SubjectMatchRule, 2> ExtraRules; 10350b57cec5SDimitry Andric for (const auto &Rule : Rules) { 10360b57cec5SDimitry Andric ExtraRules.push_back(attr::SubjectMatchRule(Rule.first)); 10370b57cec5SDimitry Andric Diagnostic << FixItHint::CreateRemoval( 10380b57cec5SDimitry Andric replacementRangeForListElement(*this, Rule.second)); 10390b57cec5SDimitry Andric } 10400b57cec5SDimitry Andric Diagnostic << attrMatcherRuleListToString(ExtraRules); 10410b57cec5SDimitry Andric } 10420b57cec5SDimitry Andric 10430b57cec5SDimitry Andric if (PragmaAttributeStack.empty()) { 10440b57cec5SDimitry Andric Diag(PragmaLoc, diag::err_pragma_attr_attr_no_push); 10450b57cec5SDimitry Andric return; 10460b57cec5SDimitry Andric } 10470b57cec5SDimitry Andric 10480b57cec5SDimitry Andric PragmaAttributeStack.back().Entries.push_back( 10490b57cec5SDimitry Andric {PragmaLoc, &Attribute, std::move(SubjectMatchRules), /*IsUsed=*/false}); 10500b57cec5SDimitry Andric } 10510b57cec5SDimitry Andric 10520b57cec5SDimitry Andric void Sema::ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc, 10530b57cec5SDimitry Andric const IdentifierInfo *Namespace) { 10540b57cec5SDimitry Andric PragmaAttributeStack.emplace_back(); 10550b57cec5SDimitry Andric PragmaAttributeStack.back().Loc = PragmaLoc; 10560b57cec5SDimitry Andric PragmaAttributeStack.back().Namespace = Namespace; 10570b57cec5SDimitry Andric } 10580b57cec5SDimitry Andric 10590b57cec5SDimitry Andric void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc, 10600b57cec5SDimitry Andric const IdentifierInfo *Namespace) { 10610b57cec5SDimitry Andric if (PragmaAttributeStack.empty()) { 10620b57cec5SDimitry Andric Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch) << 1; 10630b57cec5SDimitry Andric return; 10640b57cec5SDimitry Andric } 10650b57cec5SDimitry Andric 10660b57cec5SDimitry Andric // Dig back through the stack trying to find the most recently pushed group 10670b57cec5SDimitry Andric // that in Namespace. Note that this works fine if no namespace is present, 10680b57cec5SDimitry Andric // think of push/pops without namespaces as having an implicit "nullptr" 10690b57cec5SDimitry Andric // namespace. 10700b57cec5SDimitry Andric for (size_t Index = PragmaAttributeStack.size(); Index;) { 10710b57cec5SDimitry Andric --Index; 10720b57cec5SDimitry Andric if (PragmaAttributeStack[Index].Namespace == Namespace) { 10730b57cec5SDimitry Andric for (const PragmaAttributeEntry &Entry : 10740b57cec5SDimitry Andric PragmaAttributeStack[Index].Entries) { 10750b57cec5SDimitry Andric if (!Entry.IsUsed) { 10760b57cec5SDimitry Andric assert(Entry.Attribute && "Expected an attribute"); 10770b57cec5SDimitry Andric Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused) 10780b57cec5SDimitry Andric << *Entry.Attribute; 10790b57cec5SDimitry Andric Diag(PragmaLoc, diag::note_pragma_attribute_region_ends_here); 10800b57cec5SDimitry Andric } 10810b57cec5SDimitry Andric } 10820b57cec5SDimitry Andric PragmaAttributeStack.erase(PragmaAttributeStack.begin() + Index); 10830b57cec5SDimitry Andric return; 10840b57cec5SDimitry Andric } 10850b57cec5SDimitry Andric } 10860b57cec5SDimitry Andric 10870b57cec5SDimitry Andric if (Namespace) 10880b57cec5SDimitry Andric Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch) 10890b57cec5SDimitry Andric << 0 << Namespace->getName(); 10900b57cec5SDimitry Andric else 10910b57cec5SDimitry Andric Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch) << 1; 10920b57cec5SDimitry Andric } 10930b57cec5SDimitry Andric 10940b57cec5SDimitry Andric void Sema::AddPragmaAttributes(Scope *S, Decl *D) { 10950b57cec5SDimitry Andric if (PragmaAttributeStack.empty()) 10960b57cec5SDimitry Andric return; 10970b57cec5SDimitry Andric for (auto &Group : PragmaAttributeStack) { 10980b57cec5SDimitry Andric for (auto &Entry : Group.Entries) { 10990b57cec5SDimitry Andric ParsedAttr *Attribute = Entry.Attribute; 11000b57cec5SDimitry Andric assert(Attribute && "Expected an attribute"); 11010b57cec5SDimitry Andric assert(Attribute->isPragmaClangAttribute() && 11020b57cec5SDimitry Andric "expected #pragma clang attribute"); 11030b57cec5SDimitry Andric 11040b57cec5SDimitry Andric // Ensure that the attribute can be applied to the given declaration. 11050b57cec5SDimitry Andric bool Applies = false; 11060b57cec5SDimitry Andric for (const auto &Rule : Entry.MatchRules) { 11070b57cec5SDimitry Andric if (Attribute->appliesToDecl(D, Rule)) { 11080b57cec5SDimitry Andric Applies = true; 11090b57cec5SDimitry Andric break; 11100b57cec5SDimitry Andric } 11110b57cec5SDimitry Andric } 11120b57cec5SDimitry Andric if (!Applies) 11130b57cec5SDimitry Andric continue; 11140b57cec5SDimitry Andric Entry.IsUsed = true; 11150b57cec5SDimitry Andric PragmaAttributeCurrentTargetDecl = D; 11160b57cec5SDimitry Andric ParsedAttributesView Attrs; 11170b57cec5SDimitry Andric Attrs.addAtEnd(Attribute); 11180b57cec5SDimitry Andric ProcessDeclAttributeList(S, D, Attrs); 11190b57cec5SDimitry Andric PragmaAttributeCurrentTargetDecl = nullptr; 11200b57cec5SDimitry Andric } 11210b57cec5SDimitry Andric } 11220b57cec5SDimitry Andric } 11230b57cec5SDimitry Andric 11240b57cec5SDimitry Andric void Sema::PrintPragmaAttributeInstantiationPoint() { 11250b57cec5SDimitry Andric assert(PragmaAttributeCurrentTargetDecl && "Expected an active declaration"); 11260b57cec5SDimitry Andric Diags.Report(PragmaAttributeCurrentTargetDecl->getBeginLoc(), 11270b57cec5SDimitry Andric diag::note_pragma_attribute_applied_decl_here); 11280b57cec5SDimitry Andric } 11290b57cec5SDimitry Andric 11300b57cec5SDimitry Andric void Sema::DiagnoseUnterminatedPragmaAttribute() { 11310b57cec5SDimitry Andric if (PragmaAttributeStack.empty()) 11320b57cec5SDimitry Andric return; 11330b57cec5SDimitry Andric Diag(PragmaAttributeStack.back().Loc, diag::err_pragma_attribute_no_pop_eof); 11340b57cec5SDimitry Andric } 11350b57cec5SDimitry Andric 11360b57cec5SDimitry Andric void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) { 11370b57cec5SDimitry Andric if(On) 11380b57cec5SDimitry Andric OptimizeOffPragmaLocation = SourceLocation(); 11390b57cec5SDimitry Andric else 11400b57cec5SDimitry Andric OptimizeOffPragmaLocation = PragmaLoc; 11410b57cec5SDimitry Andric } 11420b57cec5SDimitry Andric 114381ad6265SDimitry Andric void Sema::ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn) { 114481ad6265SDimitry Andric if (!CurContext->getRedeclContext()->isFileContext()) { 114581ad6265SDimitry Andric Diag(Loc, diag::err_pragma_expected_file_scope) << "optimize"; 114681ad6265SDimitry Andric return; 114781ad6265SDimitry Andric } 114881ad6265SDimitry Andric 114981ad6265SDimitry Andric MSPragmaOptimizeIsOn = IsOn; 115081ad6265SDimitry Andric } 115181ad6265SDimitry Andric 115281ad6265SDimitry Andric void Sema::ActOnPragmaMSFunction( 115381ad6265SDimitry Andric SourceLocation Loc, const llvm::SmallVectorImpl<StringRef> &NoBuiltins) { 115481ad6265SDimitry Andric if (!CurContext->getRedeclContext()->isFileContext()) { 115581ad6265SDimitry Andric Diag(Loc, diag::err_pragma_expected_file_scope) << "function"; 115681ad6265SDimitry Andric return; 115781ad6265SDimitry Andric } 115881ad6265SDimitry Andric 115981ad6265SDimitry Andric MSFunctionNoBuiltins.insert(NoBuiltins.begin(), NoBuiltins.end()); 116081ad6265SDimitry Andric } 116181ad6265SDimitry Andric 11620b57cec5SDimitry Andric void Sema::AddRangeBasedOptnone(FunctionDecl *FD) { 11630b57cec5SDimitry Andric // In the future, check other pragmas if they're implemented (e.g. pragma 11640b57cec5SDimitry Andric // optimize 0 will probably map to this functionality too). 11650b57cec5SDimitry Andric if(OptimizeOffPragmaLocation.isValid()) 11660b57cec5SDimitry Andric AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation); 11670b57cec5SDimitry Andric } 11680b57cec5SDimitry Andric 116981ad6265SDimitry Andric void Sema::AddSectionMSAllocText(FunctionDecl *FD) { 117081ad6265SDimitry Andric if (!FD->getIdentifier()) 117181ad6265SDimitry Andric return; 117281ad6265SDimitry Andric 117381ad6265SDimitry Andric StringRef Name = FD->getName(); 117481ad6265SDimitry Andric auto It = FunctionToSectionMap.find(Name); 117581ad6265SDimitry Andric if (It != FunctionToSectionMap.end()) { 117681ad6265SDimitry Andric StringRef Section; 117781ad6265SDimitry Andric SourceLocation Loc; 117881ad6265SDimitry Andric std::tie(Section, Loc) = It->second; 117981ad6265SDimitry Andric 118081ad6265SDimitry Andric if (!FD->hasAttr<SectionAttr>()) 118181ad6265SDimitry Andric FD->addAttr(SectionAttr::CreateImplicit(Context, Section)); 118281ad6265SDimitry Andric } 118381ad6265SDimitry Andric } 118481ad6265SDimitry Andric 118581ad6265SDimitry Andric void Sema::ModifyFnAttributesMSPragmaOptimize(FunctionDecl *FD) { 118681ad6265SDimitry Andric // Don't modify the function attributes if it's "on". "on" resets the 118781ad6265SDimitry Andric // optimizations to the ones listed on the command line 118881ad6265SDimitry Andric if (!MSPragmaOptimizeIsOn) 118981ad6265SDimitry Andric AddOptnoneAttributeIfNoConflicts(FD, FD->getBeginLoc()); 119081ad6265SDimitry Andric } 119181ad6265SDimitry Andric 11920b57cec5SDimitry Andric void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, 11930b57cec5SDimitry Andric SourceLocation Loc) { 11940b57cec5SDimitry Andric // Don't add a conflicting attribute. No diagnostic is needed. 11950b57cec5SDimitry Andric if (FD->hasAttr<MinSizeAttr>() || FD->hasAttr<AlwaysInlineAttr>()) 11960b57cec5SDimitry Andric return; 11970b57cec5SDimitry Andric 11980b57cec5SDimitry Andric // Add attributes only if required. Optnone requires noinline as well, but if 11990b57cec5SDimitry Andric // either is already present then don't bother adding them. 12000b57cec5SDimitry Andric if (!FD->hasAttr<OptimizeNoneAttr>()) 12010b57cec5SDimitry Andric FD->addAttr(OptimizeNoneAttr::CreateImplicit(Context, Loc)); 12020b57cec5SDimitry Andric if (!FD->hasAttr<NoInlineAttr>()) 12030b57cec5SDimitry Andric FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc)); 12040b57cec5SDimitry Andric } 12050b57cec5SDimitry Andric 120681ad6265SDimitry Andric void Sema::AddImplicitMSFunctionNoBuiltinAttr(FunctionDecl *FD) { 120781ad6265SDimitry Andric SmallVector<StringRef> V(MSFunctionNoBuiltins.begin(), 120881ad6265SDimitry Andric MSFunctionNoBuiltins.end()); 120981ad6265SDimitry Andric if (!MSFunctionNoBuiltins.empty()) 121081ad6265SDimitry Andric FD->addAttr(NoBuiltinAttr::CreateImplicit(Context, V.data(), V.size())); 121181ad6265SDimitry Andric } 121281ad6265SDimitry Andric 12130b57cec5SDimitry Andric typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack; 12140b57cec5SDimitry Andric enum : unsigned { NoVisibility = ~0U }; 12150b57cec5SDimitry Andric 12160b57cec5SDimitry Andric void Sema::AddPushedVisibilityAttribute(Decl *D) { 12170b57cec5SDimitry Andric if (!VisContext) 12180b57cec5SDimitry Andric return; 12190b57cec5SDimitry Andric 12200b57cec5SDimitry Andric NamedDecl *ND = dyn_cast<NamedDecl>(D); 12210b57cec5SDimitry Andric if (ND && ND->getExplicitVisibility(NamedDecl::VisibilityForValue)) 12220b57cec5SDimitry Andric return; 12230b57cec5SDimitry Andric 12240b57cec5SDimitry Andric VisStack *Stack = static_cast<VisStack*>(VisContext); 12250b57cec5SDimitry Andric unsigned rawType = Stack->back().first; 12260b57cec5SDimitry Andric if (rawType == NoVisibility) return; 12270b57cec5SDimitry Andric 12280b57cec5SDimitry Andric VisibilityAttr::VisibilityType type 12290b57cec5SDimitry Andric = (VisibilityAttr::VisibilityType) rawType; 12300b57cec5SDimitry Andric SourceLocation loc = Stack->back().second; 12310b57cec5SDimitry Andric 12320b57cec5SDimitry Andric D->addAttr(VisibilityAttr::CreateImplicit(Context, type, loc)); 12330b57cec5SDimitry Andric } 12340b57cec5SDimitry Andric 12350b57cec5SDimitry Andric void Sema::FreeVisContext() { 12360b57cec5SDimitry Andric delete static_cast<VisStack*>(VisContext); 12370b57cec5SDimitry Andric VisContext = nullptr; 12380b57cec5SDimitry Andric } 12390b57cec5SDimitry Andric 12400b57cec5SDimitry Andric static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) { 12410b57cec5SDimitry Andric // Put visibility on stack. 12420b57cec5SDimitry Andric if (!S.VisContext) 12430b57cec5SDimitry Andric S.VisContext = new VisStack; 12440b57cec5SDimitry Andric 12450b57cec5SDimitry Andric VisStack *Stack = static_cast<VisStack*>(S.VisContext); 12460b57cec5SDimitry Andric Stack->push_back(std::make_pair(type, loc)); 12470b57cec5SDimitry Andric } 12480b57cec5SDimitry Andric 12490b57cec5SDimitry Andric void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType, 12500b57cec5SDimitry Andric SourceLocation PragmaLoc) { 12510b57cec5SDimitry Andric if (VisType) { 12520b57cec5SDimitry Andric // Compute visibility to use. 12530b57cec5SDimitry Andric VisibilityAttr::VisibilityType T; 12540b57cec5SDimitry Andric if (!VisibilityAttr::ConvertStrToVisibilityType(VisType->getName(), T)) { 12550b57cec5SDimitry Andric Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << VisType; 12560b57cec5SDimitry Andric return; 12570b57cec5SDimitry Andric } 12580b57cec5SDimitry Andric PushPragmaVisibility(*this, T, PragmaLoc); 12590b57cec5SDimitry Andric } else { 12600b57cec5SDimitry Andric PopPragmaVisibility(false, PragmaLoc); 12610b57cec5SDimitry Andric } 12620b57cec5SDimitry Andric } 12630b57cec5SDimitry Andric 12645ffd83dbSDimitry Andric void Sema::ActOnPragmaFPContract(SourceLocation Loc, 12655ffd83dbSDimitry Andric LangOptions::FPModeKind FPC) { 1266e8d8bef9SDimitry Andric FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); 12670b57cec5SDimitry Andric switch (FPC) { 12685ffd83dbSDimitry Andric case LangOptions::FPM_On: 12695ffd83dbSDimitry Andric NewFPFeatures.setAllowFPContractWithinStatement(); 12700b57cec5SDimitry Andric break; 12715ffd83dbSDimitry Andric case LangOptions::FPM_Fast: 12725ffd83dbSDimitry Andric NewFPFeatures.setAllowFPContractAcrossStatement(); 12730b57cec5SDimitry Andric break; 12745ffd83dbSDimitry Andric case LangOptions::FPM_Off: 12755ffd83dbSDimitry Andric NewFPFeatures.setDisallowFPContract(); 12760b57cec5SDimitry Andric break; 1277e8d8bef9SDimitry Andric case LangOptions::FPM_FastHonorPragmas: 1278e8d8bef9SDimitry Andric llvm_unreachable("Should not happen"); 12790b57cec5SDimitry Andric } 1280e8d8bef9SDimitry Andric FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(), NewFPFeatures); 12815ffd83dbSDimitry Andric CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); 12820b57cec5SDimitry Andric } 12830b57cec5SDimitry Andric 12845f757f3fSDimitry Andric void Sema::ActOnPragmaFPValueChangingOption(SourceLocation Loc, 12855f757f3fSDimitry Andric PragmaFPKind Kind, bool IsEnabled) { 128681ad6265SDimitry Andric if (IsEnabled) { 128781ad6265SDimitry Andric // For value unsafe context, combining this pragma with eval method 128881ad6265SDimitry Andric // setting is not recommended. See comment in function FixupInvocation#506. 128981ad6265SDimitry Andric int Reason = -1; 129081ad6265SDimitry Andric if (getLangOpts().getFPEvalMethod() != LangOptions::FEM_UnsetOnCommandLine) 129181ad6265SDimitry Andric // Eval method set using the option 'ffp-eval-method'. 129281ad6265SDimitry Andric Reason = 1; 129381ad6265SDimitry Andric if (PP.getLastFPEvalPragmaLocation().isValid()) 129481ad6265SDimitry Andric // Eval method set using the '#pragma clang fp eval_method'. 129581ad6265SDimitry Andric // We could have both an option and a pragma used to the set the eval 129681ad6265SDimitry Andric // method. The pragma overrides the option in the command line. The Reason 129781ad6265SDimitry Andric // of the diagnostic is overriden too. 129881ad6265SDimitry Andric Reason = 0; 129981ad6265SDimitry Andric if (Reason != -1) 130081ad6265SDimitry Andric Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context) 13015f757f3fSDimitry Andric << Reason << (Kind == PFK_Reassociate ? 4 : 5); 130281ad6265SDimitry Andric } 13035f757f3fSDimitry Andric 1304e8d8bef9SDimitry Andric FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); 13055f757f3fSDimitry Andric switch (Kind) { 13065f757f3fSDimitry Andric case PFK_Reassociate: 13075ffd83dbSDimitry Andric NewFPFeatures.setAllowFPReassociateOverride(IsEnabled); 13085f757f3fSDimitry Andric break; 13095f757f3fSDimitry Andric case PFK_Reciprocal: 13105f757f3fSDimitry Andric NewFPFeatures.setAllowReciprocalOverride(IsEnabled); 13115f757f3fSDimitry Andric break; 13125f757f3fSDimitry Andric default: 13135f757f3fSDimitry Andric llvm_unreachable("unhandled value changing pragma fp"); 13145f757f3fSDimitry Andric } 13155f757f3fSDimitry Andric 1316e8d8bef9SDimitry Andric FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); 1317e8d8bef9SDimitry Andric CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); 13180b57cec5SDimitry Andric } 13190b57cec5SDimitry Andric 132081ad6265SDimitry Andric void Sema::ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode FPR) { 1321e8d8bef9SDimitry Andric FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); 132281ad6265SDimitry Andric NewFPFeatures.setConstRoundingModeOverride(FPR); 1323e8d8bef9SDimitry Andric FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); 1324e8d8bef9SDimitry Andric CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); 13255ffd83dbSDimitry Andric } 13265ffd83dbSDimitry Andric 13275ffd83dbSDimitry Andric void Sema::setExceptionMode(SourceLocation Loc, 13285ffd83dbSDimitry Andric LangOptions::FPExceptionModeKind FPE) { 1329e8d8bef9SDimitry Andric FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); 133081ad6265SDimitry Andric NewFPFeatures.setSpecifiedExceptionModeOverride(FPE); 1331e8d8bef9SDimitry Andric FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); 1332e8d8bef9SDimitry Andric CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); 13335ffd83dbSDimitry Andric } 13345ffd83dbSDimitry Andric 13355ffd83dbSDimitry Andric void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) { 1336e8d8bef9SDimitry Andric FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); 13375ffd83dbSDimitry Andric if (IsEnabled) { 13385ffd83dbSDimitry Andric // Verify Microsoft restriction: 13395ffd83dbSDimitry Andric // You can't enable fenv_access unless precise semantics are enabled. 13405ffd83dbSDimitry Andric // Precise semantics can be enabled either by the float_control 13415ffd83dbSDimitry Andric // pragma, or by using the /fp:precise or /fp:strict compiler options 13425ffd83dbSDimitry Andric if (!isPreciseFPEnabled()) 13435ffd83dbSDimitry Andric Diag(Loc, diag::err_pragma_fenv_requires_precise); 1344e8d8bef9SDimitry Andric } 134581ad6265SDimitry Andric NewFPFeatures.setAllowFEnvAccessOverride(IsEnabled); 134606c3fb27SDimitry Andric NewFPFeatures.setRoundingMathOverride(IsEnabled); 1347e8d8bef9SDimitry Andric FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); 134881ad6265SDimitry Andric CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); 1349e8d8bef9SDimitry Andric } 1350e8d8bef9SDimitry Andric 13515f757f3fSDimitry Andric void Sema::ActOnPragmaCXLimitedRange(SourceLocation Loc, 13525f757f3fSDimitry Andric LangOptions::ComplexRangeKind Range) { 13535f757f3fSDimitry Andric FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); 13545f757f3fSDimitry Andric NewFPFeatures.setComplexRangeOverride(Range); 13555f757f3fSDimitry Andric FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); 13565f757f3fSDimitry Andric CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); 13575f757f3fSDimitry Andric } 13585f757f3fSDimitry Andric 1359e8d8bef9SDimitry Andric void Sema::ActOnPragmaFPExceptions(SourceLocation Loc, 1360e8d8bef9SDimitry Andric LangOptions::FPExceptionModeKind FPE) { 1361e8d8bef9SDimitry Andric setExceptionMode(Loc, FPE); 13625ffd83dbSDimitry Andric } 13630b57cec5SDimitry Andric 13640b57cec5SDimitry Andric void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr, 13650b57cec5SDimitry Andric SourceLocation Loc) { 13660b57cec5SDimitry Andric // Visibility calculations will consider the namespace's visibility. 13670b57cec5SDimitry Andric // Here we just want to note that we're in a visibility context 13680b57cec5SDimitry Andric // which overrides any enclosing #pragma context, but doesn't itself 13690b57cec5SDimitry Andric // contribute visibility. 13700b57cec5SDimitry Andric PushPragmaVisibility(*this, NoVisibility, Loc); 13710b57cec5SDimitry Andric } 13720b57cec5SDimitry Andric 13730b57cec5SDimitry Andric void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) { 13740b57cec5SDimitry Andric if (!VisContext) { 13750b57cec5SDimitry Andric Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch); 13760b57cec5SDimitry Andric return; 13770b57cec5SDimitry Andric } 13780b57cec5SDimitry Andric 13790b57cec5SDimitry Andric // Pop visibility from stack 13800b57cec5SDimitry Andric VisStack *Stack = static_cast<VisStack*>(VisContext); 13810b57cec5SDimitry Andric 13820b57cec5SDimitry Andric const std::pair<unsigned, SourceLocation> *Back = &Stack->back(); 13830b57cec5SDimitry Andric bool StartsWithPragma = Back->first != NoVisibility; 13840b57cec5SDimitry Andric if (StartsWithPragma && IsNamespaceEnd) { 13850b57cec5SDimitry Andric Diag(Back->second, diag::err_pragma_push_visibility_mismatch); 13860b57cec5SDimitry Andric Diag(EndLoc, diag::note_surrounding_namespace_ends_here); 13870b57cec5SDimitry Andric 13880b57cec5SDimitry Andric // For better error recovery, eat all pushes inside the namespace. 13890b57cec5SDimitry Andric do { 13900b57cec5SDimitry Andric Stack->pop_back(); 13910b57cec5SDimitry Andric Back = &Stack->back(); 13920b57cec5SDimitry Andric StartsWithPragma = Back->first != NoVisibility; 13930b57cec5SDimitry Andric } while (StartsWithPragma); 13940b57cec5SDimitry Andric } else if (!StartsWithPragma && !IsNamespaceEnd) { 13950b57cec5SDimitry Andric Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch); 13960b57cec5SDimitry Andric Diag(Back->second, diag::note_surrounding_namespace_starts_here); 13970b57cec5SDimitry Andric return; 13980b57cec5SDimitry Andric } 13990b57cec5SDimitry Andric 14000b57cec5SDimitry Andric Stack->pop_back(); 14010b57cec5SDimitry Andric // To simplify the implementation, never keep around an empty stack. 14020b57cec5SDimitry Andric if (Stack->empty()) 14030b57cec5SDimitry Andric FreeVisContext(); 14040b57cec5SDimitry Andric } 1405fe6060f1SDimitry Andric 1406fe6060f1SDimitry Andric template <typename Ty> 1407fe6060f1SDimitry Andric static bool checkCommonAttributeFeatures(Sema &S, const Ty *Node, 140881ad6265SDimitry Andric const ParsedAttr &A, 140981ad6265SDimitry Andric bool SkipArgCountCheck) { 1410fe6060f1SDimitry Andric // Several attributes carry different semantics than the parsing requires, so 1411fe6060f1SDimitry Andric // those are opted out of the common argument checks. 1412fe6060f1SDimitry Andric // 1413fe6060f1SDimitry Andric // We also bail on unknown and ignored attributes because those are handled 1414fe6060f1SDimitry Andric // as part of the target-specific handling logic. 1415fe6060f1SDimitry Andric if (A.getKind() == ParsedAttr::UnknownAttribute) 1416fe6060f1SDimitry Andric return false; 1417fe6060f1SDimitry Andric // Check whether the attribute requires specific language extensions to be 1418fe6060f1SDimitry Andric // enabled. 1419fe6060f1SDimitry Andric if (!A.diagnoseLangOpts(S)) 1420fe6060f1SDimitry Andric return true; 1421fe6060f1SDimitry Andric // Check whether the attribute appertains to the given subject. 1422fe6060f1SDimitry Andric if (!A.diagnoseAppertainsTo(S, Node)) 1423fe6060f1SDimitry Andric return true; 1424fe6060f1SDimitry Andric // Check whether the attribute is mutually exclusive with other attributes 1425fe6060f1SDimitry Andric // that have already been applied to the declaration. 1426fe6060f1SDimitry Andric if (!A.diagnoseMutualExclusion(S, Node)) 1427fe6060f1SDimitry Andric return true; 1428fe6060f1SDimitry Andric // Check whether the attribute exists in the target architecture. 1429fe6060f1SDimitry Andric if (S.CheckAttrTarget(A)) 1430fe6060f1SDimitry Andric return true; 1431fe6060f1SDimitry Andric 1432fe6060f1SDimitry Andric if (A.hasCustomParsing()) 1433fe6060f1SDimitry Andric return false; 1434fe6060f1SDimitry Andric 143581ad6265SDimitry Andric if (!SkipArgCountCheck) { 1436fe6060f1SDimitry Andric if (A.getMinArgs() == A.getMaxArgs()) { 143781ad6265SDimitry Andric // If there are no optional arguments, then checking for the argument 143881ad6265SDimitry Andric // count is trivial. 1439fe6060f1SDimitry Andric if (!A.checkExactlyNumArgs(S, A.getMinArgs())) 1440fe6060f1SDimitry Andric return true; 1441fe6060f1SDimitry Andric } else { 1442fe6060f1SDimitry Andric // There are optional arguments, so checking is slightly more involved. 1443fe6060f1SDimitry Andric if (A.getMinArgs() && !A.checkAtLeastNumArgs(S, A.getMinArgs())) 1444fe6060f1SDimitry Andric return true; 1445fe6060f1SDimitry Andric else if (!A.hasVariadicArg() && A.getMaxArgs() && 1446fe6060f1SDimitry Andric !A.checkAtMostNumArgs(S, A.getMaxArgs())) 1447fe6060f1SDimitry Andric return true; 1448fe6060f1SDimitry Andric } 144981ad6265SDimitry Andric } 1450fe6060f1SDimitry Andric 1451fe6060f1SDimitry Andric return false; 1452fe6060f1SDimitry Andric } 1453fe6060f1SDimitry Andric 145481ad6265SDimitry Andric bool Sema::checkCommonAttributeFeatures(const Decl *D, const ParsedAttr &A, 145581ad6265SDimitry Andric bool SkipArgCountCheck) { 145681ad6265SDimitry Andric return ::checkCommonAttributeFeatures(*this, D, A, SkipArgCountCheck); 1457fe6060f1SDimitry Andric } 145881ad6265SDimitry Andric bool Sema::checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A, 145981ad6265SDimitry Andric bool SkipArgCountCheck) { 146081ad6265SDimitry Andric return ::checkCommonAttributeFeatures(*this, S, A, SkipArgCountCheck); 1461fe6060f1SDimitry Andric } 1462