diff options
Diffstat (limited to 'clang/lib/Sema/SemaAttr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaAttr.cpp | 250 |
1 files changed, 172 insertions, 78 deletions
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index cd2a65276b090..b354e810974c4 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -256,12 +256,15 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionAction Action, PragmaClangSectionKind SecKind, StringRef SecName) { PragmaClangSection *CSec; + int SectionFlags = ASTContext::PSF_Read; switch (SecKind) { case PragmaClangSectionKind::PCSK_BSS: CSec = &PragmaClangBSSSection; + SectionFlags |= ASTContext::PSF_Write | ASTContext::PSF_ZeroInit; break; case PragmaClangSectionKind::PCSK_Data: CSec = &PragmaClangDataSection; + SectionFlags |= ASTContext::PSF_Write; break; case PragmaClangSectionKind::PCSK_Rodata: CSec = &PragmaClangRodataSection; @@ -271,6 +274,7 @@ void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionA break; case PragmaClangSectionKind::PCSK_Text: CSec = &PragmaClangTextSection; + SectionFlags |= ASTContext::PSF_Execute; break; default: llvm_unreachable("invalid clang section kind"); @@ -281,8 +285,11 @@ void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionA return; } + if (UnifySection(SecName, SectionFlags, PragmaLoc)) + return; + CSec->Valid = true; - CSec->SectionName = SecName; + CSec->SectionName = std::string(SecName); CSec->PragmaLocation = PragmaLoc; } @@ -407,6 +414,70 @@ void Sema::ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name, Consumer.HandleTopLevelDecl(DeclGroupRef(PDMD)); } +void Sema::ActOnPragmaFloatControl(SourceLocation Loc, + PragmaMsStackAction Action, + PragmaFloatControlKind Value) { + unsigned NewValue = FpPragmaStack.hasValue() + ? FpPragmaStack.CurrentValue + : CurFPFeatureOverrides().getAsOpaqueInt(); + FPOptionsOverride NewFPFeatures(NewValue); + if ((Action == PSK_Push_Set || Action == PSK_Push || Action == PSK_Pop) && + !(CurContext->isTranslationUnit()) && !CurContext->isNamespace()) { + // Push and pop can only occur at file or namespace scope. + Diag(Loc, diag::err_pragma_fc_pp_scope); + return; + } + switch (Value) { + default: + llvm_unreachable("invalid pragma float_control kind"); + case PFC_Precise: + NewFPFeatures.setFPPreciseEnabled(true); + NewValue = NewFPFeatures.getAsOpaqueInt(); + FpPragmaStack.Act(Loc, Action, StringRef(), NewValue); + break; + case PFC_NoPrecise: + if (CurFPFeatures.getFPExceptionMode() == LangOptions::FPE_Strict) + Diag(Loc, diag::err_pragma_fc_noprecise_requires_noexcept); + else if (CurFPFeatures.getAllowFEnvAccess()) + Diag(Loc, diag::err_pragma_fc_noprecise_requires_nofenv); + else + NewFPFeatures.setFPPreciseEnabled(false); + NewValue = NewFPFeatures.getAsOpaqueInt(); + FpPragmaStack.Act(Loc, Action, StringRef(), NewValue); + break; + case PFC_Except: + if (!isPreciseFPEnabled()) + Diag(Loc, diag::err_pragma_fc_except_requires_precise); + else + NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict); + NewValue = NewFPFeatures.getAsOpaqueInt(); + FpPragmaStack.Act(Loc, Action, StringRef(), NewValue); + break; + case PFC_NoExcept: + NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Ignore); + NewValue = NewFPFeatures.getAsOpaqueInt(); + FpPragmaStack.Act(Loc, Action, StringRef(), NewValue); + break; + case PFC_Push: + FpPragmaStack.Act(Loc, Sema::PSK_Push_Set, StringRef(), + NewFPFeatures.getAsOpaqueInt()); + break; + case PFC_Pop: + if (FpPragmaStack.Stack.empty()) { + Diag(Loc, diag::warn_pragma_pop_failed) << "float_control" + << "stack empty"; + return; + } + FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures.getAsOpaqueInt()); + NewValue = FpPragmaStack.CurrentValue; + break; + } + FPOptionsOverride NewOverrides; + if (NewValue != FpPragmaStack.DefaultValue) + NewOverrides.getFromOpaqueInt(NewValue); + CurFPFeatures = NewOverrides.applyOverrides(getLangOpts()); +} + void Sema::ActOnPragmaMSPointersToMembers( LangOptions::PragmaMSPointersToMembersKind RepresentationMethod, SourceLocation PragmaLoc) { @@ -423,83 +494,52 @@ void Sema::ActOnPragmaMSVtorDisp(PragmaMsStackAction Action, VtorDispStack.Act(PragmaLoc, Action, StringRef(), Mode); } -template<typename ValueType> -void Sema::PragmaStack<ValueType>::Act(SourceLocation PragmaLocation, - PragmaMsStackAction Action, - llvm::StringRef StackSlotLabel, - ValueType Value) { - if (Action == PSK_Reset) { - CurrentValue = DefaultValue; - CurrentPragmaLocation = PragmaLocation; - return; - } - if (Action & PSK_Push) - Stack.emplace_back(StackSlotLabel, CurrentValue, CurrentPragmaLocation, - PragmaLocation); - else if (Action & PSK_Pop) { - if (!StackSlotLabel.empty()) { - // If we've got a label, try to find it and jump there. - auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) { - return x.StackSlotLabel == StackSlotLabel; - }); - // If we found the label so pop from there. - if (I != Stack.rend()) { - CurrentValue = I->Value; - CurrentPragmaLocation = I->PragmaLocation; - Stack.erase(std::prev(I.base()), Stack.end()); - } - } else if (!Stack.empty()) { - // We do not have a label, just pop the last entry. - CurrentValue = Stack.back().Value; - CurrentPragmaLocation = Stack.back().PragmaLocation; - Stack.pop_back(); - } - } - if (Action & PSK_Set) { - CurrentValue = Value; - CurrentPragmaLocation = PragmaLocation; - } -} - bool Sema::UnifySection(StringRef SectionName, int SectionFlags, DeclaratorDecl *Decl) { - auto Section = Context.SectionInfos.find(SectionName); - if (Section == Context.SectionInfos.end()) { + SourceLocation PragmaLocation; + if (auto A = Decl->getAttr<SectionAttr>()) + if (A->isImplicit()) + PragmaLocation = A->getLocation(); + auto SectionIt = Context.SectionInfos.find(SectionName); + if (SectionIt == Context.SectionInfos.end()) { Context.SectionInfos[SectionName] = - ASTContext::SectionInfo(Decl, SourceLocation(), SectionFlags); + ASTContext::SectionInfo(Decl, PragmaLocation, SectionFlags); return false; } // A pre-declared section takes precedence w/o diagnostic. - if (Section->second.SectionFlags == SectionFlags || - !(Section->second.SectionFlags & ASTContext::PSF_Implicit)) + const auto &Section = SectionIt->second; + if (Section.SectionFlags == SectionFlags || + ((SectionFlags & ASTContext::PSF_Implicit) && + !(Section.SectionFlags & ASTContext::PSF_Implicit))) return false; - auto OtherDecl = Section->second.Decl; - Diag(Decl->getLocation(), diag::err_section_conflict) - << Decl << OtherDecl; - Diag(OtherDecl->getLocation(), diag::note_declared_at) - << OtherDecl->getName(); - if (auto A = Decl->getAttr<SectionAttr>()) - if (A->isImplicit()) - Diag(A->getLocation(), diag::note_pragma_entered_here); - if (auto A = OtherDecl->getAttr<SectionAttr>()) - if (A->isImplicit()) - Diag(A->getLocation(), diag::note_pragma_entered_here); + Diag(Decl->getLocation(), diag::err_section_conflict) << Decl << Section; + if (Section.Decl) + Diag(Section.Decl->getLocation(), diag::note_declared_at) + << Section.Decl->getName(); + if (PragmaLocation.isValid()) + Diag(PragmaLocation, diag::note_pragma_entered_here); + if (Section.PragmaSectionLocation.isValid()) + Diag(Section.PragmaSectionLocation, diag::note_pragma_entered_here); return true; } bool Sema::UnifySection(StringRef SectionName, int SectionFlags, SourceLocation PragmaSectionLocation) { - auto Section = Context.SectionInfos.find(SectionName); - if (Section != Context.SectionInfos.end()) { - if (Section->second.SectionFlags == SectionFlags) + auto SectionIt = Context.SectionInfos.find(SectionName); + if (SectionIt != Context.SectionInfos.end()) { + const auto &Section = SectionIt->second; + if (Section.SectionFlags == SectionFlags) return false; - if (!(Section->second.SectionFlags & ASTContext::PSF_Implicit)) { + if (!(Section.SectionFlags & ASTContext::PSF_Implicit)) { Diag(PragmaSectionLocation, diag::err_section_conflict) - << "this" << "a prior #pragma section"; - Diag(Section->second.PragmaSectionLocation, - diag::note_pragma_entered_here); + << "this" << Section; + if (Section.Decl) + Diag(Section.Decl->getLocation(), diag::note_declared_at) + << Section.Decl->getName(); + if (Section.PragmaSectionLocation.isValid()) + Diag(Section.PragmaSectionLocation, diag::note_pragma_entered_here); return true; } } @@ -926,31 +966,85 @@ void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType, } } -void Sema::ActOnPragmaFPContract(LangOptions::FPContractModeKind FPC) { +void Sema::ActOnPragmaFPContract(SourceLocation Loc, + LangOptions::FPModeKind FPC) { + unsigned NewValue = FpPragmaStack.hasValue() + ? FpPragmaStack.CurrentValue + : CurFPFeatureOverrides().getAsOpaqueInt(); + FPOptionsOverride NewFPFeatures(NewValue); switch (FPC) { - case LangOptions::FPC_On: - FPFeatures.setAllowFPContractWithinStatement(); + case LangOptions::FPM_On: + NewFPFeatures.setAllowFPContractWithinStatement(); break; - case LangOptions::FPC_Fast: - FPFeatures.setAllowFPContractAcrossStatement(); + case LangOptions::FPM_Fast: + NewFPFeatures.setAllowFPContractAcrossStatement(); break; - case LangOptions::FPC_Off: - FPFeatures.setDisallowFPContract(); + case LangOptions::FPM_Off: + NewFPFeatures.setDisallowFPContract(); break; } + CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); + FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(), + NewFPFeatures.getAsOpaqueInt()); } -void Sema::ActOnPragmaFEnvAccess(LangOptions::FEnvAccessModeKind FPC) { - switch (FPC) { - case LangOptions::FEA_On: - FPFeatures.setAllowFEnvAccess(); - break; - case LangOptions::FEA_Off: - FPFeatures.setDisallowFEnvAccess(); - break; - } +void Sema::ActOnPragmaFPReassociate(SourceLocation Loc, bool IsEnabled) { + unsigned NewValue = FpPragmaStack.hasValue() + ? FpPragmaStack.CurrentValue + : CurFPFeatureOverrides().getAsOpaqueInt(); + FPOptionsOverride NewFPFeatures(NewValue); + NewFPFeatures.setAllowFPReassociateOverride(IsEnabled); + NewValue = NewFPFeatures.getAsOpaqueInt(); + FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue); + FPOptionsOverride NewOverrides(NewValue); + CurFPFeatures = NewOverrides.applyOverrides(getLangOpts()); } +void Sema::setRoundingMode(SourceLocation Loc, llvm::RoundingMode FPR) { + unsigned NewValue = FpPragmaStack.hasValue() + ? FpPragmaStack.CurrentValue + : CurFPFeatureOverrides().getAsOpaqueInt(); + FPOptionsOverride NewFPFeatures(NewValue); + NewFPFeatures.setRoundingModeOverride(FPR); + NewValue = NewFPFeatures.getAsOpaqueInt(); + FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue); + FPOptionsOverride NewOverrides(NewValue); + CurFPFeatures = NewOverrides.applyOverrides(getLangOpts()); +} + +void Sema::setExceptionMode(SourceLocation Loc, + LangOptions::FPExceptionModeKind FPE) { + unsigned NewValue = FpPragmaStack.hasValue() + ? FpPragmaStack.CurrentValue + : CurFPFeatureOverrides().getAsOpaqueInt(); + FPOptionsOverride NewFPFeatures(NewValue); + NewFPFeatures.setFPExceptionModeOverride(FPE); + NewValue = NewFPFeatures.getAsOpaqueInt(); + FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue); + FPOptionsOverride NewOverrides(NewValue); + CurFPFeatures = NewOverrides.applyOverrides(getLangOpts()); +} + +void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) { + unsigned NewValue = FpPragmaStack.hasValue() + ? FpPragmaStack.CurrentValue + : CurFPFeatureOverrides().getAsOpaqueInt(); + FPOptionsOverride NewFPFeatures(NewValue); + if (IsEnabled) { + // Verify Microsoft restriction: + // You can't enable fenv_access unless precise semantics are enabled. + // Precise semantics can be enabled either by the float_control + // pragma, or by using the /fp:precise or /fp:strict compiler options + if (!isPreciseFPEnabled()) + Diag(Loc, diag::err_pragma_fenv_requires_precise); + NewFPFeatures.setAllowFEnvAccessOverride(true); + } else + NewFPFeatures.setAllowFEnvAccessOverride(false); + NewValue = NewFPFeatures.getAsOpaqueInt(); + FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue); + FPOptionsOverride NewOverrides(NewValue); + CurFPFeatures = NewOverrides.applyOverrides(getLangOpts()); +} void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr, SourceLocation Loc) { |