[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
Tue Feb 7 02:00:58 PST 2023
tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, tahonermann, shafik.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
The GetPtrBasePop op we were using only works for direct base classes.
Repository:
rG LLVM Github Monorepo
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
@@ -258,6 +258,10 @@
class _B : public _A {};
class _C : public _B {};
constexpr _C c{12};
+
+ // Cast from A to C.
+ constexpr _A a = c;
+ static_assert(a.a == 12);
};
#endif
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -263,6 +263,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
@@ -88,15 +88,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: {
@@ -1949,6 +1942,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 CXXRecordDecl *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 CXXRecordDecl *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.495432.patch
Type: text/x-patch
Size: 2938 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230207/ff153c30/attachment.bin>
More information about the cfe-commits
mailing list