Index: include/lldb/Symbol/ClangASTContext.h =================================================================== --- include/lldb/Symbol/ClangASTContext.h +++ include/lldb/Symbol/ClangASTContext.h @@ -889,6 +889,14 @@ void Dump(Stream &s); + /// Dump clang AST types from the symbol file. + /// + /// \param[in] s + /// A stream to send the dumped AST node(s) to + /// \param[in] symbol_name + /// The name of the symbol to dump, if it is empty dump all the symbols + void DumpFromSymbolFile(Stream &s, llvm::StringRef symbol_name); + void DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format, const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size, Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -3025,12 +3025,21 @@ bool parse_siblings, bool parse_children) { size_t types_added = 0; DWARFDIE die = orig_die; + while (die) { + const dw_tag_t tag = die.Tag(); bool type_is_new = false; - if (ParseType(sc, die, &type_is_new).get()) { - if (type_is_new) - ++types_added; - } + + Tag dwarf_tag = static_cast(tag); + + // TODO: Currently ParseTypeFromDWARF(...) which is called by ParseType(...) + // does not handle DW_TAG_subrange_type. It is not clear if this is a bug or + // not. + if (isType(dwarf_tag) && tag != DW_TAG_subrange_type) + ParseType(sc, die, &type_is_new); + + if (type_is_new) + ++types_added; if (parse_children && die.HasChildren()) { if (die.Tag() == DW_TAG_subprogram) { Index: source/Symbol/ClangASTContext.cpp =================================================================== --- source/Symbol/ClangASTContext.cpp +++ source/Symbol/ClangASTContext.cpp @@ -8992,6 +8992,39 @@ tu->dump(s.AsRawOstream()); } +void ClangASTContext::DumpFromSymbolFile(Stream &s, + llvm::StringRef symbol_name) { + SymbolFile *symfile = GetSymbolFile(); + + if (!symfile) + return; + + lldb_private::TypeList type_list; + symfile->GetTypes(nullptr, eTypeClassAny, type_list); + size_t ntypes = type_list.GetSize(); + + for (size_t i = 0; i < ntypes; ++i) { + TypeSP type = type_list.GetTypeAtIndex(i); + + if (!symbol_name.empty()) + if (symbol_name.compare(type->GetName().GetStringRef()) != 0) + continue; + + s << type->GetName().AsCString() << "\n"; + + if (clang::TagDecl *tag_decl = + GetAsTagDecl(type->GetFullCompilerType())) + tag_decl->dump(s.AsRawOstream()); + else if (clang::TypedefNameDecl *typedef_decl = + GetAsTypedefDecl(type->GetFullCompilerType())) + typedef_decl->dump(s.AsRawOstream()); + else { + GetCanonicalQualType(type->GetFullCompilerType().GetOpaqueQualType()) + .dump(s.AsRawOstream()); + } + } +} + void ClangASTContext::DumpValue( lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format, const DataExtractor &data, Index: tools/lldb-test/lldb-test.cpp =================================================================== --- tools/lldb-test/lldb-test.cpp +++ tools/lldb-test/lldb-test.cpp @@ -43,6 +43,7 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" #include "llvm/Support/WithColor.h" + #include #include @@ -169,6 +170,10 @@ static cl::opt DumpAST("dump-ast", cl::desc("Dump AST restored from symbols."), cl::sub(SymbolsSubcommand)); +static cl::opt + DumpClangAST("dump-clang-ast", + cl::desc("Dump clang AST restored from symbols."), + cl::sub(SymbolsSubcommand)); static cl::opt Verify("verify", cl::desc("Verify symbol information."), cl::sub(SymbolsSubcommand)); @@ -188,6 +193,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 verify(lldb_private::Module &Module); static Expected getAction(); @@ -581,11 +587,11 @@ Error opts::symbols::dumpAST(lldb_private::Module &Module) { Module.ParseAllDebugSymbols(); - auto symfile = Module.GetSymbolFile(); + SymbolFile *symfile = Module.GetSymbolFile(); if (!symfile) return make_string_error("Module has no symbol file."); - auto type_system_or_err = + llvm::Expected type_system_or_err = symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); if (!type_system_or_err) return make_string_error("Can't retrieve ClangASTContext"); @@ -599,7 +605,7 @@ if (!ast_ctx) return make_string_error("Can't retrieve AST context."); - auto tu = ast_ctx->getTranslationUnitDecl(); + clang::TranslationUnitDecl *tu = ast_ctx->getTranslationUnitDecl(); if (!tu) return make_string_error("Can't retrieve translation unit declaration."); @@ -608,6 +614,30 @@ return Error::success(); } +Error opts::symbols::dumpClangAST(lldb_private::Module &Module) { + Module.ParseAllDebugSymbols(); + + SymbolFile *symfile = Module.GetSymbolFile(); + if (!symfile) + return make_string_error("Module has no symbol file."); + + llvm::Expected type_system_or_err = + symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); + if (!type_system_or_err) + return make_string_error("Can't retrieve ClangASTContext"); + + auto *clang_ast_ctx = + llvm::dyn_cast_or_null(&type_system_or_err.get()); + if (!clang_ast_ctx) + return make_string_error("Retrieved TypeSystem was not a ClangASTContext"); + + StreamString Stream; + clang_ast_ctx->DumpFromSymbolFile(Stream, Name); + outs() << Stream.GetData() << "\n"; + + return Error::success(); +} + Error opts::symbols::verify(lldb_private::Module &Module) { SymbolFile *symfile = Module.GetSymbolFile(); if (!symfile) @@ -686,6 +716,16 @@ return dumpAST; } + 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 (Regex && !Context.empty()) return make_string_error( "Cannot search using both regular expressions and context.");