]> granicus.if.org Git - clang/commitdiff
[Modules] Allow @import to reach submodules in private module maps
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Wed, 2 May 2018 02:25:03 +0000 (02:25 +0000)
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Wed, 2 May 2018 02:25:03 +0000 (02:25 +0000)
A @import targeting a top level module from a private module map file
(@import Foo_Private), would fail if there's any submodule declaration
around (module Foo.SomeSub) in the same private module map.

This happens because compileModuleImpl, when building Foo_Private, will
start with the private module map and will not parse the public one,
which leads to unsuccessful parsing of Foo.SomeSub, since top level Foo
was never parsed.

Declaring other submodules in the private module map is not common and
should usually be avoided, but it shouldn't fail to build. Canonicalize
compileModuleImpl to always look at the public module first, so that all
necessary information is available when parsing the private one.

rdar://problem/39822328

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@331322 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Frontend/CompilerInstance.cpp
test/Modules/Inputs/submodule-in-private-mmap/A.framework/Headers/A.h [new file with mode: 0644]
test/Modules/Inputs/submodule-in-private-mmap/A.framework/Headers/SomeSub.h [new file with mode: 0644]
test/Modules/Inputs/submodule-in-private-mmap/A.framework/Modules/module.modulemap [new file with mode: 0644]
test/Modules/Inputs/submodule-in-private-mmap/A.framework/Modules/module.private.modulemap [new file with mode: 0644]
test/Modules/Inputs/submodule-in-private-mmap/A.framework/PrivateHeaders/APrivate.h [new file with mode: 0644]
test/Modules/submodule-in-private-mmap.m [new file with mode: 0644]

index f57246bec098cae12bf39c70c397ac004983a130..4199cbe0f667d8b7f3cdd41caa7ed89f6012b6b2 100644 (file)
@@ -1188,6 +1188,19 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
   return !Instance.getDiagnostics().hasErrorOccurred();
 }
 
+static const FileEntry *getPublicModuleMap(const FileEntry *File,
+                                           FileManager &FileMgr) {
+  StringRef Filename = llvm::sys::path::filename(File->getName());
+  SmallString<128> PublicFilename(File->getDir()->getName());
+  if (Filename == "module_private.map")
+    llvm::sys::path::append(PublicFilename, "module.map");
+  else if (Filename == "module.private.modulemap")
+    llvm::sys::path::append(PublicFilename, "module.modulemap");
+  else
+    return nullptr;
+  return FileMgr.getFile(PublicFilename);
+}
+
 /// \brief Compile a module file for the given module, using the options 
 /// provided by the importing compiler instance. Returns true if the module
 /// was built without errors.
@@ -1204,6 +1217,13 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
   bool Result;
   if (const FileEntry *ModuleMapFile =
           ModMap.getContainingModuleMapFile(Module)) {
+    // Canonicalize compilation to start with the public module map. This is
+    // vital for submodules declarations in the private module maps to be
+    // correctly parsed when depending on a top level module in the public one.
+    if (const FileEntry *PublicMMFile = getPublicModuleMap(
+            ModuleMapFile, ImportingInstance.getFileManager()))
+      ModuleMapFile = PublicMMFile;
+
     // Use the module map where this module resides.
     Result = compileModuleImpl(
         ImportingInstance, ImportLoc, Module->getTopLevelModuleName(),
diff --git a/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Headers/A.h b/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Headers/A.h
new file mode 100644 (file)
index 0000000..975f1f0
--- /dev/null
@@ -0,0 +1 @@
+// A.h
diff --git a/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Headers/SomeSub.h b/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Headers/SomeSub.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Modules/module.modulemap b/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Modules/module.modulemap
new file mode 100644 (file)
index 0000000..afa4839
--- /dev/null
@@ -0,0 +1,3 @@
+framework module A {
+  header "A.h"
+}
diff --git a/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Modules/module.private.modulemap b/test/Modules/Inputs/submodule-in-private-mmap/A.framework/Modules/module.private.modulemap
new file mode 100644 (file)
index 0000000..1dbd9fb
--- /dev/null
@@ -0,0 +1,7 @@
+framework module A_Private {
+  header "APrivate.h"
+}
+
+module A.SomeSub {
+  header "SomeSub.h"
+}
diff --git a/test/Modules/Inputs/submodule-in-private-mmap/A.framework/PrivateHeaders/APrivate.h b/test/Modules/Inputs/submodule-in-private-mmap/A.framework/PrivateHeaders/APrivate.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/Modules/submodule-in-private-mmap.m b/test/Modules/submodule-in-private-mmap.m
new file mode 100644 (file)
index 0000000..50e5010
--- /dev/null
@@ -0,0 +1,7 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F%S/Inputs/submodule-in-private-mmap -fsyntax-only %s -Wno-private-module -verify
+
+// expected-no-diagnostics
+
+@import A.Private;
+@import A.SomeSub;