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 {
class StoredValueRef;
// Can be re-implemented to print type-specific details, e.g. as
// template <typename ACTUAL>
@ -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 {

View File

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

View File

@ -21,19 +21,25 @@
#include <string>
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 << "<<<invalid>>> ";
}
} 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 << "<<<invalid>>>" << 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 << "<<<invalid>>> ";
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 << "<<<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
@ -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<clang::BuiltinType>(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<char>") == 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<clang::EnumType>()->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) {

View File

@ -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<RecordType>(QT.getTypePtr()))
if (const RecordType* RT = dyn_cast<RecordType>(m_Type.getTypePtr()))
if (RecordDecl* RD = RT->getDecl()) {
CXXRecordDecl* CRD = dyn_cast<CXXRecordDecl>(RD);
if (CRD && CRD->isPolymorphic())