[clang] [Clang][Interp] Assert on virtual func call from array elem (PR #158502)
marius doerner via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 14 12:12:19 PDT 2025
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.doerner1 at 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());
+}
More information about the cfe-commits
mailing list