diff --git a/lib/Interpreter/CppInterOp.cpp b/lib/Interpreter/CppInterOp.cpp index 712af4ed..5c4e9670 100644 --- a/lib/Interpreter/CppInterOp.cpp +++ b/lib/Interpreter/CppInterOp.cpp @@ -29,6 +29,7 @@ #endif #include "clang/Sema/TemplateDeduction.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" @@ -526,7 +527,11 @@ namespace Cpp { static clang::Decl* GetUnderlyingScope(clang::Decl * D) { if (auto *TND = dyn_cast_or_null(D)) { - auto Scope = GetScopeFromType(TND->getUnderlyingType()); + 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; } @@ -1151,10 +1156,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 +1174,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 +1332,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