[PATCH] D143480: [clang][Interp] Fix derived-to-base casts for >1 levels
Timm Bäder via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 3 02:36:26 PDT 2023
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG968b4172f6a9: [clang][Interp] Fix derived-to-base casts for >1 levels (authored by tbaeder).
Changed prior to commit:
https://reviews.llvm.org/D143480?vs=504022&id=510435#toc
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D143480/new/
https://reviews.llvm.org/D143480
Files:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeExprGen.h
clang/test/AST/Interp/records.cpp
Index: clang/test/AST/Interp/records.cpp
===================================================================
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -250,6 +250,21 @@
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:
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -260,6 +260,8 @@
}
bool emitRecordDestruction(const Descriptor *Desc);
+ bool emitDerivedToBaseCasts(const RecordType *DerivedType,
+ const RecordType *BaseType, const Expr *E);
protected:
/// Variable to storage mapping.
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -85,15 +85,8 @@
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 @@
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).
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D143480.510435.patch
Type: text/x-patch
Size: 3228 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230403/9286dae1/attachment-0001.bin>
More information about the cfe-commits
mailing list