diff --git a/.gitignore b/.gitignore index 259148fa1..ff720c780 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,7 @@ *.exe *.out *.app + +# Directories +build +install \ No newline at end of file diff --git a/include/clang/Interpreter/InterOp.h b/include/clang/Interpreter/InterOp.h index 0b2ea08d7..3b5d71bde 100644 --- a/include/clang/Interpreter/InterOp.h +++ b/include/clang/Interpreter/InterOp.h @@ -13,7 +13,6 @@ #include #include -namespace cling { namespace InterOp { using TCppIndex_t = size_t; using TCppScope_t = void*; @@ -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 GetAllCppNames(TCppScope_t scope); } // end namespace InterOp -} // end namespace cling - #endif // CLING_INTERPRETER_INTEROP_H diff --git a/lib/Interpreter/InterOp.cpp b/lib/Interpreter/InterOp.cpp index db5b6fbe8..163306fe2 100644 --- a/lib/Interpreter/InterOp.cpp +++ b/lib/Interpreter/InterOp.cpp @@ -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" @@ -30,7 +32,6 @@ #include #include -namespace cling { namespace InterOp { using namespace clang; using namespace llvm; @@ -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 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; @@ -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; @@ -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(D->m_DGR.getSingleDecl())) { auto *scope = GetScopeFromType(VD->getType()); @@ -1915,5 +2001,3 @@ namespace InterOp { } } // end namespace InterOp -} // end namespace cling - diff --git a/unittests/InterOp/FunctionReflectionTest.cpp b/unittests/InterOp/FunctionReflectionTest.cpp index 79f902837..354aef468 100644 --- a/unittests/InterOp/FunctionReflectionTest.cpp +++ b/unittests/InterOp/FunctionReflectionTest.cpp @@ -602,3 +602,20 @@ TEST(FunctionReflectionTest, GetFunctionCallWrapper) { EXPECT_EQ(ret, i * i); EXPECT_EQ(output, s); } + +TEST(FunctionReflectionTest, DISABLED_IsConstMethod) { + std::vector 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 +} + diff --git a/unittests/InterOp/ScopeReflectionTest.cpp b/unittests/InterOp/ScopeReflectionTest.cpp index 6e95c3600..529f7ac64 100644 --- a/unittests/InterOp/ScopeReflectionTest.cpp +++ b/unittests/InterOp/ScopeReflectionTest.cpp @@ -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"); @@ -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"); @@ -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"); @@ -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) { diff --git a/unittests/InterOp/TypeReflectionTest.cpp b/unittests/InterOp/TypeReflectionTest.cpp index b046947d4..859ef47ac 100644 --- a/unittests/InterOp/TypeReflectionTest.cpp +++ b/unittests/InterOp/TypeReflectionTest.cpp @@ -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 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)); +} + diff --git a/unittests/InterOp/VariableReflectionTest.cpp b/unittests/InterOp/VariableReflectionTest.cpp index 78bdcaab7..9c309eb14 100644 --- a/unittests/InterOp/VariableReflectionTest.cpp +++ b/unittests/InterOp/VariableReflectionTest.cpp @@ -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 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 &arr_dims, + const std::vector &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})); +} \ No newline at end of file