================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits