Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions interpreter/cling/include/cling/Interpreter/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace clang {
class Sema;
class SourceLocation;
class SourceManager;
class Type;
class PresumedLoc;
}

Expand Down Expand Up @@ -196,6 +197,12 @@ namespace cling {
///
mutable std::vector<ClangInternalState*> m_StoredStates;

enum {
kStdStringTransaction = 0, // Transaction known to contain std::string
kNumTransactions
};
mutable const Transaction* m_CachedTrns[kNumTransactions] = {};

///\brief Worker function, building block for interpreter's public
/// interfaces.
///
Expand Down Expand Up @@ -690,6 +697,12 @@ namespace cling {
///
const Transaction* getLatestTransaction() const;

///\brief Returns a reference to a Transaction known to contain std::string.
///
const Transaction*& getStdStringTransaction() const {
return m_CachedTrns[kStdStringTransaction];
}

///\brief Compile extern "C" function and return its address.
///
///\param[in] name - function name
Expand Down
27 changes: 18 additions & 9 deletions interpreter/cling/include/cling/Interpreter/LookupHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,33 @@ namespace llvm {

namespace cling {
class Interpreter;
class Transaction;

///\brief Reflection information query interface. The class performs lookups
/// in the currently loaded information in the AST, using the same Parser,
/// 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();

Expand Down Expand Up @@ -222,10 +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
Expand Down
8 changes: 8 additions & 0 deletions interpreter/cling/lib/Interpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,14 @@ namespace cling {
}
}

// Clear any cached transaction states.
for (unsigned i = 0; i < kNumTransactions; ++i) {
if (m_CachedTrns[i] == &T) {
m_CachedTrns[i] = nullptr;
break;
}
}

if (InterpreterCallbacks* callbacks = getCallbacks())
callbacks->TransactionUnloaded(T);
if (m_Executor) { // we also might be in fsyntax-only mode.
Expand Down
42 changes: 37 additions & 5 deletions interpreter/cling/lib/Interpreter/LookupHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}

Expand Down Expand Up @@ -1898,10 +1901,39 @@ namespace cling {
diagOnOff);
}

const Type* LookupHelper::getStringType() {
if (!m_StringTy)
m_StringTy = findType("std::string", WithDiagnostics).getTypePtr();
return m_StringTy;
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[kStdString]) {
if (!Cache) ::memset(m_StringTy, 0, sizeof(m_StringTy));

QualType Qt = findType("std::string", WithDiagnostics);
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");
}
}

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
23 changes: 20 additions & 3 deletions interpreter/cling/lib/Interpreter/ValuePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -776,9 +792,10 @@ static std::string printUnpackedClingValue(const Value &V) {
} else if (clang::CXXRecordDecl *CXXRD = Ty->getAsCXXRecordDecl()) {
if (CXXRD->isLambda())
return printAddress(V.getPtr(), '@');
LookupHelper& LH= V.getInterpreter()->getLookupHelper();
if (C.hasSameType(CXXRD->getTypeForDecl(), LH.getStringType()))
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()) {
Expand Down