Cache all string types.

This commit is contained in:
Frederich Munch 2017-06-04 00:18:01 -04:00 committed by sftnight
parent 8fab0d5be8
commit 7504234e21
3 changed files with 70 additions and 19 deletions

View File

@ -40,17 +40,26 @@ namespace cling {
/// Sema and Preprocessor objects.
///
class LookupHelper {
private:
std::unique_ptr<clang::Parser> 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<clang::Parser> 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

View File

@ -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

View File

@ -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<std::string>(V, *(std::string*)V.getPtr());
case LookupHelper::kWCharString:
return executePrintValue<std::wstring>(V, *(std::wstring*)V.getPtr());
case LookupHelper::kUTF16Str:
return executePrintValue<std::u16string>(V, *(std::u16string*)V.getPtr());
case LookupHelper::kUTF32Str:
return executePrintValue<std::u32string>(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<std::string>(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<clang::BuiltinType>(Td.getCanonicalType().getTypePtr())) {
switch (BT->getKind()) {