summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Expression/ASTDumper.h171
-rw-r--r--lldb/lldb.xcodeproj/project.pbxproj6
-rw-r--r--lldb/source/Expression/ASTDumper.cpp545
-rw-r--r--lldb/source/Expression/ClangExpressionDeclMap.cpp8
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());
+ }
}
}
OpenPOWER on IntegriCloud