https://github.com/sina-mahdavi updated https://github.com/llvm/llvm-project/pull/156756
>From 8ab5647fc5c51b42bb67ca46a063fa9815ea46f4 Mon Sep 17 00:00:00 2001 From: Sina Mahdavi <sina_mahd...@apple.com> Date: Wed, 3 Sep 2025 14:17:27 -0700 Subject: [PATCH 1/6] [Clang] Support includes translated to module imports in -header-include-filtering=direct-per-file --- clang/lib/Frontend/HeaderIncludeGen.cpp | 73 ++++++++++++++++++++----- 1 file changed, 60 insertions(+), 13 deletions(-) diff --git a/clang/lib/Frontend/HeaderIncludeGen.cpp b/clang/lib/Frontend/HeaderIncludeGen.cpp index 8ab335905f9f2..8de8d61b6262c 100644 --- a/clang/lib/Frontend/HeaderIncludeGen.cpp +++ b/clang/lib/Frontend/HeaderIncludeGen.cpp @@ -112,11 +112,17 @@ class HeaderIncludesJSONCallback : public PPCallbacks { /// an array of separate entries, one for each non-system source file used in /// the compilation showing only the direct includes and imports from that file. class HeaderIncludesDirectPerFileCallback : public PPCallbacks { + struct HeaderIncludeInfo { + SourceLocation location; + FileEntryRef file; + const Module *importedModule; + }; + SourceManager &SM; HeaderSearch &HSI; raw_ostream *OutputFile; bool OwnsOutputFile; - using DependencyMap = llvm::DenseMap<FileEntryRef, SmallVector<FileEntryRef>>; + using DependencyMap = llvm::DenseMap<FileEntryRef, SmallVector<HeaderIncludeInfo>>; DependencyMap Dependencies; public: @@ -390,18 +396,43 @@ void HeaderIncludesDirectPerFileCallback::EndOfMainFile() { std::string Str; llvm::raw_string_ostream OS(Str); llvm::json::OStream JOS(OS); - JOS.array([&] { - for (auto S = SourceFiles.begin(), SE = SourceFiles.end(); S != SE; ++S) { - JOS.object([&] { - SmallVector<FileEntryRef> &Deps = Dependencies[*S]; - JOS.attribute("source", S->getName().str()); - JOS.attributeArray("includes", [&] { - for (unsigned I = 0, N = Deps.size(); I != N; ++I) - JOS.value(Deps[I].getName().str()); + JOS.object([&] { + JOS.attribute("version", "2.0.0"); + JOS.attributeArray("dependencies", [&] { + for (auto S = SourceFiles.begin(), SE = SourceFiles.end(); S != SE; ++S) { + JOS.object([&] { + SmallVector<HeaderIncludeInfo> &Deps = Dependencies[*S]; + JOS.attribute("source", S->getName().str()); + JOS.attributeArray("includes", [&] { + for (unsigned I = 0, N = Deps.size(); I != N; ++I) { + if (!Deps[I].importedModule) { + JOS.object([&] { + PresumedLoc PLoc = SM.getPresumedLoc(Deps[I].location); + std::string locationStr = PLoc.isInvalid() ? "<invalid>" : std::to_string(PLoc.getLine()) + ":" + std::to_string(PLoc.getColumn()); + JOS.attribute("location", locationStr); + JOS.attribute("file", Deps[I].file.getName()); + }); + } + } + }); + JOS.attributeArray("imports", [&] { + for (unsigned I = 0, N = Deps.size(); I != N; ++I) { + if (Deps[I].importedModule) { + JOS.object([&] { + PresumedLoc PLoc = SM.getPresumedLoc(Deps[I].location); + std::string locationStr = PLoc.isInvalid() ? "<invalid>" : std::to_string(PLoc.getLine()) + ":" + std::to_string(PLoc.getColumn()); + JOS.attribute("location", locationStr); + JOS.attribute("module", Deps[I].importedModule->getTopLevelModuleName()); + JOS.attribute("file", Deps[I].file.getName()); + }); + } + } + }); }); - }); - } + } + }); }); + OS << "\n"; if (OutputFile->get_kind() == raw_ostream::OStreamKind::OK_FDStream) { @@ -427,7 +458,19 @@ void HeaderIncludesDirectPerFileCallback::InclusionDirective( if (!FromFile) return; - Dependencies[*FromFile].push_back(*File); + FileEntryRef headerOrModule = *File; + if (ModuleImported && SuggestedModule) { + OptionalFileEntryRef ModuleMapFile = HSI.getModuleMap().getModuleMapFileForUniquing(SuggestedModule); + if (ModuleMapFile) { + headerOrModule = *ModuleMapFile; + } + } + + Dependencies[*FromFile].push_back({ + .location = Loc, + .file = headerOrModule, + .importedModule = (ModuleImported ? SuggestedModule : nullptr) + }); } void HeaderIncludesDirectPerFileCallback::moduleImport(SourceLocation ImportLoc, @@ -448,5 +491,9 @@ void HeaderIncludesDirectPerFileCallback::moduleImport(SourceLocation ImportLoc, if (!ModuleMapFile) return; - Dependencies[*FromFile].push_back(*ModuleMapFile); + Dependencies[*FromFile].push_back({ + .location = Loc, + .file = *ModuleMapFile, + .importedModule = Imported + }); } >From c4405abf5830ed6f858d1ec17817e24418c62e81 Mon Sep 17 00:00:00 2001 From: Sina Mahdavi <sina_mahd...@apple.com> Date: Thu, 4 Sep 2025 17:34:18 -0700 Subject: [PATCH 2/6] [Clang] Include source location file name in include tracing output and fixing syntax --- clang/lib/Frontend/HeaderIncludeGen.cpp | 51 +++++++++++-------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/clang/lib/Frontend/HeaderIncludeGen.cpp b/clang/lib/Frontend/HeaderIncludeGen.cpp index 8de8d61b6262c..71047f95cfc2d 100644 --- a/clang/lib/Frontend/HeaderIncludeGen.cpp +++ b/clang/lib/Frontend/HeaderIncludeGen.cpp @@ -113,9 +113,12 @@ class HeaderIncludesJSONCallback : public PPCallbacks { /// the compilation showing only the direct includes and imports from that file. class HeaderIncludesDirectPerFileCallback : public PPCallbacks { struct HeaderIncludeInfo { - SourceLocation location; - FileEntryRef file; - const Module *importedModule; + SourceLocation Location; + FileEntryRef File; + const Module *ImportedModule; + + HeaderIncludeInfo(SourceLocation Location, FileEntryRef File, const Module *ImportedModule) + : Location(Location), File(File), ImportedModule(ImportedModule) {} }; SourceManager &SM; @@ -399,31 +402,27 @@ void HeaderIncludesDirectPerFileCallback::EndOfMainFile() { JOS.object([&] { JOS.attribute("version", "2.0.0"); JOS.attributeArray("dependencies", [&] { - for (auto S = SourceFiles.begin(), SE = SourceFiles.end(); S != SE; ++S) { + for (const auto &S : SourceFiles) { JOS.object([&] { - SmallVector<HeaderIncludeInfo> &Deps = Dependencies[*S]; - JOS.attribute("source", S->getName().str()); + SmallVector<HeaderIncludeInfo> &Deps = Dependencies[S]; + JOS.attribute("source", S.getName().str()); JOS.attributeArray("includes", [&] { for (unsigned I = 0, N = Deps.size(); I != N; ++I) { - if (!Deps[I].importedModule) { + if (!Deps[I].ImportedModule) { JOS.object([&] { - PresumedLoc PLoc = SM.getPresumedLoc(Deps[I].location); - std::string locationStr = PLoc.isInvalid() ? "<invalid>" : std::to_string(PLoc.getLine()) + ":" + std::to_string(PLoc.getColumn()); - JOS.attribute("location", locationStr); - JOS.attribute("file", Deps[I].file.getName()); + JOS.attribute("location", Deps[I].Location.printToString(SM)); + JOS.attribute("file", Deps[I].File.getName()); }); } } }); JOS.attributeArray("imports", [&] { for (unsigned I = 0, N = Deps.size(); I != N; ++I) { - if (Deps[I].importedModule) { + if (Deps[I].ImportedModule) { JOS.object([&] { - PresumedLoc PLoc = SM.getPresumedLoc(Deps[I].location); - std::string locationStr = PLoc.isInvalid() ? "<invalid>" : std::to_string(PLoc.getLine()) + ":" + std::to_string(PLoc.getColumn()); - JOS.attribute("location", locationStr); - JOS.attribute("module", Deps[I].importedModule->getTopLevelModuleName()); - JOS.attribute("file", Deps[I].file.getName()); + JOS.attribute("location", Deps[I].Location.printToString(SM)); + JOS.attribute("module", Deps[I].ImportedModule->getTopLevelModuleName()); + JOS.attribute("file", Deps[I].File.getName()); }); } } @@ -458,19 +457,16 @@ void HeaderIncludesDirectPerFileCallback::InclusionDirective( if (!FromFile) return; - FileEntryRef headerOrModule = *File; + FileEntryRef HeaderOrModule = *File; if (ModuleImported && SuggestedModule) { OptionalFileEntryRef ModuleMapFile = HSI.getModuleMap().getModuleMapFileForUniquing(SuggestedModule); if (ModuleMapFile) { - headerOrModule = *ModuleMapFile; + HeaderOrModule = *ModuleMapFile; } } - Dependencies[*FromFile].push_back({ - .location = Loc, - .file = headerOrModule, - .importedModule = (ModuleImported ? SuggestedModule : nullptr) - }); + HeaderIncludeInfo DependenciesEntry(Loc, HeaderOrModule, (ModuleImported ? SuggestedModule : nullptr)); + Dependencies[*FromFile].push_back(DependenciesEntry); } void HeaderIncludesDirectPerFileCallback::moduleImport(SourceLocation ImportLoc, @@ -491,9 +487,6 @@ void HeaderIncludesDirectPerFileCallback::moduleImport(SourceLocation ImportLoc, if (!ModuleMapFile) return; - Dependencies[*FromFile].push_back({ - .location = Loc, - .file = *ModuleMapFile, - .importedModule = Imported - }); + HeaderIncludeInfo DependenciesEntry(Loc, *ModuleMapFile, Imported); + Dependencies[*FromFile].push_back(DependenciesEntry); } >From e0c462e96da08702aed69d49ea07ba845ac2b415 Mon Sep 17 00:00:00 2001 From: Sina Mahdavi <sina_mahd...@apple.com> Date: Thu, 4 Sep 2025 19:18:51 -0700 Subject: [PATCH 3/6] [Clang] Add tests for -header-include-filtering=direct-per-file v2 output --- .../Preprocessor/Inputs/print-header-json/module.modulemap | 5 +++++ .../Inputs/print-header-json/system/module.modulemap | 4 ++++ clang/test/Preprocessor/print-header-json.c | 7 ++++++- 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 clang/test/Preprocessor/Inputs/print-header-json/module.modulemap create mode 100644 clang/test/Preprocessor/Inputs/print-header-json/system/module.modulemap diff --git a/clang/test/Preprocessor/Inputs/print-header-json/module.modulemap b/clang/test/Preprocessor/Inputs/print-header-json/module.modulemap new file mode 100644 index 0000000000000..024c43d89e278 --- /dev/null +++ b/clang/test/Preprocessor/Inputs/print-header-json/module.modulemap @@ -0,0 +1,5 @@ +module module0 { + header "header0.h" + header "header1.h" + export * +} diff --git a/clang/test/Preprocessor/Inputs/print-header-json/system/module.modulemap b/clang/test/Preprocessor/Inputs/print-header-json/system/module.modulemap new file mode 100644 index 0000000000000..8ed45ab4dcdbe --- /dev/null +++ b/clang/test/Preprocessor/Inputs/print-header-json/system/module.modulemap @@ -0,0 +1,4 @@ +module systemmodule0 { + header "system2.h" + export * +} diff --git a/clang/test/Preprocessor/print-header-json.c b/clang/test/Preprocessor/print-header-json.c index bb1830e5030d8..e9502f5512dcd 100644 --- a/clang/test/Preprocessor/print-header-json.c +++ b/clang/test/Preprocessor/print-header-json.c @@ -21,8 +21,13 @@ #include "header0.h" #include "system2.h" +// RUN: rm %t.txt +// 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 +// RUN: cat %t.txt | FileCheck %s --check-prefix=SUPPORTED_PERFILE_MODULES + // SUPPORTED: {"source":"{{[^,]*}}print-header-json.c","includes":["{{[^,]*}}system0.h","{{[^,]*}}system3.h","{{[^,]*}}system2.h"]} -// SUPPORTED_PERFILE: [{"source":"{{[^,]*}}print-header-json.c","includes":["{{[^,]*}}system0.h","{{[^,]*}}header0.h","{{[^,]*}}system2.h"]},{"source":"{{[^,]*}}header0.h","includes":["{{[^,]*}}system3.h","{{[^,]*}}header1.h","{{[^,]*}}header2.h"]}] +// 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":[]}]} +// 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"}]}]} // UNSUPPORTED0: error: unsupported combination: -header-include-format=textual and -header-include-filtering=only-direct-system // UNSUPPORTED1: error: unsupported combination: -header-include-format=json and -header-include-filtering=none >From e2dfe9e9c591a13b203fc2e8c1d0c2d70c54192a Mon Sep 17 00:00:00 2001 From: Sina Mahdavi <sinamhdv_ap...@icloud.com> Date: Mon, 15 Sep 2025 11:32:01 -0700 Subject: [PATCH 4/6] Rename HeaderOrModule in HeaderIncludeGen.cpp Co-authored-by: Jan Svoboda <j...@svoboda.ai> --- clang/lib/Frontend/HeaderIncludeGen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Frontend/HeaderIncludeGen.cpp b/clang/lib/Frontend/HeaderIncludeGen.cpp index 71047f95cfc2d..8ce7a1a85454f 100644 --- a/clang/lib/Frontend/HeaderIncludeGen.cpp +++ b/clang/lib/Frontend/HeaderIncludeGen.cpp @@ -457,7 +457,7 @@ void HeaderIncludesDirectPerFileCallback::InclusionDirective( if (!FromFile) return; - FileEntryRef HeaderOrModule = *File; + FileEntryRef HeaderOrModuleMapFile = *File; if (ModuleImported && SuggestedModule) { OptionalFileEntryRef ModuleMapFile = HSI.getModuleMap().getModuleMapFileForUniquing(SuggestedModule); if (ModuleMapFile) { >From 6c92ecd715aabe752e95a50f77aeab8afb6c1663 Mon Sep 17 00:00:00 2001 From: Sina Mahdavi <sinamhdv_ap...@icloud.com> Date: Fri, 19 Sep 2025 15:44:45 -0700 Subject: [PATCH 5/6] Fix formatting and a compile error --- clang/lib/Frontend/HeaderIncludeGen.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/clang/lib/Frontend/HeaderIncludeGen.cpp b/clang/lib/Frontend/HeaderIncludeGen.cpp index 8ce7a1a85454f..7cd9c8a3a5bd7 100644 --- a/clang/lib/Frontend/HeaderIncludeGen.cpp +++ b/clang/lib/Frontend/HeaderIncludeGen.cpp @@ -117,7 +117,8 @@ class HeaderIncludesDirectPerFileCallback : public PPCallbacks { FileEntryRef File; const Module *ImportedModule; - HeaderIncludeInfo(SourceLocation Location, FileEntryRef File, const Module *ImportedModule) + HeaderIncludeInfo(SourceLocation Location, FileEntryRef File, + const Module *ImportedModule) : Location(Location), File(File), ImportedModule(ImportedModule) {} }; @@ -125,7 +126,8 @@ class HeaderIncludesDirectPerFileCallback : public PPCallbacks { HeaderSearch &HSI; raw_ostream *OutputFile; bool OwnsOutputFile; - using DependencyMap = llvm::DenseMap<FileEntryRef, SmallVector<HeaderIncludeInfo>>; + using DependencyMap = + llvm::DenseMap<FileEntryRef, SmallVector<HeaderIncludeInfo>>; DependencyMap Dependencies; public: @@ -304,8 +306,8 @@ void HeaderIncludesCallback::FileChanged(SourceLocation Loc, } } -void HeaderIncludesCallback::FileSkipped(const FileEntryRef &SkippedFile, const - Token &FilenameTok, +void HeaderIncludesCallback::FileSkipped(const FileEntryRef &SkippedFile, + const Token &FilenameTok, SrcMgr::CharacteristicKind FileType) { if (!DepOpts.ShowSkippedHeaderIncludes) return; @@ -421,7 +423,9 @@ void HeaderIncludesDirectPerFileCallback::EndOfMainFile() { if (Deps[I].ImportedModule) { JOS.object([&] { JOS.attribute("location", Deps[I].Location.printToString(SM)); - JOS.attribute("module", Deps[I].ImportedModule->getTopLevelModuleName()); + JOS.attribute( + "module", + Deps[I].ImportedModule->getTopLevelModuleName()); JOS.attribute("file", Deps[I].File.getName()); }); } @@ -431,7 +435,7 @@ void HeaderIncludesDirectPerFileCallback::EndOfMainFile() { } }); }); - + OS << "\n"; if (OutputFile->get_kind() == raw_ostream::OStreamKind::OK_FDStream) { @@ -459,13 +463,15 @@ void HeaderIncludesDirectPerFileCallback::InclusionDirective( FileEntryRef HeaderOrModuleMapFile = *File; if (ModuleImported && SuggestedModule) { - OptionalFileEntryRef ModuleMapFile = HSI.getModuleMap().getModuleMapFileForUniquing(SuggestedModule); + OptionalFileEntryRef ModuleMapFile = + HSI.getModuleMap().getModuleMapFileForUniquing(SuggestedModule); if (ModuleMapFile) { - HeaderOrModule = *ModuleMapFile; + HeaderOrModuleMapFile = *ModuleMapFile; } } - HeaderIncludeInfo DependenciesEntry(Loc, HeaderOrModule, (ModuleImported ? SuggestedModule : nullptr)); + HeaderIncludeInfo DependenciesEntry( + Loc, HeaderOrModuleMapFile, (ModuleImported ? SuggestedModule : nullptr)); Dependencies[*FromFile].push_back(DependenciesEntry); } >From d498d91d7a4dfaf7e3093bc2626801813ed34541 Mon Sep 17 00:00:00 2001 From: Sina Mahdavi <sinamhdv_ap...@icloud.com> Date: Mon, 22 Sep 2025 00:59:48 -0700 Subject: [PATCH 6/6] Fix print-header-json tests failing on Windows because of wrong path separator --- clang/test/Preprocessor/print-header-json.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/Preprocessor/print-header-json.c b/clang/test/Preprocessor/print-header-json.c index e9502f5512dcd..f9ab26d9f147c 100644 --- a/clang/test/Preprocessor/print-header-json.c +++ b/clang/test/Preprocessor/print-header-json.c @@ -27,7 +27,7 @@ // SUPPORTED: {"source":"{{[^,]*}}print-header-json.c","includes":["{{[^,]*}}system0.h","{{[^,]*}}system3.h","{{[^,]*}}system2.h"]} // 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":[]}]} -// 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"}]}]} +// 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"}]}]} // UNSUPPORTED0: error: unsupported combination: -header-include-format=textual and -header-include-filtering=only-direct-system // UNSUPPORTED1: error: unsupported combination: -header-include-format=json and -header-include-filtering=none _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits