aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Sema/SemaStmtAttr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaStmtAttr.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaStmtAttr.cpp121
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;
+}