diff --git a/interpreter/CppInterOp/cppinterop-version.tag b/interpreter/CppInterOp/cppinterop-version.tag index f1e2afb3be837..7cfb21d499e7e 100644 --- a/interpreter/CppInterOp/cppinterop-version.tag +++ b/interpreter/CppInterOp/cppinterop-version.tag @@ -1 +1 @@ -c211948a266d7d42466a3ea5a3ebbf81548486e5 \ No newline at end of file +76d06008a66cf8d2a283f2ee1daecc4b81ca7d87 \ No newline at end of file diff --git a/interpreter/CppInterOp/lib/CppInterOp/CMakeLists.txt b/interpreter/CppInterOp/lib/CppInterOp/CMakeLists.txt index abdb6d3f9a026..0383055cd2481 100644 --- a/interpreter/CppInterOp/lib/CppInterOp/CMakeLists.txt +++ b/interpreter/CppInterOp/lib/CppInterOp/CMakeLists.txt @@ -54,10 +54,6 @@ if(NOT WIN32 AND NOT EMSCRIPTEN) list(APPEND link_libs dl) endif() -if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0) - list(APPEND link_libs stdc++fs) -endif() - # Get rid of libLLVM-X.so which is appended to the list of static libraries. if (LLVM_LINK_LLVM_DYLIB) set(new_libs ${link_libs}) diff --git a/interpreter/CppInterOp/lib/CppInterOp/CppInterOp.cpp b/interpreter/CppInterOp/lib/CppInterOp/CppInterOp.cpp index 8c247b1736179..85588f0fa14aa 100755 --- a/interpreter/CppInterOp/lib/CppInterOp/CppInterOp.cpp +++ b/interpreter/CppInterOp/lib/CppInterOp/CppInterOp.cpp @@ -62,6 +62,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Error.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -74,7 +75,6 @@ #include #include #include -#include #include #include #include @@ -383,9 +383,7 @@ bool IsComplete(TCppScope_t scope) { QualType QT = QualType::getFromOpaquePtr(GetTypeFromScope(scope)); clang::Sema& S = getSema(); SourceLocation fakeLoc = GetValidSLoc(S); -#ifdef CPPINTEROP_USE_CLING - cling::Interpreter::PushTransactionRAII RAII(&getInterp()); -#endif // CPPINTEROP_USE_CLING + compat::SynthesizingCodeRAII RAII(&getInterp()); return S.isCompleteType(fakeLoc, QT); } @@ -799,8 +797,8 @@ TCppScope_t GetNamed(const std::string& name, #ifdef CPPINTEROP_USE_CLING if (Within) Within->getPrimaryContext()->buildLookup(); - cling::Interpreter::PushTransactionRAII RAII(&getInterp()); #endif + compat::SynthesizingCodeRAII RAII(&getInterp()); auto* ND = CppInternal::utils::Lookup::Named(&getSema(), name, Within); if (ND && ND != (clang::NamedDecl*)-1) { return (TCppScope_t)(ND->getCanonicalDecl()); @@ -850,7 +848,7 @@ TCppScope_t GetBaseClass(TCppScope_t klass, TCppIndex_t ibase) { auto type = (CXXRD->bases_begin() + ibase)->getType(); if (auto RT = type->getAs()) - return (TCppScope_t)RT->getDecl(); + return (TCppScope_t)RT->getDecl()->getCanonicalDecl(); return 0; } @@ -958,9 +956,7 @@ static void GetClassDecls(TCppScope_t klass, return; auto* CXXRD = dyn_cast(D); -#ifdef CPPINTEROP_USE_CLING - cling::Interpreter::PushTransactionRAII RAII(&getInterp()); -#endif // CPPINTEROP_USE_CLING + compat::SynthesizingCodeRAII RAII(&getInterp()); if (CXXRD->hasDefinition()) CXXRD = CXXRD->getDefinition(); getSema().ForceDeclarationOfImplicitMembers(CXXRD); @@ -1018,6 +1014,7 @@ TCppFunction_t GetDefaultConstructor(compat::Interpreter& interp, return nullptr; auto* CXXRD = (clang::CXXRecordDecl*)scope; + compat::SynthesizingCodeRAII RAII(&getInterp()); return interp.getCI()->getSema().LookupDefaultConstructor(CXXRD); } @@ -1281,9 +1278,7 @@ BestOverloadFunctionMatch(const std::vector& candidates, auto& S = getSema(); auto& C = S.getASTContext(); -#ifdef CPPINTEROP_USE_CLING - cling::Interpreter::PushTransactionRAII RAII(&getInterp()); -#endif + compat::SynthesizingCodeRAII RAII(&getInterp()); // The overload resolution interfaces in Sema require a list of expressions. // However, unlike handwritten C++, we do not always have a expression. @@ -1655,7 +1650,8 @@ intptr_t GetVariableOffset(compat::Interpreter& I, Decl* D, } if (auto* RD = llvm::dyn_cast(FieldParentRecordDecl)) { // add in the offsets for the (multi level) base classes - while (BaseCXXRD != RD->getCanonicalDecl()) { + RD = RD->getCanonicalDecl(); + while (BaseCXXRD != RD) { CXXRecordDecl* Parent = direction.at(RD); offset += C.getASTRecordLayout(Parent).getBaseClassOffset(RD).getQuantity(); @@ -1679,9 +1675,7 @@ intptr_t GetVariableOffset(compat::Interpreter& I, Decl* D, address = I.getAddressOfGlobal(GD); if (!address) { if (!VD->hasInit()) { -#ifdef CPPINTEROP_USE_CLING - cling::Interpreter::PushTransactionRAII RAII(&getInterp()); -#endif // CPPINTEROP_USE_CLING + compat::SynthesizingCodeRAII RAII(&getInterp()); getSema().InstantiateVariableDefinition(SourceLocation(), VD); VD = VD->getDefinition(); } @@ -2611,6 +2605,7 @@ int get_wrapper_code(compat::Interpreter& I, const FunctionDecl* FD, // bool needInstantiation = false; const FunctionDecl* Definition = 0; + compat::SynthesizingCodeRAII RAII(&getInterp()); if (!FD->isDefined(Definition)) { FunctionDecl::TemplatedKind TK = FD->getTemplatedKind(); switch (TK) { @@ -3331,15 +3326,31 @@ void AddLibrarySearchPaths(const std::string& ResourceDir, false, false); } } +std::string ExtractArgument(const std::vector& Args, + const std::string& Arg) { + size_t I = 0; + for (auto i = Args.begin(); i != Args.end(); i++) + if ((++I < Args.size()) && (*i == Arg)) + return *(++i); + return ""; +} } // namespace TInterp_t CreateInterpreter(const std::vector& Args /*={}*/, const std::vector& GpuArgs /*={}*/) { std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr); - std::string ResourceDir = MakeResourcesPath(); + // In some systems, CppInterOp cannot manually detect the correct resource. + // Then the -resource-dir passed by the user is assumed to be the correct + // location. Prioritising it over detecting it within CppInterOp. Extracting + // the resource-dir from the arguments is required because we set the + // necessary library search location explicitly below. Because by default, + // linker flags are ignored in repl (issue #748) + std::string ResourceDir = ExtractArgument(Args, "-resource-dir"); + if (ResourceDir.empty()) + ResourceDir = MakeResourcesPath(); llvm::Triple T(llvm::sys::getProcessTriple()); - namespace fs = std::filesystem; - if ((!fs::is_directory(ResourceDir)) && (T.isOSDarwin() || T.isOSLinux())) + if ((!sys::fs::is_directory(ResourceDir)) && + (T.isOSDarwin() || T.isOSLinux())) ResourceDir = DetectResourceDir(); std::vector ClingArgv = {"-resource-dir", ResourceDir.c_str(), @@ -3871,11 +3882,8 @@ TCppScope_t InstantiateTemplate(compat::Interpreter& I, TCppScope_t tmpl, } TemplateDecl* TmplD = static_cast(tmpl); - // We will create a new decl, push a transaction. -#ifdef CPPINTEROP_USE_CLING - cling::Interpreter::PushTransactionRAII RAII(&I); -#endif + compat::SynthesizingCodeRAII RAII(&getInterp()); return InstantiateTemplate(TmplD, TemplateArgs, S, instantiate_body); } @@ -3934,9 +3942,7 @@ void GetAllCppNames(TCppScope_t scope, std::set& names) { clang::DeclContext* DC; clang::DeclContext::decl_iterator decl; -#ifdef CPPINTEROP_USE_CLING - cling::Interpreter::PushTransactionRAII RAII(&getInterp()); -#endif + compat::SynthesizingCodeRAII RAII(&getInterp()); if (auto* TD = dyn_cast_or_null(D)) { DC = clang::TagDecl::castToDeclContext(TD); @@ -4014,9 +4020,7 @@ bool IsTypeDerivedFrom(TCppType_t derived, TCppType_t base) { auto derivedType = clang::QualType::getFromOpaquePtr(derived); auto baseType = clang::QualType::getFromOpaquePtr(base); -#ifdef CPPINTEROP_USE_CLING - cling::Interpreter::PushTransactionRAII RAII(&getInterp()); -#endif + compat::SynthesizingCodeRAII RAII(&getInterp()); return S.IsDerivedFrom(fakeLoc, derivedType, baseType); } @@ -4035,6 +4039,7 @@ std::string GetFunctionArgDefault(TCppFunction_t func, std::string Result; llvm::raw_string_ostream OS(Result); Expr* DefaultArgExpr = nullptr; + compat::SynthesizingCodeRAII RAII(&getInterp()); if (PI->hasUninstantiatedDefaultArg()) DefaultArgExpr = PI->getUninstantiatedDefaultArg(); else @@ -4120,6 +4125,7 @@ OperatorArity GetOperatorArity(TCppFunction_t op) { void GetOperator(TCppScope_t scope, Operator op, std::vector& operators, OperatorArity kind) { Decl* D = static_cast(scope); + compat::SynthesizingCodeRAII RAII(&getInterp()); if (auto* CXXRD = llvm::dyn_cast_or_null(D)) { auto fn = [&operators, kind, op](const RecordDecl* RD) { ASTContext& C = RD->getASTContext(); @@ -4349,10 +4355,9 @@ void CodeComplete(std::vector& Results, const char* code, } int Undo(unsigned N) { + compat::SynthesizingCodeRAII RAII(&getInterp()); #ifdef CPPINTEROP_USE_CLING - auto& I = getInterp(); - cling::Interpreter::PushTransactionRAII RAII(&I); - I.unload(N); + getInterp().unload(N); return compat::Interpreter::kSuccess; #else return getInterp().undo(N); diff --git a/interpreter/CppInterOp/unittests/CppInterOp/InterpreterTest.cpp b/interpreter/CppInterOp/unittests/CppInterOp/InterpreterTest.cpp index 3c19cc9638d62..2c0e70f37df5d 100644 --- a/interpreter/CppInterOp/unittests/CppInterOp/InterpreterTest.cpp +++ b/interpreter/CppInterOp/unittests/CppInterOp/InterpreterTest.cpp @@ -272,7 +272,11 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, Interpreter_DISABLED_DetectResourceDir) { GTEST_SKIP() << "Test not run (Clang binary does not exist)"; std::string DetectedPath = Cpp::DetectResourceDir(Clang.str().str().c_str()); - EXPECT_STREQ(DetectedPath.c_str(), Cpp::GetResourceDir()); + llvm::SmallString<256> absPath(Cpp::GetResourceDir()); + EXPECT_TRUE(!llvm::sys::fs::make_absolute(absPath)); + llvm::SmallString<256> realPath; + EXPECT_TRUE(!llvm::sys::fs::real_path(absPath, realPath)); + EXPECT_STREQ(DetectedPath.c_str(), realPath.str().str().c_str()); } TYPED_TEST(CPPINTEROP_TEST_MODE, Interpreter_DetectSystemCompilerIncludePaths) {