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:
parent
e2378406a1
commit
340e954bbe
@ -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 {
|
||||
|
@ -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; }
|
||||
};
|
||||
|
@ -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) {
|
||||
|
@ -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())
|
||||
|
Loading…
x
Reference in New Issue
Block a user