diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index df2f263b18e17..75c7f230ddf3d 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -296,7 +296,7 @@ class SymbolFile : public PluginInterface { lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list); - virtual void DumpClangAST(Stream &s) {} + virtual void DumpClangAST(Stream &s, llvm::StringRef filter) {} virtual void FindGlobalVariables(ConstString name, const CompilerDeclContext &parent_decl_ctx, uint32_t max_matches, diff --git a/lldb/include/lldb/Symbol/SymbolFileOnDemand.h b/lldb/include/lldb/Symbol/SymbolFileOnDemand.h index 6ed389a48880c..ba4a7f09afeaa 100644 --- a/lldb/include/lldb/Symbol/SymbolFileOnDemand.h +++ b/lldb/include/lldb/Symbol/SymbolFileOnDemand.h @@ -127,7 +127,7 @@ class SymbolFileOnDemand : public lldb_private::SymbolFile { lldb_private::SymbolContextList &sc_list) override; void Dump(lldb_private::Stream &s) override; - void DumpClangAST(lldb_private::Stream &s) override; + void DumpClangAST(lldb_private::Stream &s, llvm::StringRef filter) override; void FindGlobalVariables(lldb_private::ConstString name, diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h index 1f1a3ac4bc56b..cb1f0130b548d 100644 --- a/lldb/include/lldb/Symbol/TypeSystem.h +++ b/lldb/include/lldb/Symbol/TypeSystem.h @@ -443,7 +443,11 @@ class TypeSystem : public PluginInterface, /// given stream. /// /// This should not modify the state of the TypeSystem if possible. - virtual void Dump(llvm::raw_ostream &output) = 0; + /// + /// \param[out] output Stream to dup the AST into. + /// \param[in] filter If empty, dump whole AST. If non-empty, will only + /// dump decls whose names contain \c filter. + virtual void Dump(llvm::raw_ostream &output, llvm::StringRef filter) = 0; /// This is used by swift. virtual bool IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) = 0; diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index e2ba0008badd3..21b21954bbc90 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -2235,11 +2235,23 @@ class CommandObjectTargetModulesDumpClangAST : CommandObjectTargetModulesModuleAutoComplete( interpreter, "target modules dump ast", "Dump the clang ast for a given module's symbol file.", - //"target modules dump ast [ ...]") - nullptr, eCommandRequiresTarget) {} + "target modules dump ast [--filter ] [ ...]", + eCommandRequiresTarget), + m_filter(LLDB_OPT_SET_1, false, "filter", 'f', 0, eArgTypeName, + "Dump only the decls whose names contain the specified filter " + "string.", + /*default_value=*/"") { + m_option_group.Append(&m_filter, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Finalize(); + } + + Options *GetOptions() override { return &m_option_group; } ~CommandObjectTargetModulesDumpClangAST() override = default; + OptionGroupOptions m_option_group; + OptionGroupString m_filter; + protected: void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetTarget(); @@ -2251,6 +2263,8 @@ class CommandObjectTargetModulesDumpClangAST return; } + llvm::StringRef filter = m_filter.GetOptionValue().GetCurrentValueAsRef(); + if (command.GetArgumentCount() == 0) { // Dump all ASTs for all modules images result.GetOutputStream().Format("Dumping clang ast for {0} modules.\n", @@ -2259,7 +2273,7 @@ class CommandObjectTargetModulesDumpClangAST if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted dumping clang ast")) break; if (SymbolFile *sf = module_sp->GetSymbolFile()) - sf->DumpClangAST(result.GetOutputStream()); + sf->DumpClangAST(result.GetOutputStream(), filter); } result.SetStatus(eReturnStatusSuccessFinishResult); return; @@ -2288,7 +2302,7 @@ class CommandObjectTargetModulesDumpClangAST Module *m = module_list.GetModulePointerAtIndex(i); if (SymbolFile *sf = m->GetSymbolFile()) - sf->DumpClangAST(result.GetOutputStream()); + sf->DumpClangAST(result.GetOutputStream(), filter); } } result.SetStatus(eReturnStatusSuccessFinishResult); @@ -5272,7 +5286,7 @@ class CommandObjectTargetDumpTypesystem : public CommandObjectParsed { // Go over every scratch TypeSystem and dump to the command output. for (lldb::TypeSystemSP ts : GetTarget().GetScratchTypeSystems()) if (ts) - ts->Dump(result.GetOutputStream().AsRawOstream()); + ts->Dump(result.GetOutputStream().AsRawOstream(), ""); result.SetStatus(eReturnStatusSuccessFinishResult); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 24f905a023317..71f204c03a42a 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -4127,7 +4127,7 @@ void SymbolFileDWARF::Dump(lldb_private::Stream &s) { m_index->Dump(s); } -void SymbolFileDWARF::DumpClangAST(Stream &s) { +void SymbolFileDWARF::DumpClangAST(Stream &s, llvm::StringRef filter) { auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); if (!ts_or_err) return; @@ -4135,7 +4135,7 @@ void SymbolFileDWARF::DumpClangAST(Stream &s) { TypeSystemClang *clang = llvm::dyn_cast_or_null(ts.get()); if (!clang) return; - clang->Dump(s.AsRawOstream()); + clang->Dump(s.AsRawOstream(), filter); } bool SymbolFileDWARF::GetSeparateDebugInfo(StructuredData::Dictionary &d, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index c9fdfb7b1cf91..d2d30d7decb16 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -276,7 +276,7 @@ class SymbolFileDWARF : public SymbolFileCommon { void Dump(Stream &s) override; - void DumpClangAST(Stream &s) override; + void DumpClangAST(Stream &s, llvm::StringRef filter) override; /// List separate dwo files. bool GetSeparateDebugInfo(StructuredData::Dictionary &d, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 961c212e2e6dc..f3a940b2ee396 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1267,9 +1267,9 @@ CompilerDeclContext SymbolFileDWARFDebugMap::FindNamespace( return matching_namespace; } -void SymbolFileDWARFDebugMap::DumpClangAST(Stream &s) { - ForEachSymbolFile("Dumping clang AST", [&s](SymbolFileDWARF &oso_dwarf) { - oso_dwarf.DumpClangAST(s); +void SymbolFileDWARFDebugMap::DumpClangAST(Stream &s, llvm::StringRef filter) { + ForEachSymbolFile("Dumping clang AST", [&](SymbolFileDWARF &oso_dwarf) { + oso_dwarf.DumpClangAST(s, filter); // The underlying assumption is that DumpClangAST(...) will obtain the // AST from the underlying TypeSystem and therefore we only need to do // this once and can stop after the first iteration hence we return true. diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index 8399a267d7856..35cbdbbb1692f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -129,7 +129,7 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon { std::vector> ParseCallEdgesInFunction(UserID func_id) override; - void DumpClangAST(Stream &s) override; + void DumpClangAST(Stream &s, llvm::StringRef filter) override; /// List separate oso files. bool GetSeparateDebugInfo(StructuredData::Dictionary &d, diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 92840da74a21f..f7cde5db31caf 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -1449,6 +1449,6 @@ PdbAstBuilder::FromCompilerDeclContext(CompilerDeclContext context) { return static_cast(context.GetOpaqueDeclContext()); } -void PdbAstBuilder::Dump(Stream &stream) { - m_clang.Dump(stream.AsRawOstream()); +void PdbAstBuilder::Dump(Stream &stream, llvm::StringRef filter) { + m_clang.Dump(stream.AsRawOstream(), filter); } diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h index b7cad30c69c0c..66a3836fac053 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h @@ -87,7 +87,7 @@ class PdbAstBuilder { TypeSystemClang &clang() { return m_clang; } ClangASTImporter &GetClangASTImporter() { return m_importer; } - void Dump(Stream &stream); + void Dump(Stream &stream, llvm::StringRef filter); private: clang::Decl *TryGetDecl(PdbSymUid uid) const; diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index dadc969c48a3a..20d8c1acf9c42 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1630,7 +1630,7 @@ size_t SymbolFileNativePDB::ParseSymbolArrayInScope( return count; } -void SymbolFileNativePDB::DumpClangAST(Stream &s) { +void SymbolFileNativePDB::DumpClangAST(Stream &s, llvm::StringRef filter) { auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); if (!ts_or_err) return; @@ -1638,7 +1638,7 @@ void SymbolFileNativePDB::DumpClangAST(Stream &s) { TypeSystemClang *clang = llvm::dyn_cast_or_null(ts.get()); if (!clang) return; - clang->GetNativePDBParser()->Dump(s); + clang->GetNativePDBParser()->Dump(s, filter); } void SymbolFileNativePDB::FindGlobalVariables( diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index b0e78a243a3c2..9891313f11d0b 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -157,7 +157,7 @@ class SymbolFileNativePDB : public SymbolFileCommon { PdbIndex &GetIndex() { return *m_index; }; - void DumpClangAST(Stream &s) override; + void DumpClangAST(Stream &s, llvm::StringRef filter) override; std::optional GetParentType(llvm::codeview::TypeIndex ti); diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index f1d98e780994d..96519ae0b3157 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -1431,7 +1431,7 @@ void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) { symtab.Finalize(); } -void SymbolFilePDB::DumpClangAST(Stream &s) { +void SymbolFilePDB::DumpClangAST(Stream &s, llvm::StringRef filter) { auto type_system_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); if (auto err = type_system_or_err.takeError()) { @@ -1445,7 +1445,7 @@ void SymbolFilePDB::DumpClangAST(Stream &s) { llvm::dyn_cast_or_null(ts.get()); if (!clang_type_system) return; - clang_type_system->Dump(s.AsRawOstream()); + clang_type_system->Dump(s.AsRawOstream(), filter); } void SymbolFilePDB::FindTypesByRegex( diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h index ea495c575f1f1..c0b25b6ee4055 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -157,7 +157,7 @@ class SymbolFilePDB : public lldb_private::SymbolFileCommon { const llvm::pdb::IPDBSession &GetPDBSession() const; - void DumpClangAST(lldb_private::Stream &s) override; + void DumpClangAST(lldb_private::Stream &s, llvm::StringRef filter) override; private: struct SecContribInfo { diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index c1917203b684c..68bb3dc8581eb 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -10,6 +10,7 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/ExprCXX.h" +#include "clang/Frontend/ASTConsumers.h" #include "llvm/Support/Casting.h" #include "llvm/Support/FormatAdapters.h" #include "llvm/Support/FormatVariadic.h" @@ -8499,8 +8500,16 @@ TypeSystemClang::dump(lldb::opaque_compiler_type_t type) const { } #endif -void TypeSystemClang::Dump(llvm::raw_ostream &output) { - GetTranslationUnitDecl()->dump(output); +void TypeSystemClang::Dump(llvm::raw_ostream &output, llvm::StringRef filter) { + auto consumer = + clang::CreateASTDumper(output, filter, + /*DumpDecls=*/true, + /*Deserialize=*/false, + /*DumpLookups=*/false, + /*DumpDeclTypes=*/false, clang::ADOF_Default); + assert(consumer); + assert(m_ast_up); + consumer->HandleTranslationUnit(*m_ast_up); } void TypeSystemClang::DumpFromSymbolFile(Stream &s, @@ -9625,10 +9634,11 @@ GetNameForIsolatedASTKind(ScratchTypeSystemClang::IsolatedASTKind kind) { llvm_unreachable("Unimplemented IsolatedASTKind?"); } -void ScratchTypeSystemClang::Dump(llvm::raw_ostream &output) { +void ScratchTypeSystemClang::Dump(llvm::raw_ostream &output, + llvm::StringRef filter) { // First dump the main scratch AST. output << "State of scratch Clang type system:\n"; - TypeSystemClang::Dump(output); + TypeSystemClang::Dump(output, filter); // Now sort the isolated sub-ASTs. typedef std::pair KeyAndTS; @@ -9643,7 +9653,7 @@ void ScratchTypeSystemClang::Dump(llvm::raw_ostream &output) { static_cast(a.first); output << "State of scratch Clang type subsystem " << GetNameForIsolatedASTKind(kind) << ":\n"; - a.second->Dump(output); + a.second->Dump(output, filter); } } diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index b9e78cc377f04..f3235da1a0f47 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -1074,7 +1074,7 @@ class TypeSystemClang : public TypeSystem { #endif /// \see lldb_private::TypeSystem::Dump - void Dump(llvm::raw_ostream &output) override; + void Dump(llvm::raw_ostream &output, llvm::StringRef filter) override; /// Dump clang AST types from the symbol file. /// @@ -1318,7 +1318,7 @@ class ScratchTypeSystemClang : public TypeSystemClang { } /// \see lldb_private::TypeSystem::Dump - void Dump(llvm::raw_ostream &output) override; + void Dump(llvm::raw_ostream &output, llvm::StringRef filter) override; UserExpression *GetUserExpression(llvm::StringRef expr, llvm::StringRef prefix, diff --git a/lldb/source/Symbol/SymbolFileOnDemand.cpp b/lldb/source/Symbol/SymbolFileOnDemand.cpp index 94979b2fb1c22..807c2124e48d9 100644 --- a/lldb/source/Symbol/SymbolFileOnDemand.cpp +++ b/lldb/source/Symbol/SymbolFileOnDemand.cpp @@ -305,13 +305,14 @@ void SymbolFileOnDemand::Dump(lldb_private::Stream &s) { return m_sym_file_impl->Dump(s); } -void SymbolFileOnDemand::DumpClangAST(lldb_private::Stream &s) { +void SymbolFileOnDemand::DumpClangAST(lldb_private::Stream &s, + llvm::StringRef filter) { if (!m_debug_info_enabled) { LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__); return; } - return m_sym_file_impl->DumpClangAST(s); + return m_sym_file_impl->DumpClangAST(s, filter); } void SymbolFileOnDemand::FindGlobalVariables(const RegularExpression ®ex, diff --git a/lldb/test/Shell/Commands/command-image-dump-ast.test b/lldb/test/Shell/Commands/command-image-dump-ast.test new file mode 100644 index 0000000000000..ca57570ab7224 --- /dev/null +++ b/lldb/test/Shell/Commands/command-image-dump-ast.test @@ -0,0 +1,70 @@ +# Test `image dump ast` command. + +# RUN: split-file %s %t +# RUN: %clang_host -g -gdwarf %t/main.cpp -o %t.out +# RUN: %lldb -x -b -s %t/commands.input %t.out -o exit 2>&1 \ +# RUN: | FileCheck %s + +#--- main.cpp + +void A() {} +void A1() {} +void BA1() {} +void AB() {} + +int main() { + A(); + A1(); + BA1(); + AB(); +} + +#--- commands.input + +break set -n main +run +expr A(); A1(); BA1(); AB() + +image dump ast + +# CHECK: image dump ast +# CHECK-DAG: FunctionDecl {{.*}} main +# CHECK-DAG: FunctionDecl {{.*}} A +# CHECK-DAG: FunctionDecl {{.*}} A1 +# CHECK-DAG: FunctionDecl {{.*}} BA1 +# CHECK-DAG: FunctionDecl {{.*}} AB + +image dump ast --filter A + +# CHECK: image dump ast --filter A +# CHECK: Dumping A +# CHECK-NOT: FunctionDecl {{.*}} main +# CHECK-DAG: FunctionDecl {{.*}} A1 +# CHECK-DAG: FunctionDecl {{.*}} BA1 +# CHECK-DAG: FunctionDecl {{.*}} AB + +image dump ast --filter A1 + +# CHECK: image dump ast --filter A1 +# CHECK: Dumping A +# CHECK-NOT: FunctionDecl {{.*}} main +# CHECK-NOT: FunctionDecl {{.*}} AB +# CHECK-DAG: FunctionDecl {{.*}} A1 +# CHECK-DAG: FunctionDecl {{.*}} BA1 + +image dump ast --filter "" + +# CHECK: image dump ast --filter "" +# CHECK-DAG: FunctionDecl {{.*}} main +# CHECK-DAG: FunctionDecl {{.*}} AB +# CHECK-DAG: FunctionDecl {{.*}} A1 +# CHECK-DAG: FunctionDecl {{.*}} BA1 + +image dump ast -f AB + +# CHECK: image dump ast -f AB +# CHECK: Dumping AB +# CHECK-NOT: FunctionDecl {{.*}} main +# CHECK-NOT: FunctionDecl {{.*}} A1 +# CHECK-NOT: FunctionDecl {{.*}} BA1 +# CHECK: FunctionDecl {{.*}} AB