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
This commit is contained in:
Axel Naumann 2012-11-12 10:27:13 +00:00
parent e2378406a1
commit 340e954bbe
4 changed files with 100 additions and 75 deletions

View File

@ -14,6 +14,7 @@ namespace llvm {
} }
namespace cling { namespace cling {
class StoredValueRef;
// Can be re-implemented to print type-specific details, e.g. as // Can be re-implemented to print type-specific details, e.g. as
// template <typename ACTUAL> // template <typename ACTUAL>
@ -26,6 +27,9 @@ namespace cling {
void printValuePublicDefault(llvm::raw_ostream& o, const void* const p, void printValuePublicDefault(llvm::raw_ostream& o, const void* const p,
const ValuePrinterInfo& PVI); 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); void flushOStream(llvm::raw_ostream& o);
namespace valuePrinterInternal { namespace valuePrinterInternal {

View File

@ -7,6 +7,8 @@
#ifndef CLING_VALUE_PRINTER_INFO_H #ifndef CLING_VALUE_PRINTER_INFO_H
#define CLING_VALUE_PRINTER_INFO_H #define CLING_VALUE_PRINTER_INFO_H
#include "clang/AST/Type.h"
namespace clang { namespace clang {
class ASTContext; class ASTContext;
class Expr; class Expr;
@ -16,10 +18,12 @@ namespace cling {
class ValuePrinterInfo { class ValuePrinterInfo {
private: private:
const clang::Expr* m_Expr; clang::QualType m_Type;
clang::ASTContext* m_Context; clang::ASTContext* m_Context;
unsigned m_Flags; unsigned m_Flags;
void Init();
public: public:
enum ValuePrinterFlags { enum ValuePrinterFlags {
VPI_Ptr = 1, VPI_Ptr = 1,
@ -27,8 +31,9 @@ namespace cling {
VPI_Polymorphic = 4 VPI_Polymorphic = 4
}; };
ValuePrinterInfo(const clang::Expr* E, clang::ASTContext* Ctx); ValuePrinterInfo(clang::Expr* Expr, clang::ASTContext* Ctx);
const clang::Expr* getExpr() const { return m_Expr; } ValuePrinterInfo(clang::QualType Ty, clang::ASTContext* Ctx);
const clang::QualType getType() const { return m_Type; }
clang::ASTContext* getASTContext() const { return m_Context; } clang::ASTContext* getASTContext() const { return m_Context; }
unsigned getFlags() { return m_Flags; } unsigned getFlags() { return m_Flags; }
}; };

View File

@ -21,19 +21,25 @@
#include <string> #include <string>
using namespace cling;
// Implements the CValuePrinter interface. // Implements the CValuePrinter interface.
extern "C" void cling_PrintValue(void* /*clang::Expr**/ E, extern "C" void cling_PrintValue(void* /*clang::Expr**/ E,
void* /*clang::ASTContext**/ C, void* /*clang::ASTContext**/ C,
const void* value) { const void* value) {
clang::Expr* Exp = (clang::Expr*)E; clang::Expr* Exp = (clang::Expr*)E;
clang::ASTContext* Context = (clang::ASTContext*)C; clang::ASTContext* Context = (clang::ASTContext*)C;
cling::ValuePrinterInfo VPI(Exp, Context); ValuePrinterInfo VPI(Exp->getType(), Context);
cling::printValuePublic(llvm::outs(), value, value, VPI); 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, static void StreamChar(llvm::raw_ostream& o, const char v,
const char* Sep = "\n") { const char* Sep = "\n") {
o << '"' << v << "\"" << Sep; o << '"' << v << "\"" << Sep;
@ -60,16 +66,11 @@ static void StreamPtr(llvm::raw_ostream& o, const void* v,
o << v << Sep; 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, static void StreamArr(llvm::raw_ostream& o, const void* p,
const cling::ValuePrinterInfo& VPI, const ValuePrinterInfo& VPI,
clang::QualType Ty,
const char* Sep = "\n") { 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(); const clang::ArrayType* ArrTy = Ty->getAsArrayTypeUnsafe();
clang::QualType ElementTy = ArrTy->getElementType(); clang::QualType ElementTy = ArrTy->getElementType();
if (ElementTy->isCharType()) 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 ElBytes = C.getTypeSize(ElementTy) / C.getCharWidth();
size_t Size = (size_t)APSize.getZExtValue(); size_t Size = (size_t)APSize.getZExtValue();
o << "{ "; o << "{ ";
ValuePrinterInfo ElVPI(ElementTy, &C);
for (size_t i = 0; i < Size; ++i) { 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 + 1 < Size) {
if (i == 4) { if (i == 4) {
o << "..."; o << "...";
@ -97,45 +99,53 @@ static void StreamArr(llvm::raw_ostream& o, const void* p,
StreamPtr(o, p, Sep); StreamPtr(o, p, Sep);
} }
static void StreamObj(llvm::raw_ostream& o, const void* v, static void StreamClingValue(llvm::raw_ostream& o, const Value* value,
const cling::ValuePrinterInfo& VPI, clang::ASTContext& C, const char* Sep = "\n") {
clang::QualType QTy, if (!value || !value->isValid()) {
const char* Sep = "\n") { o << "<<<invalid>>>" << Sep;
const clang::Type* Ty = QTy.getTypePtr(); } else {
if (clang::CXXRecordDecl* CXXRD = Ty->getAsCXXRecordDecl()) { o << "boxes [";
const cling::Value* value = 0; o << "("
if (CXXRD->getQualifiedNameAsString().compare("cling::StoredValueRef") == 0){ << value->type.getAsString(C.getPrintingPolicy())
const cling::StoredValueRef* VR = (const cling::StoredValueRef*)v; << ") ";
if (VR->isValid()) { clang::QualType valType = value->type.getDesugaredType(C);
value = &VR->get(); if (valType->isFloatingType())
} else { o << value->value.DoubleVal;
o << "<<<invalid>>> "; else if (valType->isIntegerType())
} o << value->value.IntVal.getSExtValue();
} else if (CXXRD->getQualifiedNameAsString().compare("cling::Value") == 0) { else if (valType->isBooleanType())
value = (const cling::Value*)v; o << value->value.IntVal.getBoolValue();
} else
if (value) { StreamValue(o, value->value.PointerVal,
if (value->isValid()) { ValuePrinterInfo(valType, &C), "");
o << "boxes ["; o << "]" << Sep;
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;
return; void cling::StreamStoredValueRef(llvm::raw_ostream& o, const StoredValueRef* VR,
} else clang::ASTContext& C,
o << "<<<invalid>>> "; const char* Sep /*= "\n"*/) {
if (VR->isValid()) {
StreamClingValue(o, &VR->get(), C, Sep);
} else {
o << "<<<invalid>>> @" << 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 } // 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, static void StreamValue(llvm::raw_ostream& o, const void* const p,
const cling::ValuePrinterInfo& VPI, const ValuePrinterInfo& VPI,
clang::QualType Ty,
const char* Sep /*= "\n"*/) { const char* Sep /*= "\n"*/) {
const clang::ASTContext& C = *VPI.getASTContext(); clang::ASTContext& C = *VPI.getASTContext();
Ty = Ty.getDesugaredType(C); clang::QualType Ty = VPI.getType().getDesugaredType(C);
if (const clang::BuiltinType *BT if (const clang::BuiltinType *BT
= llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) { = llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) {
switch (BT->getKind()) { 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::Float: o << *(const float*)p << Sep; break;
case clang::BuiltinType::Double: o << *(const double*)p << Sep; break; case clang::BuiltinType::Double: o << *(const double*)p << Sep; break;
default: default:
StreamObj(o, p, VPI, Ty, Sep); StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep);
} }
} }
else if (Ty.getAsString().compare("class std::basic_string<char>") == 0) { else if (Ty.getAsString().compare("class std::basic_string<char>") == 0) {
StreamObj(o, p, VPI, Ty, Sep); StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep);
if (!Sep[0]) o << " "; // force a space if (!Sep[0]) o << " "; // force a space
o <<"c_str: "; o <<"c_str: ";
StreamCharPtr(o, ((const char*) (*(const std::string*)p).c_str()), Sep); StreamCharPtr(o, ((const char*) (*(const std::string*)p).c_str()), Sep);
} }
else if (Ty->isEnumeralType()) { else if (Ty->isEnumeralType()) {
StreamObj(o, p, VPI, Ty, Sep); StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep);
clang::EnumDecl* ED = Ty->getAs<clang::EnumType>()->getDecl(); clang::EnumDecl* ED = Ty->getAs<clang::EnumType>()->getDecl();
uint64_t value = *(const uint64_t*)p; uint64_t value = *(const uint64_t*)p;
bool IsFirst = true; bool IsFirst = true;
@ -217,19 +226,18 @@ static void StreamValue(llvm::raw_ostream& o, const void* const p,
StreamPtr(o, p, Sep); StreamPtr(o, p, Sep);
} }
else if (Ty->isArrayType()) else if (Ty->isArrayType())
StreamArr(o, p, VPI, Ty, Sep); StreamArr(o, p, ValuePrinterInfo(Ty, &C), Sep);
else else
StreamObj(o, p, VPI, Ty, Sep); StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep);
} }
namespace cling { namespace cling {
void printValuePublicDefault(llvm::raw_ostream& o, const void* const p, void printValuePublicDefault(llvm::raw_ostream& o, const void* const p,
const ValuePrinterInfo& VPI) { const ValuePrinterInfo& VPI) {
const clang::Expr* E = VPI.getExpr();
o << "("; o << "(";
o << E->getType().getAsString(); o << VPI.getType().getAsString();
o << ") "; o << ") ";
StreamValue(o, p, VPI, VPI.getExpr()->getType()); StreamValue(o, p, VPI);
} }
void flushOStream(llvm::raw_ostream& o) { void flushOStream(llvm::raw_ostream& o) {

View File

@ -13,24 +13,32 @@
using namespace clang; using namespace clang;
namespace cling { namespace cling {
ValuePrinterInfo::ValuePrinterInfo(const Expr* E, ASTContext* Ctx) ValuePrinterInfo::ValuePrinterInfo(Expr* E, ASTContext* Ctx)
: m_Expr(E), m_Context(Ctx), m_Flags(0) { : m_Type(E->getType()), m_Context(Ctx), m_Flags(0) {
assert(E && "Expression cannot be null!"); Init();
assert(Ctx && "ASTContext cannot be null!"); }
// 1. Get the flags
const QualType QT = m_Expr->getType();
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; m_Flags |= VPI_Const;
} }
if (QT->isPointerType()) { if (m_Type->isPointerType()) {
// treat arrary-to-pointer decay as array: // treat arrary-to-pointer decay as array:
QualType PQT = QT->getPointeeType(); QualType PQT = m_Type->getPointeeType();
const Type* PTT = PQT.getTypePtr(); const Type* PTT = PQT.getTypePtr();
if (!PTT || !PTT->isArrayType()) { if (!PTT || !PTT->isArrayType()) {
m_Flags |= VPI_Ptr; m_Flags |= VPI_Ptr;
if (const RecordType* RT = dyn_cast<RecordType>(QT.getTypePtr())) if (const RecordType* RT = dyn_cast<RecordType>(m_Type.getTypePtr()))
if (RecordDecl* RD = RT->getDecl()) { if (RecordDecl* RD = RT->getDecl()) {
CXXRecordDecl* CRD = dyn_cast<CXXRecordDecl>(RD); CXXRecordDecl* CRD = dyn_cast<CXXRecordDecl>(RD);
if (CRD && CRD->isPolymorphic()) if (CRD && CRD->isPolymorphic())