Index: clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp =================================================================== --- clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -170,8 +170,15 @@ if (!Instance.getPreprocessorOpts().ImplicitPCHInclude.empty()) MDC.FileDeps.push_back(Instance.getPreprocessorOpts().ImplicitPCHInclude); - for (const Module *M : DirectModularDeps) + for (const Module *M : DirectModularDeps) { + // A top-level module might not be actually imported as a module when + // -fmodule-name is used to compile a translation unit that imports this + // module. In that case it can be skipped. The appropriate header + // dependencies will still be reported as expected. + if (!M->getASTFile()) + continue; handleTopLevelModule(M); + } MDC.Consumer.handleDependencyOutputOpts(*MDC.Opts); Index: clang/test/ClangScanDeps/Inputs/header3.h =================================================================== --- /dev/null +++ clang/test/ClangScanDeps/Inputs/header3.h @@ -0,0 +1,2 @@ +// import another header from the same module +#include "header.h" Index: clang/test/ClangScanDeps/Inputs/module.modulemap =================================================================== --- clang/test/ClangScanDeps/Inputs/module.modulemap +++ clang/test/ClangScanDeps/Inputs/module.modulemap @@ -5,3 +5,8 @@ module header2 { header "header2.h" } + +module header3 { + header "header.h" + header "header3.h" +} Index: clang/test/ClangScanDeps/Inputs/module_fmodule_name_cdb.json =================================================================== --- /dev/null +++ clang/test/ClangScanDeps/Inputs/module_fmodule_name_cdb.json @@ -0,0 +1,7 @@ +[ +{ + "directory": "DIR", + "command": "clang -E DIR/modules-fmodule-name-no-module-built.m -IInputs -D INCLUDE_HEADER2 -MD -MF DIR/modules_cdb.d -fmodules -fcxx-modules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fmodule-name=header3 -fimplicit-module-maps", + "file": "DIR/modules-fmodule-name-no-module-built.m" +} +] Index: clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m =================================================================== --- /dev/null +++ clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m @@ -0,0 +1,59 @@ +// RUN: rm -rf %t.dir +// RUN: rm -rf %t.cdb +// RUN: mkdir -p %t.dir +// RUN: cp %s %t.dir/modules-fmodule-name-no-module-built.m +// RUN: mkdir %t.dir/Inputs +// RUN: cp %S/Inputs/header.h %t.dir/Inputs/header.h +// RUN: cp %S/Inputs/header2.h %t.dir/Inputs/header2.h +// RUN: cp %S/Inputs/header3.h %t.dir/Inputs/header3.h +// RUN: cp %S/Inputs/module.modulemap %t.dir/Inputs/module.modulemap +// RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/module_fmodule_name_cdb.json > %t.cdb + +// RUN: echo %t.dir > %t.result +// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -format experimental-full \ +// RUN: -generate-modules-path-args -mode preprocess-minimized-sources >> %t.result +// RUN: cat %t.result | sed 's:\\\\\?:/:g' | FileCheck --check-prefixes=CHECK %s + +#import "header3.h" +#import "header.h" + +// CHECK: [[PREFIX:.*]] +// CHECK-NEXT: { +// CHECK-NEXT: "modules": [ +// CHECK-NEXT: { +// CHECK-NEXT: "clang-module-deps": [] +// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/Inputs/module.modulemap", +// CHECK-NEXT: "command-line": [ +// CHECK: ], +// CHECK-NEXT: "context-hash": "[[HASH_H2:[A-Z0-9]+]]", +// CHECK-NEXT: "file-deps": [ +// CHECK-NEXT: "[[PREFIX]]/Inputs/header2.h", +// CHECK-NEXT: "[[PREFIX]]/Inputs/module.modulemap" +// CHECK-NEXT: ], +// CHECK-NEXT: "name": "header2" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "translation-units": [ +// CHECK-NEXT: { +// CHECK-NEXT: "clang-context-hash": "[[HASH_TU:[A-Z0-9]+]]", +// CHECK-NEXT: "clang-module-deps": [ +// CHECK-NEXT: { +// CHECK-NEXT: "context-hash": "[[HASH_H2]]", +// CHECK-NEXT: "module-name": "header2" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "command-line": [ +// CHECK-NEXT: "-fno-implicit-modules" +// CHECK-NEXT: "-fno-implicit-module-maps" +// CHECK-NEXT: "-fmodule-file=[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H2]]/header2-{{[A-Z0-9]+}}.pcm" +// CHECK-NEXT: "-fmodule-map-file=[[PREFIX]]/Inputs/module.modulemap" +// CHECK-NEXT: ], +// CHECK-NEXT: "file-deps": [ +// CHECK-NEXT: "[[PREFIX]]/modules-fmodule-name-no-module-built.m" +// CHECK-NEXT: "[[PREFIX]]/Inputs/header3.h" +// CHECK-NEXT: "[[PREFIX]]/Inputs/header.h" +// CHECK-NEXT: ], +// CHECK-NEXT: "input-file": "[[PREFIX]]/modules-fmodule-name-no-module-built.m" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }