Skip to content

Commit d530129

Browse files
handle forward declarations of classes when retrieving methods (#688)
1 parent 82f08c6 commit d530129

File tree

2 files changed

+12
-6
lines changed

2 files changed

+12
-6
lines changed

lib/CppInterOp/CppInterOp.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,9 @@ static Decl* GetScopeFromType(QualType QT) {
615615
Type = Type->getUnqualifiedDesugaredType();
616616
if (auto* ET = llvm::dyn_cast<EnumType>(Type))
617617
return ET->getDecl();
618-
return Type->getAsCXXRecordDecl();
618+
CXXRecordDecl* CXXRD = Type->getAsCXXRecordDecl();
619+
if (CXXRD)
620+
return CXXRD->getCanonicalDecl();
619621
}
620622
return 0;
621623
}
@@ -634,7 +636,7 @@ static clang::Decl* GetUnderlyingScope(clang::Decl* D) {
634636
D = Scope;
635637
}
636638

637-
return D;
639+
return D->getCanonicalDecl();
638640
}
639641

640642
TCppScope_t GetUnderlyingScope(TCppScope_t scope) {
@@ -843,6 +845,8 @@ static void GetClassDecls(TCppScope_t klass,
843845
#ifdef CPPINTEROP_USE_CLING
844846
cling::Interpreter::PushTransactionRAII RAII(&getInterp());
845847
#endif // CPPINTEROP_USE_CLING
848+
if (CXXRD->hasDefinition())
849+
CXXRD = CXXRD->getDefinition();
846850
getSema().ForceDeclarationOfImplicitMembers(CXXRD);
847851
for (Decl* DI : CXXRD->decls()) {
848852
if (auto* MD = dyn_cast<DeclType>(DI))

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ using namespace clang;
2222
TEST(FunctionReflectionTest, GetClassMethods) {
2323
std::vector<Decl*> Decls;
2424
std::string code = R"(
25+
class A;
26+
2527
class A {
2628
public:
2729
int f1(int a, int b) { return a + b; }
@@ -70,7 +72,7 @@ TEST(FunctionReflectionTest, GetClassMethods) {
7072
EXPECT_EQ(get_method_name(methods0[10]), "inline A::~A()");
7173

7274
std::vector<Cpp::TCppFunction_t> methods1;
73-
Cpp::GetClassMethods(Decls[1], methods1);
75+
Cpp::GetClassMethods(Decls[2], methods1);
7476
EXPECT_EQ(methods0.size(), methods1.size());
7577
EXPECT_EQ(methods0[0], methods1[0]);
7678
EXPECT_EQ(methods0[1], methods1[1]);
@@ -79,7 +81,7 @@ TEST(FunctionReflectionTest, GetClassMethods) {
7981
EXPECT_EQ(methods0[4], methods1[4]);
8082

8183
std::vector<Cpp::TCppFunction_t> methods2;
82-
Cpp::GetClassMethods(Decls[2], methods2);
84+
Cpp::GetClassMethods(Decls[3], methods2);
8385

8486
EXPECT_EQ(methods2.size(), 6);
8587
EXPECT_EQ(get_method_name(methods2[0]), "B::B(int n)");
@@ -90,7 +92,7 @@ TEST(FunctionReflectionTest, GetClassMethods) {
9092
EXPECT_EQ(get_method_name(methods2[5]), "inline B &B::operator=(B &&)");
9193

9294
std::vector<Cpp::TCppFunction_t> methods3;
93-
Cpp::GetClassMethods(Decls[3], methods3);
95+
Cpp::GetClassMethods(Decls[4], methods3);
9496

9597
EXPECT_EQ(methods3.size(), 9);
9698
EXPECT_EQ(get_method_name(methods3[0]), "B::B(int n)");
@@ -104,7 +106,7 @@ TEST(FunctionReflectionTest, GetClassMethods) {
104106

105107
// Should not crash.
106108
std::vector<Cpp::TCppFunction_t> methods4;
107-
Cpp::GetClassMethods(Decls[4], methods4);
109+
Cpp::GetClassMethods(Decls[5], methods4);
108110
EXPECT_EQ(methods4.size(), 0);
109111

110112
std::vector<Cpp::TCppFunction_t> methods5;

0 commit comments

Comments
 (0)