Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions include/clang/Interpreter/CppInterOp.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ namespace Cpp {
///\returns the version string information of the library.
CPPINTEROP_API std::string GetVersion();

///\returns the demangled representation of the given mangled_name
CPPINTEROP_API std::string Demangle(const std::string& mangled_name);

/// Enables or disables the debugging printouts on stderr.
/// Debugging output can be enabled also by the environment variable
/// CPPINTEROP_EXTRA_INTERPRETER_ARGS. For example,
Expand All @@ -207,6 +210,10 @@ namespace Cpp {
/// Checks if the scope is a class or not.
CPPINTEROP_API bool IsClass(TCppScope_t scope);

/// Checks if the klass polymorphic.
/// which means that the class contains or inherits a virtual function
CPPINTEROP_API bool IsClassPolymorphic(TCppScope_t klass);

// See TClingClassInfo::IsLoaded
/// Checks if the class definition is present, or not. Performs a
/// template instantiation if necessary.
Expand Down
28 changes: 28 additions & 0 deletions lib/Interpreter/CppInterOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_os_ostream.h"
Expand Down Expand Up @@ -155,6 +156,25 @@ namespace Cpp {
return fullVersion + "[" + clang::getClangFullVersion() + "])\n";
}

std::string Demangle(const std::string& mangled_name) {
#if CLANG_VERSION_MAJOR > 16
#ifdef _WIN32
std::string demangle = microsoftDemangle(mangled_name, nullptr, nullptr);
#else
std::string demangle = itaniumDemangle(mangled_name);
#endif
#else
#ifdef _WIN32
std::string demangle = microsoftDemangle(mangled_name.c_str(), nullptr,
nullptr, nullptr, nullptr);
#else
std::string demangle =
itaniumDemangle(mangled_name.c_str(), nullptr, nullptr, nullptr);
#endif
#endif
return demangle;
}

void EnableDebugOutput(bool value/* =true*/) {
llvm::DebugFlag = value;
}
Expand Down Expand Up @@ -188,6 +208,14 @@ namespace Cpp {
return isa<CXXRecordDecl>(D);
}

bool IsClassPolymorphic(TCppScope_t klass) {
Decl* D = static_cast<Decl*>(klass);
if (auto* CXXRD = llvm::dyn_cast<CXXRecordDecl>(D))
if (auto* CXXRDD = CXXRD->getDefinition())
return CXXRDD->isPolymorphic();
return false;
}

static SourceLocation GetValidSLoc(Sema& semaRef) {
auto& SM = semaRef.getSourceManager();
return SM.getLocForStartOfFile(SM.getMainFileID());
Expand Down
60 changes: 59 additions & 1 deletion unittests/CppInterOp/ScopeReflectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,51 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Sema/Sema.h"

#include "clang/AST/DeclBase.h"
#include "clang/AST/ASTDumper.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/GlobalDecl.h"

#include "llvm/Support/Valgrind.h"

#include "gtest/gtest.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'gtest/gtest.h' file not found [clang-diagnostic-error]

#include "gtest/gtest.h"
         ^


#include <string>

using namespace TestUtils;
using namespace llvm;
using namespace clang;

TEST(ScopeReflectionTest, Demangle) {
if (llvm::sys::RunningOnValgrind())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "llvm::sys::RunningOnValgrind" is directly included [misc-include-cleaner]

unittests/CppInterOp/ScopeReflectionTest.cpp:14:

+ #include <llvm/Support/Valgrind.h>

GTEST_SKIP() << "XFAIL due to Valgrind report";

std::string code = R"(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "std::string" is directly included [misc-include-cleaner]

unittests/CppInterOp/ScopeReflectionTest.cpp:14:

+ #include <string>

int add(int x, int y) { return x + y; }
int add(double x, double y) { return x + y; }
)";

std::vector<Decl*> Decls;
GetAllTopLevelDecls(code, Decls);
EXPECT_EQ(Decls.size(), 2);

auto Add_int = clang::GlobalDecl(static_cast<clang::NamedDecl*>(Decls[0]));
auto Add_double = clang::GlobalDecl(static_cast<clang::NamedDecl*>(Decls[1]));

std::string mangled_add_int;
std::string mangled_add_double;
compat::maybeMangleDeclName(Add_int, mangled_add_int);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "compat::maybeMangleDeclName" is directly included [misc-include-cleaner]

unittests/CppInterOp/ScopeReflectionTest.cpp:3:

- #include "clang-c/CXCppInterOp.h"
+ #include "/github/workspace/lib/Interpreter/Compatibility.h"
+ #include "clang-c/CXCppInterOp.h"

compat::maybeMangleDeclName(Add_double, mangled_add_double);

std::string demangled_add_int = Cpp::Demangle(mangled_add_int);
std::string demangled_add_double = Cpp::Demangle(mangled_add_double);

EXPECT_NE(demangled_add_int.find(Cpp::GetQualifiedCompleteName(Decls[0])),
std::string::npos);
EXPECT_NE(demangled_add_double.find(Cpp::GetQualifiedCompleteName(Decls[1])),
std::string::npos);
}

TEST(ScopeReflectionTest, IsAggregate) {
std::vector<Decl *> Decls;
std::string code = R"(
Expand Down Expand Up @@ -59,6 +95,28 @@ TEST(ScopeReflectionTest, IsClass) {
EXPECT_FALSE(Cpp::IsClass(Decls[2]));
}

TEST(ScopeReflectionTest, IsClassPolymorphic) {
std::vector<Decl*> Decls;
GetAllTopLevelDecls(R"(
namespace N {}

class C{};

class C2 {
public:
virtual ~C2() {}
};

int I;
)",
Decls);

EXPECT_FALSE(Cpp::IsClassPolymorphic(Decls[0]));
EXPECT_FALSE(Cpp::IsClassPolymorphic(Decls[1]));
EXPECT_TRUE(Cpp::IsClassPolymorphic(Decls[2]));
EXPECT_FALSE(Cpp::IsClassPolymorphic(Decls[3]));
}

TEST(ScopeReflectionTest, IsComplete) {
std::vector<Decl*> Decls;
std::string code = R"(
Expand Down