[clang] nonblocking/nonallocating attributes (was: nolock/noalloc) (PR #84983)
Chris Apple via cfe-commits
cfe-commits at lists.llvm.org
Sat May 4 06:11:15 PDT 2024
================
@@ -7963,6 +7967,148 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
llvm_unreachable("unexpected attribute kind!");
}
+ExprResult Sema::ActOnEffectExpression(Expr *CondExpr, FunctionEffectMode &Mode,
+ bool RequireConstexpr) {
+ // see checkFunctionConditionAttr, Sema::CheckCXXBooleanCondition
+ if (RequireConstexpr || !CondExpr->isTypeDependent()) {
+ ExprResult E = PerformContextuallyConvertToBool(CondExpr);
+ if (E.isInvalid())
+ return E;
+ CondExpr = E.get();
+ if (RequireConstexpr || !CondExpr->isValueDependent()) {
+ llvm::APSInt CondInt;
+ E = VerifyIntegerConstantExpression(
+ E.get(), &CondInt,
+ // TODO: have our own diagnostic
+ diag::err_constexpr_if_condition_expression_is_not_constant);
+ if (E.isInvalid()) {
+ return E;
+ }
+ Mode =
+ (CondInt != 0) ? FunctionEffectMode::True : FunctionEffectMode::False;
+ } else {
+ Mode = FunctionEffectMode::Dependent;
+ }
+ } else {
+ Mode = FunctionEffectMode::Dependent;
+ }
+ return CondExpr;
+}
+
+static bool
+handleNonBlockingNonAllocatingTypeAttr(TypeProcessingState &TPState,
+ ParsedAttr &PAttr, QualType &QT,
+ FunctionTypeUnwrapper &Unwrapped) {
+ // Delay if this is not a function type.
+ if (!Unwrapped.isFunctionType())
+ return false;
+
+ // Require FunctionProtoType
+ auto *FPT = Unwrapped.get()->getAs<FunctionProtoType>();
+ if (FPT == nullptr) {
+ // TODO: special diagnostic?
+ return false;
+ }
+
+ // Parse the new attribute.
+ // non/blocking or non/allocating? Or conditional (computed)?
+ const bool isNonBlocking = PAttr.getKind() == ParsedAttr::AT_NonBlocking ||
+ PAttr.getKind() == ParsedAttr::AT_Blocking;
+ Sema &S = TPState.getSema();
+
+ FunctionEffectMode NewMode = FunctionEffectMode::None;
+ Expr *CondExpr = nullptr; // only valid if dependent
+
+ if (PAttr.getKind() == ParsedAttr::AT_NonBlocking ||
+ PAttr.getKind() == ParsedAttr::AT_NonAllocating) {
+ if (!PAttr.checkAtMostNumArgs(S, 1)) {
+ PAttr.setInvalid();
+ return true;
+ }
+
+ // Parse the conditional expression, if any
+ if (PAttr.getNumArgs() == 1) {
+ CondExpr = PAttr.getArgAsExpr(0);
+ ExprResult E = S.ActOnEffectExpression(CondExpr, NewMode);
+ if (E.isInvalid())
+ return false;
+ CondExpr = NewMode == FunctionEffectMode::Dependent ? E.get() : nullptr;
+ } else {
+ NewMode = FunctionEffectMode::True;
+ }
+ } else {
+ // This is the `blocking` or `allocating` attribute.
+ if (S.CheckAttrNoArgs(PAttr))
+ return true;
+ NewMode = FunctionEffectMode::False;
+ }
+
+ const FunctionEffect::Kind FEKind =
+ (NewMode == FunctionEffectMode::False)
+ ? (isNonBlocking ? FunctionEffect::Kind::Blocking
+ : FunctionEffect::Kind::Allocating)
+ : (isNonBlocking ? FunctionEffect::Kind::NonBlocking
+ : FunctionEffect::Kind::NonAllocating);
+ const FunctionEffectWithCondition NewEC{FunctionEffect(FEKind),
+ FunctionEffectCondition(CondExpr)};
+
+ // Diagnose the newly provided attribute as incompatible with a previous one.
+ auto incompatible = [&](const FunctionEffectWithCondition &PrevEC) {
+ S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
+ << ("'" + NewEC.description() + "'")
+ << ("'" + PrevEC.description() + "'") << false;
+ // we don't necessarily have the location of the previous attribute,
+ // so no note.
+ PAttr.setInvalid();
+ return true;
+ };
+
+ // Find previous attributes
+ std::optional<FunctionEffectWithCondition> PrevNonBlocking;
+ std::optional<FunctionEffectWithCondition> PrevNonAllocating;
+
+ for (const FunctionEffectWithCondition &PrevEC : FPT->getFunctionEffects()) {
+ if (PrevEC.Effect.kind() == FEKind ||
+ PrevEC.Effect.oppositeKind() == FEKind)
+ return incompatible(PrevEC);
+ switch (PrevEC.Effect.kind()) {
+ case FunctionEffect::Kind::Blocking:
+ case FunctionEffect::Kind::NonBlocking:
+ PrevNonBlocking = PrevEC;
+ break;
+ case FunctionEffect::Kind::Allocating:
+ case FunctionEffect::Kind::NonAllocating:
+ PrevNonAllocating = PrevEC;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (isNonBlocking) {
----------------
cjappl wrote:
minor: only var I've seen so far not UpperCamelCase
https://github.com/llvm/llvm-project/pull/84983
More information about the cfe-commits
mailing list