Skip to content

Conversation

tbaederr
Copy link
Contributor

@tbaederr tbaederr commented Sep 3, 2025

If we create an implicit local variable for a derived-to-base cast, we still should allocate enough space for the entire derived type.

Fixes #156219

@tbaederr tbaederr added clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:bytecode Issues for the clang bytecode constexpr interpreter labels Sep 3, 2025
@llvmbot llvmbot added the clang Clang issues not falling into any other category label Sep 4, 2025
@llvmbot
Copy link
Member

llvmbot commented Sep 4, 2025

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

Changes

If we create an implicit local variable for a derived-to-base cast, we still should allocate enough space for the entire derived type.

Fixes #156219


Full diff: https://github.com/llvm/llvm-project/pull/156658.diff

2 Files Affected:

  • (modified) clang/lib/AST/ByteCode/Compiler.cpp (+14-13)
  • (modified) clang/test/AST/ByteCode/cxx03.cpp (+11)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 89ff5d27a4143..908c2c15cb041 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -4191,6 +4191,19 @@ template <class Emitter> bool Compiler<Emitter>::delegate(const Expr *E) {
   return this->Visit(E);
 }
 
+static const Expr *stripDerivedToBaseCasts(const Expr *E) {
+  if (const auto *PE = dyn_cast<ParenExpr>(E))
+    return stripDerivedToBaseCasts(PE->getSubExpr());
+
+  if (const auto *CE = dyn_cast<CastExpr>(E);
+      CE && (CE->getCastKind() == CK_DerivedToBase ||
+             CE->getCastKind() == CK_UncheckedDerivedToBase ||
+             CE->getCastKind() == CK_NoOp))
+    return stripDerivedToBaseCasts(CE->getSubExpr());
+
+  return E;
+}
+
 template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {
   if (E->getType().isNull())
     return false;
@@ -4200,7 +4213,7 @@ template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {
 
   // Create local variable to hold the return value.
   if (!E->isGLValue() && !canClassify(E->getType())) {
-    UnsignedOrNone LocalIndex = allocateLocal(E);
+    UnsignedOrNone LocalIndex = allocateLocal(stripDerivedToBaseCasts(E));
     if (!LocalIndex)
       return false;
 
@@ -5078,18 +5091,6 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
   return true;
 }
 
-static const Expr *stripDerivedToBaseCasts(const Expr *E) {
-  if (const auto *PE = dyn_cast<ParenExpr>(E))
-    return stripDerivedToBaseCasts(PE->getSubExpr());
-
-  if (const auto *CE = dyn_cast<CastExpr>(E);
-      CE &&
-      (CE->getCastKind() == CK_DerivedToBase || CE->getCastKind() == CK_NoOp))
-    return stripDerivedToBaseCasts(CE->getSubExpr());
-
-  return E;
-}
-
 template <class Emitter>
 bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
   const FunctionDecl *FuncDecl = E->getDirectCallee();
diff --git a/clang/test/AST/ByteCode/cxx03.cpp b/clang/test/AST/ByteCode/cxx03.cpp
index 70ae4134842b5..10e5232b9f873 100644
--- a/clang/test/AST/ByteCode/cxx03.cpp
+++ b/clang/test/AST/ByteCode/cxx03.cpp
@@ -29,3 +29,14 @@ void LambdaAccessingADummy() {
   int d;
   int a9[1] = {[d = 0] = 1}; // both-error {{is not an integral constant expression}}
 }
+
+const int p = 10;
+struct B {
+  int a;
+  void *p;
+};
+struct B2 : B {
+  void *q;
+};
+_Static_assert(&(B2().a) == &p, ""); // both-error {{taking the address of a temporary object of type 'int'}} \
+                                     // both-error {{not an integral constant expression}}

If we create an implicit local variable for a derived-to-base cast,
we still should allocate enough space for the entire derived type.

Fixes llvm#156219
@tbaederr tbaederr merged commit 9e75544 into llvm:main Sep 4, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:bytecode Issues for the clang bytecode constexpr interpreter clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[clang][bytecode] Assertion `isDereferencable()' failed.
2 participants