aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2024-07-30 13:38:15 +0200
committerGitHub <noreply@github.com>2024-07-30 13:38:15 +0200
commitc39daa6e19800d9a1b20ec6e04b2a68149dcf89c (patch)
tree0b7c51de3a47d7176788b2db23121b1c3e42a068
parent53925e33c5943bee7cf2fe29ca1274a42a5d5687 (diff)
downloadllvm-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.h20
-rw-r--r--clang/test/AST/Interp/records.cpp16
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