[clang] 968b417 - [clang][Interp] Fix derived-to-base casts for >1 levels
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 3 02:36:18 PDT 2023
Author: Timm Bäder
Date: 2023-04-03T11:35:55+02:00
New Revision: 968b4172f6a9878e56dc911f3f9df089d2a9134f
URL: https://github.com/llvm/llvm-project/commit/968b4172f6a9878e56dc911f3f9df089d2a9134f
DIFF: https://github.com/llvm/llvm-project/commit/968b4172f6a9878e56dc911f3f9df089d2a9134f.diff
LOG: [clang][Interp] Fix derived-to-base casts for >1 levels
The GetPtrBasePop op we were using only works for direct base classes.
Differential Revision: https://reviews.llvm.org/D143480
Added:
Modified:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeExprGen.h
clang/test/AST/Interp/records.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 733247787d760..ad802f72aad4c 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -85,15 +85,8 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
if (!this->visit(SubExpr))
return false;
- const CXXRecordDecl *FromDecl = getRecordDecl(SubExpr);
- assert(FromDecl);
- const CXXRecordDecl *ToDecl = getRecordDecl(CE);
- assert(ToDecl);
- const Record *R = getRecord(FromDecl);
- const Record::Base *ToBase = R->getBase(ToDecl);
- assert(ToBase);
-
- return this->emitGetPtrBasePop(ToBase->Offset, CE);
+ return this->emitDerivedToBaseCasts(getRecordTy(SubExpr->getType()),
+ getRecordTy(CE->getType()), CE);
}
case CK_FloatingCast: {
@@ -1873,6 +1866,38 @@ void ByteCodeExprGen<Emitter>::emitCleanup() {
C->emitDestruction();
}
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::emitDerivedToBaseCasts(
+ const RecordType *DerivedType, const RecordType *BaseType, const Expr *E) {
+ // Pointer of derived type is already on the stack.
+ const auto *FinalDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+ const RecordDecl *CurDecl = DerivedType->getDecl();
+ const Record *CurRecord = getRecord(CurDecl);
+ assert(CurDecl && FinalDecl);
+ for (;;) {
+ assert(CurRecord->getNumBases() > 0);
+ // One level up
+ for (const Record::Base &B : CurRecord->bases()) {
+ const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl);
+
+ if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
+ // This decl will lead us to the final decl, so emit a base cast.
+ if (!this->emitGetPtrBasePop(B.Offset, E))
+ return false;
+
+ CurRecord = B.R;
+ CurDecl = BaseDecl;
+ break;
+ }
+ }
+ if (CurDecl == FinalDecl)
+ return true;
+ }
+
+ llvm_unreachable("Couldn't find the base class?");
+ return false;
+}
+
/// When calling this, we have a pointer of the local-to-destroy
/// on the stack.
/// Emit destruction of record types (or arrays of record types).
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index 4baf5d433c9e0..af5b4678b0703 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -260,6 +260,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
}
bool emitRecordDestruction(const Descriptor *Desc);
+ bool emitDerivedToBaseCasts(const RecordType *DerivedType,
+ const RecordType *BaseType, const Expr *E);
protected:
/// Variable to storage mapping.
diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp
index 448e1c0eb7223..188db827fe08b 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -250,6 +250,21 @@ struct S {
constexpr S s;
static_assert(s.m() == 1, "");
+#if __cplusplus >= 201703L
+namespace BaseInit {
+ class A {public: int a;};
+ class B : public A {};
+ class C : public A {};
+ class D : public B, public C {};
+
+ // FIXME: Enable this once we support the initialization.
+ // This initializes D::B::A::a and not D::C::A::a.
+ //constexpr D d{12};
+ //static_assert(d.B::a == 12);
+ //static_assert(d.C::a == 0);
+};
+#endif
+
namespace MI {
class A {
public:
More information about the cfe-commits
mailing list