[clang] 3775d81 - Improve module dumping for debugging.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 22 19:07:57 PDT 2021
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();
More information about the cfe-commits
mailing list