Skip to content

Commit 8df194f

Browse files
authored
[Clang] Support includes translated to module imports in -header-include-filtering=direct-per-file (llvm#156756)
This PR is a follow-up to llvm#137087 that extends the output format generated by -header-include-filtering=direct-per-file to include information about the source location where those include/imports happended, as well as include information about the imported module when an include is translated to a module import.
1 parent ef5e5ef commit 8df194f

File tree

4 files changed

+76
-16
lines changed

4 files changed

+76
-16
lines changed

clang/lib/Frontend/HeaderIncludeGen.cpp

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,22 @@ class HeaderIncludesJSONCallback : public PPCallbacks {
112112
/// an array of separate entries, one for each non-system source file used in
113113
/// the compilation showing only the direct includes and imports from that file.
114114
class HeaderIncludesDirectPerFileCallback : public PPCallbacks {
115+
struct HeaderIncludeInfo {
116+
SourceLocation Location;
117+
FileEntryRef File;
118+
const Module *ImportedModule;
119+
120+
HeaderIncludeInfo(SourceLocation Location, FileEntryRef File,
121+
const Module *ImportedModule)
122+
: Location(Location), File(File), ImportedModule(ImportedModule) {}
123+
};
124+
115125
SourceManager &SM;
116126
HeaderSearch &HSI;
117127
raw_ostream *OutputFile;
118128
bool OwnsOutputFile;
119-
using DependencyMap = llvm::DenseMap<FileEntryRef, SmallVector<FileEntryRef>>;
129+
using DependencyMap =
130+
llvm::DenseMap<FileEntryRef, SmallVector<HeaderIncludeInfo>>;
120131
DependencyMap Dependencies;
121132

122133
public:
@@ -295,8 +306,8 @@ void HeaderIncludesCallback::FileChanged(SourceLocation Loc,
295306
}
296307
}
297308

298-
void HeaderIncludesCallback::FileSkipped(const FileEntryRef &SkippedFile, const
299-
Token &FilenameTok,
309+
void HeaderIncludesCallback::FileSkipped(const FileEntryRef &SkippedFile,
310+
const Token &FilenameTok,
300311
SrcMgr::CharacteristicKind FileType) {
301312
if (!DepOpts.ShowSkippedHeaderIncludes)
302313
return;
@@ -390,18 +401,41 @@ void HeaderIncludesDirectPerFileCallback::EndOfMainFile() {
390401
std::string Str;
391402
llvm::raw_string_ostream OS(Str);
392403
llvm::json::OStream JOS(OS);
393-
JOS.array([&] {
394-
for (auto S = SourceFiles.begin(), SE = SourceFiles.end(); S != SE; ++S) {
395-
JOS.object([&] {
396-
SmallVector<FileEntryRef> &Deps = Dependencies[*S];
397-
JOS.attribute("source", S->getName().str());
398-
JOS.attributeArray("includes", [&] {
399-
for (unsigned I = 0, N = Deps.size(); I != N; ++I)
400-
JOS.value(Deps[I].getName().str());
404+
JOS.object([&] {
405+
JOS.attribute("version", "2.0.0");
406+
JOS.attributeArray("dependencies", [&] {
407+
for (const auto &S : SourceFiles) {
408+
JOS.object([&] {
409+
SmallVector<HeaderIncludeInfo> &Deps = Dependencies[S];
410+
JOS.attribute("source", S.getName().str());
411+
JOS.attributeArray("includes", [&] {
412+
for (unsigned I = 0, N = Deps.size(); I != N; ++I) {
413+
if (!Deps[I].ImportedModule) {
414+
JOS.object([&] {
415+
JOS.attribute("location", Deps[I].Location.printToString(SM));
416+
JOS.attribute("file", Deps[I].File.getName());
417+
});
418+
}
419+
}
420+
});
421+
JOS.attributeArray("imports", [&] {
422+
for (unsigned I = 0, N = Deps.size(); I != N; ++I) {
423+
if (Deps[I].ImportedModule) {
424+
JOS.object([&] {
425+
JOS.attribute("location", Deps[I].Location.printToString(SM));
426+
JOS.attribute(
427+
"module",
428+
Deps[I].ImportedModule->getTopLevelModuleName());
429+
JOS.attribute("file", Deps[I].File.getName());
430+
});
431+
}
432+
}
433+
});
401434
});
402-
});
403-
}
435+
}
436+
});
404437
});
438+
405439
OS << "\n";
406440

407441
if (OutputFile->get_kind() == raw_ostream::OStreamKind::OK_FDStream) {
@@ -427,7 +461,18 @@ void HeaderIncludesDirectPerFileCallback::InclusionDirective(
427461
if (!FromFile)
428462
return;
429463

430-
Dependencies[*FromFile].push_back(*File);
464+
FileEntryRef HeaderOrModuleMapFile = *File;
465+
if (ModuleImported && SuggestedModule) {
466+
OptionalFileEntryRef ModuleMapFile =
467+
HSI.getModuleMap().getModuleMapFileForUniquing(SuggestedModule);
468+
if (ModuleMapFile) {
469+
HeaderOrModuleMapFile = *ModuleMapFile;
470+
}
471+
}
472+
473+
HeaderIncludeInfo DependenciesEntry(
474+
Loc, HeaderOrModuleMapFile, (ModuleImported ? SuggestedModule : nullptr));
475+
Dependencies[*FromFile].push_back(DependenciesEntry);
431476
}
432477

433478
void HeaderIncludesDirectPerFileCallback::moduleImport(SourceLocation ImportLoc,
@@ -448,5 +493,6 @@ void HeaderIncludesDirectPerFileCallback::moduleImport(SourceLocation ImportLoc,
448493
if (!ModuleMapFile)
449494
return;
450495

451-
Dependencies[*FromFile].push_back(*ModuleMapFile);
496+
HeaderIncludeInfo DependenciesEntry(Loc, *ModuleMapFile, Imported);
497+
Dependencies[*FromFile].push_back(DependenciesEntry);
452498
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module module0 {
2+
header "header0.h"
3+
header "header1.h"
4+
export *
5+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module systemmodule0 {
2+
header "system2.h"
3+
export *
4+
}

clang/test/Preprocessor/print-header-json.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,13 @@
2121
#include "header0.h"
2222
#include "system2.h"
2323

24+
// RUN: rm %t.txt
25+
// RUN: env CC_PRINT_HEADERS_FORMAT=json CC_PRINT_HEADERS_FILTERING=direct-per-file CC_PRINT_HEADERS_FILE=%t.txt %clang -fsyntax-only -I %S/Inputs/print-header-json -isystem %S/Inputs/print-header-json/system -fmodules -fimplicit-module-maps -fmodules-cache-path=%t %s -o /dev/null
26+
// RUN: cat %t.txt | FileCheck %s --check-prefix=SUPPORTED_PERFILE_MODULES
27+
2428
// SUPPORTED: {"source":"{{[^,]*}}print-header-json.c","includes":["{{[^,]*}}system0.h","{{[^,]*}}system3.h","{{[^,]*}}system2.h"]}
25-
// SUPPORTED_PERFILE: [{"source":"{{[^,]*}}print-header-json.c","includes":["{{[^,]*}}system0.h","{{[^,]*}}header0.h","{{[^,]*}}system2.h"]},{"source":"{{[^,]*}}header0.h","includes":["{{[^,]*}}system3.h","{{[^,]*}}header1.h","{{[^,]*}}header2.h"]}]
29+
// SUPPORTED_PERFILE: {"version":"2.0.0","dependencies":[{"source":"{{[^,]*}}print-header-json.c","includes":[{"location":"{{[^,]*}}print-header-json.c:20:1","file":"{{[^,]*}}system0.h"},{"location":"{{[^,]*}}print-header-json.c:21:1","file":"{{[^,]*}}header0.h"},{"location":"{{[^,]*}}print-header-json.c:22:1","file":"{{[^,]*}}system2.h"}],"imports":[]},{"source":"{{[^,]*}}header0.h","includes":[{"location":"{{[^,]*}}header0.h:1:1","file":"{{[^,]*}}system3.h"},{"location":"{{[^,]*}}header0.h:2:1","file":"{{[^,]*}}header1.h"},{"location":"{{[^,]*}}header0.h:3:1","file":"{{[^,]*}}header2.h"}],"imports":[]}]}
30+
// SUPPORTED_PERFILE_MODULES: {"version":"2.0.0","dependencies":[{"source":"{{[^,]*}}print-header-json.c","includes":[{"location":"{{[^,]*}}print-header-json.c:20:1","file":"{{[^,]*}}system0.h"}],"imports":[{"location":"{{[^,]*}}print-header-json.c:21:1","module":"module0","file":"{{[^,]*}}print-header-json{{[\/\\]+}}module.modulemap"},{"location":"{{[^,]*}}print-header-json.c:22:1","module":"systemmodule0","file":"{{[^,]*}}print-header-json{{[\/\\]+}}system{{[\/\\]+}}module.modulemap"}]}]}
2631

2732
// UNSUPPORTED0: error: unsupported combination: -header-include-format=textual and -header-include-filtering=only-direct-system
2833
// UNSUPPORTED1: error: unsupported combination: -header-include-format=json and -header-include-filtering=none

0 commit comments

Comments
 (0)