forked from OSchip/llvm-project
Added a new class, ASTDumper, that provides verbose
diagnostics of Clang AST classes for the purpose of debugging the types LLDB produces for DWARF objects. The ASTDumper is currently only used in log output if you enable verbose mode in the expression log: log enable -v lldb expr Its output then appears in the log for external variables used by the expr command. llvm-svn: 124703
This commit is contained in:
parent
71de91cc09
commit
0917d6e5d5
|
@ -0,0 +1,171 @@
|
|||
//===-- ASTDumper.h ---------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/AST/DeclVisitor.h"
|
||||
#include "clang/AST/StmtVisitor.h"
|
||||
#include "clang/AST/TypeVisitor.h"
|
||||
|
||||
#include "lldb/Core/Stream.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// @class ASTDumper ASTDumper.h "lldb/Expression/ASTDumper.h"
|
||||
/// @brief Encapsulates a recursive dumper for Clang AST nodes.
|
||||
///
|
||||
/// ASTDumper contains a variety of methods for printing fields of Clang
|
||||
/// AST structures, for debugging purposes. It prints the AST objects
|
||||
/// hierarchically:
|
||||
///
|
||||
/// ---
|
||||
/// class : InheritedClass
|
||||
/// someAccessor() : result
|
||||
/// accessorReturningObject() :
|
||||
/// class : ChildClass [object returned by accessorReturningObject]
|
||||
/// ...
|
||||
/// class : BaseClass [same object as InheritedClass]
|
||||
/// baseAccessor() : result
|
||||
///
|
||||
/// The output format is YAML.
|
||||
//----------------------------------------------------------------------
|
||||
class ASTDumper :
|
||||
public clang::DeclVisitor <ASTDumper, void>,
|
||||
public clang::StmtVisitor <ASTDumper, void>,
|
||||
public clang::TypeVisitor <ASTDumper, void>
|
||||
{
|
||||
private:
|
||||
ASTDumper (Stream &stream) :
|
||||
m_stream(stream),
|
||||
m_base_indentation(stream.GetIndentLevel()),
|
||||
m_max_indentation(10)
|
||||
{
|
||||
}
|
||||
|
||||
// MARK: Utility functions
|
||||
|
||||
bool KeepDumping ()
|
||||
{
|
||||
return (m_stream.GetIndentLevel() - m_base_indentation <= m_max_indentation);
|
||||
}
|
||||
|
||||
void PushIndent()
|
||||
{
|
||||
m_stream.IndentMore(1);
|
||||
}
|
||||
|
||||
void PopIndent()
|
||||
{
|
||||
m_stream.IndentLess(1);
|
||||
}
|
||||
|
||||
bool Visiting (const void *entity)
|
||||
{
|
||||
return m_visited_entities.count(entity);
|
||||
}
|
||||
|
||||
void WillVisit (const void *entity)
|
||||
{
|
||||
m_visited_entities.insert(entity);
|
||||
}
|
||||
|
||||
void DidVisit (const void *entity)
|
||||
{
|
||||
m_visited_entities.erase(entity);
|
||||
}
|
||||
|
||||
public:
|
||||
// MARK: DeclVisitor
|
||||
|
||||
void VisitDecl (clang::Decl *decl);
|
||||
void VisitTranslationUnitDecl (clang::TranslationUnitDecl *translation_unit_decl);
|
||||
void VisitNamedDecl (clang::NamedDecl *named_decl);
|
||||
void VisitNamespaceDecl (clang::NamespaceDecl *namespace_decl);
|
||||
void VisitValueDecl (clang::ValueDecl *value_decl);
|
||||
void VisitDeclaratorDecl (clang::DeclaratorDecl *declarator_decl);
|
||||
void VisitVarDecl (clang::VarDecl *var_decl);
|
||||
void VisitTypeDecl (clang::TypeDecl *type_decl);
|
||||
void VisitTagDecl (clang::TagDecl *tag_decl);
|
||||
void VisitRecordDecl (clang::RecordDecl *record_decl);
|
||||
void VisitCXXRecordDecl (clang::CXXRecordDecl *cxx_record_decl);
|
||||
|
||||
// MARK: StmtVisitor
|
||||
|
||||
// MARK: TypeVisitor
|
||||
|
||||
void VisitType (const clang::Type *type);
|
||||
void VisitReferenceType (const clang::ReferenceType *reference_type);
|
||||
void VisitLValueReferenceType (const clang::LValueReferenceType *lvalue_reference_type);
|
||||
void VisitPointerType (const clang::PointerType *pointer_type);
|
||||
void VisitTagType (const clang::TagType *tag_type);
|
||||
void VisitRecordType (const clang::RecordType *record_type);
|
||||
|
||||
private:
|
||||
llvm::DenseSet <const void *> m_visited_entities; ///< A set of all entities that have already been printed, to prevent loops
|
||||
Stream &m_stream; ///< A stream to print output to
|
||||
unsigned m_base_indentation; ///< The indentation of m_stream when the ASTDumper was entered
|
||||
unsigned m_max_indentation; ///< The maximum depth of indentation (added to m_base_indentation)
|
||||
public:
|
||||
//------------------------------------------------------------------
|
||||
/// DumpDecl - Create an ASTDumper and use it to dump a Decl.
|
||||
///
|
||||
/// @param[in] stream
|
||||
/// The stream to use when printing output.
|
||||
///
|
||||
/// @param[in] decl
|
||||
/// The AST Decl to print.
|
||||
//------------------------------------------------------------------
|
||||
static void DumpDecl (Stream &stream, clang::Decl *decl)
|
||||
{
|
||||
ASTDumper dumper(stream);
|
||||
|
||||
stream.Printf("---\n");
|
||||
|
||||
dumper.::clang::DeclVisitor<ASTDumper, void>::Visit(decl);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// DumpDecl - Create an ASTDumper and use it to dump a Stmt.
|
||||
///
|
||||
/// @param[in] stream
|
||||
/// The stream to use when printing output.
|
||||
///
|
||||
/// @param[in] stmt
|
||||
/// The AST Stmt to print.
|
||||
//------------------------------------------------------------------
|
||||
static void DumpStmt (Stream &stream, clang::Stmt *stmt)
|
||||
{
|
||||
ASTDumper dumper(stream);
|
||||
|
||||
stream.Printf("---\n");
|
||||
|
||||
dumper.::clang::StmtVisitor<ASTDumper, void>::Visit(stmt);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// DumpDecl - Create an ASTDumper and use it to dump a Type.
|
||||
///
|
||||
/// @param[in] stream
|
||||
/// The stream to use when printing output.
|
||||
///
|
||||
/// @param[in] type
|
||||
/// The AST Type to print.
|
||||
//------------------------------------------------------------------
|
||||
static void DumpType (Stream &stream, clang::Type *type)
|
||||
{
|
||||
ASTDumper dumper(stream);
|
||||
|
||||
stream.Printf("---\n");
|
||||
|
||||
dumper.::clang::TypeVisitor<ASTDumper, void>::Visit(type);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
|
@ -318,6 +318,7 @@
|
|||
26F5C32D10F3DFDD009D5894 /* libtermcap.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32B10F3DFDD009D5894 /* libtermcap.dylib */; };
|
||||
26F5C37510F3F61B009D5894 /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C37410F3F61B009D5894 /* libobjc.dylib */; };
|
||||
26F5C39110F3FA26009D5894 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C39010F3FA26009D5894 /* CoreFoundation.framework */; };
|
||||
4906FD4212F2255300A2A77C /* ASTDumper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4906FD4012F2255300A2A77C /* ASTDumper.cpp */; };
|
||||
491193521226386000578B7F /* ASTStructExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491193501226386000578B7F /* ASTStructExtractor.cpp */; };
|
||||
49307AAE11DEA4D90081F992 /* IRForTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49307AAD11DEA4D90081F992 /* IRForTarget.cpp */; };
|
||||
49445C2612245E3600C11A81 /* ClangExpressionParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49445C2512245E3600C11A81 /* ClangExpressionParser.cpp */; };
|
||||
|
@ -925,6 +926,8 @@
|
|||
26F996A8119B79C300412154 /* ARM_GCC_Registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARM_GCC_Registers.h; path = source/Utility/ARM_GCC_Registers.h; sourceTree = "<group>"; };
|
||||
26FE25221146CADE00F4085A /* GDBRemoteCommunication.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GDBRemoteCommunication.cpp; path = "source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp"; sourceTree = "<group>"; };
|
||||
26FE25231146CADE00F4085A /* GDBRemoteCommunication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GDBRemoteCommunication.h; path = "source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h"; sourceTree = "<group>"; };
|
||||
4906FD4012F2255300A2A77C /* ASTDumper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTDumper.cpp; path = source/Expression/ASTDumper.cpp; sourceTree = "<group>"; };
|
||||
4906FD4412F2257600A2A77C /* ASTDumper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTDumper.h; path = include/lldb/Expression/ASTDumper.h; sourceTree = "<group>"; };
|
||||
4911934B1226383D00578B7F /* ASTStructExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTStructExtractor.h; path = include/lldb/Expression/ASTStructExtractor.h; sourceTree = "<group>"; };
|
||||
491193501226386000578B7F /* ASTStructExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTStructExtractor.cpp; path = source/Expression/ASTStructExtractor.cpp; sourceTree = "<group>"; };
|
||||
49307AAD11DEA4D90081F992 /* IRForTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRForTarget.cpp; path = source/Expression/IRForTarget.cpp; sourceTree = "<group>"; };
|
||||
|
@ -1939,6 +1942,8 @@
|
|||
497C86BD122823D800B54702 /* ClangUtilityFunction.cpp */,
|
||||
26BC7DC310F1B79500F91463 /* DWARFExpression.h */,
|
||||
26BC7ED810F1B86700F91463 /* DWARFExpression.cpp */,
|
||||
4906FD4412F2257600A2A77C /* ASTDumper.h */,
|
||||
4906FD4012F2255300A2A77C /* ASTDumper.cpp */,
|
||||
49A8A3A311D568BF00AD3B68 /* ASTResultSynthesizer.h */,
|
||||
49A8A39F11D568A300AD3B68 /* ASTResultSynthesizer.cpp */,
|
||||
4911934B1226383D00578B7F /* ASTStructExtractor.h */,
|
||||
|
@ -2834,6 +2839,7 @@
|
|||
B296983712C2FB98002D92C3 /* CommandObjectVersion.cpp in Sources */,
|
||||
26D9FDC912F784FD0003F2EE /* EmulateInstruction.cpp in Sources */,
|
||||
26D9FDCE12F7853F0003F2EE /* EmulateInstructionARM.cpp in Sources */,
|
||||
4906FD4212F2255300A2A77C /* ASTDumper.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,545 @@
|
|||
//===-- 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("isPODType() : %s\n", SfB(type->isPODType()));
|
||||
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);
|
||||
}
|
|
@ -21,6 +21,7 @@
|
|||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/ValueObjectConstResult.h"
|
||||
#include "lldb/Expression/ASTDumper.h"
|
||||
#include "lldb/Expression/ClangASTSource.h"
|
||||
#include "lldb/Expression/ClangPersistentVariables.h"
|
||||
#include "lldb/Host/Endian.h"
|
||||
|
@ -1904,6 +1905,13 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, Variable* va
|
|||
var_decl_print_stream.flush();
|
||||
|
||||
log->Printf("Found variable %s, returned %s", decl_name.c_str(), var_decl_print_string.c_str());
|
||||
|
||||
if (log->GetVerbose())
|
||||
{
|
||||
StreamString var_decl_dump_string;
|
||||
ASTDumper::DumpDecl(var_decl_dump_string, var_decl);
|
||||
log->Printf("%s\n", var_decl_dump_string.GetData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue