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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@
*.exe
*.out
*.app

# Directories
build
install
15 changes: 10 additions & 5 deletions include/clang/Interpreter/InterOp.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#include <string>
#include <vector>

namespace cling {
namespace InterOp {
using TCppIndex_t = size_t;
using TCppScope_t = void*;
Expand Down Expand Up @@ -152,22 +151,28 @@ namespace InterOp {
CallFuncWrapper_t GetFunctionCallWrapper(TInterp_t interp,
TCppFunction_t func);

TInterp_t CreateInterpreter(const char *resource_dir = nullptr);

TCppSema_t GetSema(TInterp_t interp);

void AddSearchPath(TInterp_t interp, const char *dir, bool isUser = true,
bool prepend = false);

void AddIncludePath(TInterp_t interp, const char *dir);

TCppIndex_t Declare(TInterp_t interp, const char *code);
TCppIndex_t Declare(TInterp_t interp, const char *code, bool silent = false);

void Process(TInterp_t interp, const char *code);

const std::string LookupLibrary(TInterp_t interp, const char *lib_name);

bool LoadLibrary(TInterp_t interp, const char *lib_path);
bool LoadLibrary(TInterp_t interp, const char *lib_path, bool lookup = true);

std::string ObjToString(TInterp_t interp, const char *type, void *obj);

TCppScope_t InstantiateClassTemplate(TInterp_t interp, const char *tmpl_name);

std::vector<std::string> GetAllCppNames(TCppScope_t scope);
} // end namespace InterOp

} // end namespace cling

#endif // CLING_INTERPRETER_INTEROP_H
100 changes: 92 additions & 8 deletions lib/Interpreter/InterOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "clang/AST/GlobalDecl.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/Lookup.h"
Expand All @@ -30,7 +32,6 @@
#include <sstream>
#include <string>

namespace cling {
namespace InterOp {
using namespace clang;
using namespace llvm;
Expand Down Expand Up @@ -1829,6 +1830,56 @@ namespace InterOp {
return 0;
}

namespace {

std::string GetExecutablePath(const char *Argv0, void *MainAddr) {
return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
}

std::string MakeResourcesPath() {
// Dir is bin/ or lib/, depending on where BinaryPath is.
void *MainAddr = (void *)(intptr_t)GetExecutablePath;
std::string BinaryPath = GetExecutablePath(/*Argv0=*/nullptr, MainAddr);

// build/tools/clang/unittests/Interpreter/Executable -> build/
llvm::StringRef Dir = llvm::sys::path::parent_path(BinaryPath);

Dir = llvm::sys::path::parent_path(Dir);
Dir = llvm::sys::path::parent_path(Dir);
Dir = llvm::sys::path::parent_path(Dir);
Dir = llvm::sys::path::parent_path(Dir);
//Dir = sys::path::parent_path(Dir);
llvm::SmallString<128> P(Dir);
llvm::sys::path::append(P, llvm::Twine("lib") + CLANG_LIBDIR_SUFFIX,
"clang", CLANG_VERSION_STRING);

return std::string(P.str());
}

}

TInterp_t CreateInterpreter(const char *resource_dir) {
std::string MainExecutableName =
llvm::sys::fs::getMainExecutable(nullptr, nullptr);

std::string ResourceDir;
if (!resource_dir)
ResourceDir = MakeResourcesPath();
else
ResourceDir = resource_dir;

std::vector<const char *> InterpArgv = {"-resource-dir", ResourceDir.c_str(),
"-std=c++14"};
InterpArgv.insert(InterpArgv.begin(), MainExecutableName.c_str());
return (TInterp_t) new cling::Interpreter(InterpArgv.size(), &InterpArgv[0]);
}

TCppSema_t GetSema(TInterp_t interp) {
auto* I = (cling::Interpreter*)interp;

return (TCppSema_t) &I->getSema();
}

void AddSearchPath(TInterp_t interp, const char *dir, bool isUser,
bool prepend) {
auto* I = (cling::Interpreter*)interp;
Expand All @@ -1842,26 +1893,61 @@ namespace InterOp {
I->AddIncludePath(dir);
}

TCppIndex_t Declare(TInterp_t interp, const char *code) {
namespace {

class clangSilent {
public:
clangSilent(clang::DiagnosticsEngine& diag) : fDiagEngine(diag) {
fOldDiagValue = fDiagEngine.getSuppressAllDiagnostics();
fDiagEngine.setSuppressAllDiagnostics(true);
}

~clangSilent() {
fDiagEngine.setSuppressAllDiagnostics(fOldDiagValue);
}
protected:
clang::DiagnosticsEngine& fDiagEngine;
bool fOldDiagValue;
};

}

TCppIndex_t Declare(TInterp_t interp, const char *code, bool silent) {
auto* I = (cling::Interpreter*)interp;

if (silent) {
clangSilent diagSuppr(I->getSema().getDiagnostics());
return I->declare(code);
}

return I->declare(code);
}

void Process(TInterp_t interp, const char *code) {
auto* I = (cling::Interpreter*)interp;

I->process(code);
}

const std::string LookupLibrary(TInterp_t interp, const char *lib_name) {
auto* I = (cling::Interpreter*)interp;

return I->getDynamicLibraryManager()->lookupLibrary(lib_name);
}

bool LoadLibrary(TInterp_t interp, const char *lib_name) {
bool LoadLibrary(TInterp_t interp, const char *lib_name, bool lookup) {
auto* I = (cling::Interpreter*)interp;
cling::Interpreter::CompilationResult res =
I->loadLibrary(lib_name, /* lookup */ true);
I->loadLibrary(lib_name, lookup);

return res == cling::Interpreter::kSuccess;
}

std::string ObjToString(TInterp_t interp, const char *type, void *obj) {
auto* I = (cling::Interpreter*)interp;
return I->toString(type, obj);
}

TCppScope_t InstantiateClassTemplate(TInterp_t interp, const char *tmpl_name) {
auto* I = (cling::Interpreter*)interp;

Expand All @@ -1870,9 +1956,9 @@ namespace InterOp {

ss << "auto _t" << counter++ << " = " << tmpl_name << "();";
printf("%s\n", ss.str().c_str());
Transaction *T = nullptr;
cling::Transaction *T = nullptr;
auto x = I->declare(ss.str(), &T);
if (x == Interpreter::CompilationResult::kSuccess) {
if (x == cling::Interpreter::CompilationResult::kSuccess) {
for (auto D = T->decls_begin(); D != T->decls_end(); D++) {
if (auto *VD = llvm::dyn_cast_or_null<VarDecl>(D->m_DGR.getSingleDecl())) {
auto *scope = GetScopeFromType(VD->getType());
Expand Down Expand Up @@ -1915,5 +2001,3 @@ namespace InterOp {
}
} // end namespace InterOp

} // end namespace cling

17 changes: 17 additions & 0 deletions unittests/InterOp/FunctionReflectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -602,3 +602,20 @@ TEST(FunctionReflectionTest, GetFunctionCallWrapper) {
EXPECT_EQ(ret, i * i);
EXPECT_EQ(output, s);
}

TEST(FunctionReflectionTest, DISABLED_IsConstMethod) {
std::vector<Decl*> Decls, SubDecls;
std::string code = R"(
class C {
void f1() const {}
void f2() {}
};
)";

GetAllTopLevelDecls(code, Decls);
GetAllSubDecls(Decls[0], SubDecls);

// EXPECT_TRUE(InterOp::IsConstMethod(SubDecls[1])); // f1
// EXPECT_FALSE(InterOp::IsConstMethod(SubDecls[2])); // f2
}

30 changes: 15 additions & 15 deletions unittests/InterOp/ScopeReflectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,9 @@ TEST(ScopeReflectionTest, GetScope) {
Interp = createInterpreter();
Interp->declare(code);
Sema *S = &Interp->getCI()->getSema();
cling::InterOp::TCppScope_t tu = InterOp::GetScope(S, "", 0);
cling::InterOp::TCppScope_t ns_N = InterOp::GetScope(S, "N", 0);
cling::InterOp::TCppScope_t cl_C = InterOp::GetScope(S, "C", ns_N);
InterOp::TCppScope_t tu = InterOp::GetScope(S, "", 0);
InterOp::TCppScope_t ns_N = InterOp::GetScope(S, "N", 0);
InterOp::TCppScope_t cl_C = InterOp::GetScope(S, "C", ns_N);

EXPECT_EQ(InterOp::GetCompleteName(tu), "");
EXPECT_EQ(InterOp::GetCompleteName(ns_N), "N");
Expand Down Expand Up @@ -275,10 +275,10 @@ TEST(ScopeReflectionTest, GetNamed) {
Interp = createInterpreter();
Interp->declare(code);
Sema *S = &Interp->getCI()->getSema();
cling::InterOp::TCppScope_t ns_N1 = InterOp::GetNamed(S, "N1", 0);
cling::InterOp::TCppScope_t ns_N2 = InterOp::GetNamed(S, "N2", ns_N1);
cling::InterOp::TCppScope_t cl_C = InterOp::GetNamed(S, "C", ns_N2);
cling::InterOp::TCppScope_t en_E = InterOp::GetNamed(S, "E", cl_C);
InterOp::TCppScope_t ns_N1 = InterOp::GetNamed(S, "N1", 0);
InterOp::TCppScope_t ns_N2 = InterOp::GetNamed(S, "N2", ns_N1);
InterOp::TCppScope_t cl_C = InterOp::GetNamed(S, "C", ns_N2);
InterOp::TCppScope_t en_E = InterOp::GetNamed(S, "E", cl_C);
EXPECT_EQ(InterOp::GetCompleteName(ns_N1), "N1");
EXPECT_EQ(InterOp::GetCompleteName(ns_N2), "N1::N2");
EXPECT_EQ(InterOp::GetCompleteName(cl_C), "N1::N2::C");
Expand Down Expand Up @@ -307,13 +307,13 @@ TEST(ScopeReflectionTest, GetParentScope) {
Interp = createInterpreter();
Interp->declare(code);
Sema *S = &Interp->getCI()->getSema();
cling::InterOp::TCppScope_t ns_N1 = InterOp::GetNamed(S, "N1", 0);
cling::InterOp::TCppScope_t ns_N2 = InterOp::GetNamed(S, "N2", ns_N1);
cling::InterOp::TCppScope_t cl_C = InterOp::GetNamed(S, "C", ns_N2);
cling::InterOp::TCppScope_t int_i = InterOp::GetNamed(S, "i", cl_C);
cling::InterOp::TCppScope_t en_E = InterOp::GetNamed(S, "E", cl_C);
cling::InterOp::TCppScope_t en_A = InterOp::GetNamed(S, "A", cl_C);
cling::InterOp::TCppScope_t en_B = InterOp::GetNamed(S, "B", cl_C);
InterOp::TCppScope_t ns_N1 = InterOp::GetNamed(S, "N1", 0);
InterOp::TCppScope_t ns_N2 = InterOp::GetNamed(S, "N2", ns_N1);
InterOp::TCppScope_t cl_C = InterOp::GetNamed(S, "C", ns_N2);
InterOp::TCppScope_t int_i = InterOp::GetNamed(S, "i", cl_C);
InterOp::TCppScope_t en_E = InterOp::GetNamed(S, "E", cl_C);
InterOp::TCppScope_t en_A = InterOp::GetNamed(S, "A", cl_C);
InterOp::TCppScope_t en_B = InterOp::GetNamed(S, "B", cl_C);

EXPECT_EQ(InterOp::GetCompleteName(InterOp::GetParentScope(ns_N1)), "");
EXPECT_EQ(InterOp::GetCompleteName(InterOp::GetParentScope(ns_N2)), "N1");
Expand Down Expand Up @@ -348,7 +348,7 @@ TEST(ScopeReflectionTest, GetScopeFromType) {
EXPECT_EQ(InterOp::GetCompleteName(InterOp::GetScopeFromType(QT2.getAsOpaquePtr())),
"N::S");
EXPECT_EQ(InterOp::GetScopeFromType(QT3.getAsOpaquePtr()),
(cling::InterOp::TCppScope_t) 0);
(InterOp::TCppScope_t) 0);
}

TEST(ScopeReflectionTest, GetNumBases) {
Expand Down
25 changes: 25 additions & 0 deletions unittests/InterOp/TypeReflectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,28 @@ TEST(TypeReflectionTest, GetTypeFromScope) {
EXPECT_EQ(InterOp::GetTypeAsString(InterOp::GetTypeFromScope(Decls[0])), "class C");
EXPECT_EQ(InterOp::GetTypeAsString(InterOp::GetTypeFromScope(Decls[1])), "struct S");
}

TEST(TypeReflectionTest, DISABLED_IsSubType) {
std::vector<Decl *> Decls;

std::string code = R"(
class A {};
class B : A {};
class C {};

A a;
B b;
C c;
)";

GetAllTopLevelDecls(code, Decls);

InterOp::TCppType_t type_A = InterOp::GetVariableType(Decls[3]);
InterOp::TCppType_t type_B = InterOp::GetVariableType(Decls[4]);
InterOp::TCppType_t type_C = InterOp::GetVariableType(Decls[5]);

// EXPECT_TRUE(InterOp::IsSubType(type_B, type_A));
// EXPECT_FALSE(InterOp::IsSubType(type_A, type_B));
// EXPECT_FALSE(InterOp::IsSubType(type_C, type_A));
}

23 changes: 23 additions & 0 deletions unittests/InterOp/VariableReflectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,26 @@ TEST(VariableReflectionTest, IsConstVariable) {
EXPECT_FALSE(InterOp::IsConstVariable(SubDecls[1]));
EXPECT_TRUE(InterOp::IsConstVariable(SubDecls[2]));
}

TEST(VariableReflectionTest, DISABLED_GetArrayDimensions) {
std::vector<Decl *> Decls, SubDecls;
std::string code = R"(
int a;
int b[1];
int c[1][2];
)";

GetAllTopLevelDecls(code, Decls);

auto is_vec_eq = [](const std::vector<size_t> &arr_dims,
const std::vector<size_t> &truth_vals) {
if (arr_dims.size() != truth_vals.size())
return false;

return std::equal(arr_dims.begin(), arr_dims.end(), truth_vals.begin());
};

// EXPECT_TRUE(is_vec_eq(InterOp::GetArrayDimensions(Decls[0]), {}));
// EXPECT_TRUE(is_vec_eq(InterOp::GetArrayDimensions(Decls[1]), {1}));
// EXPECT_TRUE(is_vec_eq(InterOp::GetArrayDimensions(Decls[2]), {1,2}));
}