From f4c5d4d3522ffb84c8274ad3ee144340a037220b Mon Sep 17 00:00:00 2001 From: Frederich Munch Date: Tue, 4 Jul 2017 15:09:23 -0400 Subject: [PATCH 1/8] Let RuntimeUniverse.h be included by languages other than C++. --- include/cling/Interpreter/RuntimeUniverse.h | 29 ++++++++++++++------- lib/Interpreter/Interpreter.cpp | 22 +++++++--------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/include/cling/Interpreter/RuntimeUniverse.h b/include/cling/Interpreter/RuntimeUniverse.h index c316fff2e7..3838e96a5e 100644 --- a/include/cling/Interpreter/RuntimeUniverse.h +++ b/include/cling/Interpreter/RuntimeUniverse.h @@ -21,7 +21,11 @@ #define __STDC_CONSTANT_MACROS // needed by System/DataTypes.h #endif -#ifdef __cplusplus +#ifndef __cplusplus + +extern void* gCling; + +#else #include @@ -177,15 +181,20 @@ namespace cling { using namespace cling::runtime; extern "C" { - ///\brief a function that throws InvalidDerefException. This allows to 'hide' - /// the definition of the exceptions from the RuntimeUniverse and allows us to - /// run cling in -no-rtti mode. - /// - - void* cling_runtime_internal_throwIfInvalidPointer(void* Sema, - void* Expr, - const void* Arg); -} + #endif // __cplusplus +///\brief a function that throws InvalidDerefException. This allows to 'hide' +/// the definition of the exceptions from the RuntimeUniverse and allows us to +/// run cling in -no-rtti mode. +/// + +void* cling_runtime_internal_throwIfInvalidPointer(void* Sema, + void* Expr, + const void* Arg); + +#ifdef __cplusplus +} // extern "C" +#endif + #endif // CLING_RUNTIME_UNIVERSE_H diff --git a/lib/Interpreter/Interpreter.cpp b/lib/Interpreter/Interpreter.cpp index 50965d7156..806087e226 100644 --- a/lib/Interpreter/Interpreter.cpp +++ b/lib/Interpreter/Interpreter.cpp @@ -356,26 +356,22 @@ namespace cling { // (on OS X at least, so probably Linux too) and the JIT thinks the symbol // is undefined in a child Interpreter. And speaking of children, should // gCling actually be thisCling, so a child Interpreter can only access - // itself? One could use a macro (simillar to __dso_handle) to block - // assignemnt and get around the mangling issue. - const char* Linkage = LangOpts.CPlusPlus ? "extern \"C\"" : ""; + // itself? if (!NoRuntime) { - if (LangOpts.CPlusPlus) { - Strm << "#include \"cling/Interpreter/RuntimeUniverse.h\"\n"; - if (EmitDefinitions) + Strm << "#include \"cling/Interpreter/RuntimeUniverse.h\"\n"; + if (EmitDefinitions) { + if (LangOpts.CPlusPlus) { Strm << "namespace cling { class Interpreter; namespace runtime { " - "Interpreter* gCling=(Interpreter*)" << ThisP << ";}}\n"; - } else { - Strm << "#include \"cling/Interpreter/CValuePrinter.h\"\n" - << "void* gCling"; - if (EmitDefinitions) - Strm << "=(void*)" << ThisP; - Strm << ";\n"; + "Interpreter* gCling=(Interpreter*)" + << ThisP << ";}}\n"; + } else + Strm << "gCling =(void*)" << ThisP; } } // Intercept all atexit calls, as the Interpreter and functions will be long // gone when the -native- versions invoke them. + const char* Linkage = LangOpts.CPlusPlus ? "extern \"C\"" : ""; #if defined(__GLIBCXX__) && !defined(__APPLE__) const char* LinkageCxx = "extern \"C++\""; const char* Attr = LangOpts.CPlusPlus ? " throw () " : ""; From 3e2cc259b06344575d739c71d6d3014fb8fafcb2 Mon Sep 17 00:00:00 2001 From: Frederich Munch Date: Tue, 20 Jun 2017 03:23:56 -0400 Subject: [PATCH 2/8] Add more general interfaces for Analyze::maybeMangleDeclName. Mangling with a GlobalDecl is only really necessary for constructors and destructors. --- include/cling/Utils/AST.h | 20 ++++++++ lib/Utils/AST.cpp | 105 ++++++++++++++++++++++---------------- 2 files changed, 82 insertions(+), 43 deletions(-) diff --git a/include/cling/Utils/AST.h b/include/cling/Utils/AST.h index 3b4fe50832..6cb296abee 100644 --- a/include/cling/Utils/AST.h +++ b/include/cling/Utils/AST.h @@ -50,6 +50,18 @@ namespace utils { /// bool IsWrapper(const clang::FunctionDecl* ND); + ///\brief Get the mangled name of a NamedDecl. + /// + ///\param [in] ND - Try to mangle this decl's name. + ///\param [in] GD - Provide the GlobalDecl if what is to be mangled is a + /// constructor or destructor. + /// + ///\returns The mangled or pure name (when ND should not be mangled) on + /// success or an empty string on failure. + /// + std::string maybeMangleDeclName(const clang::NamedDecl* ND, + const clang::GlobalDecl* GD = nullptr); + ///\brief Get the mangled name of a GlobalDecl. /// ///\param [in] GD - try to mangle this decl's name. @@ -58,6 +70,14 @@ namespace utils { void maybeMangleDeclName(const clang::GlobalDecl& GD, std::string& mangledName); + ///\brief Get the mangled name of a clang::Decl subclass. FunctionDecls and + /// VarDecls are currently supported. + /// + ///\param [in] Decl - try to mangle this decl's name. + ///\param [out] mangledName - put the mangled name in here. + /// + template + void maybeMangleDeclName(const T* Decl, std::string& mangledName); ///\brief Retrieves the last expression of a function body. If it was a /// DeclStmt with a variable declaration, creates DeclRefExpr and adds it to diff --git a/lib/Utils/AST.cpp b/lib/Utils/AST.cpp index 6d46522ab5..ccdb5b6129 100644 --- a/lib/Utils/AST.cpp +++ b/lib/Utils/AST.cpp @@ -8,6 +8,7 @@ //------------------------------------------------------------------------------ #include "cling/Utils/AST.h" +#include "cling/Utils/Output.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclarationName.h" @@ -57,53 +58,71 @@ namespace utils { .startswith(Synthesize::UniquePrefix); } - void Analyze::maybeMangleDeclName(const GlobalDecl& GD, - std::string& mangledName) { - // copied and adapted from CodeGen::CodeGenModule::getMangledName - - NamedDecl* D - = cast(const_cast(GD.getDecl())); - std::unique_ptr mangleCtx; - mangleCtx.reset(D->getASTContext().createMangleContext()); - if (!mangleCtx->shouldMangleDeclName(D)) { - IdentifierInfo *II = D->getIdentifier(); - assert(II && "Attempt to mangle unnamed decl."); - mangledName = II->getName(); - return; - } + namespace Analyze { + std::string maybeMangleDeclName(const NamedDecl *ND, const GlobalDecl* GD) { + // copied and adapted from CodeGen::CodeGenModule::getMangledName - llvm::raw_string_ostream RawStr(mangledName); - switch(D->getKind()) { - case Decl::CXXConstructor: - //Ctor_Complete, // Complete object ctor - //Ctor_Base, // Base object ctor - //Ctor_CompleteAllocating // Complete object allocating ctor (unused) - mangleCtx->mangleCXXCtor(cast(D), - GD.getCtorType(), RawStr); - break; - - case Decl::CXXDestructor: - //Dtor_Deleting, // Deleting dtor - //Dtor_Complete, // Complete object dtor - //Dtor_Base // Base object dtor -#if defined(LLVM_ON_WIN32) - // MicrosoftMangle.cpp:954 calls llvm_unreachable when mangling Dtor_Comdat - if (GD.getDtorType() == Dtor_Comdat) { - if (const IdentifierInfo* II = D->getIdentifier()) - RawStr << II->getName(); - } else -#endif - { - mangleCtx->mangleCXXDtor(cast(D), - GD.getDtorType(), RawStr); + std::unique_ptr mangleCtx; + mangleCtx.reset(ND->getASTContext().createMangleContext()); + if (!mangleCtx->shouldMangleDeclName(ND)) { + IdentifierInfo *II = ND->getIdentifier(); + assert(II && "Attempt to mangle unnamed decl."); + return II->getName(); + } + + stdstrstream RawStr; + switch (ND->getKind()) { + case Decl::CXXConstructor: + //Ctor_Complete, // Complete object ctor + //Ctor_Base, // Base object ctor + //Ctor_CompleteAllocating // Complete object allocating ctor (unused) + if (GD) { + mangleCtx->mangleCXXCtor(cast(ND), + GD->getCtorType(), RawStr); + break; + } + + case Decl::CXXDestructor: + //Dtor_Deleting, // Deleting dtor + //Dtor_Complete, // Complete object dtor + //Dtor_Base // Base object dtor + if (GD) { + #if defined(LLVM_ON_WIN32) + // MicrosoftMangle.cpp:954 calls llvm_unreachable when mangling Dtor_Comdat + if (GD->getDtorType() == Dtor_Comdat) { + if (const IdentifierInfo* II = ND->getIdentifier()) + RawStr << II->getName(); + } else + #endif + { + mangleCtx->mangleCXXDtor(cast(ND), + GD->getDtorType(), RawStr); + } + break; + } + + default : + mangleCtx->mangleName(ND, RawStr); + break; } - break; + return RawStr.str(); + } + + void maybeMangleDeclName(const GlobalDecl& GD, std::string& mangledName) { + mangledName = maybeMangleDeclName(cast(GD.getDecl()), &GD); + } + + template <> + void maybeMangleDeclName(const FunctionDecl* FD, + std::string& mangledName) { + return maybeMangleDeclName(GlobalDecl(FD), mangledName); + } - default : - mangleCtx->mangleName(D, RawStr); - break; + template <> + void maybeMangleDeclName(const VarDecl* VD, + std::string& mangledName) { + return maybeMangleDeclName(GlobalDecl(VD), mangledName); } - RawStr.flush(); } Expr* Analyze::GetOrCreateLastExpr(FunctionDecl* FD, From 15278a0b91f86101403757fb2d06f93a095e2915 Mon Sep 17 00:00:00 2001 From: Frederich Munch Date: Fri, 16 Jun 2017 17:54:51 -0400 Subject: [PATCH 3/8] Add accessors for a child Interpreter to get its parent. --- include/cling/Interpreter/Interpreter.h | 13 +++++++++++++ lib/Interpreter/Interpreter.cpp | 24 +++++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/include/cling/Interpreter/Interpreter.h b/include/cling/Interpreter/Interpreter.h index 0c23a90519..4980510df1 100644 --- a/include/cling/Interpreter/Interpreter.h +++ b/include/cling/Interpreter/Interpreter.h @@ -142,6 +142,11 @@ namespace cling { /// InvocationOptions m_Opts; + ///\brief Back pointer to *this* which stores parent information. + /// FIXME: Will also allow to link in gCling rather than runtime define it. + /// + Interpreter** m_Parenting; + ///\brief The llvm library state, a per-thread object. /// std::unique_ptr m_LLVMContext; @@ -332,6 +337,14 @@ namespace cling { /// bool isValid() const; + ///\brief Returns this interpreter's parent or null: while (P = parent()) + /// + Interpreter* parent(); + + ///\brief Returns greatest ancestor of this interpreter. Might be itself. + /// + Interpreter& ancestor(); + const InvocationOptions& getOptions() const { return m_Opts; } InvocationOptions& getOptions() { return m_Opts; } diff --git a/lib/Interpreter/Interpreter.cpp b/lib/Interpreter/Interpreter.cpp index 806087e226..f1555d5fae 100644 --- a/lib/Interpreter/Interpreter.cpp +++ b/lib/Interpreter/Interpreter.cpp @@ -185,12 +185,19 @@ namespace cling { Interpreter::Interpreter(int argc, const char* const *argv, const char* llvmdir /*= 0*/, bool noRuntime, const Interpreter* parentInterp) : - m_Opts(argc, argv), + m_Opts(argc, argv), m_Parenting(nullptr), m_UniqueCounter(parentInterp ? parentInterp->m_UniqueCounter + 1 : 0), m_PrintDebug(false), m_DynamicLookupDeclared(false), m_DynamicLookupEnabled(false), m_RawInputEnabled(false), m_OptLevel(parentInterp ? parentInterp->m_OptLevel : -1) { + if (parentInterp) { + m_Parenting = new Interpreter*[2]; + m_Parenting[0] = this; + m_Parenting[1] = const_cast(parentInterp); + } else + m_Parenting = reinterpret_cast(this); + if (handleSimpleOptions(m_Opts)) return; @@ -340,6 +347,21 @@ namespace cling { // explicitly, before the implicit destruction (through the unique_ptr) of // the callbacks. m_IncrParser.reset(0); + + if (m_Parenting != reinterpret_cast(this)) + delete [] m_Parenting; + } + + Interpreter* Interpreter::parent() { + if (m_Parenting == reinterpret_cast(this)) + return nullptr; + return m_Parenting[1]; + } + + Interpreter& Interpreter::ancestor() { + if (m_Parenting == reinterpret_cast(this)) + return *this; + return m_Parenting[1]->ancestor(); } Transaction* Interpreter::Initialize(bool NoRuntime, bool SyntaxOnly, From 5ac84b3f9c5a0a81caa3f141c291758984adf3a6 Mon Sep 17 00:00:00 2001 From: Frederich Munch Date: Fri, 16 Jun 2017 17:54:52 -0400 Subject: [PATCH 4/8] Add pointer to gCling as a symbol in the JIT. --- .../DynamicLookupRuntimeUniverse.h | 2 +- include/cling/Interpreter/Interpreter.h | 4 +- include/cling/Interpreter/RuntimeUniverse.h | 4 +- lib/Interpreter/Interpreter.cpp | 41 +++++++++++++------ 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/include/cling/Interpreter/DynamicLookupRuntimeUniverse.h b/include/cling/Interpreter/DynamicLookupRuntimeUniverse.h index 7e17db3ab6..e8f0d807ba 100644 --- a/include/cling/Interpreter/DynamicLookupRuntimeUniverse.h +++ b/include/cling/Interpreter/DynamicLookupRuntimeUniverse.h @@ -21,7 +21,7 @@ namespace cling { /// \brief Contains declarations for cling's runtime. namespace runtime { - extern Interpreter* gCling; + extern Interpreter* const gCling; /// \brief Provides builtins, which are neccessary for the dynamic scopes /// and runtime bindings. These builtins should be used for other purposes. diff --git a/include/cling/Interpreter/Interpreter.h b/include/cling/Interpreter/Interpreter.h index 4980510df1..9e91cda0a3 100644 --- a/include/cling/Interpreter/Interpreter.h +++ b/include/cling/Interpreter/Interpreter.h @@ -142,8 +142,8 @@ namespace cling { /// InvocationOptions m_Opts; - ///\brief Back pointer to *this* which stores parent information. - /// FIXME: Will also allow to link in gCling rather than runtime define it. + ///\brief Storage to hold parenting information, which is also used as a + /// a fixed address/location passed to the JIT's linker for gCling. /// Interpreter** m_Parenting; diff --git a/include/cling/Interpreter/RuntimeUniverse.h b/include/cling/Interpreter/RuntimeUniverse.h index 3838e96a5e..db8f1abc46 100644 --- a/include/cling/Interpreter/RuntimeUniverse.h +++ b/include/cling/Interpreter/RuntimeUniverse.h @@ -23,7 +23,7 @@ #ifndef __cplusplus -extern void* gCling; +extern const void* const gCling; #else @@ -40,7 +40,7 @@ namespace cling { /// \brief The interpreter provides itself as a builtin, i.e. it /// interprets itself. This is particularly important for implementing /// the dynamic scopes and the runtime bindings - extern Interpreter* gCling; + extern Interpreter* const gCling; namespace internal { /// \brief Some of clang's routines rely on valid source locations and diff --git a/lib/Interpreter/Interpreter.cpp b/lib/Interpreter/Interpreter.cpp index f1555d5fae..eef74f3ee6 100644 --- a/lib/Interpreter/Interpreter.cpp +++ b/lib/Interpreter/Interpreter.cpp @@ -229,9 +229,12 @@ namespace cling { return; } + const CompilerInstance* CI = getCI(); + const LangOptions& LangOpts = CI->getLangOpts(); + // Tell the diagnostic client that we are entering file parsing mode. - DiagnosticConsumer& DClient = getCI()->getDiagnosticClient(); - DClient.BeginSourceFile(getCI()->getLangOpts(), &PP); + DiagnosticConsumer& DClient = CI->getDiagnosticClient(); + DClient.BeginSourceFile(LangOpts, &PP); llvm::SmallVector IncrParserTransactions; @@ -272,6 +275,29 @@ namespace cling { } else cling::errs() << Sym << " not in Module!\n"; } + + const clang::Decl* Scope = + LangOpts.CPlusPlus + ? m_LookupHelper->findScope("cling::runtime", + LookupHelper::NoDiagnostics) + : CI->getSema().getASTContext().getTranslationUnitDecl(); + if (!Scope) { + cling::errs() << "Scope for gCling was not found\n"; + } else if (const clang::ValueDecl* gCling = + m_LookupHelper->findDataMember( + Scope, "gCling", LookupHelper::NoDiagnostics)) { + std::string Name = !LangOpts.CPlusPlus ? "gCling" : + utils::Analyze::maybeMangleDeclName(gCling); + if (!Name.empty()) { + // gCling gets linked to top-most Interpreter. + if (!parent()) + m_Executor->addSymbol(Name.c_str(), &m_Parenting, true); + else + m_Executor->addSymbol(Name.c_str(), &m_Parenting[1], true); + } + } else { + cling::errs() << "gCling was not found\n"; + } } } } @@ -379,17 +405,8 @@ namespace cling { // is undefined in a child Interpreter. And speaking of children, should // gCling actually be thisCling, so a child Interpreter can only access // itself? - if (!NoRuntime) { + if (!NoRuntime) Strm << "#include \"cling/Interpreter/RuntimeUniverse.h\"\n"; - if (EmitDefinitions) { - if (LangOpts.CPlusPlus) { - Strm << "namespace cling { class Interpreter; namespace runtime { " - "Interpreter* gCling=(Interpreter*)" - << ThisP << ";}}\n"; - } else - Strm << "gCling =(void*)" << ThisP; - } - } // Intercept all atexit calls, as the Interpreter and functions will be long // gone when the -native- versions invoke them. From f82b25e372092a50d52a9cd28574220860b5e131 Mon Sep 17 00:00:00 2001 From: Frederich Munch Date: Fri, 16 Jun 2017 17:54:53 -0400 Subject: [PATCH 5/8] Windows: Fix gCling name mangling returning a prefix of '\x1'. --- lib/Interpreter/Interpreter.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/Interpreter/Interpreter.cpp b/lib/Interpreter/Interpreter.cpp index eef74f3ee6..118aa55839 100644 --- a/lib/Interpreter/Interpreter.cpp +++ b/lib/Interpreter/Interpreter.cpp @@ -289,6 +289,11 @@ namespace cling { std::string Name = !LangOpts.CPlusPlus ? "gCling" : utils::Analyze::maybeMangleDeclName(gCling); if (!Name.empty()) { +#ifdef LLVM_ON_WIN32 + // MS mangling is purposely adding a prefix of '\x1'...why? + if (Name[0] == '\x1') + Name.erase(0, 1); +#endif // gCling gets linked to top-most Interpreter. if (!parent()) m_Executor->addSymbol(Name.c_str(), &m_Parenting, true); From 560819d78572e60e38622a5c74112d4135d04721 Mon Sep 17 00:00:00 2001 From: Frederich Munch Date: Thu, 16 Mar 2017 16:51:00 -0400 Subject: [PATCH 6/8] Make IncrementalExecutor::addSymbol take an llvm::StringRef. --- lib/Interpreter/IncrementalExecutor.cpp | 2 +- lib/Interpreter/IncrementalExecutor.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Interpreter/IncrementalExecutor.cpp b/lib/Interpreter/IncrementalExecutor.cpp index 1b1b2c79b7..a40027dd52 100644 --- a/lib/Interpreter/IncrementalExecutor.cpp +++ b/lib/Interpreter/IncrementalExecutor.cpp @@ -317,7 +317,7 @@ IncrementalExecutor::installLazyFunctionCreator(LazyFunctionCreatorFunc_t fp) } bool -IncrementalExecutor::addSymbol(const char* Name, void* Addr, +IncrementalExecutor::addSymbol(llvm::StringRef Name, void* Addr, bool Jit) { return m_JIT->lookupSymbol(Name, Addr, Jit).second; } diff --git a/lib/Interpreter/IncrementalExecutor.h b/lib/Interpreter/IncrementalExecutor.h index 5b00ce627c..22e084a7be 100644 --- a/lib/Interpreter/IncrementalExecutor.h +++ b/lib/Interpreter/IncrementalExecutor.h @@ -209,7 +209,7 @@ namespace cling { /// @param[in] JIT - Add to the JIT injected symbol table /// @returns true if the symbol is successfully registered, false otherwise. /// - bool addSymbol(const char* Name, void* Address, bool JIT = false); + bool addSymbol(llvm::StringRef Name, void* Address, bool JIT = false); ///\brief Add a llvm::Module to the JIT. /// From fa5df84e23f3ac4440f36e50330455f6a65a7d7e Mon Sep 17 00:00:00 2001 From: Frederich Munch Date: Thu, 16 Mar 2017 16:51:01 -0400 Subject: [PATCH 7/8] Avoid allocating std::strings when calling m_Executor->addSymbol. --- lib/Interpreter/Interpreter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Interpreter/Interpreter.cpp b/lib/Interpreter/Interpreter.cpp index 118aa55839..ccc387f40f 100644 --- a/lib/Interpreter/Interpreter.cpp +++ b/lib/Interpreter/Interpreter.cpp @@ -269,7 +269,7 @@ namespace cling { #endif if (GV) { if (void* Addr = m_Executor->getPointerToGlobalFromJIT(*GV)) - m_Executor->addSymbol(Sym.str().c_str(), Addr, true); + m_Executor->addSymbol(Sym, Addr, true); else cling::errs() << Sym << " not defined\n"; } else @@ -296,9 +296,9 @@ namespace cling { #endif // gCling gets linked to top-most Interpreter. if (!parent()) - m_Executor->addSymbol(Name.c_str(), &m_Parenting, true); + m_Executor->addSymbol(Name, &m_Parenting, true); else - m_Executor->addSymbol(Name.c_str(), &m_Parenting[1], true); + m_Executor->addSymbol(Name, &m_Parenting[1], true); } } else { cling::errs() << "gCling was not found\n"; From d14e9b46350f795306b90fb31861a695191e186d Mon Sep 17 00:00:00 2001 From: Frederich Munch Date: Thu, 16 Mar 2017 16:51:03 -0400 Subject: [PATCH 8/8] Make all maybeMangleDeclName overrides return a std::string. --- include/cling/Utils/AST.h | 21 ++++++++++++--------- lib/Interpreter/DeclUnloader.cpp | 9 ++++----- lib/Interpreter/Interpreter.cpp | 8 ++------ lib/Utils/AST.cpp | 26 +++++++++++++++++--------- 4 files changed, 35 insertions(+), 29 deletions(-) diff --git a/include/cling/Utils/AST.h b/include/cling/Utils/AST.h index 6cb296abee..78d30ee689 100644 --- a/include/cling/Utils/AST.h +++ b/include/cling/Utils/AST.h @@ -64,20 +64,23 @@ namespace utils { ///\brief Get the mangled name of a GlobalDecl. /// - ///\param [in] GD - try to mangle this decl's name. - ///\param [out] mangledName - put the mangled name in here. + ///\param [in] GD - Try to mangle this decl's name. /// - void maybeMangleDeclName(const clang::GlobalDecl& GD, - std::string& mangledName); + ///\returns The mangled or pure name (when ND should not be mangled) on + /// success or an empty string on failure. + /// + std::string maybeMangleDeclName(const clang::GlobalDecl& GD); - ///\brief Get the mangled name of a clang::Decl subclass. FunctionDecls and - /// VarDecls are currently supported. + ///\brief Get the mangled name of a clang::Decl subclass. FunctionDecl, + /// VarDecl, ValueDecl, and NamedDecl are currently supported. /// - ///\param [in] Decl - try to mangle this decl's name. - ///\param [out] mangledName - put the mangled name in here. + ///\param [in] Decl - Try to mangle this decl's name. + /// + ///\returns The mangled or pure name (when ND should not be mangled) on + /// success or an empty string on failure. /// template - void maybeMangleDeclName(const T* Decl, std::string& mangledName); + std::string maybeMangleDeclName(const T* Decl); ///\brief Retrieves the last expression of a function body. If it was a /// DeclStmt with a variable declaration, creates DeclRefExpr and adds it to diff --git a/lib/Interpreter/DeclUnloader.cpp b/lib/Interpreter/DeclUnloader.cpp index 83fd4b56ec..8b57d92a9c 100644 --- a/lib/Interpreter/DeclUnloader.cpp +++ b/lib/Interpreter/DeclUnloader.cpp @@ -853,17 +853,16 @@ bool DeclUnloader::VisitRedeclarable(clang::Redeclarable* R, DeclContext* DC) utils::DiagnosticsOverride IgnoreMangleErrors(m_Sema->getDiagnostics()); #endif #endif - utils::Analyze::maybeMangleDeclName(GD, mangledName); + utils::Analyze::maybeMangleDeclName(GD).swap(mangledName); } // Handle static locals. void func() { static int var; } is represented // in the llvm::Module is a global named @func.var if (const VarDecl* VD = dyn_cast(GD.getDecl())) { if (VD->isStaticLocal()) { - std::string functionMangledName; - GlobalDecl FDGD(cast(VD->getDeclContext())); - utils::Analyze::maybeMangleDeclName(FDGD, functionMangledName); - mangledName = functionMangledName + "." + mangledName; + mangledName = utils::Analyze::maybeMangleDeclName(GlobalDecl( + cast(VD->getDeclContext()))) + + "." + mangledName; } } diff --git a/lib/Interpreter/Interpreter.cpp b/lib/Interpreter/Interpreter.cpp index ccc387f40f..7b29488831 100644 --- a/lib/Interpreter/Interpreter.cpp +++ b/lib/Interpreter/Interpreter.cpp @@ -983,10 +983,8 @@ namespace cling { if (!FD) return kExeUnkownFunction; - std::string mangledNameIfNeeded; - utils::Analyze::maybeMangleDeclName(FD, mangledNameIfNeeded); IncrementalExecutor::ExecutionResult ExeRes = - m_Executor->executeWrapper(mangledNameIfNeeded, res); + m_Executor->executeWrapper(utils::Analyze::maybeMangleDeclName(FD), res); return ConvertExecutionResult(ExeRes); } @@ -1550,9 +1548,7 @@ namespace cling { void* Interpreter::getAddressOfGlobal(const GlobalDecl& GD, bool* fromJIT /*=0*/) const { // Return a symbol's address, and whether it was jitted. - std::string mangledName; - utils::Analyze::maybeMangleDeclName(GD, mangledName); - return getAddressOfGlobal(mangledName, fromJIT); + return getAddressOfGlobal(utils::Analyze::maybeMangleDeclName(GD), fromJIT); } void* Interpreter::getAddressOfGlobal(llvm::StringRef SymName, diff --git a/lib/Utils/AST.cpp b/lib/Utils/AST.cpp index ccdb5b6129..89a9cd1b76 100644 --- a/lib/Utils/AST.cpp +++ b/lib/Utils/AST.cpp @@ -107,21 +107,29 @@ namespace utils { } return RawStr.str(); } - - void maybeMangleDeclName(const GlobalDecl& GD, std::string& mangledName) { - mangledName = maybeMangleDeclName(cast(GD.getDecl()), &GD); + + std::string maybeMangleDeclName(const GlobalDecl& GD) { + return maybeMangleDeclName(cast(GD.getDecl()), &GD); } template <> - void maybeMangleDeclName(const FunctionDecl* FD, - std::string& mangledName) { - return maybeMangleDeclName(GlobalDecl(FD), mangledName); + std::string maybeMangleDeclName(const FunctionDecl* FD) { + return maybeMangleDeclName(GlobalDecl(FD)); + } + + template <> + std::string maybeMangleDeclName(const VarDecl* VD) { + return maybeMangleDeclName(GlobalDecl(VD)); + } + + template <> + std::string maybeMangleDeclName(const ValueDecl* VD) { + return maybeMangleDeclName(cast(VD), nullptr); } template <> - void maybeMangleDeclName(const VarDecl* VD, - std::string& mangledName) { - return maybeMangleDeclName(GlobalDecl(VD), mangledName); + std::string maybeMangleDeclName(const NamedDecl* ND) { + return maybeMangleDeclName(ND, nullptr); } }