diff options
-rw-r--r-- | lldb/include/lldb/Expression/ASTDumper.h | 171 | ||||
-rw-r--r-- | lldb/lldb.xcodeproj/project.pbxproj | 6 | ||||
-rw-r--r-- | lldb/source/Expression/ASTDumper.cpp | 545 | ||||
-rw-r--r-- | lldb/source/Expression/ClangExpressionDeclMap.cpp | 8 |
4 files changed, 730 insertions, 0 deletions
diff --git a/lldb/include/lldb/Expression/ASTDumper.h b/lldb/include/lldb/Expression/ASTDumper.h new file mode 100644 index 00000000000..0aecfab6555 --- /dev/null +++ b/lldb/include/lldb/Expression/ASTDumper.h @@ -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 diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 4d3a82952fe..2d224bd7583 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -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; }; diff --git a/lldb/source/Expression/ASTDumper.cpp b/lldb/source/Expression/ASTDumper.cpp new file mode 100644 index 00000000000..76be4408fa2 --- /dev/null +++ b/lldb/source/Expression/ASTDumper.cpp @@ -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); +} diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp index f863969d1e4..6df0692666f 100644 --- a/lldb/source/Expression/ClangExpressionDeclMap.cpp +++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp @@ -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()); + } } } |