Author: Richard Smith Date: 2021-03-22T19:07:46-07:00 New Revision: 3775d811ff6dc1ed844aee7d15263a447ee18d52
URL: https://github.com/llvm/llvm-project/commit/3775d811ff6dc1ed844aee7d15263a447ee18d52 DIFF: https://github.com/llvm/llvm-project/commit/3775d811ff6dc1ed844aee7d15263a447ee18d52.diff LOG: Improve module dumping for debugging. * List inferred lists of imports in `#pragma clang __debug module_map`. * Add `#pragma clang __debug modules {all,visible,building}` to dump lists of known / visible module names or the building modules stack. Added: Modified: clang/include/clang/Basic/Module.h clang/include/clang/Lex/ModuleMap.h clang/include/clang/Lex/Preprocessor.h clang/lib/Basic/Module.cpp clang/lib/Lex/Pragma.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index 82ea1f462949a..16f34d11398af 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -637,7 +637,7 @@ class Module { } /// Print the module map for this module to the given stream. - void print(raw_ostream &OS, unsigned Indent = 0) const; + void print(raw_ostream &OS, unsigned Indent = 0, bool Dump = false) const; /// Dump the contents of this module to the given output stream. void dump() const; diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h index f6423e5b42589..64562e6760df8 100644 --- a/clang/include/clang/Lex/ModuleMap.h +++ b/clang/include/clang/Lex/ModuleMap.h @@ -696,6 +696,9 @@ class ModuleMap { module_iterator module_begin() const { return Modules.begin(); } module_iterator module_end() const { return Modules.end(); } + llvm::iterator_range<module_iterator> modules() const { + return {module_begin(), module_end()}; + } /// Cache a module load. M might be nullptr. void cacheModuleLoad(const IdentifierInfo &II, Module *M) { diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 68139cb24b31d..e34e35be30b37 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -1163,6 +1163,11 @@ class Preprocessor { return None; } + /// Get the list of submodules that we're currently building. + ArrayRef<BuildingSubmoduleInfo> getBuildingSubmodules() const { + return BuildingSubmoduleStack; + } + /// \{ /// Iterators for the macro history table. Currently defined macros have /// IdentifierInfo::hasMacroDefinition() set and an empty diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index 8730a5d5f4e70..8d26149cd39d9 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -429,7 +429,7 @@ void Module::buildVisibleModulesCache() const { } } -void Module::print(raw_ostream &OS, unsigned Indent) const { +void Module::print(raw_ostream &OS, unsigned Indent, bool Dump) const { OS.indent(Indent); if (IsFramework) OS << "framework "; @@ -535,7 +535,7 @@ void Module::print(raw_ostream &OS, unsigned Indent) const { // the module. Regular inferred submodules are OK, as we need to look at all // those header files anyway. if (!(*MI)->IsInferred || (*MI)->IsFramework) - (*MI)->print(OS, Indent + 2); + (*MI)->print(OS, Indent + 2, Dump); for (unsigned I = 0, N = Exports.size(); I != N; ++I) { OS.indent(Indent + 2); @@ -559,6 +559,13 @@ void Module::print(raw_ostream &OS, unsigned Indent) const { OS << "\n"; } + if (Dump) { + for (Module *M : Imports) { + OS.indent(Indent + 2); + llvm::errs() << "import " << M->getFullModuleName() << "\n"; + } + } + for (unsigned I = 0, N = DirectUses.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "use "; @@ -619,7 +626,7 @@ void Module::print(raw_ostream &OS, unsigned Indent) const { } LLVM_DUMP_METHOD void Module::dump() const { - print(llvm::errs()); + print(llvm::errs(), 0, true); } void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc, diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index a05df060813e7..5b42241a32c2e 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -1122,6 +1122,57 @@ struct PragmaDebugHandler : public PragmaHandler { DebugOverflowStack(); } else if (II->isStr("captured")) { HandleCaptured(PP); + } else if (II->isStr("modules")) { + struct ModuleVisitor { + Preprocessor &PP; + void visit(Module *M, bool VisibleOnly) { + SourceLocation ImportLoc = PP.getModuleImportLoc(M); + if (!VisibleOnly || ImportLoc.isValid()) { + llvm::errs() << M->getFullModuleName() << " "; + if (ImportLoc.isValid()) { + llvm::errs() << M << " visible "; + ImportLoc.print(llvm::errs(), PP.getSourceManager()); + } + llvm::errs() << "\n"; + } + for (Module *Sub : M->submodules()) { + if (!VisibleOnly || ImportLoc.isInvalid() || Sub->IsExplicit) + visit(Sub, VisibleOnly); + } + } + void visitAll(bool VisibleOnly) { + for (auto &NameAndMod : + PP.getHeaderSearchInfo().getModuleMap().modules()) + visit(NameAndMod.second, VisibleOnly); + } + } Visitor{PP}; + + Token Kind; + PP.LexUnexpandedToken(Kind); + auto *DumpII = Kind.getIdentifierInfo(); + if (!DumpII) { + PP.Diag(Kind, diag::warn_pragma_debug_missing_argument) + << II->getName(); + } else if (DumpII->isStr("all")) { + Visitor.visitAll(false); + } else if (DumpII->isStr("visible")) { + Visitor.visitAll(true); + } else if (DumpII->isStr("building")) { + for (auto &Building : PP.getBuildingSubmodules()) { + llvm::errs() << "in " << Building.M->getFullModuleName(); + if (Building.ImportLoc.isValid()) { + llvm::errs() << " imported "; + if (Building.IsPragma) + llvm::errs() << "via pragma "; + llvm::errs() << "at "; + Building.ImportLoc.print(llvm::errs(), PP.getSourceManager()); + llvm::errs() << "\n"; + } + } + } else { + PP.Diag(Tok, diag::warn_pragma_debug_unexpected_command) + << DumpII->getName(); + } } else { PP.Diag(Tok, diag::warn_pragma_debug_unexpected_command) << II->getName(); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits