https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/109967
>From 29429e66580e242c4e6f1a9a86e9c0a5182b72fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Wed, 25 Sep 2024 13:50:19 +0200 Subject: [PATCH] [clang][bytecode] Override InConstantContext flag for immediate calls And fix the diagnostics for __builtin_is_constant_evaluated(). We can be in a non-constant context, but calling an immediate function always makes the context constant for the duration of that call. --- clang/lib/AST/ByteCode/Interp.cpp | 1 + clang/lib/AST/ByteCode/InterpBuiltin.cpp | 15 +++++++------- clang/lib/AST/ByteCode/InterpState.cpp | 7 +++++++ clang/lib/AST/ByteCode/InterpState.h | 24 ++++++++++++++++++++++- clang/test/CodeGenCXX/cxx2a-consteval.cpp | 8 ++++++++ 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index b9c85626ffa990..2f4a05a85753c0 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -1136,6 +1136,7 @@ bool Call(InterpState &S, CodePtr OpPC, const Function *Func, InterpFrame *FrameBefore = S.Current; S.Current = NewFrame.get(); + InterpStateCCOverride CCOverride(S, Func->getDecl()->isImmediateFunction()); APValue CallResult; // Note that we cannot assert(CallResult.hasValue()) here since // Ret() above only sets the APValue if the curent frame doesn't diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 68710f67be2003..82ed6d9e7a2ff4 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -136,16 +136,17 @@ static bool retPrimValue(InterpState &S, CodePtr OpPC, APValue &Result, static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { + unsigned Depth = S.Current->getDepth(); + auto isStdCall = [](const FunctionDecl *F) -> bool { + return F && F->isInStdNamespace() && F->getIdentifier() && + F->getIdentifier()->isStr("is_constant_evaluated"); + }; + const InterpFrame *Caller = Frame->Caller; // The current frame is the one for __builtin_is_constant_evaluated. // The one above that, potentially the one for std::is_constant_evaluated(). if (S.inConstantContext() && !S.checkingPotentialConstantExpression() && - Frame->Caller && S.getEvalStatus().Diag) { - auto isStdCall = [](const FunctionDecl *F) -> bool { - return F && F->isInStdNamespace() && F->getIdentifier() && - F->getIdentifier()->isStr("is_constant_evaluated"); - }; - const InterpFrame *Caller = Frame->Caller; - + S.getEvalStatus().Diag && + (Depth == 1 || (Depth == 2 && isStdCall(Caller->getCallee())))) { if (Caller->Caller && isStdCall(Caller->getCallee())) { const Expr *E = Caller->Caller->getExpr(Caller->getRetPC()); S.report(E->getExprLoc(), diff --git a/clang/lib/AST/ByteCode/InterpState.cpp b/clang/lib/AST/ByteCode/InterpState.cpp index 4ea05305540ee1..287c3bd3bca3a5 100644 --- a/clang/lib/AST/ByteCode/InterpState.cpp +++ b/clang/lib/AST/ByteCode/InterpState.cpp @@ -19,6 +19,13 @@ InterpState::InterpState(State &Parent, Program &P, InterpStack &Stk, Context &Ctx, SourceMapper *M) : Parent(Parent), M(M), P(P), Stk(Stk), Ctx(Ctx), Current(nullptr) {} +bool InterpState::inConstantContext() const { + if (ConstantContextOverride) + return *ConstantContextOverride; + + return Parent.InConstantContext; +} + InterpState::~InterpState() { while (Current) { InterpFrame *Next = Current->Caller; diff --git a/clang/lib/AST/ByteCode/InterpState.h b/clang/lib/AST/ByteCode/InterpState.h index 4b7371450cc98e..2a1311c86a2f2a 100644 --- a/clang/lib/AST/ByteCode/InterpState.h +++ b/clang/lib/AST/ByteCode/InterpState.h @@ -77,7 +77,7 @@ class InterpState final : public State, public SourceMapper { bool noteUndefinedBehavior() override { return Parent.noteUndefinedBehavior(); } - bool inConstantContext() const { return Parent.InConstantContext; } + bool inConstantContext() const; bool hasActiveDiagnostic() override { return Parent.hasActiveDiagnostic(); } void setActiveDiagnostic(bool Flag) override { Parent.setActiveDiagnostic(Flag); @@ -116,6 +116,7 @@ class InterpState final : public State, public SourceMapper { private: friend class EvaluationResult; + friend class InterpStateCCOverride; /// AST Walker state. State &Parent; /// Dead block chain. @@ -124,6 +125,7 @@ class InterpState final : public State, public SourceMapper { SourceMapper *M; /// Allocator used for dynamic allocations performed via the program. DynamicAllocator Alloc; + std::optional<bool> ConstantContextOverride; public: /// Reference to the module containing all bytecode. @@ -144,6 +146,26 @@ class InterpState final : public State, public SourceMapper { SeenGlobalTemporaries; }; +class InterpStateCCOverride final { +public: + InterpStateCCOverride(InterpState &Ctx, bool Value) + : Ctx(Ctx), OldCC(Ctx.ConstantContextOverride) { + // We only override this if the new value is true. + Enabled = Value; + if (Enabled) + Ctx.ConstantContextOverride = Value; + } + ~InterpStateCCOverride() { + if (Enabled) + Ctx.ConstantContextOverride = OldCC; + } + +private: + bool Enabled; + InterpState &Ctx; + std::optional<bool> OldCC; +}; + } // namespace interp } // namespace clang diff --git a/clang/test/CodeGenCXX/cxx2a-consteval.cpp b/clang/test/CodeGenCXX/cxx2a-consteval.cpp index a58a09554699db..bfeabc946da413 100644 --- a/clang/test/CodeGenCXX/cxx2a-consteval.cpp +++ b/clang/test/CodeGenCXX/cxx2a-consteval.cpp @@ -6,6 +6,14 @@ // RUN: %clang_cc1 -emit-llvm %s -Dconsteval="" -std=c++2a -triple x86_64-unknown-linux-gnu -o %t.ll // RUN: FileCheck -check-prefix=EXPR -input-file=%t.ll %s +// RUN: %clang_cc1 -emit-llvm %s -std=c++2a -triple x86_64-unknown-linux-gnu -o %t.ll -fexperimental-new-constant-interpreter +// RUN: FileCheck -check-prefix=EVAL -input-file=%t.ll %s +// RUN: FileCheck -check-prefix=EVAL-STATIC -input-file=%t.ll %s +// RUN: FileCheck -check-prefix=EVAL-FN -input-file=%t.ll %s +// +// RUN: %clang_cc1 -emit-llvm %s -Dconsteval="" -std=c++2a -triple x86_64-unknown-linux-gnu -o %t.ll -fexperimental-new-constant-interpreter +// RUN: FileCheck -check-prefix=EXPR -input-file=%t.ll %s + // there is two version of symbol checks to ensure // that the symbol we are looking for are correct // EVAL-NOT: @__cxx_global_var_init() _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits