Skip to content

Commit 7c01c2b

Browse files
committed
[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.
1 parent 4cabd1e commit 7c01c2b

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,10 +1666,15 @@ bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
16661666
TypePtr = TypePtr.getBase();
16671667

16681668
QualType DynamicType = TypePtr.getType();
1669-
if (DynamicType->isPointerType() || DynamicType->isReferenceType())
1669+
if (DynamicType->isPointerType() || DynamicType->isReferenceType()) {
16701670
DynamicDecl = DynamicType->getPointeeCXXRecordDecl();
1671-
else
1671+
} else if (DynamicType->isArrayType()) {
1672+
const Type *ElemType = DynamicType->getPointeeOrArrayElementType();
1673+
assert(ElemType);
1674+
DynamicDecl = ElemType->getAsCXXRecordDecl();
1675+
} else {
16721676
DynamicDecl = DynamicType->getAsCXXRecordDecl();
1677+
}
16731678
}
16741679
assert(DynamicDecl);
16751680

clang/test/AST/ByteCode/cxx20.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,3 +1100,25 @@ namespace DiscardedTrivialCXXConstructExpr {
11001100
constexpr int y = foo(12); // both-error {{must be initialized by a constant expression}} \
11011101
// both-note {{in call to}}
11021102
}
1103+
1104+
namespace VirtualFunctionCallThroughArrayElem {
1105+
struct X {
1106+
constexpr virtual int foo() const {
1107+
return 3;
1108+
}
1109+
};
1110+
constexpr X xs[5];
1111+
static_assert(xs[3].foo() == 3);
1112+
1113+
constexpr X xs2[1][2];
1114+
static_assert(xs2[0].foo() == 3); // both-error {{is not a structure or union}}
1115+
static_assert(xs2[0][0].foo() == 3);
1116+
1117+
struct Y: public X {
1118+
constexpr int foo() const override {
1119+
return 1;
1120+
}
1121+
};
1122+
constexpr Y ys[20];
1123+
static_assert(ys[12].foo() == static_cast<const X&>(ys[12]).foo());
1124+
}

0 commit comments

Comments
 (0)