https://github.com/tbaederr updated 
https://github.com/llvm/llvm-project/pull/135806

>From 038f7cbb3cfa03045e1ccdc10ea68842ec85232c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com>
Date: Mon, 14 Apr 2025 17:18:50 +0200
Subject: [PATCH] [clang][bytecode] Explicitly mark constexpr-unknown variables
 as such

Instead of trying to figure out what's constexpr-unknown later on.
---
 clang/lib/AST/ByteCode/Compiler.cpp | 24 +++++++++++++-------
 clang/lib/AST/ByteCode/Compiler.h   | 12 ++++++----
 clang/lib/AST/ByteCode/Descriptor.h |  1 +
 clang/lib/AST/ByteCode/Disasm.cpp   |  2 ++
 clang/lib/AST/ByteCode/Interp.cpp   |  9 ++++----
 clang/lib/AST/ByteCode/Program.cpp  |  2 +-
 clang/test/AST/ByteCode/codegen.cpp | 35 +++++++++++++++++++++++++++--
 7 files changed, 65 insertions(+), 20 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index 2e22c85ed5f6d..afd8d09a088cd 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -4293,7 +4293,8 @@ bool Compiler<Emitter>::emitConst(const APSInt &Value, 
const Expr *E) {
 
 template <class Emitter>
 unsigned Compiler<Emitter>::allocateLocalPrimitive(
-    DeclTy &&Src, PrimType Ty, bool IsConst, const ValueDecl *ExtendingDecl) {
+    DeclTy &&Src, PrimType Ty, bool IsConst, const ValueDecl *ExtendingDecl,
+    bool IsConstexprUnknown) {
   // Make sure we don't accidentally register the same decl twice.
   if (const auto *VD =
           dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
@@ -4307,6 +4308,7 @@ unsigned Compiler<Emitter>::allocateLocalPrimitive(
   //   or isa<MaterializeTemporaryExpr>().
   Descriptor *D = P.createDescriptor(Src, Ty, nullptr, 
Descriptor::InlineDescMD,
                                      IsConst, isa<const Expr *>(Src));
+  D->IsConstexprUnknown = IsConstexprUnknown;
   Scope::Local Local = this->createLocal(D);
   if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>()))
     Locals.insert({VD, Local});
@@ -4320,7 +4322,8 @@ unsigned Compiler<Emitter>::allocateLocalPrimitive(
 template <class Emitter>
 std::optional<unsigned>
 Compiler<Emitter>::allocateLocal(DeclTy &&Src, QualType Ty,
-                                 const ValueDecl *ExtendingDecl) {
+                                 const ValueDecl *ExtendingDecl,
+                                 bool IsConstexprUnknown) {
   // Make sure we don't accidentally register the same decl twice.
   if ([[maybe_unused]] const auto *VD =
           dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
@@ -4349,6 +4352,7 @@ Compiler<Emitter>::allocateLocal(DeclTy &&Src, QualType 
Ty,
       IsTemporary, /*IsMutable=*/false, Init);
   if (!D)
     return std::nullopt;
+  D->IsConstexprUnknown = IsConstexprUnknown;
 
   Scope::Local Local = this->createLocal(D);
   if (Key)
@@ -4460,9 +4464,10 @@ bool Compiler<Emitter>::visitExpr(const Expr *E, bool 
DestroyToplevelScope) {
 }
 
 template <class Emitter>
-VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD) {
+VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD,
+                                              bool IsConstexprUnknown) {
 
-  auto R = this->visitVarDecl(VD, /*Toplevel=*/true);
+  auto R = this->visitVarDecl(VD, /*Toplevel=*/true, IsConstexprUnknown);
 
   if (R.notCreated())
     return R;
@@ -4550,7 +4555,8 @@ bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl 
*VD,
 
 template <class Emitter>
 VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
-                                                 bool Toplevel) {
+                                                 bool Toplevel,
+                                                 bool IsConstexprUnknown) {
   // We don't know what to do with these, so just return false.
   if (VD->getType().isNull())
     return false;
@@ -4620,7 +4626,8 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const 
VarDecl *VD,
 
     if (VarT) {
       unsigned Offset = this->allocateLocalPrimitive(
-          VD, *VarT, VD->getType().isConstQualified());
+          VD, *VarT, VD->getType().isConstQualified(), nullptr,
+          IsConstexprUnknown);
       if (Init) {
         // If this is a toplevel declaration, create a scope for the
         // initializer.
@@ -4636,7 +4643,8 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const 
VarDecl *VD,
         }
       }
     } else {
-      if (std::optional<unsigned> Offset = this->allocateLocal(VD)) {
+      if (std::optional<unsigned> Offset = this->allocateLocal(
+              VD, VD->getType(), nullptr, IsConstexprUnknown)) {
         if (!Init)
           return true;
 
@@ -6461,7 +6469,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, 
const Expr *E) {
 
   // In case we need to re-visit a declaration.
   auto revisit = [&](const VarDecl *VD) -> bool {
-    auto VarState = this->visitDecl(VD);
+    auto VarState = this->visitDecl(VD, /*IsConstexprUnknown=*/true);
 
     if (VarState.notCreated())
       return true;
diff --git a/clang/lib/AST/ByteCode/Compiler.h 
b/clang/lib/AST/ByteCode/Compiler.h
index 858957367d85d..a3090a8a31189 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -286,8 +286,10 @@ class Compiler : public 
ConstStmtVisitor<Compiler<Emitter>, bool>,
   /// intact.
   bool delegate(const Expr *E);
   /// Creates and initializes a variable from the given decl.
-  VarCreationState visitVarDecl(const VarDecl *VD, bool Toplevel = false);
-  VarCreationState visitDecl(const VarDecl *VD);
+  VarCreationState visitVarDecl(const VarDecl *VD, bool Toplevel = false,
+                                bool IsConstexprUnknown = false);
+  VarCreationState visitDecl(const VarDecl *VD,
+                             bool IsConstexprUnknown = false);
   /// Visit an APValue.
   bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E);
   bool visitAPValueInitializer(const APValue &Val, const Expr *E, QualType T);
@@ -303,12 +305,14 @@ class Compiler : public 
ConstStmtVisitor<Compiler<Emitter>, bool>,
 
   /// Creates a local primitive value.
   unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst,
-                                  const ValueDecl *ExtendingDecl = nullptr);
+                                  const ValueDecl *ExtendingDecl = nullptr,
+                                  bool IsConstexprUnknown = false);
 
   /// Allocates a space storing a local given its type.
   std::optional<unsigned>
   allocateLocal(DeclTy &&Decl, QualType Ty = QualType(),
-                const ValueDecl *ExtendingDecl = nullptr);
+                const ValueDecl *ExtendingDecl = nullptr,
+                bool IsConstexprUnknown = false);
   std::optional<unsigned> allocateTemporary(const Expr *E);
 
 private:
diff --git a/clang/lib/AST/ByteCode/Descriptor.h 
b/clang/lib/AST/ByteCode/Descriptor.h
index 9acabfd31d80b..a0705cc8c377f 100644
--- a/clang/lib/AST/ByteCode/Descriptor.h
+++ b/clang/lib/AST/ByteCode/Descriptor.h
@@ -168,6 +168,7 @@ struct Descriptor final {
   const bool IsArray = false;
   /// Flag indicating if this is a dummy descriptor.
   bool IsDummy = false;
+  bool IsConstexprUnknown = false;
 
   /// Storage management methods.
   const BlockCtorFn CtorFn = nullptr;
diff --git a/clang/lib/AST/ByteCode/Disasm.cpp 
b/clang/lib/AST/ByteCode/Disasm.cpp
index d4c9ce6050b85..4bdf0f0afb1b0 100644
--- a/clang/lib/AST/ByteCode/Disasm.cpp
+++ b/clang/lib/AST/ByteCode/Disasm.cpp
@@ -376,6 +376,8 @@ LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream 
&OS) const {
 
   if (isDummy())
     OS << " dummy";
+  if (IsConstexprUnknown)
+    OS << " constexpr-unknown";
 }
 
 /// Dump descriptor, including all valid offsets.
diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index 3e1f36da8925f..4625154ac353d 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -299,15 +299,14 @@ void cleanupAfterFunctionCall(InterpState &S, CodePtr 
OpPC,
     TYPE_SWITCH(Ty, S.Stk.discard<T>());
 }
 
-// FIXME: Instead of using this fairly expensive test, we should
-// just mark constexpr-unknown values when creating them.
 bool isConstexprUnknown(const Pointer &P) {
   if (!P.isBlockPointer())
     return false;
+
   if (P.isDummy())
-    return false;
-  const VarDecl *VD = P.block()->getDescriptor()->asVarDecl();
-  return VD && VD->hasLocalStorage() && !isa<ParmVarDecl>(VD);
+    return isa_and_nonnull<ParmVarDecl>(P.getDeclDesc()->asValueDecl());
+
+  return P.getDeclDesc()->IsConstexprUnknown;
 }
 
 bool CheckBCPResult(InterpState &S, const Pointer &Ptr) {
diff --git a/clang/lib/AST/ByteCode/Program.cpp 
b/clang/lib/AST/ByteCode/Program.cpp
index c83f5579fd55f..fdb7b960ff06d 100644
--- a/clang/lib/AST/ByteCode/Program.cpp
+++ b/clang/lib/AST/ByteCode/Program.cpp
@@ -156,7 +156,7 @@ unsigned Program::getOrCreateDummy(const DeclTy &D) {
   if (const auto *E = dyn_cast<const Expr *>(D)) {
     QT = E->getType();
   } else {
-    const ValueDecl *VD = cast<ValueDecl>(cast<const Decl *>(D));
+    const auto *VD = cast<ValueDecl>(cast<const Decl *>(D));
     IsWeak = VD->isWeak();
     QT = VD->getType();
     if (const auto *RT = QT->getAs<ReferenceType>())
diff --git a/clang/test/AST/ByteCode/codegen.cpp 
b/clang/test/AST/ByteCode/codegen.cpp
index 7c853a20362b8..6f9e75eac6026 100644
--- a/clang/test/AST/ByteCode/codegen.cpp
+++ b/clang/test/AST/ByteCode/codegen.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s                     
                    | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s 
-fexperimental-new-constant-interpreter | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s -fcxx-exceptions    
                                     | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s -fcxx-exceptions 
-fexperimental-new-constant-interpreter | FileCheck %s
 
 #ifdef __SIZEOF_INT128__
 // CHECK: @PR11705 = global i128 0
@@ -104,3 +104,34 @@ int notdead() {
 }
 // CHECK: _ZZ7notdeadvEN3$_0clEv
 // CHECK: ret i32 %cond
+
+/// The conmparison of those two parameters should NOT work.
+bool paramcmp(const int& lhs, const int& rhs) {
+  if (&lhs == &rhs)
+    return true;
+  return false;
+}
+// CHECK: _Z8paramcmpRKiS0_
+// CHECK: if.then
+// CHECK: if.end
+
+/// &x == &OuterX should work and return 0.
+class X {
+public:
+  X();
+  X(const X&);
+  X(const volatile X &);
+  ~X();
+};
+
+extern X OuterX;
+
+X test24() {
+  X x;
+  if (&x == &OuterX)
+    throw 0;
+  return x;
+}
+// CHECK: _Z6test24v
+// CHECK-NOT: eh.resume
+// CHECK-NOT: unreachable

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to