Skip to content

Commit 180869d

Browse files
fix: handle cases where a class is declared before defining (#644)
1 parent 3bc692b commit 180869d

File tree

2 files changed

+23
-2
lines changed

2 files changed

+23
-2
lines changed

lib/CppInterOp/CppInterOp.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,8 @@ void GetDatamembers(TCppScope_t scope, std::vector<TCppScope_t>& datamembers) {
13251325

13261326
if (auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
13271327
getSema().ForceDeclarationOfImplicitMembers(CXXRD);
1328+
if (CXXRD->hasDefinition())
1329+
CXXRD = CXXRD->getDefinition();
13281330

13291331
llvm::SmallVector<RecordDecl::decl_iterator, 2> stack_begin;
13301332
llvm::SmallVector<RecordDecl::decl_iterator, 2> stack_end;
@@ -1445,7 +1447,7 @@ intptr_t GetVariableOffset(compat::Interpreter& I, Decl* D,
14451447
}
14461448
offset += C.toCharUnitsFromBits(C.getFieldOffset(FD)).getQuantity();
14471449
}
1448-
if (BaseCXXRD && BaseCXXRD != FieldParentRecordDecl) {
1450+
if (BaseCXXRD && BaseCXXRD != FieldParentRecordDecl->getCanonicalDecl()) {
14491451
// FieldDecl FD belongs to some class C, but the base class BaseCXXRD is
14501452
// not C. That means BaseCXXRD derives from C. Offset needs to be
14511453
// calculated for Derived class
@@ -1474,7 +1476,7 @@ intptr_t GetVariableOffset(compat::Interpreter& I, Decl* D,
14741476
}
14751477
if (auto* RD = llvm::dyn_cast<CXXRecordDecl>(FieldParentRecordDecl)) {
14761478
// add in the offsets for the (multi level) base classes
1477-
while (BaseCXXRD != RD) {
1479+
while (BaseCXXRD != RD->getCanonicalDecl()) {
14781480
CXXRecordDecl* Parent = direction.at(RD);
14791481
offset +=
14801482
C.getASTRecordLayout(Parent).getBaseClassOffset(RD).getQuantity();

unittests/CppInterOp/VariableReflectionTest.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,25 @@ TEST(VariableReflectionTest, GetVariableOffset) {
299299

300300
auto* VD_C_s_a = Cpp::GetNamed("s_a", Decls[4]); // C::s_a
301301
EXPECT_TRUE((bool) Cpp::GetVariableOffset(VD_C_s_a));
302+
303+
struct K {
304+
int x;
305+
int y;
306+
int z;
307+
};
308+
Cpp::Declare("struct K;");
309+
Cpp::TCppScope_t k = Cpp::GetNamed("K");
310+
EXPECT_TRUE(k);
311+
312+
Cpp::Declare("struct K { int x; int y; int z; };");
313+
314+
datamembers.clear();
315+
Cpp::GetDatamembers(k, datamembers);
316+
EXPECT_EQ(datamembers.size(), 3);
317+
318+
EXPECT_EQ(Cpp::GetVariableOffset(datamembers[0]), offsetof(K, x));
319+
EXPECT_EQ(Cpp::GetVariableOffset(datamembers[1]), offsetof(K, y));
320+
EXPECT_EQ(Cpp::GetVariableOffset(datamembers[2]), offsetof(K, z));
302321
}
303322

304323
#define CODE \

0 commit comments

Comments
 (0)