Index: lldb/include/lldb/Symbol/CompilerType.h =================================================================== --- lldb/include/lldb/Symbol/CompilerType.h +++ lldb/include/lldb/Symbol/CompilerType.h @@ -371,9 +371,15 @@ size_t data_byte_size); /// Dump to stdout. - void DumpTypeDescription() const; - - void DumpTypeDescription(Stream *s) const; + void DumpTypeDescription(lldb::DescriptionLevel level = + lldb::eDescriptionLevelFull) const; + + /// Print a description of the type to a stream. The exact implementation + /// varies, but the expectation is that eDescriptionLevelFull returns a + /// source-like representation of the type, whereas eDescriptionLevelVerbose + /// does a dump of the underlying AST if applicable. + void DumpTypeDescription(Stream *s, lldb::DescriptionLevel level = + lldb::eDescriptionLevelFull) const; /// \} bool GetValueAsScalar(const DataExtractor &data, lldb::offset_t data_offset, Index: lldb/include/lldb/Symbol/Type.h =================================================================== --- lldb/include/lldb/Symbol/Type.h +++ lldb/include/lldb/Symbol/Type.h @@ -103,7 +103,8 @@ // they get an error. Type(); - void Dump(Stream *s, bool show_context); + void Dump(Stream *s, bool show_context, + lldb::DescriptionLevel level = lldb::eDescriptionLevelFull); void DumpTypeName(Stream *s); Index: lldb/include/lldb/Symbol/TypeMap.h =================================================================== --- lldb/include/lldb/Symbol/TypeMap.h +++ lldb/include/lldb/Symbol/TypeMap.h @@ -26,7 +26,8 @@ void Clear(); - void Dump(Stream *s, bool show_context); + void Dump(Stream *s, bool show_context, + lldb::DescriptionLevel level = lldb::eDescriptionLevelFull); TypeMap FindTypes(ConstString name); Index: lldb/include/lldb/Symbol/TypeSystem.h =================================================================== --- lldb/include/lldb/Symbol/TypeSystem.h +++ lldb/include/lldb/Symbol/TypeSystem.h @@ -374,11 +374,18 @@ uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope) = 0; - virtual void - DumpTypeDescription(lldb::opaque_compiler_type_t type) = 0; // Dump to stdout - - virtual void DumpTypeDescription(lldb::opaque_compiler_type_t type, - Stream *s) = 0; + /// Dump the type to stdout. + virtual void DumpTypeDescription( + lldb::opaque_compiler_type_t type, + lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) = 0; + + /// Print a description of the type to a stream. The exact implementation + /// varies, but the expectation is that eDescriptionLevelFull returns a + /// source-like representation of the type, whereas eDescriptionLevelVerbose + /// does a dump of the underlying AST if applicable. + virtual void DumpTypeDescription( + lldb::opaque_compiler_type_t type, Stream *s, + lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) = 0; // TODO: These methods appear unused. Should they be removed? Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h =================================================================== --- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -975,10 +975,12 @@ lldb::offset_t data_offset, size_t data_byte_size) override; void DumpTypeDescription( - lldb::opaque_compiler_type_t type) override; // Dump to stdout + lldb::opaque_compiler_type_t type, + lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) override; - void DumpTypeDescription(lldb::opaque_compiler_type_t type, - Stream *s) override; + void DumpTypeDescription( + lldb::opaque_compiler_type_t type, Stream *s, + lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) override; static void DumpTypeName(const CompilerType &type); Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp =================================================================== --- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -8774,9 +8774,10 @@ } } -void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type) { +void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type, + lldb::DescriptionLevel level) { StreamFile s(stdout, false); - DumpTypeDescription(type, &s); + DumpTypeDescription(type, &s, level); CompilerType ct(this, type); const clang::Type *clang_type = ClangUtil::GetQualType(ct).getTypePtr(); @@ -8787,7 +8788,8 @@ } void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type, - Stream *s) { + Stream *s, + lldb::DescriptionLevel level) { if (type) { clang::QualType qual_type = RemoveWrappingTypes(GetQualType(type), {clang::Type::Typedef}); @@ -8804,14 +8806,18 @@ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); assert(objc_class_type); - if (objc_class_type) { - clang::ObjCInterfaceDecl *class_interface_decl = + if (!objc_class_type) + break; + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - if (class_interface_decl) { - clang::PrintingPolicy policy = getASTContext().getPrintingPolicy(); - class_interface_decl->print(llvm_ostrm, policy, s->GetIndentLevel()); - } - } + if (!class_interface_decl) + break; + if (level == eDescriptionLevelVerbose) + class_interface_decl->dump(llvm_ostrm); + else + class_interface_decl->print(llvm_ostrm, + getASTContext().getPrintingPolicy(), + s->GetIndentLevel()); } break; case clang::Type::Typedef: { @@ -8863,7 +8869,7 @@ if (buf.size() > 0) { s->Write(buf.data(), buf.size()); } - } +} } void TypeSystemClang::DumpTypeName(const CompilerType &type) { Index: lldb/source/Symbol/CompilerType.cpp =================================================================== --- lldb/source/Symbol/CompilerType.cpp +++ lldb/source/Symbol/CompilerType.cpp @@ -744,14 +744,15 @@ data_byte_size); } -void CompilerType::DumpTypeDescription() const { +void CompilerType::DumpTypeDescription(lldb::DescriptionLevel level) const { if (IsValid()) - m_type_system->DumpTypeDescription(m_type); + m_type_system->DumpTypeDescription(m_type, level); } -void CompilerType::DumpTypeDescription(Stream *s) const { +void CompilerType::DumpTypeDescription(Stream *s, + lldb::DescriptionLevel level) const { if (IsValid()) { - m_type_system->DumpTypeDescription(m_type, s); + m_type_system->DumpTypeDescription(m_type, s, level); } } Index: lldb/source/Symbol/Type.cpp =================================================================== --- lldb/source/Symbol/Type.cpp +++ lldb/source/Symbol/Type.cpp @@ -234,7 +234,7 @@ } } -void Type::Dump(Stream *s, bool show_context) { +void Type::Dump(Stream *s, bool show_context, lldb::DescriptionLevel level) { s->Printf("%p: ", static_cast(this)); s->Indent(); *s << "Type" << static_cast(*this) << ' '; @@ -255,7 +255,7 @@ if (m_compiler_type.IsValid()) { *s << ", compiler_type = " << m_compiler_type.GetOpaqueQualType() << ' '; - GetForwardCompilerType().DumpTypeDescription(s); + GetForwardCompilerType().DumpTypeDescription(s, level); } else if (m_encoding_uid != LLDB_INVALID_UID) { s->Format(", type_data = {0:x-16}", m_encoding_uid); switch (m_encoding_uid_type) { Index: lldb/source/Symbol/TypeMap.cpp =================================================================== --- lldb/source/Symbol/TypeMap.cpp +++ lldb/source/Symbol/TypeMap.cpp @@ -121,9 +121,9 @@ return false; } -void TypeMap::Dump(Stream *s, bool show_context) { +void TypeMap::Dump(Stream *s, bool show_context, lldb::DescriptionLevel level) { for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { - pos->second->Dump(s, show_context); + pos->second->Dump(s, show_context, level); } } Index: lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/A.h =================================================================== --- lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/A.h +++ lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/A.h @@ -18,6 +18,7 @@ @interface SomeClass { } +@property (readonly) int number; @end template struct Template { T field; }; Index: lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm =================================================================== --- lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm +++ lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm @@ -1,7 +1,6 @@ // RUN: %clang --target=x86_64-apple-macosx -g -gmodules \ // RUN: -fmodules -fmodules-cache-path=%t.cache \ // RUN: -c -o %t.o %s -I%S/Inputs -// RUN: lldb-test symbols -dump-clang-ast %t.o | FileCheck %s // Verify that the owning module information from DWARF is preserved in the AST. @import A; @@ -29,7 +28,13 @@ // FIXME: -EnumConstantDecl {{.*}} imported in A a SomeClass *obj1; -// CHECK-DAG: ObjCInterfaceDecl {{.*}} imported in A {{.*}} SomeClass +// RUN: lldb-test symbols -dump-clang-ast -find type --language=ObjC++ \ +// RUN: -compiler-context 'Module:A,Struct:SomeClass' %t.o \ +// RUN: | FileCheck %s --check-prefix=CHECK-OBJC +// CHECK-OBJC: ObjCInterfaceDecl {{.*}} imported in A SomeClass +// CHECK-OBJC: |-ObjCPropertyDecl {{.*}} imported in A number 'int' readonly +// CHECK-OBJC: | `-getter ObjCMethod {{.*}} 'number' +// CHECK-OBJC: `-ObjCMethodDecl {{.*}} imported in A implicit - number 'int' // Template specializations are not yet supported, so they lack the ownership info: Template t2; Index: lldb/tools/lldb-test/lldb-test.cpp =================================================================== --- lldb/tools/lldb-test/lldb-test.cpp +++ lldb/tools/lldb-test/lldb-test.cpp @@ -192,7 +192,7 @@ static Error findVariables(lldb_private::Module &Module); static Error dumpModule(lldb_private::Module &Module); static Error dumpAST(lldb_private::Module &Module); -static Error dumpClangAST(lldb_private::Module &Module); +static Error dumpEntireClangAST(lldb_private::Module &Module); static Error verify(lldb_private::Module &Module); static Expected getAction(); @@ -404,6 +404,10 @@ return List.GetVariableAtIndex(0)->GetDeclContext(); } +static lldb::DescriptionLevel GetDescriptionLevel() { + return opts::symbols::DumpClangAST ? eDescriptionLevelVerbose : eDescriptionLevelFull; +} + Error opts::symbols::findFunctions(lldb_private::Module &Module) { SymbolFile &Symfile = *Module.GetSymbolFile(); SymbolContextList List; @@ -534,7 +538,7 @@ outs() << formatv("Found {0} types:\n", Map.GetSize()); StreamString Stream; - Map.Dump(&Stream, false); + Map.Dump(&Stream, false, GetDescriptionLevel()); outs() << Stream.GetData() << "\n"; return Error::success(); } @@ -615,7 +619,7 @@ return Error::success(); } -Error opts::symbols::dumpClangAST(lldb_private::Module &Module) { +Error opts::symbols::dumpEntireClangAST(lldb_private::Module &Module) { Module.ParseAllDebugSymbols(); SymbolFile *symfile = Module.GetSymbolFile(); @@ -719,13 +723,17 @@ } if (DumpClangAST) { - if (Find != FindType::None) - return make_string_error("Cannot both search and dump clang AST."); - if (Regex || !Context.empty() || !File.empty() || Line != 0) - return make_string_error( - "-regex, -context, -name, -file and -line options are not " - "applicable for dumping clang AST."); - return dumpClangAST; + if (Find == FindType::None) { + if (Regex || !Context.empty() || !File.empty() || Line != 0) + return make_string_error( + "-regex, -context, -name, -file and -line options are not " + "applicable for dumping the entire clang AST. Either combine with " + "-find, or use -dump-clang-ast as a standalone option."); + return dumpEntireClangAST; + } + if (Find != FindType::Type) + return make_string_error("This combination of -dump-clang-ast and -find " + " is not yet implemented."); } if (Regex && !Context.empty())