Mercurial > hg > CbC > CbC_llvm
diff clang/lib/Sema/SemaAttr.cpp @ 236:c4bab56944e8 llvm-original
LLVM 16
author | kono |
---|---|
date | Wed, 09 Nov 2022 17:45:10 +0900 |
parents | 79ff65ed7e25 |
children | 1f2b6ac9f198 |
line wrap: on
line diff
--- a/clang/lib/Sema/SemaAttr.cpp Wed Jul 21 10:27:27 2021 +0900 +++ b/clang/lib/Sema/SemaAttr.cpp Wed Nov 09 17:45:10 2022 +0900 @@ -34,6 +34,7 @@ S.BSSSegStack.SentinelAction(PSK_Push, SlotLabel); S.ConstSegStack.SentinelAction(PSK_Push, SlotLabel); S.CodeSegStack.SentinelAction(PSK_Push, SlotLabel); + S.StrictGuardStackCheckStack.SentinelAction(PSK_Push, SlotLabel); } } @@ -44,6 +45,7 @@ S.BSSSegStack.SentinelAction(PSK_Pop, SlotLabel); S.ConstSegStack.SentinelAction(PSK_Pop, SlotLabel); S.CodeSegStack.SentinelAction(PSK_Pop, SlotLabel); + S.StrictGuardStackCheckStack.SentinelAction(PSK_Pop, SlotLabel); } } @@ -340,7 +342,7 @@ // pack(0) is like pack(), which just works out since that is what // we use 0 for in PackAttr. - if (Alignment->isTypeDependent() || Alignment->isValueDependent() || !Val || + if (Alignment->isTypeDependent() || !Val || !(*Val == 0 || Val->isPowerOf2()) || Val->getZExtValue() > 16) { Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); return; // Ignore @@ -384,6 +386,54 @@ AlignPackStack.Act(PragmaLoc, Action, SlotLabel, Info); } +bool Sema::ConstantFoldAttrArgs(const AttributeCommonInfo &CI, + MutableArrayRef<Expr *> Args) { + llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + for (unsigned Idx = 0; Idx < Args.size(); Idx++) { + Expr *&E = Args.begin()[Idx]; + assert(E && "error are handled before"); + if (E->isValueDependent() || E->isTypeDependent()) + continue; + + // FIXME: Use DefaultFunctionArrayLValueConversion() in place of the logic + // that adds implicit casts here. + if (E->getType()->isArrayType()) + E = ImpCastExprToType(E, Context.getPointerType(E->getType()), + clang::CK_ArrayToPointerDecay) + .get(); + if (E->getType()->isFunctionType()) + E = ImplicitCastExpr::Create(Context, + Context.getPointerType(E->getType()), + clang::CK_FunctionToPointerDecay, E, nullptr, + VK_PRValue, FPOptionsOverride()); + if (E->isLValue()) + E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(), + clang::CK_LValueToRValue, E, nullptr, + VK_PRValue, FPOptionsOverride()); + + Expr::EvalResult Eval; + Notes.clear(); + Eval.Diag = &Notes; + + bool Result = E->EvaluateAsConstantExpr(Eval, Context); + + /// Result means the expression can be folded to a constant. + /// Note.empty() means the expression is a valid constant expression in the + /// current language mode. + if (!Result || !Notes.empty()) { + Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type) + << CI << (Idx + 1) << AANT_ArgumentConstantExpr; + for (auto &Note : Notes) + Diag(Note.first, Note.second); + return false; + } + assert(Eval.Val.hasValue()); + E = ConstantExpr::Create(Context, E, Eval.Val); + } + + return true; +} + void Sema::DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind, SourceLocation IncludeLoc) { if (Kind == PragmaAlignPackDiagnoseKind::NonDefaultStateAtInclude) { @@ -470,13 +520,41 @@ Consumer.HandleTopLevelDecl(DeclGroupRef(PDMD)); } +void Sema::ActOnPragmaFPEvalMethod(SourceLocation Loc, + LangOptions::FPEvalMethodKind Value) { + FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); + switch (Value) { + default: + llvm_unreachable("invalid pragma eval_method kind"); + case LangOptions::FEM_Source: + NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Source); + break; + case LangOptions::FEM_Double: + NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Double); + break; + case LangOptions::FEM_Extended: + NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Extended); + break; + } + if (getLangOpts().ApproxFunc) + Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context) << 0 << 0; + if (getLangOpts().AllowFPReassoc) + Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context) << 0 << 1; + if (getLangOpts().AllowRecip) + Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context) << 0 << 2; + FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); + CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); + PP.setCurrentFPEvalMethod(Loc, Value); +} + void Sema::ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction Action, PragmaFloatControlKind Value) { FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); 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. + !CurContext->getRedeclContext()->isFileContext()) { + // Push and pop can only occur at file or namespace scope, or within a + // language linkage declaration. Diag(Loc, diag::err_pragma_fc_pp_scope); return; } @@ -486,25 +564,36 @@ case PFC_Precise: NewFPFeatures.setFPPreciseEnabled(true); FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); + if (PP.getCurrentFPEvalMethod() == + LangOptions::FPEvalMethodKind::FEM_Indeterminable && + PP.getLastFPEvalPragmaLocation().isValid()) + // A preceding `pragma float_control(precise,off)` has changed + // the value of the evaluation method. + // Set it back to its old value. + PP.setCurrentFPEvalMethod(SourceLocation(), PP.getLastFPEvalMethod()); break; case PFC_NoPrecise: - if (CurFPFeatures.getFPExceptionMode() == LangOptions::FPE_Strict) + if (CurFPFeatures.getExceptionMode() == 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); FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); + PP.setLastFPEvalMethod(PP.getCurrentFPEvalMethod()); + // `AllowFPReassoc` or `AllowReciprocal` option is enabled. + PP.setCurrentFPEvalMethod( + Loc, LangOptions::FPEvalMethodKind::FEM_Indeterminable); break; case PFC_Except: if (!isPreciseFPEnabled()) Diag(Loc, diag::err_pragma_fc_except_requires_precise); else - NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict); + NewFPFeatures.setSpecifiedExceptionModeOverride(LangOptions::FPE_Strict); FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); break; case PFC_NoExcept: - NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Ignore); + NewFPFeatures.setSpecifiedExceptionModeOverride(LangOptions::FPE_Ignore); FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); break; case PFC_Push: @@ -518,6 +607,12 @@ } FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); NewFPFeatures = FpPragmaStack.CurrentValue; + if (CurFPFeatures.getAllowFPReassociate() || + CurFPFeatures.getAllowReciprocal()) + // Since we are popping the pragma, we don't want to be passing + // a location here. + PP.setCurrentFPEvalMethod(SourceLocation(), + CurFPFeatures.getFPEvalMethod()); break; } CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); @@ -681,6 +776,17 @@ Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName); } +/// Called on well formed \#pragma strict_gs_check(). +void Sema::ActOnPragmaMSStrictGuardStackCheck(SourceLocation PragmaLocation, + PragmaMsStackAction Action, + bool Value) { + if (Action & PSK_Pop && StrictGuardStackCheckStack.Stack.empty()) + Diag(PragmaLocation, diag::warn_pragma_pop_failed) << "strict_gs_check" + << "stack empty"; + + StrictGuardStackCheckStack.Act(PragmaLocation, Action, StringRef(), Value); +} + /// Called on well formed \#pragma bss_seg(). void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation, int SectionFlags, StringLiteral *SegmentName) { @@ -696,6 +802,42 @@ CurInitSegLoc = PragmaLocation; } +void Sema::ActOnPragmaMSAllocText( + SourceLocation PragmaLocation, StringRef Section, + const SmallVector<std::tuple<IdentifierInfo *, SourceLocation>> + &Functions) { + if (!CurContext->getRedeclContext()->isFileContext()) { + Diag(PragmaLocation, diag::err_pragma_expected_file_scope) << "alloc_text"; + return; + } + + for (auto &Function : Functions) { + IdentifierInfo *II; + SourceLocation Loc; + std::tie(II, Loc) = Function; + + DeclarationName DN(II); + NamedDecl *ND = LookupSingleName(TUScope, DN, Loc, LookupOrdinaryName); + if (!ND) { + Diag(Loc, diag::err_undeclared_use) << II->getName(); + return; + } + + auto *FD = dyn_cast<FunctionDecl>(ND->getCanonicalDecl()); + if (!FD) { + Diag(Loc, diag::err_pragma_alloc_text_not_function); + return; + } + + if (getLangOpts().CPlusPlus && !FD->isInExternCContext()) { + Diag(Loc, diag::err_pragma_alloc_text_c_linkage); + return; + } + + FunctionToSectionMap[II->getName()] = std::make_tuple(Section, Loc); + } +} + void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope, SourceLocation PragmaLoc) { @@ -791,7 +933,7 @@ OS << (I.index() == Rules.size() - 1 ? ", and " : ", "); OS << "'" << attr::getSubjectMatchRuleSpelling(I.value()) << "'"; } - return OS.str(); + return Result; } } // end anonymous namespace @@ -1020,6 +1162,25 @@ OptimizeOffPragmaLocation = PragmaLoc; } +void Sema::ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn) { + if (!CurContext->getRedeclContext()->isFileContext()) { + Diag(Loc, diag::err_pragma_expected_file_scope) << "optimize"; + return; + } + + MSPragmaOptimizeIsOn = IsOn; +} + +void Sema::ActOnPragmaMSFunction( + SourceLocation Loc, const llvm::SmallVectorImpl<StringRef> &NoBuiltins) { + if (!CurContext->getRedeclContext()->isFileContext()) { + Diag(Loc, diag::err_pragma_expected_file_scope) << "function"; + return; + } + + MSFunctionNoBuiltins.insert(NoBuiltins.begin(), NoBuiltins.end()); +} + void Sema::AddRangeBasedOptnone(FunctionDecl *FD) { // In the future, check other pragmas if they're implemented (e.g. pragma // optimize 0 will probably map to this functionality too). @@ -1027,6 +1188,29 @@ AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation); } +void Sema::AddSectionMSAllocText(FunctionDecl *FD) { + if (!FD->getIdentifier()) + return; + + StringRef Name = FD->getName(); + auto It = FunctionToSectionMap.find(Name); + if (It != FunctionToSectionMap.end()) { + StringRef Section; + SourceLocation Loc; + std::tie(Section, Loc) = It->second; + + if (!FD->hasAttr<SectionAttr>()) + FD->addAttr(SectionAttr::CreateImplicit(Context, Section)); + } +} + +void Sema::ModifyFnAttributesMSPragmaOptimize(FunctionDecl *FD) { + // Don't modify the function attributes if it's "on". "on" resets the + // optimizations to the ones listed on the command line + if (!MSPragmaOptimizeIsOn) + AddOptnoneAttributeIfNoConflicts(FD, FD->getBeginLoc()); +} + void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, SourceLocation Loc) { // Don't add a conflicting attribute. No diagnostic is needed. @@ -1041,6 +1225,13 @@ FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc)); } +void Sema::AddImplicitMSFunctionNoBuiltinAttr(FunctionDecl *FD) { + SmallVector<StringRef> V(MSFunctionNoBuiltins.begin(), + MSFunctionNoBuiltins.end()); + if (!MSFunctionNoBuiltins.empty()) + FD->addAttr(NoBuiltinAttr::CreateImplicit(Context, V.data(), V.size())); +} + typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack; enum : unsigned { NoVisibility = ~0U }; @@ -1114,22 +1305,32 @@ } void Sema::ActOnPragmaFPReassociate(SourceLocation Loc, bool IsEnabled) { + if (IsEnabled) { + // For value unsafe context, combining this pragma with eval method + // setting is not recommended. See comment in function FixupInvocation#506. + int Reason = -1; + if (getLangOpts().getFPEvalMethod() != LangOptions::FEM_UnsetOnCommandLine) + // Eval method set using the option 'ffp-eval-method'. + Reason = 1; + if (PP.getLastFPEvalPragmaLocation().isValid()) + // Eval method set using the '#pragma clang fp eval_method'. + // We could have both an option and a pragma used to the set the eval + // method. The pragma overrides the option in the command line. The Reason + // of the diagnostic is overriden too. + Reason = 0; + if (Reason != -1) + Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context) + << Reason << 4; + } FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); NewFPFeatures.setAllowFPReassociateOverride(IsEnabled); FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); } -void Sema::setRoundingMode(SourceLocation Loc, llvm::RoundingMode FPR) { - // C2x: 7.6.2p3 If the FE_DYNAMIC mode is specified and FENV_ACCESS is "off", - // the translator may assume that the default rounding mode is in effect. - if (FPR == llvm::RoundingMode::Dynamic && - !CurFPFeatures.getAllowFEnvAccess() && - CurFPFeatures.getFPExceptionMode() == LangOptions::FPE_Ignore) - FPR = llvm::RoundingMode::NearestTiesToEven; - +void Sema::ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode FPR) { FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); - NewFPFeatures.setRoundingModeOverride(FPR); + NewFPFeatures.setConstRoundingModeOverride(FPR); FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); } @@ -1137,14 +1338,13 @@ void Sema::setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind FPE) { FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); - NewFPFeatures.setFPExceptionModeOverride(FPE); + NewFPFeatures.setSpecifiedExceptionModeOverride(FPE); FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); } void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) { FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); - auto LO = getLangOpts(); if (IsEnabled) { // Verify Microsoft restriction: // You can't enable fenv_access unless precise semantics are enabled. @@ -1152,16 +1352,10 @@ // 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); - // Enabling FENV access sets the RoundingMode to Dynamic. - // and ExceptionBehavior to Strict - NewFPFeatures.setRoundingModeOverride(llvm::RoundingMode::Dynamic); - NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict); - } else { - NewFPFeatures.setAllowFEnvAccessOverride(false); } + NewFPFeatures.setAllowFEnvAccessOverride(IsEnabled); FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); - CurFPFeatures = NewFPFeatures.applyOverrides(LO); + CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); } void Sema::ActOnPragmaFPExceptions(SourceLocation Loc, @@ -1212,8 +1406,9 @@ } template <typename Ty> -static bool checkCommonAttributeFeatures(Sema& S, const Ty *Node, - const ParsedAttr& A) { +static bool checkCommonAttributeFeatures(Sema &S, const Ty *Node, + const ParsedAttr &A, + bool SkipArgCountCheck) { // Several attributes carry different semantics than the parsing requires, so // those are opted out of the common argument checks. // @@ -1239,26 +1434,30 @@ if (A.hasCustomParsing()) return false; - if (A.getMinArgs() == A.getMaxArgs()) { - // If there are no optional arguments, then checking for the argument count - // is trivial. - if (!A.checkExactlyNumArgs(S, A.getMinArgs())) - return true; - } else { - // There are optional arguments, so checking is slightly more involved. - if (A.getMinArgs() && !A.checkAtLeastNumArgs(S, A.getMinArgs())) - return true; - else if (!A.hasVariadicArg() && A.getMaxArgs() && - !A.checkAtMostNumArgs(S, A.getMaxArgs())) - return true; + if (!SkipArgCountCheck) { + if (A.getMinArgs() == A.getMaxArgs()) { + // If there are no optional arguments, then checking for the argument + // count is trivial. + if (!A.checkExactlyNumArgs(S, A.getMinArgs())) + return true; + } else { + // There are optional arguments, so checking is slightly more involved. + if (A.getMinArgs() && !A.checkAtLeastNumArgs(S, A.getMinArgs())) + return true; + else if (!A.hasVariadicArg() && A.getMaxArgs() && + !A.checkAtMostNumArgs(S, A.getMaxArgs())) + return true; + } } return false; } -bool Sema::checkCommonAttributeFeatures(const Decl *D, const ParsedAttr &A) { - return ::checkCommonAttributeFeatures(*this, D, A); +bool Sema::checkCommonAttributeFeatures(const Decl *D, const ParsedAttr &A, + bool SkipArgCountCheck) { + return ::checkCommonAttributeFeatures(*this, D, A, SkipArgCountCheck); } -bool Sema::checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A) { - return ::checkCommonAttributeFeatures(*this, S, A); +bool Sema::checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A, + bool SkipArgCountCheck) { + return ::checkCommonAttributeFeatures(*this, S, A, SkipArgCountCheck); }