[clang] a82f309 - [clang][bytecode] Allow more function calls in CPCE mode (#192597)

via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 17 03:04:18 PDT 2026


Author: Timm Baeder
Date: 2026-04-17T12:04:13+02:00
New Revision: a82f3093a05bf00bc959ba439a616efa787c8086

URL: https://github.com/llvm/llvm-project/commit/a82f3093a05bf00bc959ba439a616efa787c8086
DIFF: https://github.com/llvm/llvm-project/commit/a82f3093a05bf00bc959ba439a616efa787c8086.diff

LOG: [clang][bytecode] Allow more function calls in CPCE mode (#192597)

We previously didn't diagnose the attached test cases correctly.

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/Interp.cpp
    clang/lib/AST/ByteCode/Interp.h
    clang/lib/AST/ByteCode/Pointer.cpp
    clang/test/AST/ByteCode/new-delete.cpp
    clang/test/SemaCXX/cxx2a-consteval.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index f5fb9f6b7bbfa..6d1598655659d 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1008,9 +1008,6 @@ static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
     return false;
   }
 
-  if (S.checkingPotentialConstantExpression() && S.Current->getDepth() != 0)
-    return false;
-
   if (F->isValid() && F->hasBody() &&
       (F->isConstexpr() || (S.Current->MSVCConstexprAllowed &&
                             F->getDecl()->hasAttr<MSConstexprAttr>())))

diff  --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 2bc74fcfe7b95..0f7f2c4e1fdec 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -2070,7 +2070,7 @@ inline bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off,
 }
 
 inline bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
-  if (S.checkingPotentialConstantExpression())
+  if (S.checkingPotentialConstantExpression() && S.Current->isBottomFrame())
     return false;
   if (!CheckThis(S, OpPC))
     return false;

diff  --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp
index b1f88b2a3a316..b4e9afa6c1519 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -958,7 +958,8 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
     return std::nullopt;
 
   // Invalid to read from.
-  if (isDummy() || !isLive() || isPastEnd())
+  if (isDummy() || !isLive() || isPastEnd() ||
+      (isOnePastEnd() && !isZeroSizeArray()))
     return std::nullopt;
 
   // We can return these as rvalues, but we can't deref() them.

diff  --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp
index 3eb0d1a13bf49..6467aa2e1d20b 100644
--- a/clang/test/AST/ByteCode/new-delete.cpp
+++ b/clang/test/AST/ByteCode/new-delete.cpp
@@ -612,6 +612,16 @@ namespace CastedDelete {
   }
   static_assert(foo() == 1); // both-error {{not an integral constant expression}} \
                              // both-note {{in call to}}
+
+  constexpr bool nvdtor() { // both-error {{never produces a constant expression}}
+    struct S {
+      constexpr ~S() {}
+    };
+    struct T : S {};
+    delete (S*)new T; // both-note {{delete of object with dynamic type 'T' through pointer to base class type 'S' with non-virtual destructor}}
+    return true;
+  }
+
 }
 
 constexpr void use_after_free_2() { // both-error {{never produces a constant expression}}

diff  --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index 92bfa40caec4e..6440a4e85df83 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -std=c++2a -emit-llvm-only -Wno-unused-value -Wno-vla %s -verify
+// RUN: %clang_cc1 -std=c++2a -emit-llvm-only -Wno-unused-value -Wno-vla %s -verify -fexperimental-new-constant-interpreter
 
 typedef __SIZE_TYPE__ size_t;
 


        


More information about the cfe-commits mailing list