https://github.com/mariusdr created 
https://github.com/llvm/llvm-project/pull/158502

Fixes #152893.

An assert was raised when a constexpr virtual function was called from an 
constexpr array element with -fexperimental-new-constant-interpreter set.

>From 26e222a60af111c638d87176c20e9cb6a11a4ce7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marius=20D=C3=B6rner?= <marius.doern...@icloud.com>
Date: Sun, 14 Sep 2025 21:03:57 +0200
Subject: [PATCH] [Clang][Interp] Assert on virtual func call from array elem

Fixes #152893.

An assert was raised when a constexpr virtual function was called from
an constexpr array element with -fexperimental-new-constant-interpreter
set.
---
 clang/lib/AST/ByteCode/Interp.cpp |  9 +++++++--
 clang/test/AST/ByteCode/cxx20.cpp | 22 ++++++++++++++++++++++
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index f1b9104c04feb..c739fa0c19d84 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1664,10 +1664,15 @@ bool CallVirt(InterpState &S, CodePtr OpPC, const 
Function *Func,
       TypePtr = TypePtr.getBase();
 
     QualType DynamicType = TypePtr.getType();
-    if (DynamicType->isPointerType() || DynamicType->isReferenceType())
+    if (DynamicType->isPointerType() || DynamicType->isReferenceType()) {
       DynamicDecl = DynamicType->getPointeeCXXRecordDecl();
-    else
+    } else if (DynamicType->isArrayType()) {
+      const Type *ElemType = DynamicType->getPointeeOrArrayElementType();
+      assert(ElemType);
+      DynamicDecl = ElemType->getAsCXXRecordDecl();
+    } else {
       DynamicDecl = DynamicType->getAsCXXRecordDecl();
+    }
   }
   assert(DynamicDecl);
 
diff --git a/clang/test/AST/ByteCode/cxx20.cpp 
b/clang/test/AST/ByteCode/cxx20.cpp
index 67bf9a732d8b7..8e77a081e3e60 100644
--- a/clang/test/AST/ByteCode/cxx20.cpp
+++ b/clang/test/AST/ByteCode/cxx20.cpp
@@ -1100,3 +1100,25 @@ namespace DiscardedTrivialCXXConstructExpr {
   constexpr int y = foo(12); // both-error {{must be initialized by a constant 
expression}} \
                              // both-note {{in call to}}
 }
+
+namespace VirtualFunctionCallThroughArrayElem {
+  struct X {
+    constexpr virtual int foo() const {
+      return 3;
+    }
+  };
+  constexpr X xs[5];
+  static_assert(xs[3].foo() == 3);
+
+  constexpr X xs2[1][2];
+  static_assert(xs2[0].foo() == 3); // both-error {{is not a structure or 
union}}
+  static_assert(xs2[0][0].foo() == 3);
+
+  struct Y: public X {
+    constexpr int foo() const override {
+      return 1;
+    }
+  };
+  constexpr Y ys[20];
+  static_assert(ys[12].foo() == static_cast<const X&>(ys[12]).foo());
+}

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

Reply via email to