From 7504234e219715398bf6c8e1e4009b65381b2f49 Mon Sep 17 00:00:00 2001 From: Frederich Munch Date: Sun, 4 Jun 2017 00:18:01 -0400 Subject: [PATCH] Cache all string types. --- include/cling/Interpreter/LookupHelper.h | 24 +++++++++----- lib/Interpreter/LookupHelper.cpp | 40 ++++++++++++++++++++---- lib/Interpreter/ValuePrinter.cpp | 25 ++++++++++++--- 3 files changed, 70 insertions(+), 19 deletions(-) diff --git a/include/cling/Interpreter/LookupHelper.h b/include/cling/Interpreter/LookupHelper.h index abfc1bc8..3b58393e 100644 --- a/include/cling/Interpreter/LookupHelper.h +++ b/include/cling/Interpreter/LookupHelper.h @@ -40,17 +40,26 @@ namespace cling { /// Sema and Preprocessor objects. /// class LookupHelper { - private: - std::unique_ptr m_Parser; - Interpreter* m_Interpreter; // we do not own. - const clang::Type* m_StringTy; public: - + enum StringType { + kStdString, + kWCharString, + kUTF16Str, + kUTF32Str, + kNumCachedStrings, + kNotAString = kNumCachedStrings, + }; enum DiagSetting { NoDiagnostics, WithDiagnostics }; + private: + std::unique_ptr m_Parser; + Interpreter* m_Interpreter; // we do not own. + const clang::Type* m_StringTy[kNumCachedStrings]; + + public: LookupHelper(clang::Parser* P, Interpreter* interp); ~LookupHelper(); @@ -224,9 +233,8 @@ namespace cling { bool hasFunction(const clang::Decl* scopeDecl, llvm::StringRef funcName, DiagSetting diagOnOff) const; - - ///\brief Retrieve the QualType of `std::string`. - const clang::Type* getStringType(); + ///\brief Retrieve the StringType of given Type. + StringType getStringType(const clang::Type* Type); }; } // end namespace diff --git a/lib/Interpreter/LookupHelper.cpp b/lib/Interpreter/LookupHelper.cpp index 839fbc84..4fd3629c 100644 --- a/lib/Interpreter/LookupHelper.cpp +++ b/lib/Interpreter/LookupHelper.cpp @@ -38,7 +38,10 @@ namespace cling { // pin *tor here so that we can have clang::Parser defined and be able to call // the dtor on the OwningPtr LookupHelper::LookupHelper(clang::Parser* P, Interpreter* interp) - : m_Parser(P), m_Interpreter(interp), m_StringTy(nullptr) {} + : m_Parser(P), m_Interpreter(interp) { + // Always properly initialized in getStringType + // ::memset(m_StringTy, 0, sizeof(m_StringTy)); + } LookupHelper::~LookupHelper() {} @@ -1898,14 +1901,39 @@ namespace cling { diagOnOff); } - const Type* LookupHelper::getStringType() { + static const clang::Type* getType(LookupHelper* LH, llvm::StringRef Type) { + QualType Qt = LH->findType(Type, LookupHelper::WithDiagnostics); + assert(!Qt.isNull() && "Type should exist"); + return Qt.getTypePtr(); + } + + LookupHelper::StringType + LookupHelper::getStringType(const clang::Type* Type) { + assert(Type && "Type cannot be null"); const Transaction*& Cache = m_Interpreter->getStdStringTransaction(); - if (!Cache || !m_StringTy) { + if (!Cache || !m_StringTy[kStdString]) { + if (!Cache) ::memset(m_StringTy, 0, sizeof(m_StringTy)); + QualType Qt = findType("std::string", WithDiagnostics); - if ((m_StringTy = Qt.isNull() ? nullptr : Qt.getTypePtr())) - Cache = m_Interpreter->getLatestTransaction(); + m_StringTy[kStdString] = Qt.isNull() ? nullptr : Qt.getTypePtr(); + if (!m_StringTy[kStdString]) return kNotAString; + + Cache = m_Interpreter->getLatestTransaction(); + m_StringTy[kWCharString] = getType(this, "std::wstring"); + + const clang::LangOptions& LO = m_Interpreter->getCI()->getLangOpts(); + if (LO.CPlusPlus11) { + m_StringTy[kUTF16Str] = getType(this, "std::u16string"); + m_StringTy[kUTF32Str] = getType(this, "std::u32string"); + } } - return m_StringTy; + + ASTContext& Ctx = m_Interpreter->getSema().getASTContext(); + for (unsigned I = 0; I < kNumCachedStrings; ++I) { + if (m_StringTy[I] && Ctx.hasSameType(Type, m_StringTy[I])) + return StringType(I); + } + return kNotAString; } } // end namespace cling diff --git a/lib/Interpreter/ValuePrinter.cpp b/lib/Interpreter/ValuePrinter.cpp index d039ff09..f2adf160 100644 --- a/lib/Interpreter/ValuePrinter.cpp +++ b/lib/Interpreter/ValuePrinter.cpp @@ -754,6 +754,22 @@ static std::string printFunctionValue(const Value &V, const void *ptr, clang::Qu return o.str(); } +static std::string printStringType(const Value &V, const clang::Type* Type) { + switch (V.getInterpreter()->getLookupHelper().getStringType(Type)) { + case LookupHelper::kStdString: + return executePrintValue(V, *(std::string*)V.getPtr()); + case LookupHelper::kWCharString: + return executePrintValue(V, *(std::wstring*)V.getPtr()); + case LookupHelper::kUTF16Str: + return executePrintValue(V, *(std::u16string*)V.getPtr()); + case LookupHelper::kUTF32Str: + return executePrintValue(V, *(std::u32string*)V.getPtr()); + default: + break; + } + return ""; +} + static std::string printUnpackedClingValue(const Value &V) { // Find the Type for `std::string`. We are guaranteed to have that declared // when this function is called; RuntimePrintValue.h #includes it. @@ -776,11 +792,10 @@ static std::string printUnpackedClingValue(const Value &V) { } else if (clang::CXXRecordDecl *CXXRD = Ty->getAsCXXRecordDecl()) { if (CXXRD->isLambda()) return printAddress(V.getPtr(), '@'); - if (const clang::Type* StrTy = - V.getInterpreter()->getLookupHelper().getStringType()) { - if (C.hasSameType(CXXRD->getTypeForDecl(), StrTy)) - return executePrintValue(V, *(std::string*)V.getPtr()); - } + + std::string Str = printStringType(V, CXXRD->getTypeForDecl()); + if (!Str.empty()) + return Str; } else if (const clang::BuiltinType *BT = llvm::dyn_cast(Td.getCanonicalType().getTypePtr())) { switch (BT->getKind()) {