https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/203838
There are some instances where we want to know _if_ a diagnostic has been emitted, but we're not interested in the actual diagnostic. Emitting the diagnostics can be rather costly, especially because we add the callstack as notes. >From 55f9cbb4e5b9e64191ca524845b202c54a90c8a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]> Date: Mon, 15 Jun 2026 07:19:24 +0200 Subject: [PATCH] DiagEmmitted flag --- clang/include/clang/AST/Expr.h | 4 ++++ clang/lib/AST/ByteCode/State.cpp | 3 +++ clang/lib/AST/ComputeDependence.cpp | 6 ++---- clang/lib/AST/ExprConstant.cpp | 6 ++---- clang/lib/Sema/SemaExpr.cpp | 4 +--- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index eeac69cb1d0eb..b17957f2c08f6 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -619,6 +619,10 @@ class Expr : public ValueStmt { /// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB. bool HasUndefinedBehavior = false; + /// Whether any diagnostic has been emitted. This is set regardless of + /// whether @ref #Diag is set or not. + bool DiagEmitted = false; + /// Diag - If this is non-null, it will be filled in with a stack of notes /// indicating why evaluation failed (or why it failed to produce a constant /// expression). diff --git a/clang/lib/AST/ByteCode/State.cpp b/clang/lib/AST/ByteCode/State.cpp index e612c6863e60f..e62b77272046c 100644 --- a/clang/lib/AST/ByteCode/State.cpp +++ b/clang/lib/AST/ByteCode/State.cpp @@ -25,6 +25,7 @@ OptionalDiagnostic State::FFDiag(SourceLocation Loc, diag::kind DiagId, OptionalDiagnostic State::FFDiag(const Expr *E, diag::kind DiagId, unsigned ExtraNotes) { + EvalStatus.DiagEmitted = true; if (EvalStatus.Diag) return diag(E->getExprLoc(), DiagId, ExtraNotes, false); setActiveDiagnostic(false); @@ -33,6 +34,7 @@ OptionalDiagnostic State::FFDiag(const Expr *E, diag::kind DiagId, OptionalDiagnostic State::FFDiag(SourceInfo SI, diag::kind DiagId, unsigned ExtraNotes) { + EvalStatus.DiagEmitted = true; if (EvalStatus.Diag) return diag(SI.getLoc(), DiagId, ExtraNotes, false); setActiveDiagnostic(false); @@ -41,6 +43,7 @@ OptionalDiagnostic State::FFDiag(SourceInfo SI, diag::kind DiagId, OptionalDiagnostic State::CCEDiag(SourceLocation Loc, diag::kind DiagId, unsigned ExtraNotes) { + EvalStatus.DiagEmitted = true; // Don't override a previous diagnostic. Don't bother collecting // diagnostics if we're evaluating for overflow. if (!EvalStatus.Diag || !EvalStatus.Diag->empty()) { diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp index 34167eee8d8f2..95cfd19c0bcc8 100644 --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -57,11 +57,9 @@ ExprDependence clang::computeDependence(UnaryOperator *E, if (Ctx.getLangOpts().CPlusPlus && E->getOpcode() == UO_AddrOf && !(Dep & ExprDependence::Value)) { Expr::EvalResult Result; - SmallVector<PartialDiagnosticAt, 8> Diag; - Result.Diag = &Diag; // FIXME: This doesn't enforce the C++98 constant expression rules. - if (E->getSubExpr()->EvaluateAsConstantExpr(Result, Ctx) && Diag.empty() && - Result.Val.isLValue()) { + if (E->getSubExpr()->EvaluateAsConstantExpr(Result, Ctx) && + !Result.DiagEmitted && Result.Val.isLValue()) { auto *VD = Result.Val.getLValueBase().dyn_cast<const ValueDecl *>(); if (VD && VD->isTemplated()) { auto *VarD = dyn_cast<VarDecl>(VD); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 1642c41a99a2f..0c5bf231c9f0a 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -22292,17 +22292,15 @@ bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result) const { // Build evaluation settings. Expr::EvalStatus Status; - SmallVector<PartialDiagnosticAt, 8> Diags; - Status.Diag = &Diags; EvalInfo Info(Ctx, Status, EvaluationMode::ConstantExpression); bool IsConstExpr = ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch) && - // FIXME: We don't produce a diagnostic for this, but the callers that + // NOTE: We don't produce a diagnostic for this, but the callers that // call us on arbitrary full-expressions should generally not care. Info.discardCleanups() && !Status.HasSideEffects; - return IsConstExpr && Diags.empty(); + return IsConstExpr && !Status.DiagEmitted; } bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f2745425588f5..675d0bd389e28 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -18340,12 +18340,10 @@ ExprResult Sema::CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl) { // immediate invocation. APValue Cached; auto CheckConstantExpressionAndKeepResult = [&]() { - llvm::SmallVector<PartialDiagnosticAt, 8> Notes; Expr::EvalResult Eval; - Eval.Diag = &Notes; bool Res = E.get()->EvaluateAsConstantExpr( Eval, getASTContext(), ConstantExprKind::ImmediateInvocation); - if (Res && Notes.empty()) { + if (Res && !Eval.DiagEmitted) { Cached = std::move(Eval.Val); return true; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
