Index: include/lldb/Symbol/ClangASTContext.h =================================================================== --- include/lldb/Symbol/ClangASTContext.h +++ include/lldb/Symbol/ClangASTContext.h @@ -892,6 +892,14 @@ void Dump(Stream &s); + /// Dump clang AST types from the symbol table + /// + /// \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 DumpFromSymbols(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/Core/Module.cpp =================================================================== --- source/Core/Module.cpp +++ source/Core/Module.cpp @@ -374,7 +374,6 @@ continue; symbols->ParseVariablesForContext(sc); - symbols->ParseFunctions(*sc.comp_unit); sc.comp_unit->ForeachFunction([&sc, &symbols](const FunctionSP &f) { Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -3049,12 +3049,18 @@ 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); + + 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 @@ -9163,6 +9163,43 @@ tu->dump(s.AsRawOstream()); } +void ClangASTContext::DumpFromSymbols(Stream &s, llvm::StringRef symbol_name) { + SymbolFile *symfile = GetSymbolFile(); + + if (!symfile) + return; + + lldb_private::TypeList type_list; + size_t ntypes = symfile->GetTypes(nullptr, eTypeClassAny, type_list); + + for (size_t i = 0; i < ntypes; ++i) { + auto type = type_list.GetTypeAtIndex(i); + + if (!symbol_name.empty()) + if (symbol_name.compare(type->GetName().AsCString()) != 0) + continue; + + s << type->GetName().AsCString() << "\n"; + + if (clang::CXXRecordDecl *record_decl = + GetAsCXXRecordDecl(type->GetFullCompilerType().GetOpaqueQualType())) + record_decl->dump(s.AsRawOstream()); + else 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 if (clang::EnumDecl *enum_decl = + GetAsEnumDecl(type->GetFullCompilerType())) + enum_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 @@ -42,6 +42,7 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" #include "llvm/Support/WithColor.h" + #include #include @@ -159,6 +160,13 @@ 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 + SymbolName("symbol-name", cl::desc("Symbol to dump complete AST for"), + cl::sub(SymbolsSubcommand)); static cl::opt Verify("verify", cl::desc("Verify symbol information."), cl::sub(SymbolsSubcommand)); @@ -178,6 +186,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(); @@ -524,11 +533,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"); @@ -542,7 +551,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."); @@ -551,6 +560,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->DumpFromSymbols(Stream, SymbolName); + outs() << Stream.GetData() << "\n"; + + return Error::success(); +} + Error opts::symbols::verify(lldb_private::Module &Module) { SymbolFile *symfile = Module.GetSymbolFile(); if (!symfile) @@ -629,6 +662,17 @@ return dumpAST; } + if (DumpClangAST) { + if (Find != FindType::None) + return make_string_error("Cannot both search and dump clang AST."); + if (Regex || !Context.empty() || !Name.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.");