aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Frontend/FrontendActions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Frontend/FrontendActions.cpp')
-rw-r--r--clang/lib/Frontend/FrontendActions.cpp103
1 files changed, 101 insertions, 2 deletions
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index ad2e603..baf3ac3 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -11,6 +11,7 @@
#include "clang/AST/Decl.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangStandard.h"
+#include "clang/Basic/Module.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/CompilerInstance.h"
@@ -24,6 +25,7 @@
#include "clang/Sema/TemplateInstCallback.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTWriter.h"
+#include "clang/Serialization/ModuleFile.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -806,7 +808,25 @@ bool DumpModuleInfoAction::BeginInvocation(CompilerInstance &CI) {
return true;
}
+static StringRef ModuleKindName(Module::ModuleKind MK) {
+ switch (MK) {
+ case Module::ModuleMapModule:
+ return "Module Map Module";
+ case Module::ModuleInterfaceUnit:
+ return "Interface Unit";
+ case Module::ModulePartitionInterface:
+ return "Partition Interface";
+ case Module::ModulePartitionImplementation:
+ return "Partition Implementation";
+ case Module::GlobalModuleFragment:
+ return "Global Module Fragment";
+ case Module::PrivateModuleFragment:
+ return "Private Module Fragment";
+ }
+}
+
void DumpModuleInfoAction::ExecuteAction() {
+ assert(isCurrentFileAST() && "dumping non-AST?");
// Set up the output file.
std::unique_ptr<llvm::raw_fd_ostream> OutFile;
StringRef OutputFileName = getCompilerInstance().getFrontendOpts().OutputFile;
@@ -827,8 +847,87 @@ void DumpModuleInfoAction::ExecuteAction() {
Preprocessor &PP = getCompilerInstance().getPreprocessor();
DumpModuleInfoListener Listener(Out);
- HeaderSearchOptions &HSOpts =
- PP.getHeaderSearchInfo().getHeaderSearchOpts();
+ HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();
+
+ // The FrontendAction::BeginSourceFile () method loads the AST so that much
+ // of the information is already available and modules should have been
+ // loaded.
+
+ const LangOptions &LO = getCurrentASTUnit().getLangOpts();
+ if (LO.CPlusPlusModules && !LO.CurrentModule.empty()) {
+
+ ASTReader *R = getCurrentASTUnit().getASTReader().get();
+ unsigned SubModuleCount = R->getTotalNumSubmodules();
+ serialization::ModuleFile &MF = R->getModuleManager().getPrimaryModule();
+ Out << " ====== C++20 Module structure ======\n";
+
+ if (MF.ModuleName != LO.CurrentModule)
+ Out << " Mismatched module names : " << MF.ModuleName << " and "
+ << LO.CurrentModule << "\n";
+
+ struct SubModInfo {
+ unsigned Idx;
+ Module *Mod;
+ Module::ModuleKind Kind;
+ std::string &Name;
+ bool Seen;
+ };
+ std::map<std::string, SubModInfo> SubModMap;
+ auto PrintSubMapEntry = [&](std::string Name, Module::ModuleKind Kind) {
+ Out << " " << ModuleKindName(Kind) << " '" << Name << "'";
+ auto I = SubModMap.find(Name);
+ if (I == SubModMap.end())
+ Out << " was not found in the sub modules!\n";
+ else {
+ I->second.Seen = true;
+ Out << " is at index #" << I->second.Idx << "\n";
+ }
+ };
+ Module *Primary = nullptr;
+ for (unsigned Idx = 0; Idx <= SubModuleCount; ++Idx) {
+ Module *M = R->getModule(Idx);
+ if (!M)
+ continue;
+ if (M->Name == LO.CurrentModule) {
+ Primary = M;
+ Out << " " << ModuleKindName(M->Kind) << " '" << LO.CurrentModule
+ << "' is the Primary Module at index #" << Idx << "\n";
+ SubModMap.insert({M->Name, {Idx, M, M->Kind, M->Name, true}});
+ } else
+ SubModMap.insert({M->Name, {Idx, M, M->Kind, M->Name, false}});
+ }
+ if (Primary) {
+ if (!Primary->submodules().empty())
+ Out << " Sub Modules:\n";
+ for (auto MI : Primary->submodules()) {
+ PrintSubMapEntry(MI->Name, MI->Kind);
+ }
+ if (!Primary->Imports.empty())
+ Out << " Imports:\n";
+ for (auto IMP : Primary->Imports) {
+ PrintSubMapEntry(IMP->Name, IMP->Kind);
+ }
+ if (!Primary->Exports.empty())
+ Out << " Exports:\n";
+ for (unsigned MN = 0, N = Primary->Exports.size(); MN != N; ++MN) {
+ if (Module *M = Primary->Exports[MN].getPointer()) {
+ PrintSubMapEntry(M->Name, M->Kind);
+ }
+ }
+ }
+ // Now let's print out any modules we did not see as part of the Primary.
+ for (auto SM : SubModMap) {
+ if (!SM.second.Seen && SM.second.Mod) {
+ Out << " " << ModuleKindName(SM.second.Kind) << " '" << SM.first
+ << "' at index #" << SM.second.Idx
+ << " has no direct reference in the Primary\n";
+ }
+ }
+ Out << " ====== ======\n";
+ }
+
+ // The reminder of the output is produced from the listener as the AST
+ // FileCcontrolBlock is (re-)parsed.
ASTReader::readASTFileControlBlock(
getCurrentFile(), FileMgr, getCompilerInstance().getPCHContainerReader(),
/*FindModuleFileExtensions=*/true, Listener,