Make QualType::dump() produce a useful dump of the structure of the type,

rather than simply pretty-printing it.

llvm-svn: 220942
This commit is contained in:
Richard Smith 2014-10-31 01:17:45 +00:00
parent c158884726
commit d5e7ff856c
2 changed files with 247 additions and 17 deletions

View File

@ -20,6 +20,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/raw_ostream.h"
@ -90,7 +91,7 @@ namespace {
class ASTDumper
: public ConstDeclVisitor<ASTDumper>, public ConstStmtVisitor<ASTDumper>,
public ConstCommentVisitor<ASTDumper> {
public ConstCommentVisitor<ASTDumper>, public TypeVisitor<ASTDumper> {
raw_ostream &OS;
const CommandTraits *Traits;
const SourceManager *SM;
@ -217,8 +218,10 @@ namespace {
void dumpPointer(const void *Ptr);
void dumpSourceRange(SourceRange R);
void dumpLocation(SourceLocation Loc);
void dumpBareType(QualType T);
void dumpBareType(QualType T, bool Desugar = true);
void dumpType(QualType T);
void dumpTypeAsChild(QualType T);
void dumpTypeAsChild(const Type *T);
void dumpBareDeclRef(const Decl *Node);
void dumpDeclRef(const Decl *Node, const char *Label = nullptr);
void dumpName(const NamedDecl *D);
@ -237,6 +240,175 @@ namespace {
void dumpTemplateArgument(const TemplateArgument &A,
SourceRange R = SourceRange());
// Types
void VisitComplexType(const ComplexType *T) {
dumpTypeAsChild(T->getElementType());
}
void VisitPointerType(const PointerType *T) {
dumpTypeAsChild(T->getPointeeType());
}
void VisitBlockPointerType(const BlockPointerType *T) {
dumpTypeAsChild(T->getPointeeType());
}
void VisitReferenceType(const ReferenceType *T) {
dumpTypeAsChild(T->getPointeeType());
}
void VisitRValueReferenceType(const ReferenceType *T) {
if (T->isSpelledAsLValue())
OS << " written as lvalue reference";
VisitReferenceType(T);
}
void VisitMemberPointerType(const MemberPointerType *T) {
dumpTypeAsChild(T->getClass());
dumpTypeAsChild(T->getPointeeType());
}
void VisitArrayType(const ArrayType *T) {
switch (T->getSizeModifier()) {
case ArrayType::Normal: break;
case ArrayType::Static: OS << " static"; break;
case ArrayType::Star: OS << " *"; break;
}
OS << " " << T->getIndexTypeQualifiers().getAsString();
dumpTypeAsChild(T->getElementType());
}
void VisitConstantArrayType(const ConstantArrayType *T) {
OS << " " << T->getSize();
VisitArrayType(T);
}
void VisitVariableArrayType(const VariableArrayType *T) {
OS << " ";
dumpSourceRange(T->getBracketsRange());
VisitArrayType(T);
dumpStmt(T->getSizeExpr());
}
void VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
VisitArrayType(T);
OS << " ";
dumpSourceRange(T->getBracketsRange());
dumpStmt(T->getSizeExpr());
}
void VisitDependentSizedExtVectorType(
const DependentSizedExtVectorType *T) {
OS << " ";
dumpLocation(T->getAttributeLoc());
dumpTypeAsChild(T->getElementType());
dumpStmt(T->getSizeExpr());
}
void VisitVectorType(const VectorType *T) {
switch (T->getVectorKind()) {
case VectorType::GenericVector: break;
case VectorType::AltiVecVector: OS << " altivec"; break;
case VectorType::AltiVecPixel: OS << " altivec pixel"; break;
case VectorType::AltiVecBool: OS << " altivec bool"; break;
case VectorType::NeonVector: OS << " neon"; break;
case VectorType::NeonPolyVector: OS << " neon poly"; break;
}
OS << " " << T->getNumElements();
dumpTypeAsChild(T->getElementType());
}
void VisitFunctionType(const FunctionType *T) {
auto EI = T->getExtInfo();
if (EI.getNoReturn()) OS << " noreturn";
if (EI.getProducesResult()) OS << " produces_result";
if (EI.getHasRegParm()) OS << " regparm " << EI.getRegParm();
OS << " " << FunctionType::getNameForCallConv(EI.getCC());
dumpTypeAsChild(T->getReturnType());
}
void VisitFunctionProtoType(const FunctionProtoType *T) {
auto EPI = T->getExtProtoInfo();
if (EPI.HasTrailingReturn) OS << " trailing_return";
if (T->isConst()) OS << " const";
if (T->isVolatile()) OS << " volatile";
if (T->isRestrict()) OS << " restrict";
switch (EPI.RefQualifier) {
case RQ_None: break;
case RQ_LValue: OS << " &"; break;
case RQ_RValue: OS << " &&"; break;
}
// FIXME: Exception specification.
// FIXME: Consumed parameters.
VisitFunctionType(T);
for (QualType PT : T->getParamTypes())
dumpTypeAsChild(PT);
if (EPI.Variadic)
dumpChild([=] { OS << "..."; });
}
void VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
dumpDeclRef(T->getDecl());
}
void VisitTypedefType(const TypedefType *T) {
dumpDeclRef(T->getDecl());
}
void VisitTypeOfExprType(const TypeOfExprType *T) {
dumpStmt(T->getUnderlyingExpr());
}
void VisitDecltypeType(const DecltypeType *T) {
dumpStmt(T->getUnderlyingExpr());
}
void VisitUnaryTransformType(const UnaryTransformType *T) {
switch (T->getUTTKind()) {
case UnaryTransformType::EnumUnderlyingType:
OS << " underlying_type";
break;
}
dumpTypeAsChild(T->getBaseType());
}
void VisitTagType(const TagType *T) {
dumpDeclRef(T->getDecl());
}
void VisitAttributedType(const AttributedType *T) {
// FIXME: AttrKind
dumpTypeAsChild(T->getModifiedType());
}
void VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
OS << " depth " << T->getDepth() << " index " << T->getIndex();
if (T->isParameterPack()) OS << " pack";
dumpDeclRef(T->getDecl());
}
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
dumpTypeAsChild(T->getReplacedParameter());
}
void VisitSubstTemplateTypeParmPackType(
const SubstTemplateTypeParmPackType *T) {
dumpTypeAsChild(T->getReplacedParameter());
dumpTemplateArgument(T->getArgumentPack());
}
void VisitAutoType(const AutoType *T) {
if (T->isDecltypeAuto()) OS << " decltype(auto)";
if (!T->isDeduced())
OS << " undeduced";
}
void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
if (T->isTypeAlias()) OS << " alias";
OS << " "; T->getTemplateName().dump(OS);
for (auto &Arg : *T)
dumpTemplateArgument(Arg);
if (T->isTypeAlias())
dumpTypeAsChild(T->getAliasedType());
}
void VisitInjectedClassNameType(const InjectedClassNameType *T) {
dumpDeclRef(T->getDecl());
}
void VisitObjCInterfaceType(const ObjCInterfaceType *T) {
dumpDeclRef(T->getDecl());
}
void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
dumpTypeAsChild(T->getPointeeType());
}
void VisitAtomicType(const AtomicType *T) {
dumpTypeAsChild(T->getValueType());
}
void VisitAdjustedType(const AdjustedType *T) {
dumpTypeAsChild(T->getOriginalType());
}
void VisitPackExpansionType(const PackExpansionType *T) {
if (auto N = T->getNumExpansions()) OS << " expansions " << *N;
if (!T->isSugared())
dumpTypeAsChild(T->getPattern());
}
// FIXME: ElaboratedType, DependentNameType,
// DependentTemplateSpecializationType, ObjCObjectType
// Decls
void VisitLabelDecl(const LabelDecl *D);
void VisitTypedefDecl(const TypedefDecl *D);
@ -433,13 +605,13 @@ void ASTDumper::dumpSourceRange(SourceRange R) {
}
void ASTDumper::dumpBareType(QualType T) {
void ASTDumper::dumpBareType(QualType T, bool Desugar) {
ColorScope Color(*this, TypeColor);
SplitQualType T_split = T.split();
OS << "'" << QualType::getAsString(T_split) << "'";
if (!T.isNull()) {
if (Desugar && !T.isNull()) {
// If the type is sugared, also dump a (shallow) desugared type.
SplitQualType D_split = T.getSplitDesugaredType();
if (T_split != D_split)
@ -452,6 +624,59 @@ void ASTDumper::dumpType(QualType T) {
dumpBareType(T);
}
void ASTDumper::dumpTypeAsChild(QualType T) {
SplitQualType SQT = T.split();
if (!SQT.Quals.hasQualifiers())
return dumpTypeAsChild(SQT.Ty);
dumpChild([=] {
OS << "QualType";
dumpPointer(T.getAsOpaquePtr());
OS << " ";
dumpBareType(T, false);
OS << " " << T.split().Quals.getAsString();
dumpTypeAsChild(T.split().Ty);
});
}
void ASTDumper::dumpTypeAsChild(const Type *T) {
dumpChild([=] {
if (!T) {
ColorScope Color(*this, NullColor);
OS << "<<<NULL>>>";
return;
}
{
ColorScope Color(*this, TypeColor);
OS << T->getTypeClassName() << "Type";
}
dumpPointer(T);
OS << " ";
dumpBareType(QualType(T, 0), false);
QualType SingleStepDesugar =
T->getLocallyUnqualifiedSingleStepDesugaredType();
if (SingleStepDesugar != QualType(T, 0))
OS << " sugar";
if (T->isDependentType())
OS << " dependent";
else if (T->isInstantiationDependentType())
OS << " instantiation_dependent";
if (T->isVariablyModifiedType())
OS << " variably_modified";
if (T->containsUnexpandedParameterPack())
OS << " contains_unexpanded_pack";
if (T->isFromAST())
OS << " imported";
TypeVisitor<ASTDumper>::Visit(T);
if (SingleStepDesugar != QualType(T, 0))
dumpTypeAsChild(SingleStepDesugar);
});
}
void ASTDumper::dumpBareDeclRef(const Decl *D) {
{
ColorScope Color(*this, DeclKindNameColor);
@ -1964,6 +2189,23 @@ void ASTDumper::visitVerbatimLineComment(const VerbatimLineComment *C) {
OS << " Text=\"" << C->getText() << "\"";
}
//===----------------------------------------------------------------------===//
// Type method implementations
//===----------------------------------------------------------------------===//
void QualType::dump(const char *msg) const {
if (msg)
llvm::errs() << msg << ": ";
dump();
}
LLVM_DUMP_METHOD void QualType::dump() const {
ASTDumper Dumper(llvm::errs(), nullptr, nullptr);
Dumper.dumpTypeAsChild(*this);
}
LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
//===----------------------------------------------------------------------===//
// Decl method implementations
//===----------------------------------------------------------------------===//

View File

@ -1432,18 +1432,6 @@ PrintTemplateArgumentList(raw_ostream &OS,
OS << '>';
}
void QualType::dump(const char *msg) const {
if (msg)
llvm::errs() << msg << ": ";
LangOptions LO;
print(llvm::errs(), PrintingPolicy(LO), "identifier");
llvm::errs() << '\n';
}
LLVM_DUMP_METHOD void QualType::dump() const { dump(nullptr); }
LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
std::string Qualifiers::getAsString() const {
LangOptions LO;
return getAsString(PrintingPolicy(LO));