diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaStmtAttr.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaStmtAttr.cpp | 121 |
1 files changed, 114 insertions, 7 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaStmtAttr.cpp b/contrib/llvm-project/clang/lib/Sema/SemaStmtAttr.cpp index e6a4d3e63e4a..7f452d177c16 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaStmtAttr.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaStmtAttr.cpp @@ -16,6 +16,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/ParsedAttr.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/StringExtras.h" @@ -109,9 +110,16 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, SetHints(LoopHintAttr::Unroll, LoopHintAttr::Disable); } else if (PragmaName == "unroll") { // #pragma unroll N - if (ValueExpr) - SetHints(LoopHintAttr::UnrollCount, LoopHintAttr::Numeric); - else + if (ValueExpr) { + if (!ValueExpr->isValueDependent()) { + auto Value = ValueExpr->EvaluateKnownConstInt(S.getASTContext()); + if (Value.isZero() || Value.isOne()) + SetHints(LoopHintAttr::Unroll, LoopHintAttr::Disable); + else + SetHints(LoopHintAttr::UnrollCount, LoopHintAttr::Numeric); + } else + SetHints(LoopHintAttr::UnrollCount, LoopHintAttr::Numeric); + } else SetHints(LoopHintAttr::Unroll, LoopHintAttr::Enable); } else if (PragmaName == "nounroll_and_jam") { SetHints(LoopHintAttr::UnrollAndJam, LoopHintAttr::Disable); @@ -142,7 +150,8 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, if (Option == LoopHintAttr::VectorizeWidth) { assert((ValueExpr || (StateLoc && StateLoc->Ident)) && "Attribute must have a valid value expression or argument."); - if (ValueExpr && S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc())) + if (ValueExpr && S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc(), + /*AllowZero=*/false)) return nullptr; if (StateLoc && StateLoc->Ident && StateLoc->Ident->isStr("scalable")) State = LoopHintAttr::ScalableWidth; @@ -152,7 +161,8 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, Option == LoopHintAttr::UnrollCount || Option == LoopHintAttr::PipelineInitiationInterval) { assert(ValueExpr && "Attribute must have a valid value expression."); - if (S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc())) + if (S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc(), + /*AllowZero=*/false)) return nullptr; State = LoopHintAttr::Numeric; } else if (Option == LoopHintAttr::Vectorize || @@ -276,7 +286,7 @@ bool Sema::CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt, static Attr *handleNoInlineAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range) { NoInlineAttr NIA(S.Context, A); - if (!NIA.isClangNoInline()) { + if (!NIA.isStmtNoInline()) { S.Diag(St->getBeginLoc(), diag::warn_function_attribute_ignored_in_stmt) << "[[clang::noinline]]"; return nullptr; @@ -303,6 +313,15 @@ static Attr *handleAlwaysInlineAttr(Sema &S, Stmt *St, const ParsedAttr &A, return ::new (S.Context) AlwaysInlineAttr(S.Context, A); } +static Attr *handleCXXAssumeAttr(Sema &S, Stmt *St, const ParsedAttr &A, + SourceRange Range) { + ExprResult Res = S.ActOnCXXAssumeAttr(St, A, Range); + if (!Res.isUsable()) + return nullptr; + + return ::new (S.Context) CXXAssumeAttr(S.Context, A, Res.get()); +} + static Attr *handleMustTailAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range) { // Validation is in Sema::ActOnAttributedStmt(). @@ -397,8 +416,8 @@ static void CheckForDuplicateLoopAttrs(Sema &S, ArrayRef<const Attr *> Attrs) { << *FirstItr; S.Diag((*FirstItr)->getLocation(), diag::note_previous_attribute); } - return; } + return; } static Attr *handleMSConstexprAttr(Sema &S, Stmt *St, const ParsedAttr &A, @@ -566,6 +585,39 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A, return ::new (S.Context) OpenCLUnrollHintAttr(S.Context, A, UnrollFactor); } +static Attr *handleHLSLLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, + SourceRange Range) { + + if (A.getSemanticSpelling() == HLSLLoopHintAttr::Spelling::Microsoft_loop && + !A.checkAtMostNumArgs(S, 0)) + return nullptr; + + unsigned UnrollFactor = 0; + if (A.getNumArgs() == 1) { + + if (A.isArgIdent(0)) { + S.Diag(A.getLoc(), diag::err_attribute_argument_type) + << A << AANT_ArgumentIntegerConstant << A.getRange(); + return nullptr; + } + + Expr *E = A.getArgAsExpr(0); + + if (S.CheckLoopHintExpr(E, St->getBeginLoc(), + /*AllowZero=*/false)) + return nullptr; + + std::optional<llvm::APSInt> ArgVal = E->getIntegerConstantExpr(S.Context); + // CheckLoopHintExpr handles non int const cases + assert(ArgVal != std::nullopt && "ArgVal should be an integer constant."); + int Val = ArgVal->getSExtValue(); + // CheckLoopHintExpr handles negative and zero cases + assert(Val > 0 && "Val should be a positive integer greater than zero."); + UnrollFactor = static_cast<unsigned>(Val); + } + return ::new (S.Context) HLSLLoopHintAttr(S.Context, A, UnrollFactor); +} + static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range) { if (A.isInvalid() || A.getKind() == ParsedAttr::IgnoredAttribute) @@ -594,10 +646,14 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, switch (A.getKind()) { case ParsedAttr::AT_AlwaysInline: return handleAlwaysInlineAttr(S, St, A, Range); + case ParsedAttr::AT_CXXAssume: + return handleCXXAssumeAttr(S, St, A, Range); case ParsedAttr::AT_FallThrough: return handleFallThroughAttr(S, St, A, Range); case ParsedAttr::AT_LoopHint: return handleLoopHintAttr(S, St, A, Range); + case ParsedAttr::AT_HLSLLoopHint: + return handleHLSLLoopHintAttr(S, St, A, Range); case ParsedAttr::AT_OpenCLUnrollHint: return handleOpenCLUnrollHint(S, St, A, Range); case ParsedAttr::AT_Suppress: @@ -641,3 +697,54 @@ bool Sema::CheckRebuiltStmtAttributes(ArrayRef<const Attr *> Attrs) { CheckForDuplicateLoopAttrs<CodeAlignAttr>(*this, Attrs); return false; } + +ExprResult Sema::ActOnCXXAssumeAttr(Stmt *St, const ParsedAttr &A, + SourceRange Range) { + if (A.getNumArgs() != 1 || !A.getArgAsExpr(0)) { + Diag(A.getLoc(), diag::err_attribute_wrong_number_arguments) + << A.getAttrName() << 1 << Range; + return ExprError(); + } + + auto *Assumption = A.getArgAsExpr(0); + + if (DiagnoseUnexpandedParameterPack(Assumption)) { + return ExprError(); + } + + if (Assumption->getDependence() == ExprDependence::None) { + ExprResult Res = BuildCXXAssumeExpr(Assumption, A.getAttrName(), Range); + if (Res.isInvalid()) + return ExprError(); + Assumption = Res.get(); + } + + if (!getLangOpts().CPlusPlus23 && + A.getSyntax() == AttributeCommonInfo::AS_CXX11) + Diag(A.getLoc(), diag::ext_cxx23_attr) << A << Range; + + return Assumption; +} + +ExprResult Sema::BuildCXXAssumeExpr(Expr *Assumption, + const IdentifierInfo *AttrName, + SourceRange Range) { + ExprResult Res = CorrectDelayedTyposInExpr(Assumption); + if (Res.isInvalid()) + return ExprError(); + + Res = CheckPlaceholderExpr(Res.get()); + if (Res.isInvalid()) + return ExprError(); + + Res = PerformContextuallyConvertToBool(Res.get()); + if (Res.isInvalid()) + return ExprError(); + + Assumption = Res.get(); + if (Assumption->HasSideEffects(Context)) + Diag(Assumption->getBeginLoc(), diag::warn_assume_side_effects) + << AttrName << Range; + + return Assumption; +} |