Skip to content

Commit c39daa6

Browse files
authored
[clang][Interp] Pick right dynamic type when doing virtual calls (#101166)
1 parent 53925e3 commit c39daa6

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

clang/lib/AST/Interp/Interp.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2588,12 +2588,20 @@ inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
25882588
size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
25892589
Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
25902590

2591-
QualType DynamicType = ThisPtr.getDeclDesc()->getType();
2592-
const CXXRecordDecl *DynamicDecl;
2593-
if (DynamicType->isPointerType() || DynamicType->isReferenceType())
2594-
DynamicDecl = DynamicType->getPointeeCXXRecordDecl();
2595-
else
2596-
DynamicDecl = ThisPtr.getDeclDesc()->getType()->getAsCXXRecordDecl();
2591+
const CXXRecordDecl *DynamicDecl = nullptr;
2592+
{
2593+
Pointer TypePtr = ThisPtr;
2594+
while (TypePtr.isBaseClass())
2595+
TypePtr = TypePtr.getBase();
2596+
2597+
QualType DynamicType = TypePtr.getType();
2598+
if (DynamicType->isPointerType() || DynamicType->isReferenceType())
2599+
DynamicDecl = DynamicType->getPointeeCXXRecordDecl();
2600+
else
2601+
DynamicDecl = DynamicType->getAsCXXRecordDecl();
2602+
}
2603+
assert(DynamicDecl);
2604+
25972605
const auto *StaticDecl = cast<CXXRecordDecl>(Func->getParentDecl());
25982606
const auto *InitialFunction = cast<CXXMethodDecl>(Func->getDecl());
25992607
const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(

clang/test/AST/Interp/records.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,3 +1560,19 @@ namespace ArrayInitChain {
15601560
static_assert(A[1].Width == 12, "");
15611561
static_assert(A[1].Mask == 13, "");
15621562
}
1563+
1564+
#if __cplusplus >= 202002L
1565+
namespace ctorOverrider {
1566+
// Ensure that we pick the right final overrider during construction.
1567+
struct A {
1568+
virtual constexpr char f() const { return 'A'; }
1569+
char a = f();
1570+
};
1571+
1572+
struct Covariant1 {
1573+
A d;
1574+
};
1575+
1576+
constexpr Covariant1 cb;
1577+
}
1578+
#endif

0 commit comments

Comments
 (0)