From 6c2414b1c63c81bf8b88c65fbb102df35b52ab6a Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 2 Jun 2025 10:19:24 +0100 Subject: [PATCH 1/2] [clang][Frontend] Add overload to ASTPrinter that doesn't own output stream (#142163) We're planning on using the ASTPrinter in LLDB for AST dumping. But it currently takes the output stream via `unique_ptr`. In LLDB we don't have the output stream available in this form and instead it would be convenient if we could just pass a reference to the stream. This patch adds that overload. (cherry picked from commit 41d634397823d01c20db783cf18c9b0c2c41fbf4) --- clang/include/clang/Frontend/ASTConsumers.h | 5 +++++ clang/lib/Frontend/ASTConsumers.cpp | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/clang/include/clang/Frontend/ASTConsumers.h b/clang/include/clang/Frontend/ASTConsumers.h index 0e068bf5cccb5..890701b6ff188 100644 --- a/clang/include/clang/Frontend/ASTConsumers.h +++ b/clang/include/clang/Frontend/ASTConsumers.h @@ -35,6 +35,11 @@ CreateASTDumper(std::unique_ptr OS, StringRef FilterString, bool DumpDecls, bool Deserialize, bool DumpLookups, bool DumpDeclTypes, ASTDumpOutputFormat Format); +std::unique_ptr +CreateASTDumper(raw_ostream &OS, StringRef FilterString, bool DumpDecls, + bool Deserialize, bool DumpLookups, bool DumpDeclTypes, + ASTDumpOutputFormat Format); + // AST Decl node lister: prints qualified names of all filterable AST Decl // nodes. std::unique_ptr CreateASTDeclNodeLister(); diff --git a/clang/lib/Frontend/ASTConsumers.cpp b/clang/lib/Frontend/ASTConsumers.cpp index 7b58eaa04df95..99a9eb11e981e 100644 --- a/clang/lib/Frontend/ASTConsumers.cpp +++ b/clang/lib/Frontend/ASTConsumers.cpp @@ -41,6 +41,13 @@ namespace { OutputKind(K), OutputFormat(Format), FilterString(FilterString), DumpLookups(DumpLookups), DumpDeclTypes(DumpDeclTypes) {} + ASTPrinter(raw_ostream &Out, Kind K, ASTDumpOutputFormat Format, + StringRef FilterString, bool DumpLookups = false, + bool DumpDeclTypes = false) + : Out(Out), OwnedOut(nullptr), OutputKind(K), OutputFormat(Format), + FilterString(FilterString), DumpLookups(DumpLookups), + DumpDeclTypes(DumpDeclTypes) {} + void HandleTranslationUnit(ASTContext &Context) override { TranslationUnitDecl *D = Context.getTranslationUnitDecl(); @@ -175,6 +182,19 @@ clang::CreateASTDumper(std::unique_ptr Out, StringRef FilterString, Format, FilterString, DumpLookups, DumpDeclTypes); } +std::unique_ptr +clang::CreateASTDumper(raw_ostream &Out, StringRef FilterString, bool DumpDecls, + bool Deserialize, bool DumpLookups, bool DumpDeclTypes, + ASTDumpOutputFormat Format) { + assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump"); + return std::make_unique(Out, + Deserialize ? ASTPrinter::DumpFull + : DumpDecls ? ASTPrinter::Dump + : ASTPrinter::None, + Format, FilterString, DumpLookups, + DumpDeclTypes); +} + std::unique_ptr clang::CreateASTDeclNodeLister() { return std::make_unique(nullptr); } From be90a2777428d777ca7c38271991ff79eecbca60 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 2 Jun 2025 10:55:04 +0100 Subject: [PATCH 2/2] [lldb] Add filter option to AST dump command (#142164) Depends on https://github.com/llvm/llvm-project/pull/142163 This patch makes the `-ast-dump-filter` Clang option available to the `target modules dump ast` command. This allows us to selectively dump parts of the AST by name. The AST can quickly grow way too large to skim on the console. This will aid in debugging AST related issues. Example: ``` (lldb) target modules dump ast --filter func Dumping clang ast for 48 modules. Dumping func: FunctionDecl 0xc4b785008 <> func 'void (int)' extern |-ParmVarDecl 0xc4b7853d8 <> x 'int' `-AsmLabelAttr 0xc4b785358 <> Implicit "_Z4funcIiEvT_" Dumping func: FunctionDecl 0xc4b7850b8 <> func 'void (int)' implicit_instantiation extern |-TemplateArgument type 'int' | `-BuiltinType 0xc4b85b110 'int' `-ParmVarDecl 0xc4b7853d8 <> x 'int' ``` The majority of this patch is adjust the `Dump` API. The main change in behaviour is in `TypeSystemClang::Dump`, where we now use the `ASTPrinter` for dumping the `TranslationUnitDecl`. This is where the `-ast-dump-filter` functionality lives in Clang. (cherry picked from commit 0f7e10b0272bb297568075e73cf76abbf10db4f8) --- lldb/include/lldb/Symbol/SymbolFile.h | 2 +- lldb/include/lldb/Symbol/SymbolFileOnDemand.h | 2 +- lldb/include/lldb/Symbol/TypeSystem.h | 6 +- lldb/source/Commands/CommandObjectTarget.cpp | 24 +++++-- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 4 +- .../SymbolFile/DWARF/SymbolFileDWARF.h | 2 +- .../DWARF/SymbolFileDWARFDebugMap.cpp | 4 +- .../DWARF/SymbolFileDWARFDebugMap.h | 2 +- .../SymbolFile/NativePDB/PdbAstBuilder.cpp | 4 +- .../SymbolFile/NativePDB/PdbAstBuilder.h | 2 +- .../NativePDB/SymbolFileNativePDB.cpp | 4 +- .../NativePDB/SymbolFileNativePDB.h | 2 +- .../Plugins/SymbolFile/PDB/SymbolFilePDB.cpp | 4 +- .../Plugins/SymbolFile/PDB/SymbolFilePDB.h | 2 +- .../TypeSystem/Clang/TypeSystemClang.cpp | 20 ++++-- .../TypeSystem/Clang/TypeSystemClang.h | 4 +- lldb/source/Symbol/SymbolFileOnDemand.cpp | 5 +- .../Commands/command-image-dump-ast.test | 70 +++++++++++++++++++ 18 files changed, 131 insertions(+), 32 deletions(-) create mode 100644 lldb/test/Shell/Commands/command-image-dump-ast.test diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index 8d6f090605628..c6fa11a6bccc6 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -302,7 +302,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 7a366bfabec86..0c769142993c0 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 c3f32ca8d97bf..d1c336573b327 100644 --- a/lldb/include/lldb/Symbol/TypeSystem.h +++ b/lldb/include/lldb/Symbol/TypeSystem.h @@ -482,7 +482,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 446d2492caf89..322e97d88e789 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -2237,11 +2237,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(); @@ -2253,6 +2265,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", @@ -2261,7 +2275,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; @@ -2290,7 +2304,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); @@ -5290,7 +5304,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 83f4416b59d78..62be7d3f80a26 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -4355,7 +4355,7 @@ void SymbolFileDWARF::Dump(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; @@ -4363,7 +4363,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 44354594e847d..1e15f926997dc 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -299,7 +299,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 42c16b941e8d6..377ad47f7d7fb 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1280,9 +1280,9 @@ bool SymbolFileDWARFDebugMap::GetCompileOption(const char *option, return success; } -void SymbolFileDWARFDebugMap::DumpClangAST(Stream &s) { +void SymbolFileDWARFDebugMap::DumpClangAST(Stream &s, llvm::StringRef filter) { ForEachSymbolFile([&s](SymbolFileDWARF *oso_dwarf) { - oso_dwarf->DumpClangAST(s); + 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 f4b4bfb152786..44188d2abbfa3 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -139,7 +139,7 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon { std::vector GetASTData(lldb::LanguageType language) 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 b79d3e63f72b1..54d3111fe7bb6 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 4e50b5d961436..cd3f073db2327 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1640,7 +1640,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; @@ -1648,7 +1648,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 669c44aa131ed..03777678431ce 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 18f5080573f16..9dc919ae09e05 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -1446,7 +1446,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()) { @@ -1460,7 +1460,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 3dc6e391e5d83..5d046942d4ba7 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -11,6 +11,7 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" +#include "clang/Frontend/ASTConsumers.h" #include "llvm/ADT/STLForwardCompat.h" #include "llvm/Support/Casting.h" #include "llvm/Support/FormatAdapters.h" @@ -8819,8 +8820,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, @@ -10029,10 +10038,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; @@ -10047,7 +10057,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 778f444b9e1bc..d12cdf0012f27 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -1131,7 +1131,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. /// @@ -1392,7 +1392,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