diff options
| author | Timm Baeder <tbaeder@redhat.com> | 2024-07-30 13:38:15 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-30 13:38:15 +0200 |
| commit | c39daa6e19800d9a1b20ec6e04b2a68149dcf89c (patch) | |
| tree | 0b7c51de3a47d7176788b2db23121b1c3e42a068 | |
| parent | 53925e33c5943bee7cf2fe29ca1274a42a5d5687 (diff) | |
| download | llvm-c39daa6e19800d9a1b20ec6e04b2a68149dcf89c.zip llvm-c39daa6e19800d9a1b20ec6e04b2a68149dcf89c.tar.gz llvm-c39daa6e19800d9a1b20ec6e04b2a68149dcf89c.tar.bz2 | |
[clang][Interp] Pick right dynamic type when doing virtual calls (#101166)
| -rw-r--r-- | clang/lib/AST/Interp/Interp.h | 20 | ||||
| -rw-r--r-- | clang/test/AST/Interp/records.cpp | 16 |
2 files changed, 30 insertions, 6 deletions
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 22a86ab..d128988 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -2588,12 +2588,20 @@ inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func, size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0); Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset); - QualType DynamicType = ThisPtr.getDeclDesc()->getType(); - const CXXRecordDecl *DynamicDecl; - if (DynamicType->isPointerType() || DynamicType->isReferenceType()) - DynamicDecl = DynamicType->getPointeeCXXRecordDecl(); - else - DynamicDecl = ThisPtr.getDeclDesc()->getType()->getAsCXXRecordDecl(); + const CXXRecordDecl *DynamicDecl = nullptr; + { + Pointer TypePtr = ThisPtr; + while (TypePtr.isBaseClass()) + TypePtr = TypePtr.getBase(); + + QualType DynamicType = TypePtr.getType(); + if (DynamicType->isPointerType() || DynamicType->isReferenceType()) + DynamicDecl = DynamicType->getPointeeCXXRecordDecl(); + else + DynamicDecl = DynamicType->getAsCXXRecordDecl(); + } + assert(DynamicDecl); + const auto *StaticDecl = cast<CXXRecordDecl>(Func->getParentDecl()); const auto *InitialFunction = cast<CXXMethodDecl>(Func->getDecl()); const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction( diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp index 9551630..479c048 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -1560,3 +1560,19 @@ namespace ArrayInitChain { static_assert(A[1].Width == 12, ""); static_assert(A[1].Mask == 13, ""); } + +#if __cplusplus >= 202002L +namespace ctorOverrider { + // Ensure that we pick the right final overrider during construction. + struct A { + virtual constexpr char f() const { return 'A'; } + char a = f(); + }; + + struct Covariant1 { + A d; + }; + + constexpr Covariant1 cb; +} +#endif |
