From 340e954bbe7e5ec358ef5e48ccd79055860c8cb9 Mon Sep 17 00:00:00 2001 From: Axel Naumann Date: Mon, 12 Nov 2012 10:27:13 +0000 Subject: [PATCH] ValuePrinterInfo doesn't need to store the Expr but the QualType; shortens signatures. Factor out StoredValueRef streaming, expose so it can later be used by StoreValueRef::dump(). git-svn-id: http://root.cern.ch/svn/root/trunk@47178 27541ba8-7e3a-0410-8455-c3a389f83636 --- include/cling/Interpreter/ValuePrinter.h | 4 + include/cling/Interpreter/ValuePrinterInfo.h | 11 +- lib/Interpreter/ValuePrinter.cpp | 132 ++++++++++--------- lib/Interpreter/ValuePrinterInfo.cpp | 28 ++-- 4 files changed, 100 insertions(+), 75 deletions(-) diff --git a/include/cling/Interpreter/ValuePrinter.h b/include/cling/Interpreter/ValuePrinter.h index 5e05d75f..29132fba 100644 --- a/include/cling/Interpreter/ValuePrinter.h +++ b/include/cling/Interpreter/ValuePrinter.h @@ -14,6 +14,7 @@ namespace llvm { } namespace cling { + class StoredValueRef; // Can be re-implemented to print type-specific details, e.g. as // template @@ -26,6 +27,9 @@ namespace cling { void printValuePublicDefault(llvm::raw_ostream& o, const void* const p, const ValuePrinterInfo& PVI); + void StreamStoredValueRef(llvm::raw_ostream& o, const StoredValueRef* VR, + clang::ASTContext& C, const char* Sep = "\n"); + void flushOStream(llvm::raw_ostream& o); namespace valuePrinterInternal { diff --git a/include/cling/Interpreter/ValuePrinterInfo.h b/include/cling/Interpreter/ValuePrinterInfo.h index 79a8cba0..bfe7b6e8 100644 --- a/include/cling/Interpreter/ValuePrinterInfo.h +++ b/include/cling/Interpreter/ValuePrinterInfo.h @@ -7,6 +7,8 @@ #ifndef CLING_VALUE_PRINTER_INFO_H #define CLING_VALUE_PRINTER_INFO_H +#include "clang/AST/Type.h" + namespace clang { class ASTContext; class Expr; @@ -16,10 +18,12 @@ namespace cling { class ValuePrinterInfo { private: - const clang::Expr* m_Expr; + clang::QualType m_Type; clang::ASTContext* m_Context; unsigned m_Flags; + void Init(); + public: enum ValuePrinterFlags { VPI_Ptr = 1, @@ -27,8 +31,9 @@ namespace cling { VPI_Polymorphic = 4 }; - ValuePrinterInfo(const clang::Expr* E, clang::ASTContext* Ctx); - const clang::Expr* getExpr() const { return m_Expr; } + ValuePrinterInfo(clang::Expr* Expr, clang::ASTContext* Ctx); + ValuePrinterInfo(clang::QualType Ty, clang::ASTContext* Ctx); + const clang::QualType getType() const { return m_Type; } clang::ASTContext* getASTContext() const { return m_Context; } unsigned getFlags() { return m_Flags; } }; diff --git a/lib/Interpreter/ValuePrinter.cpp b/lib/Interpreter/ValuePrinter.cpp index 40527b18..47d237e5 100644 --- a/lib/Interpreter/ValuePrinter.cpp +++ b/lib/Interpreter/ValuePrinter.cpp @@ -21,19 +21,25 @@ #include +using namespace cling; + // Implements the CValuePrinter interface. extern "C" void cling_PrintValue(void* /*clang::Expr**/ E, void* /*clang::ASTContext**/ C, const void* value) { clang::Expr* Exp = (clang::Expr*)E; clang::ASTContext* Context = (clang::ASTContext*)C; - cling::ValuePrinterInfo VPI(Exp, Context); - cling::printValuePublic(llvm::outs(), value, value, VPI); + ValuePrinterInfo VPI(Exp->getType(), Context); + printValuePublic(llvm::outs(), value, value, VPI); - cling::flushOStream(llvm::outs()); + flushOStream(llvm::outs()); } +static void StreamValue(llvm::raw_ostream& o, const void* const p, + const ValuePrinterInfo& VPI, + const char* Sep = "\n"); + static void StreamChar(llvm::raw_ostream& o, const char v, const char* Sep = "\n") { o << '"' << v << "\"" << Sep; @@ -60,16 +66,11 @@ static void StreamPtr(llvm::raw_ostream& o, const void* v, o << v << Sep; } -static void StreamValue(llvm::raw_ostream& o, const void* const p, - const cling::ValuePrinterInfo& VPI, - clang::QualType Ty, - const char* Sep = "\n"); - static void StreamArr(llvm::raw_ostream& o, const void* p, - const cling::ValuePrinterInfo& VPI, - clang::QualType Ty, + const ValuePrinterInfo& VPI, const char* Sep = "\n") { - const clang::ASTContext& C = *VPI.getASTContext(); + const clang::QualType& Ty = VPI.getType(); + clang::ASTContext& C = *VPI.getASTContext(); const clang::ArrayType* ArrTy = Ty->getAsArrayTypeUnsafe(); clang::QualType ElementTy = ArrTy->getElementType(); if (ElementTy->isCharType()) @@ -82,8 +83,9 @@ static void StreamArr(llvm::raw_ostream& o, const void* p, size_t ElBytes = C.getTypeSize(ElementTy) / C.getCharWidth(); size_t Size = (size_t)APSize.getZExtValue(); o << "{ "; + ValuePrinterInfo ElVPI(ElementTy, &C); for (size_t i = 0; i < Size; ++i) { - StreamValue(o, ((const char*)p) + i * ElBytes, VPI, ElementTy, ""); + StreamValue(o, ((const char*)p) + i * ElBytes, ElVPI, ""); if (i + 1 < Size) { if (i == 4) { o << "..."; @@ -97,45 +99,53 @@ static void StreamArr(llvm::raw_ostream& o, const void* p, StreamPtr(o, p, Sep); } -static void StreamObj(llvm::raw_ostream& o, const void* v, - const cling::ValuePrinterInfo& VPI, - clang::QualType QTy, - const char* Sep = "\n") { - const clang::Type* Ty = QTy.getTypePtr(); - if (clang::CXXRecordDecl* CXXRD = Ty->getAsCXXRecordDecl()) { - const cling::Value* value = 0; - if (CXXRD->getQualifiedNameAsString().compare("cling::StoredValueRef") == 0){ - const cling::StoredValueRef* VR = (const cling::StoredValueRef*)v; - if (VR->isValid()) { - value = &VR->get(); - } else { - o << "<<>> "; - } - } else if (CXXRD->getQualifiedNameAsString().compare("cling::Value") == 0) { - value = (const cling::Value*)v; - } - if (value) { - if (value->isValid()) { - o << "boxes ["; - const clang::ASTContext& C = *VPI.getASTContext(); - o << - "(" << - value->type.getAsString(C.getPrintingPolicy()) << - ") "; - clang::QualType valType = value->type.getDesugaredType(C); - if (valType->isFloatingType()) - o << value->value.DoubleVal; - else if (valType->isIntegerType()) - o << value->value.IntVal.getSExtValue(); - else if (valType->isBooleanType()) - o << value->value.IntVal.getBoolValue(); - else - StreamValue(o, value->value.PointerVal, VPI, valType, ""); - o << "]" << Sep; +static void StreamClingValue(llvm::raw_ostream& o, const Value* value, + clang::ASTContext& C, const char* Sep = "\n") { + if (!value || !value->isValid()) { + o << "<<>>" << Sep; + } else { + o << "boxes ["; + o << "(" + << value->type.getAsString(C.getPrintingPolicy()) + << ") "; + clang::QualType valType = value->type.getDesugaredType(C); + if (valType->isFloatingType()) + o << value->value.DoubleVal; + else if (valType->isIntegerType()) + o << value->value.IntVal.getSExtValue(); + else if (valType->isBooleanType()) + o << value->value.IntVal.getBoolValue(); + else + StreamValue(o, value->value.PointerVal, + ValuePrinterInfo(valType, &C), ""); + o << "]" << Sep; + } +} - return; - } else - o << "<<>> "; +void cling::StreamStoredValueRef(llvm::raw_ostream& o, const StoredValueRef* VR, + clang::ASTContext& C, + const char* Sep /*= "\n"*/) { + + if (VR->isValid()) { + StreamClingValue(o, &VR->get(), C, Sep); + } else { + o << "<<>> @" << VR << Sep; + } +} + +static void StreamObj(llvm::raw_ostream& o, const void* v, + const ValuePrinterInfo& VPI, + const char* Sep = "\n") { + const clang::Type* Ty = VPI.getType().getTypePtr(); + if (clang::CXXRecordDecl* CXXRD = Ty->getAsCXXRecordDecl()) { + std::string QualName = CXXRD->getQualifiedNameAsString(); + if (QualName == "cling::StoredValueRef"){ + StreamStoredValueRef(o, (const StoredValueRef*)v, + *VPI.getASTContext(), Sep); + return; + } else if (QualName == "cling::Value") { + StreamClingValue(o, (const Value*)v, *VPI.getASTContext(), Sep); + return; } } // if CXXRecordDecl @@ -144,11 +154,10 @@ static void StreamObj(llvm::raw_ostream& o, const void* v, } static void StreamValue(llvm::raw_ostream& o, const void* const p, - const cling::ValuePrinterInfo& VPI, - clang::QualType Ty, + const ValuePrinterInfo& VPI, const char* Sep /*= "\n"*/) { - const clang::ASTContext& C = *VPI.getASTContext(); - Ty = Ty.getDesugaredType(C); + clang::ASTContext& C = *VPI.getASTContext(); + clang::QualType Ty = VPI.getType().getDesugaredType(C); if (const clang::BuiltinType *BT = llvm::dyn_cast(Ty.getCanonicalType())) { switch (BT->getKind()) { @@ -180,17 +189,17 @@ static void StreamValue(llvm::raw_ostream& o, const void* const p, case clang::BuiltinType::Float: o << *(const float*)p << Sep; break; case clang::BuiltinType::Double: o << *(const double*)p << Sep; break; default: - StreamObj(o, p, VPI, Ty, Sep); + StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep); } } else if (Ty.getAsString().compare("class std::basic_string") == 0) { - StreamObj(o, p, VPI, Ty, Sep); + StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep); if (!Sep[0]) o << " "; // force a space o <<"c_str: "; StreamCharPtr(o, ((const char*) (*(const std::string*)p).c_str()), Sep); } else if (Ty->isEnumeralType()) { - StreamObj(o, p, VPI, Ty, Sep); + StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep); clang::EnumDecl* ED = Ty->getAs()->getDecl(); uint64_t value = *(const uint64_t*)p; bool IsFirst = true; @@ -217,19 +226,18 @@ static void StreamValue(llvm::raw_ostream& o, const void* const p, StreamPtr(o, p, Sep); } else if (Ty->isArrayType()) - StreamArr(o, p, VPI, Ty, Sep); + StreamArr(o, p, ValuePrinterInfo(Ty, &C), Sep); else - StreamObj(o, p, VPI, Ty, Sep); + StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep); } namespace cling { void printValuePublicDefault(llvm::raw_ostream& o, const void* const p, const ValuePrinterInfo& VPI) { - const clang::Expr* E = VPI.getExpr(); o << "("; - o << E->getType().getAsString(); + o << VPI.getType().getAsString(); o << ") "; - StreamValue(o, p, VPI, VPI.getExpr()->getType()); + StreamValue(o, p, VPI); } void flushOStream(llvm::raw_ostream& o) { diff --git a/lib/Interpreter/ValuePrinterInfo.cpp b/lib/Interpreter/ValuePrinterInfo.cpp index f15906d9..d9690fce 100644 --- a/lib/Interpreter/ValuePrinterInfo.cpp +++ b/lib/Interpreter/ValuePrinterInfo.cpp @@ -13,24 +13,32 @@ using namespace clang; namespace cling { - ValuePrinterInfo::ValuePrinterInfo(const Expr* E, ASTContext* Ctx) - : m_Expr(E), m_Context(Ctx), m_Flags(0) { - assert(E && "Expression cannot be null!"); - assert(Ctx && "ASTContext cannot be null!"); - // 1. Get the flags - const QualType QT = m_Expr->getType(); + ValuePrinterInfo::ValuePrinterInfo(Expr* E, ASTContext* Ctx) + : m_Type(E->getType()), m_Context(Ctx), m_Flags(0) { + Init(); + } - if (E->isRValue() || QT.isLocalConstQualified() || QT.isConstant(*Ctx)){ + ValuePrinterInfo::ValuePrinterInfo(QualType Ty, ASTContext* Ctx) + : m_Type(Ty), m_Context(Ctx), m_Flags(0) { + Init(); + } + + void ValuePrinterInfo::Init() { + assert(!m_Type.isNull() && "Type must be valid!"); + assert(m_Context && "ASTContext cannot be null!"); + // 1. Get the flags + + if (m_Type.isLocalConstQualified() || m_Type.isConstant(*m_Context)){ m_Flags |= VPI_Const; } - if (QT->isPointerType()) { + if (m_Type->isPointerType()) { // treat arrary-to-pointer decay as array: - QualType PQT = QT->getPointeeType(); + QualType PQT = m_Type->getPointeeType(); const Type* PTT = PQT.getTypePtr(); if (!PTT || !PTT->isArrayType()) { m_Flags |= VPI_Ptr; - if (const RecordType* RT = dyn_cast(QT.getTypePtr())) + if (const RecordType* RT = dyn_cast(m_Type.getTypePtr())) if (RecordDecl* RD = RT->getDecl()) { CXXRecordDecl* CRD = dyn_cast(RD); if (CRD && CRD->isPolymorphic())