mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-03 10:56:06 +00:00

completes the support in the LLDB expression parser for incomplete types. Clang now imports types lazily, and we complete those types as necessary. Changes include: - ClangASTSource now supports three APIs which it passes to ClangExpressionDeclMap. CompleteType completes a TagDecl or an ObjCInterfaceDecl when needed; FindExternalVisibleDecls finds named entities that are visible in the expression's scope; and FindExternalLexicalDecls performs a (potentially restricted) search for entities inside a lexical scope like a namespace. These changes mean that entities in namespaces should work normally. - The SymbolFileDWARF code for searching a context for a specific name is now more general, and can search arbitrary contexts. - We are continuing to adapt our calls into LLVM from interfaces that take start and end iterators when accepting multiple items to interfaces that use ArrayRef. - I have cleaned up some code, especially our use of namespaces. This change is neutral for our testsuite and greatly improves correctness for large programs (like Clang) with complicated type systems. It should also lay the groundwork for improving the expression parser's performance as we are lazier and lazier about providing type information. llvm-svn: 136555
545 lines
19 KiB
C++
545 lines
19 KiB
C++
//===-- ASTDumper.cpp -------------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/Expression/ASTDumper.h"
|
|
|
|
using namespace lldb_private;
|
|
using namespace clang;
|
|
|
|
// MARK: Utility functions
|
|
|
|
static const char* SfB (bool b)
|
|
{
|
|
return b ? "True" : "False";
|
|
}
|
|
|
|
// MARK: DeclVisitor
|
|
|
|
void ASTDumper::VisitDecl (clang::Decl *decl)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : Decl\n");
|
|
m_stream.Indent(); m_stream.Printf("getDeclKindName() : %s\n", decl->getDeclKindName());
|
|
m_stream.Indent(); m_stream.Printf("getTranslationUnitDecl() : ");
|
|
|
|
TranslationUnitDecl *translation_unit_decl = decl->getTranslationUnitDecl();
|
|
|
|
if (translation_unit_decl)
|
|
{
|
|
if (KeepDumping() && !Visiting(translation_unit_decl))
|
|
{
|
|
m_stream.Printf("\n");
|
|
|
|
PushIndent();
|
|
WillVisit(translation_unit_decl);
|
|
VisitTranslationUnitDecl(translation_unit_decl);
|
|
DidVisit(translation_unit_decl);
|
|
PopIndent();
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("capped\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("~\n");
|
|
}
|
|
|
|
m_stream.Indent(); m_stream.Printf("getAccess() : ");
|
|
switch (decl->getAccess())
|
|
{
|
|
default: m_stream.Printf("~\n");
|
|
case AS_public: m_stream.Printf("AS_public\n");
|
|
case AS_protected: m_stream.Printf("AS_protected\n");
|
|
case AS_private: m_stream.Printf("AS_private\n");
|
|
case AS_none: m_stream.Printf("AS_none\n");
|
|
}
|
|
m_stream.Indent(); m_stream.Printf("getMaxAlignment() : %d\n", decl->getMaxAlignment());
|
|
m_stream.Indent(); m_stream.Printf("isInvalidDecl() : %s\n", SfB(decl->isInvalidDecl()));
|
|
m_stream.Indent(); m_stream.Printf("isImplicit() : %s\n", SfB(decl->isImplicit()));
|
|
m_stream.Indent(); m_stream.Printf("isUsed() : %s\n", SfB(decl->isUsed()));
|
|
m_stream.Indent(); m_stream.Printf("isOutOfLine() : %s\n", SfB(decl->isOutOfLine()));
|
|
m_stream.Indent(); m_stream.Printf("isCanonicalDecl() : %s\n", SfB(decl->isCanonicalDecl()));
|
|
m_stream.Indent(); m_stream.Printf("hasBody() : %s\n", SfB(decl->hasBody()));
|
|
m_stream.Indent(); m_stream.Printf("isTemplateParameter() : %s\n", SfB(decl->isTemplateParameter()));
|
|
m_stream.Indent(); m_stream.Printf("isTemplateParameterPack() : %s\n", SfB(decl->isTemplateParameterPack()));
|
|
m_stream.Indent(); m_stream.Printf("isParameterPack() : %s\n", SfB(decl->isParameterPack()));
|
|
m_stream.Indent(); m_stream.Printf("isFunctionOrFunctionTemplate() : %s\n", SfB(decl->isFunctionOrFunctionTemplate()));
|
|
m_stream.Indent(); m_stream.Printf("getFriendObjectKind() : ");
|
|
switch (decl->getFriendObjectKind())
|
|
{
|
|
default: m_stream.Printf("~\n"); break;
|
|
case Decl::FOK_None: m_stream.Printf("FOK_None\n"); break;
|
|
case Decl::FOK_Declared: m_stream.Printf("FOK_Declared\n"); break;
|
|
case Decl::FOK_Undeclared: m_stream.Printf("FOK_Undeclared\n"); break;
|
|
}
|
|
}
|
|
|
|
void ASTDumper::VisitTranslationUnitDecl (clang::TranslationUnitDecl *translation_unit_decl)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : TranslationUnitDecl\n");
|
|
m_stream.Indent(); m_stream.Printf("getAnonymousNamespace() : ");
|
|
|
|
NamespaceDecl *anonymous_namespace = translation_unit_decl->getAnonymousNamespace();
|
|
|
|
if (anonymous_namespace)
|
|
{
|
|
if (KeepDumping() && !Visiting(anonymous_namespace))
|
|
{
|
|
m_stream.Printf("\n");
|
|
|
|
PushIndent();
|
|
WillVisit(anonymous_namespace);
|
|
VisitNamespaceDecl(anonymous_namespace);
|
|
DidVisit(anonymous_namespace);
|
|
PopIndent();
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("capped\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("~\n");
|
|
}
|
|
|
|
VisitDecl (translation_unit_decl);
|
|
}
|
|
|
|
void ASTDumper::VisitNamedDecl (clang::NamedDecl *named_decl)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : NamedDecl\n");
|
|
m_stream.Indent(); m_stream.Printf("getNameAsString() : %s\n", named_decl->getNameAsString().c_str());
|
|
m_stream.Indent(); m_stream.Printf("hasLinkage() : %s\n", SfB(named_decl->hasLinkage()));
|
|
m_stream.Indent(); m_stream.Printf("isCXXClassMember() : %s\n", SfB(named_decl->isCXXClassMember()));
|
|
m_stream.Indent(); m_stream.Printf("isCXXInstanceMember() : %s\n", SfB(named_decl->isCXXClassMember()));
|
|
m_stream.Indent(); m_stream.Printf("getVisibility() : ");
|
|
switch (named_decl->getVisibility())
|
|
{
|
|
default: m_stream.Printf("~\n"); break;
|
|
case HiddenVisibility: m_stream.Printf("HiddenVisibility\n"); break;
|
|
case ProtectedVisibility: m_stream.Printf("ProtectedVisibility\n"); break;
|
|
case DefaultVisibility: m_stream.Printf("DefaultVisibility\n"); break;
|
|
}
|
|
m_stream.Indent(); m_stream.Printf("getUnderlyingDecl() : ");
|
|
|
|
NamedDecl *underlying_decl = named_decl->getUnderlyingDecl();
|
|
|
|
if (underlying_decl)
|
|
{
|
|
if (KeepDumping() && !Visiting(underlying_decl))
|
|
{
|
|
m_stream.Printf("\n");
|
|
|
|
PushIndent();
|
|
WillVisit(underlying_decl);
|
|
::clang::DeclVisitor<ASTDumper, void>::Visit(underlying_decl);
|
|
DidVisit(underlying_decl);
|
|
PopIndent();
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("capped\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("~\n");
|
|
}
|
|
|
|
VisitDecl (named_decl);
|
|
}
|
|
|
|
void ASTDumper::VisitNamespaceDecl (clang::NamespaceDecl *namespace_decl)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : NamespaceDecl\n");
|
|
m_stream.Indent(); m_stream.Printf("isAnonymousNamespace() : %s\n", SfB(namespace_decl->isAnonymousNamespace()));
|
|
m_stream.Indent(); m_stream.Printf("isInline() : %s\n", SfB(namespace_decl->isInline()));
|
|
m_stream.Indent(); m_stream.Printf("isOriginalNamespace() : %s\n", SfB(namespace_decl->isOriginalNamespace()));
|
|
|
|
VisitNamedDecl (namespace_decl);
|
|
}
|
|
|
|
void ASTDumper::VisitValueDecl (clang::ValueDecl *value_decl)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : ValueDecl\n");
|
|
m_stream.Indent(); m_stream.Printf("getType() : ");
|
|
if (value_decl->getType().getTypePtrOrNull())
|
|
{
|
|
const clang::Type *type_ptr = value_decl->getType().getTypePtr();
|
|
|
|
if (KeepDumping() && !Visiting(type_ptr))
|
|
{
|
|
m_stream.Printf("\n");
|
|
|
|
PushIndent();
|
|
WillVisit(type_ptr);
|
|
::clang::TypeVisitor<ASTDumper, void>::Visit(type_ptr);
|
|
DidVisit(type_ptr);
|
|
PopIndent();
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("capped\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("~\n");
|
|
}
|
|
|
|
VisitNamedDecl (value_decl);
|
|
}
|
|
|
|
void ASTDumper::VisitDeclaratorDecl (clang::DeclaratorDecl *declarator_decl)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : DeclaratorDecl\n");
|
|
VisitValueDecl (declarator_decl);
|
|
}
|
|
|
|
void ASTDumper::VisitVarDecl (clang::VarDecl *var_decl)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : VarDecl\n");
|
|
VisitDeclaratorDecl (var_decl);
|
|
}
|
|
|
|
void ASTDumper::VisitTypeDecl (clang::TypeDecl *type_decl)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : TypeDecl\n");
|
|
m_stream.Indent(); m_stream.Printf("getTypeForDecl() : ");
|
|
|
|
const clang::Type *type_for_decl = type_decl->getTypeForDecl();
|
|
|
|
if (type_for_decl)
|
|
{
|
|
if (KeepDumping() && !Visiting(type_for_decl))
|
|
{
|
|
m_stream.Printf("\n");
|
|
|
|
PushIndent();
|
|
WillVisit(type_for_decl);
|
|
::clang::TypeVisitor<ASTDumper, void>::Visit(type_for_decl);
|
|
DidVisit(type_for_decl);
|
|
PopIndent();
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("capped\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("~\n");
|
|
}
|
|
|
|
VisitNamedDecl (type_decl);
|
|
}
|
|
|
|
void ASTDumper::VisitTagDecl (clang::TagDecl *tag_decl)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : TagDecl\n");
|
|
m_stream.Indent(); m_stream.Printf("isDefinition() : %s\n", SfB(tag_decl->isDefinition()));
|
|
m_stream.Indent(); m_stream.Printf("isBeingDefined() : %s\n", SfB(tag_decl->isBeingDefined()));
|
|
m_stream.Indent(); m_stream.Printf("isEmbeddedInDeclarator() : %s\n", SfB(tag_decl->isEmbeddedInDeclarator()));
|
|
m_stream.Indent(); m_stream.Printf("isDependentType() : %s\n", SfB(tag_decl->isDependentType()));
|
|
m_stream.Indent(); m_stream.Printf("getDefinition() : ");
|
|
|
|
TagDecl *definition = tag_decl->getDefinition();
|
|
|
|
if (definition)
|
|
{
|
|
if (KeepDumping() && !Visiting(definition))
|
|
{
|
|
m_stream.Printf("\n");
|
|
|
|
PushIndent();
|
|
WillVisit(definition);
|
|
::clang::DeclVisitor<ASTDumper, void>::Visit(tag_decl->getDefinition());
|
|
DidVisit(definition);
|
|
PopIndent();
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("capped\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("~\n");
|
|
}
|
|
m_stream.Indent(); m_stream.Printf("getKindName() : %s\n", tag_decl->getKindName());
|
|
|
|
VisitTypeDecl(tag_decl);
|
|
}
|
|
|
|
void ASTDumper::VisitRecordDecl (clang::RecordDecl *record_decl)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : RecordDecl\n");
|
|
m_stream.Indent(); m_stream.Printf("hasFlexibleArrayMember() : %s\n", SfB(record_decl->hasFlexibleArrayMember()));
|
|
m_stream.Indent(); m_stream.Printf("isAnonymousStructOrUnion() : %s\n", SfB(record_decl->isAnonymousStructOrUnion()));
|
|
m_stream.Indent(); m_stream.Printf("hasObjectMember() : %s\n", SfB(record_decl->hasObjectMember()));
|
|
m_stream.Indent(); m_stream.Printf("isInjectedClassName() : %s\n", SfB(record_decl->isInjectedClassName()));
|
|
m_stream.Indent(); m_stream.Printf("field_begin() ... field_end() : ");
|
|
if (KeepDumping())
|
|
{
|
|
if (record_decl->field_empty())
|
|
{
|
|
m_stream.Printf("~\n");
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("\n");
|
|
PushIndent();
|
|
for (RecordDecl::field_iterator iter = record_decl->field_begin(), end_iter = record_decl->field_end();
|
|
iter != end_iter;
|
|
++iter)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("- field:\n");
|
|
PushIndent();
|
|
if (Visiting (*iter))
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("capped\n");
|
|
}
|
|
else
|
|
{
|
|
WillVisit(*iter);
|
|
::clang::DeclVisitor<ASTDumper, void>::Visit(*iter);
|
|
DidVisit(*iter);
|
|
}
|
|
PopIndent();
|
|
}
|
|
PopIndent();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("capped\n");
|
|
}
|
|
|
|
VisitTagDecl (record_decl);
|
|
}
|
|
|
|
void ASTDumper::VisitCXXRecordDecl (clang::CXXRecordDecl *cxx_record_decl)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : CXXRecordDecl\n");
|
|
m_stream.Indent(); m_stream.Printf("isDynamicClass() : %s\n", SfB(cxx_record_decl->isDynamicClass()));
|
|
m_stream.Indent(); m_stream.Printf("bases_begin() ... bases_end() : ");
|
|
if (KeepDumping())
|
|
{
|
|
if (cxx_record_decl->bases_begin() == cxx_record_decl->bases_end())
|
|
{
|
|
m_stream.Printf("~\n");
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("\n");
|
|
PushIndent();
|
|
for (CXXRecordDecl::base_class_iterator iter = cxx_record_decl->bases_begin(), end_iter = cxx_record_decl->bases_end();
|
|
iter != end_iter;
|
|
++iter)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("- CXXBaseSpecifier:\n");
|
|
PushIndent();
|
|
m_stream.Indent(); m_stream.Printf("isVirtual() : %s\n", SfB(iter->isVirtual()));
|
|
m_stream.Indent(); m_stream.Printf("isBaseOfClass() : %s\n", SfB(iter->isBaseOfClass()));
|
|
m_stream.Indent(); m_stream.Printf("isPackExpansion() : %s\n", SfB(iter->isPackExpansion()));
|
|
m_stream.Indent(); m_stream.Printf("getAccessSpecifier() : ");
|
|
switch (iter->getAccessSpecifier())
|
|
{
|
|
default: m_stream.Printf("~\n"); break;
|
|
case clang::AS_none: m_stream.Printf("AS_none\n"); break;
|
|
case clang::AS_private: m_stream.Printf("AS_private\n"); break;
|
|
case clang::AS_protected: m_stream.Printf("AS_protected\n"); break;
|
|
case clang::AS_public: m_stream.Printf("AS_public\n"); break;
|
|
}
|
|
m_stream.Indent(); m_stream.Printf("getType() : ");
|
|
const clang::Type *base_type = iter->getType().getTypePtr();
|
|
|
|
if (Visiting(base_type))
|
|
{
|
|
m_stream.Printf("capped\n");
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("\n");
|
|
PushIndent();
|
|
WillVisit(base_type);
|
|
::clang::TypeVisitor<ASTDumper, void>::Visit(base_type);
|
|
DidVisit(base_type);
|
|
PopIndent();
|
|
}
|
|
PopIndent();
|
|
}
|
|
PopIndent();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("capped\n");
|
|
}
|
|
|
|
VisitRecordDecl(cxx_record_decl);
|
|
}
|
|
|
|
// MARK: TypeVisitor
|
|
|
|
void ASTDumper::VisitType (const clang::Type *type)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : Type\n");
|
|
m_stream.Indent(); m_stream.Printf("getTypeClass() : ");
|
|
switch (type->getTypeClass())
|
|
{
|
|
default: m_stream.Printf("~\n"); break;
|
|
#define TYPE(Class, Base) case clang::Type::Class: m_stream.Printf("%s\n", #Class); break;
|
|
#define ABSTRACT_TYPE(Class, Base)
|
|
#include "clang/AST/TypeNodes.def"
|
|
}
|
|
m_stream.Indent(); m_stream.Printf("isFromAST() : %s\n", SfB(type->isFromAST()));
|
|
m_stream.Indent(); m_stream.Printf("containsUnexpandedParameterPack() : %s\n", SfB(type->containsUnexpandedParameterPack()));
|
|
m_stream.Indent(); m_stream.Printf("isCanonicalUnqualified() : %s\n", SfB(type->isCanonicalUnqualified()));
|
|
m_stream.Indent(); m_stream.Printf("isIncompleteType() : %s\n", SfB(type->isIncompleteType()));
|
|
m_stream.Indent(); m_stream.Printf("isObjectType() : %s\n", SfB(type->isObjectType()));
|
|
m_stream.Indent(); m_stream.Printf("isLiteralType() : %s\n", SfB(type->isLiteralType()));
|
|
m_stream.Indent(); m_stream.Printf("isBuiltinType() : %s\n", SfB(type->isBuiltinType()));
|
|
m_stream.Indent(); m_stream.Printf("isPlaceholderType() : %s\n", SfB(type->isPlaceholderType()));
|
|
m_stream.Indent(); m_stream.Printf("isScalarType() : %s\n", SfB(type->isScalarType()));
|
|
m_stream.Indent(); m_stream.Printf("getScalarTypeKind() : ");
|
|
if (type->isScalarType())
|
|
{
|
|
switch (type->getScalarTypeKind())
|
|
{
|
|
default: m_stream.Printf("~\n"); break;
|
|
case clang::Type::STK_Pointer: m_stream.Printf("STK_Pointer\n"); break;
|
|
case clang::Type::STK_MemberPointer: m_stream.Printf("STK_MemberPointer\n"); break;
|
|
case clang::Type::STK_Bool: m_stream.Printf("STK_Bool\n"); break;
|
|
case clang::Type::STK_Integral: m_stream.Printf("STK_Integral\n"); break;
|
|
case clang::Type::STK_Floating: m_stream.Printf("STK_Floating\n"); break;
|
|
case clang::Type::STK_IntegralComplex: m_stream.Printf("STK_IntegralComplex\n"); break;
|
|
case clang::Type::STK_FloatingComplex: m_stream.Printf("STK_FloatingComplex\n"); break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("~\n");
|
|
}
|
|
// ...
|
|
}
|
|
|
|
void ASTDumper::VisitReferenceType(const clang::ReferenceType *reference_type)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : ReferenceType\n");
|
|
m_stream.Indent(); m_stream.Printf("isSpelledAsLValue() : %s\n", SfB(reference_type->isSpelledAsLValue()));
|
|
m_stream.Indent(); m_stream.Printf("isInnerRef() : %s\n", SfB(reference_type->isInnerRef()));
|
|
m_stream.Indent(); m_stream.Printf("getPointeeType() : ");
|
|
|
|
const clang::Type *pointee_type = reference_type->getPointeeType().getTypePtrOrNull();
|
|
|
|
if (pointee_type)
|
|
{
|
|
if (KeepDumping() && !Visiting(pointee_type))
|
|
{
|
|
m_stream.Printf("\n");
|
|
|
|
PushIndent();
|
|
WillVisit(pointee_type);
|
|
::clang::TypeVisitor<ASTDumper, void>::Visit(pointee_type);
|
|
DidVisit(pointee_type);
|
|
PopIndent();
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("capped\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("~\n");
|
|
}
|
|
VisitType(reference_type);
|
|
}
|
|
|
|
void ASTDumper::VisitLValueReferenceType(const clang::LValueReferenceType *lvalue_reference_type)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : LValueReferenceType\n");
|
|
m_stream.Indent(); m_stream.Printf("isSugared() : %s\n", SfB(lvalue_reference_type->isSugared()));
|
|
VisitReferenceType(lvalue_reference_type);
|
|
}
|
|
|
|
void ASTDumper::VisitPointerType(const clang::PointerType *pointer_type)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : PointerType\n");
|
|
m_stream.Indent(); m_stream.Printf("getPointeeType() : ");
|
|
|
|
const clang::Type *pointee_type = pointer_type->getPointeeType().getTypePtrOrNull();
|
|
|
|
if (pointee_type)
|
|
{
|
|
if (KeepDumping() && !Visiting(pointee_type))
|
|
{
|
|
m_stream.Printf("\n");
|
|
|
|
PushIndent();
|
|
WillVisit(pointee_type);
|
|
::clang::TypeVisitor<ASTDumper, void>::Visit(pointee_type);
|
|
DidVisit(pointee_type);
|
|
PopIndent();
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("capped\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("~\n");
|
|
}
|
|
m_stream.Indent(); m_stream.Printf("isSugared() : %s\n", SfB (pointer_type->isSugared()));
|
|
VisitType(pointer_type);
|
|
}
|
|
|
|
void ASTDumper::VisitTagType(const clang::TagType *tag_type)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : TagType\n");
|
|
m_stream.Indent(); m_stream.Printf("getDecl() : ");
|
|
|
|
Decl *decl = tag_type->getDecl();
|
|
|
|
if (decl)
|
|
{
|
|
if (KeepDumping() && !Visiting(decl))
|
|
{
|
|
m_stream.Printf("\n");
|
|
|
|
PushIndent();
|
|
WillVisit(decl);
|
|
::clang::DeclVisitor<ASTDumper, void>::Visit(decl);
|
|
DidVisit(decl);
|
|
PopIndent();
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("capped\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_stream.Printf("~\n");
|
|
}
|
|
m_stream.Indent(); m_stream.Printf("isBeingDefined() : %s\n", SfB(tag_type->isBeingDefined()));
|
|
VisitType(tag_type);
|
|
}
|
|
|
|
void ASTDumper::VisitRecordType(const clang::RecordType *record_type)
|
|
{
|
|
m_stream.Indent(); m_stream.Printf("class : RecordType\n");
|
|
m_stream.Indent(); m_stream.Printf("hasConstFields() : %s\n", SfB(record_type->hasConstFields()));
|
|
VisitTagType(record_type);
|
|
}
|