[clang] [Clang][Interp] Assert on virtual func call from array elem (PR #158502)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 14 12:12:51 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: marius doerner (mariusdr)
<details>
<summary>Changes</summary>
Fixes #<!-- -->152893.
An assert was raised when a constexpr virtual function was called from an constexpr array element with -fexperimental-new-constant-interpreter set.
---
Full diff: https://github.com/llvm/llvm-project/pull/158502.diff
2 Files Affected:
- (modified) clang/lib/AST/ByteCode/Interp.cpp (+7-2)
- (modified) clang/test/AST/ByteCode/cxx20.cpp (+22)
``````````diff
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());
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/158502
More information about the cfe-commits
mailing list