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