jansvoboda11 created this revision.
jansvoboda11 added reviewers: benlangmuir, Bigcheese.
Herald added a subscriber: ributzka.
Herald added a project: All.
jansvoboda11 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

When Clang loads a PCM that depends on another PCM describing framework module 
"FW", `ModuleMap` registers "FW" as known, without seeing the module that 
defines it (or the adjacent "FW_Private" module). Later, when looking at a 
header from "FW_Private", `ModuleMap` returns early due to having knowledge 
about "FW" and never associates that header with "FW_Private", leading to it 
being treated as textual. This behavior is caused by D150292 
<https://reviews.llvm.org/D150292>, where the scanner stops calling 
`HeaderSearch::lookupModule()` eagerly for every loaded PCM.

This patch skips an early check when trying to figure out the framework module 
for a header, which ensures the "FW" and (most importantly) "FW_Private" module 
maps can be parsed even after loading "FW" from a PCM. Note that the 
`HeaderSearch::loadModuleMapFile()` function we not call unconditionally has 
caching behavior of its own, meaning it will avoid parsing module map file 
repeatedly.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D150478

Files:
  clang/lib/Lex/HeaderSearch.cpp
  clang/test/ClangScanDeps/modules-private-framework-submodule.c


Index: clang/test/ClangScanDeps/modules-private-framework-submodule.c
===================================================================
--- /dev/null
+++ clang/test/ClangScanDeps/modules-private-framework-submodule.c
@@ -0,0 +1,54 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+//--- frameworks1/FW1.framework/Modules/module.modulemap
+framework module FW1 { header "FW1.h" }
+//--- frameworks1/FW1.framework/Headers/FW1.h
+#import <FW2/FW2.h>
+
+//--- frameworks2/FW2.framework/Modules/module.modulemap
+framework module FW2 { header "FW2.h" }
+//--- frameworks2/FW2.framework/Modules/module.private.modulemap
+framework module FW2_Private { header "FW2_Private.h" }
+//--- frameworks2/FW2.framework/Headers/FW2.h
+//--- frameworks2/FW2.framework/PrivateHeaders/FW2_Private.h
+
+//--- tu.c
+#import <FW1/FW1.h>
+#import <FW2/FW2_Private.h>
+
+//--- cdb.json.template
+[{
+  "file": "DIR/tu.c",
+  "directory": "DIR",
+  "command": "clang -fmodules -fmodules-cache-path=DIR/cache 
-fimplicit-module-maps -F DIR/frameworks1 -F DIR/frameworks2 -c DIR/tu.c -o 
DIR/tu.o"
+}]
+
+// RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json
+// RUN: clang-scan-deps -format experimental-full -compilation-database 
%t/cdb.json > %t/result.json
+// RUN: cat %t/result.json | FileCheck %s -DPREFIX=%/t
+
+// CHECK:       "translation-units": [
+// CHECK-NEXT:     {
+// CHECK-NEXT:       "commands": [
+// CHECK-NEXT:         {
+// CHECK-NEXT:           "clang-context-hash": "{{.*}}",
+// CHECK-NEXT:           "clang-module-deps": [
+// CHECK-NEXT:             {
+// CHECK-NEXT:               "context-hash": "{{.*}}",
+// CHECK-NEXT:               "module-name": "FW1"
+// CHECK-NEXT:             },
+// CHECK-NEXT:             {
+// CHECK-NEXT:               "context-hash": "{{.*}}",
+// CHECK-NEXT:               "module-name": "FW2_Private"
+// CHECK-NEXT:             }
+// CHECK-NEXT:           ],
+// CHECK:                "file-deps": [
+// CHECK-NEXT:             "[[PREFIX]]/tu.c"
+// CHECK-NEXT:           ],
+// CHECK-NEXT:           "input-file": "[[PREFIX]]/tu.c"
+// CHECK:              }
+// CHECK:            ]
+// CHECK:          }
+// CHECK:        ]
+// CHECK:      }
Index: clang/lib/Lex/HeaderSearch.cpp
===================================================================
--- clang/lib/Lex/HeaderSearch.cpp
+++ clang/lib/Lex/HeaderSearch.cpp
@@ -1774,9 +1774,6 @@
 
 Module *HeaderSearch::loadFrameworkModule(StringRef Name, DirectoryEntryRef 
Dir,
                                           bool IsSystem) {
-  if (Module *Module = ModMap.findModule(Name))
-    return Module;
-
   // Try to load a module map file.
   switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/true)) {
   case LMM_InvalidModuleMap:


Index: clang/test/ClangScanDeps/modules-private-framework-submodule.c
===================================================================
--- /dev/null
+++ clang/test/ClangScanDeps/modules-private-framework-submodule.c
@@ -0,0 +1,54 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+//--- frameworks1/FW1.framework/Modules/module.modulemap
+framework module FW1 { header "FW1.h" }
+//--- frameworks1/FW1.framework/Headers/FW1.h
+#import <FW2/FW2.h>
+
+//--- frameworks2/FW2.framework/Modules/module.modulemap
+framework module FW2 { header "FW2.h" }
+//--- frameworks2/FW2.framework/Modules/module.private.modulemap
+framework module FW2_Private { header "FW2_Private.h" }
+//--- frameworks2/FW2.framework/Headers/FW2.h
+//--- frameworks2/FW2.framework/PrivateHeaders/FW2_Private.h
+
+//--- tu.c
+#import <FW1/FW1.h>
+#import <FW2/FW2_Private.h>
+
+//--- cdb.json.template
+[{
+  "file": "DIR/tu.c",
+  "directory": "DIR",
+  "command": "clang -fmodules -fmodules-cache-path=DIR/cache -fimplicit-module-maps -F DIR/frameworks1 -F DIR/frameworks2 -c DIR/tu.c -o DIR/tu.o"
+}]
+
+// RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json
+// RUN: clang-scan-deps -format experimental-full -compilation-database %t/cdb.json > %t/result.json
+// RUN: cat %t/result.json | FileCheck %s -DPREFIX=%/t
+
+// CHECK:       "translation-units": [
+// CHECK-NEXT:     {
+// CHECK-NEXT:       "commands": [
+// CHECK-NEXT:         {
+// CHECK-NEXT:           "clang-context-hash": "{{.*}}",
+// CHECK-NEXT:           "clang-module-deps": [
+// CHECK-NEXT:             {
+// CHECK-NEXT:               "context-hash": "{{.*}}",
+// CHECK-NEXT:               "module-name": "FW1"
+// CHECK-NEXT:             },
+// CHECK-NEXT:             {
+// CHECK-NEXT:               "context-hash": "{{.*}}",
+// CHECK-NEXT:               "module-name": "FW2_Private"
+// CHECK-NEXT:             }
+// CHECK-NEXT:           ],
+// CHECK:                "file-deps": [
+// CHECK-NEXT:             "[[PREFIX]]/tu.c"
+// CHECK-NEXT:           ],
+// CHECK-NEXT:           "input-file": "[[PREFIX]]/tu.c"
+// CHECK:              }
+// CHECK:            ]
+// CHECK:          }
+// CHECK:        ]
+// CHECK:      }
Index: clang/lib/Lex/HeaderSearch.cpp
===================================================================
--- clang/lib/Lex/HeaderSearch.cpp
+++ clang/lib/Lex/HeaderSearch.cpp
@@ -1774,9 +1774,6 @@
 
 Module *HeaderSearch::loadFrameworkModule(StringRef Name, DirectoryEntryRef Dir,
                                           bool IsSystem) {
-  if (Module *Module = ModMap.findModule(Name))
-    return Module;
-
   // Try to load a module map file.
   switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/true)) {
   case LMM_InvalidModuleMap:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to