diff --git a/lib/Interpreter/CppInterOp.cpp b/lib/Interpreter/CppInterOp.cpp index 712af4ed..1f7fa6b2 100644 --- a/lib/Interpreter/CppInterOp.cpp +++ b/lib/Interpreter/CppInterOp.cpp @@ -529,6 +529,10 @@ namespace Cpp { auto Scope = GetScopeFromType(TND->getUnderlyingType()); if (Scope) D = Scope; + } else if (auto* USS = dyn_cast_or_null(D)) { + auto Scope = USS->getTargetDecl(); + if (Scope) + D = Scope; } return D; @@ -1151,10 +1155,12 @@ namespace Cpp { auto *D = (Decl *) scope; if (auto* CXXRD = llvm::dyn_cast_or_null(D)) { - llvm::SmallVector stack_begin; - llvm::SmallVector stack_end; - stack_begin.push_back(CXXRD->field_begin()); - stack_end.push_back(CXXRD->field_end()); + getSema().ForceDeclarationOfImplicitMembers(CXXRD); + + llvm::SmallVector stack_begin; + llvm::SmallVector stack_end; + stack_begin.push_back(CXXRD->decls_begin()); + stack_end.push_back(CXXRD->decls_end()); while (!stack_begin.empty()) { if (stack_begin.back() == stack_end.back()) { stack_begin.pop_back(); @@ -1167,14 +1173,18 @@ namespace Cpp { if (const auto* RT = FD->getType()->getAs()) { if (auto* CXXRD = llvm::dyn_cast(RT->getDecl())) { stack_begin.back()++; - stack_begin.push_back(CXXRD->field_begin()); - stack_end.push_back(CXXRD->field_end()); + stack_begin.push_back(CXXRD->decls_begin()); + stack_end.push_back(CXXRD->decls_end()); continue; } } } + datamembers.push_back((TCppScope_t)D); + + } else if (auto* USD = llvm::dyn_cast(D)) { + if (llvm::isa(USD->getTargetDecl())) + datamembers.push_back(USD); } - datamembers.push_back((TCppScope_t)D); stack_begin.back()++; } } @@ -1321,11 +1331,7 @@ namespace Cpp { bool CheckVariableAccess(TCppScope_t var, AccessSpecifier AS) { auto *D = (Decl *) var; - if (auto *CXXMD = llvm::dyn_cast_or_null(D)) { - return CXXMD->getAccess() == AS; - } - - return false; + return D->getAccess() == AS; } bool IsPublicVariable(TCppScope_t var) diff --git a/unittests/CppInterOp/VariableReflectionTest.cpp b/unittests/CppInterOp/VariableReflectionTest.cpp index d075c1bc..10ab3a46 100644 --- a/unittests/CppInterOp/VariableReflectionTest.cpp +++ b/unittests/CppInterOp/VariableReflectionTest.cpp @@ -26,13 +26,21 @@ TEST(VariableReflectionTest, GetDatamembers) { static int f; }; void sum(int,int); + + class D : public C { + public: + int x; + using C::e; + }; )"; std::vector datamembers; std::vector datamembers1; + std::vector datamembers2; GetAllTopLevelDecls(code, Decls); Cpp::GetDatamembers(Decls[0], datamembers); Cpp::GetDatamembers(Decls[1], datamembers1); + Cpp::GetDatamembers(Decls[2], datamembers2); // non static field EXPECT_EQ(Cpp::GetQualifiedName(datamembers[0]), "C::a"); @@ -53,6 +61,16 @@ TEST(VariableReflectionTest, GetDatamembers) { EXPECT_EQ(Cpp::GetQualifiedName(datamembers[2]), "C::f"); EXPECT_EQ(datamembers.size(), 3); EXPECT_EQ(datamembers1.size(), 0); + + // derived class + EXPECT_EQ(datamembers2.size(), 2); + EXPECT_EQ(Cpp::GetQualifiedName(datamembers2[0]), "D::x"); + EXPECT_EQ(Cpp::GetQualifiedName(Cpp::GetUnderlyingScope(datamembers2[1])), + "C::e"); + EXPECT_TRUE(Cpp::IsPublicVariable(datamembers2[0])); + EXPECT_TRUE(Cpp::IsPublicVariable(datamembers2[1])); + EXPECT_TRUE( + Cpp::IsProtectedVariable(Cpp::GetUnderlyingScope(datamembers2[1]))); } // If on Windows disable warning due to unnamed structs/unions in defined CODE. #ifdef _WIN32