Skip to content

Commit

Permalink
Update GetDatamembers and GetUnderlyingScope to work with `UsingS…
Browse files Browse the repository at this point in the history
…hadowDecl`

`GetDatamembers` now also returns `UsingShadowDecl` that point to `FieldDecl`.

Update `GetUnderlyingScope` to return the target Decl of using statements.

Simplified `CheckVariableAccess` logic.
  • Loading branch information
Vipul-Cariappa committed Dec 11, 2024
1 parent 557e048 commit e943f38
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 14 deletions.
33 changes: 19 additions & 14 deletions lib/Interpreter/CppInterOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -526,8 +527,10 @@ namespace Cpp {

static clang::Decl* GetUnderlyingScope(clang::Decl * D) {
if (auto *TND = dyn_cast_or_null<TypedefNameDecl>(D)) {
auto Scope = GetScopeFromType(TND->getUnderlyingType());
if (Scope)
if (auto* Scope = GetScopeFromType(TND->getUnderlyingType()))
D = Scope;
} else if (auto* USS = dyn_cast_or_null<UsingShadowDecl>(D)) {
if (auto* Scope = USS->getTargetDecl())
D = Scope;
}

Expand Down Expand Up @@ -1151,10 +1154,12 @@ namespace Cpp {
auto *D = (Decl *) scope;

if (auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
llvm::SmallVector<RecordDecl::field_iterator, 2> stack_begin;
llvm::SmallVector<RecordDecl::field_iterator, 2> stack_end;
stack_begin.push_back(CXXRD->field_begin());
stack_end.push_back(CXXRD->field_end());
getSema().ForceDeclarationOfImplicitMembers(CXXRD);

llvm::SmallVector<RecordDecl::decl_iterator, 2> stack_begin;
llvm::SmallVector<RecordDecl::decl_iterator, 2> 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();
Expand All @@ -1167,14 +1172,18 @@ namespace Cpp {
if (const auto* RT = FD->getType()->getAs<RecordType>()) {
if (auto* CXXRD = llvm::dyn_cast<CXXRecordDecl>(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<UsingShadowDecl>(D)) {
if (llvm::isa<FieldDecl>(USD->getTargetDecl()))
datamembers.push_back(USD);
}
datamembers.push_back((TCppScope_t)D);
stack_begin.back()++;
}
}
Expand Down Expand Up @@ -1321,11 +1330,7 @@ namespace Cpp {
bool CheckVariableAccess(TCppScope_t var, AccessSpecifier AS)
{
auto *D = (Decl *) var;
if (auto *CXXMD = llvm::dyn_cast_or_null<DeclaratorDecl>(D)) {
return CXXMD->getAccess() == AS;
}

return false;
return D->getAccess() == AS;
}

bool IsPublicVariable(TCppScope_t var)
Expand Down
18 changes: 18 additions & 0 deletions unittests/CppInterOp/VariableReflectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Cpp::TCppScope_t> datamembers;
std::vector<Cpp::TCppScope_t> datamembers1;
std::vector<Cpp::TCppScope_t> 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");
Expand All @@ -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
Expand Down

0 comments on commit e943f38

Please sign in to comment.