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:
parent
c158884726
commit
d5e7ff856c
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue