[PATCH] D147477: [clang][modules] Handle explicit modules when checking for .Private -> _Private

2023-04-04 Thread Ben Langmuir via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG8ec36e6956cb: [clang][modules] Handle explicit modules when 
checking for .Private - _Private (authored by benlangmuir).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D147477/new/

https://reviews.llvm.org/D147477

Files:
  clang/lib/Frontend/CompilerInstance.cpp
  clang/test/Modules/implicit-private-with-submodule-explicit.m


Index: clang/test/Modules/implicit-private-with-submodule-explicit.m
===
--- /dev/null
+++ clang/test/Modules/implicit-private-with-submodule-explicit.m
@@ -0,0 +1,31 @@
+// Checks that the use of .Private to refer to _Private modules works with an
+// explicit module.
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module 
-fmodule-name=A %t/module.modulemap -o %t/A.pcm
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module 
-fmodule-name=A_Private %t/module.modulemap -o %t/A_Private.pcm
+
+// Check lazily-loaded module
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules 
-fmodule-file=A=%t/A.pcm -fmodule-file=A_Private=%t/A_Private.pcm -fsyntax-only 
%t/tu.m
+
+// Check eagerly-loaded module
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules 
-fmodule-file=%t/A.pcm -fmodule-file=%t/A_Private.pcm -fsyntax-only %t/tu.m
+
+//--- module.modulemap
+module A { header "a.h" }
+module A_Private { header "priv.h" }
+
+//--- a.h
+
+//--- priv.h
+void priv(void);
+
+//--- tu.m
+@import A.Private; // expected-warning{{no submodule named 'Private' in module 
'A'; using top level 'A_Private'}}
+// expected-note@*:* {{defined here}}
+
+void tu(void) {
+  priv();
+}
\ No newline at end of file
Index: clang/lib/Frontend/CompilerInstance.cpp
===
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -2026,8 +2026,12 @@
   PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
   PrivPath.push_back(std::make_pair(, Path[0].second));
 
+  std::string FileName;
+  // If there is a modulemap module or prebuilt module, load it.
   if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, ImportLoc, 
true,
- !IsInclusionDirective))
+ !IsInclusionDirective) ||
+  selectModuleSource(nullptr, PrivateModule, FileName, BuiltModules,
+ PP->getHeaderSearchInfo()) != MS_ModuleNotFound)
 Sub = loadModule(ImportLoc, PrivPath, Visibility, 
IsInclusionDirective);
   if (Sub) {
 MapPrivateSubModToTopLevel = true;


Index: clang/test/Modules/implicit-private-with-submodule-explicit.m
===
--- /dev/null
+++ clang/test/Modules/implicit-private-with-submodule-explicit.m
@@ -0,0 +1,31 @@
+// Checks that the use of .Private to refer to _Private modules works with an
+// explicit module.
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module -fmodule-name=A %t/module.modulemap -o %t/A.pcm
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module -fmodule-name=A_Private %t/module.modulemap -o %t/A_Private.pcm
+
+// Check lazily-loaded module
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules -fmodule-file=A=%t/A.pcm -fmodule-file=A_Private=%t/A_Private.pcm -fsyntax-only %t/tu.m
+
+// Check eagerly-loaded module
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules -fmodule-file=%t/A.pcm -fmodule-file=%t/A_Private.pcm -fsyntax-only %t/tu.m
+
+//--- module.modulemap
+module A { header "a.h" }
+module A_Private { header "priv.h" }
+
+//--- a.h
+
+//--- priv.h
+void priv(void);
+
+//--- tu.m
+@import A.Private; // expected-warning{{no submodule named 'Private' in module 'A'; using top level 'A_Private'}}
+// expected-note@*:* {{defined here}}
+
+void tu(void) {
+  priv();
+}
\ No newline at end of file
Index: clang/lib/Frontend/CompilerInstance.cpp
===
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -2026,8 +2026,12 @@
   PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
   PrivPath.push_back(std::make_pair(, Path[0].second));
 
+  std::string FileName;
+  // If there is a modulemap module or prebuilt module, load it.
   if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, ImportLoc, true,
- !IsInclusionDirective))
+ !IsInclusionDirective) ||
+  

[PATCH] D147477: [clang][modules] Handle explicit modules when checking for .Private -> _Private

2023-04-03 Thread Jan Svoboda via Phabricator via cfe-commits
jansvoboda11 accepted this revision.
jansvoboda11 added a comment.
This revision is now accepted and ready to land.

LGTM!


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D147477/new/

https://reviews.llvm.org/D147477

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D147477: [clang][modules] Handle explicit modules when checking for .Private -> _Private

2023-04-03 Thread Ben Langmuir via Phabricator via cfe-commits
benlangmuir updated this revision to Diff 510629.
benlangmuir added a comment.

Upload correct diff this time


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D147477/new/

https://reviews.llvm.org/D147477

Files:
  clang/lib/Frontend/CompilerInstance.cpp
  clang/test/Modules/implicit-private-with-submodule-explicit.m


Index: clang/test/Modules/implicit-private-with-submodule-explicit.m
===
--- /dev/null
+++ clang/test/Modules/implicit-private-with-submodule-explicit.m
@@ -0,0 +1,31 @@
+// Checks that the use of .Private to refer to _Private modules works with an
+// explicit module.
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module 
-fmodule-name=A %t/module.modulemap -o %t/A.pcm
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module 
-fmodule-name=A_Private %t/module.modulemap -o %t/A_Private.pcm
+
+// Check lazily-loaded module
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules 
-fmodule-file=A=%t/A.pcm -fmodule-file=A_Private=%t/A_Private.pcm -fsyntax-only 
%t/tu.m
+
+// Check eagerly-loaded module
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules 
-fmodule-file=%t/A.pcm -fmodule-file=%t/A_Private.pcm -fsyntax-only %t/tu.m
+
+//--- module.modulemap
+module A { header "a.h" }
+module A_Private { header "priv.h" }
+
+//--- a.h
+
+//--- priv.h
+void priv(void);
+
+//--- tu.m
+@import A.Private; // expected-warning{{no submodule named 'Private' in module 
'A'; using top level 'A_Private'}}
+// expected-note@*:* {{defined here}}
+
+void tu(void) {
+  priv();
+}
\ No newline at end of file
Index: clang/lib/Frontend/CompilerInstance.cpp
===
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -2026,8 +2026,12 @@
   PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
   PrivPath.push_back(std::make_pair(, Path[0].second));
 
+  std::string FileName;
+  // If there is a modulemap module or prebuilt module, load it.
   if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, ImportLoc, 
true,
- !IsInclusionDirective))
+ !IsInclusionDirective) ||
+  selectModuleSource(nullptr, PrivateModule, FileName, BuiltModules,
+ PP->getHeaderSearchInfo()) != MS_ModuleNotFound)
 Sub = loadModule(ImportLoc, PrivPath, Visibility, 
IsInclusionDirective);
   if (Sub) {
 MapPrivateSubModToTopLevel = true;


Index: clang/test/Modules/implicit-private-with-submodule-explicit.m
===
--- /dev/null
+++ clang/test/Modules/implicit-private-with-submodule-explicit.m
@@ -0,0 +1,31 @@
+// Checks that the use of .Private to refer to _Private modules works with an
+// explicit module.
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module -fmodule-name=A %t/module.modulemap -o %t/A.pcm
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module -fmodule-name=A_Private %t/module.modulemap -o %t/A_Private.pcm
+
+// Check lazily-loaded module
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules -fmodule-file=A=%t/A.pcm -fmodule-file=A_Private=%t/A_Private.pcm -fsyntax-only %t/tu.m
+
+// Check eagerly-loaded module
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules -fmodule-file=%t/A.pcm -fmodule-file=%t/A_Private.pcm -fsyntax-only %t/tu.m
+
+//--- module.modulemap
+module A { header "a.h" }
+module A_Private { header "priv.h" }
+
+//--- a.h
+
+//--- priv.h
+void priv(void);
+
+//--- tu.m
+@import A.Private; // expected-warning{{no submodule named 'Private' in module 'A'; using top level 'A_Private'}}
+// expected-note@*:* {{defined here}}
+
+void tu(void) {
+  priv();
+}
\ No newline at end of file
Index: clang/lib/Frontend/CompilerInstance.cpp
===
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -2026,8 +2026,12 @@
   PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
   PrivPath.push_back(std::make_pair(, Path[0].second));
 
+  std::string FileName;
+  // If there is a modulemap module or prebuilt module, load it.
   if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, ImportLoc, true,
- !IsInclusionDirective))
+ !IsInclusionDirective) ||
+  selectModuleSource(nullptr, PrivateModule, FileName, BuiltModules,
+ PP->getHeaderSearchInfo()) != MS_ModuleNotFound)
 

[PATCH] D147477: [clang][modules] Handle explicit modules when checking for .Private -> _Private

2023-04-03 Thread Ben Langmuir via Phabricator via cfe-commits
benlangmuir updated this revision to Diff 510628.
benlangmuir added a comment.

Also test eagerly-loaded pcm


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D147477/new/

https://reviews.llvm.org/D147477

Files:
  clang/lib/Frontend/CompilerInstance.cpp
  clang/test/Modules/implicit-private-with-submodule-explicit.m


Index: clang/test/Modules/implicit-private-with-submodule-explicit.m
===
--- /dev/null
+++ clang/test/Modules/implicit-private-with-submodule-explicit.m
@@ -0,0 +1,31 @@
+// Checks that the use of .Private to refer to _Private modules works with an
+// explicit module.
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module 
-fmodule-name=A %t/module.modulemap -o %t/A.pcm
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module 
-fmodule-name=A_Private %t/module.modulemap -o %t/A_Private.pcm
+
+// Check lazily-loaded module
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules 
-fmodule-file=A=%t/A.pcm -fmodule-file=A_Private=%t/A_Private.pcm -fsyntax-only 
%t/tu.m
+
+// Check eagerly-loaded module
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules 
-fmodule-file=A=%t/A.pcm -fmodule-file=%t/A_Private.pcm -fsyntax-only %t/tu.m
+
+//--- module.modulemap
+module A { header "a.h" }
+module A_Private { header "priv.h" }
+
+//--- a.h
+
+//--- priv.h
+void priv(void);
+
+//--- tu.m
+@import A.Private; // expected-warning{{no submodule named 'Private' in module 
'A'; using top level 'A_Private'}}
+// expected-note@*:* {{defined here}}
+
+void tu(void) {
+  priv();
+}
\ No newline at end of file
Index: clang/lib/Frontend/CompilerInstance.cpp
===
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -2026,8 +2026,12 @@
   PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
   PrivPath.push_back(std::make_pair(, Path[0].second));
 
+  std::string FileName;
+  // If there is a modulemap module or prebuilt module, load it.
   if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, ImportLoc, 
true,
- !IsInclusionDirective))
+ !IsInclusionDirective) ||
+  selectModuleSource(nullptr, PrivateModule, FileName, BuiltModules,
+ PP->getHeaderSearchInfo()) != MS_ModuleNotFound)
 Sub = loadModule(ImportLoc, PrivPath, Visibility, 
IsInclusionDirective);
   if (Sub) {
 MapPrivateSubModToTopLevel = true;


Index: clang/test/Modules/implicit-private-with-submodule-explicit.m
===
--- /dev/null
+++ clang/test/Modules/implicit-private-with-submodule-explicit.m
@@ -0,0 +1,31 @@
+// Checks that the use of .Private to refer to _Private modules works with an
+// explicit module.
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module -fmodule-name=A %t/module.modulemap -o %t/A.pcm
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module -fmodule-name=A_Private %t/module.modulemap -o %t/A_Private.pcm
+
+// Check lazily-loaded module
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules -fmodule-file=A=%t/A.pcm -fmodule-file=A_Private=%t/A_Private.pcm -fsyntax-only %t/tu.m
+
+// Check eagerly-loaded module
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules -fmodule-file=A=%t/A.pcm -fmodule-file=%t/A_Private.pcm -fsyntax-only %t/tu.m
+
+//--- module.modulemap
+module A { header "a.h" }
+module A_Private { header "priv.h" }
+
+//--- a.h
+
+//--- priv.h
+void priv(void);
+
+//--- tu.m
+@import A.Private; // expected-warning{{no submodule named 'Private' in module 'A'; using top level 'A_Private'}}
+// expected-note@*:* {{defined here}}
+
+void tu(void) {
+  priv();
+}
\ No newline at end of file
Index: clang/lib/Frontend/CompilerInstance.cpp
===
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -2026,8 +2026,12 @@
   PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
   PrivPath.push_back(std::make_pair(, Path[0].second));
 
+  std::string FileName;
+  // If there is a modulemap module or prebuilt module, load it.
   if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, ImportLoc, true,
- !IsInclusionDirective))
+ !IsInclusionDirective) ||
+  selectModuleSource(nullptr, PrivateModule, FileName, BuiltModules,
+ PP->getHeaderSearchInfo()) != 

[PATCH] D147477: [clang][modules] Handle explicit modules when checking for .Private -> _Private

2023-04-03 Thread Jan Svoboda via Phabricator via cfe-commits
jansvoboda11 added inline comments.



Comment at: clang/test/Modules/implicit-private-with-submodule-explicit.m:9
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module 
-fmodule-name=A_Private %t/module.modulemap -o %t/A_Private.pcm
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules 
-fmodule-file=A=%t/A.pcm -fmodule-file=A_Private=%t/A_Private.pcm -fsyntax-only 
%t/tu.m
+

Can we also test the `-fmodule-file=` mode? I assume it doesn't go 
through the changed code path, but having extra test coverage could be useful.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D147477/new/

https://reviews.llvm.org/D147477

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D147477: [clang][modules] Handle explicit modules when checking for .Private -> _Private

2023-04-03 Thread Ben Langmuir via Phabricator via cfe-commits
benlangmuir updated this revision to Diff 510623.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D147477/new/

https://reviews.llvm.org/D147477

Files:
  clang/lib/Frontend/CompilerInstance.cpp
  clang/test/Modules/implicit-private-with-submodule-explicit.m


Index: clang/test/Modules/implicit-private-with-submodule-explicit.m
===
--- /dev/null
+++ clang/test/Modules/implicit-private-with-submodule-explicit.m
@@ -0,0 +1,26 @@
+// Checks that the use of .Private to refer to _Private modules works with an
+// explicit module.
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module 
-fmodule-name=A %t/module.modulemap -o %t/A.pcm
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module 
-fmodule-name=A_Private %t/module.modulemap -o %t/A_Private.pcm
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules 
-fmodule-file=A=%t/A.pcm -fmodule-file=A_Private=%t/A_Private.pcm -fsyntax-only 
%t/tu.m
+
+//--- module.modulemap
+module A { header "a.h" }
+module A_Private { header "priv.h" }
+
+//--- a.h
+
+//--- priv.h
+void priv(void);
+
+//--- tu.m
+@import A.Private; // expected-warning{{no submodule named 'Private' in module 
'A'; using top level 'A_Private'}}
+// expected-note@*:* {{defined here}}
+
+void tu(void) {
+  priv();
+}
\ No newline at end of file
Index: clang/lib/Frontend/CompilerInstance.cpp
===
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -2026,8 +2026,12 @@
   PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
   PrivPath.push_back(std::make_pair(, Path[0].second));
 
+  std::string FileName;
+  // If there is a modulemap module or prebuilt module, load it.
   if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, ImportLoc, 
true,
- !IsInclusionDirective))
+ !IsInclusionDirective) ||
+  selectModuleSource(nullptr, PrivateModule, FileName, BuiltModules,
+ PP->getHeaderSearchInfo()) != MS_ModuleNotFound)
 Sub = loadModule(ImportLoc, PrivPath, Visibility, 
IsInclusionDirective);
   if (Sub) {
 MapPrivateSubModToTopLevel = true;


Index: clang/test/Modules/implicit-private-with-submodule-explicit.m
===
--- /dev/null
+++ clang/test/Modules/implicit-private-with-submodule-explicit.m
@@ -0,0 +1,26 @@
+// Checks that the use of .Private to refer to _Private modules works with an
+// explicit module.
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module -fmodule-name=A %t/module.modulemap -o %t/A.pcm
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module -fmodule-name=A_Private %t/module.modulemap -o %t/A_Private.pcm
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules -fmodule-file=A=%t/A.pcm -fmodule-file=A_Private=%t/A_Private.pcm -fsyntax-only %t/tu.m
+
+//--- module.modulemap
+module A { header "a.h" }
+module A_Private { header "priv.h" }
+
+//--- a.h
+
+//--- priv.h
+void priv(void);
+
+//--- tu.m
+@import A.Private; // expected-warning{{no submodule named 'Private' in module 'A'; using top level 'A_Private'}}
+// expected-note@*:* {{defined here}}
+
+void tu(void) {
+  priv();
+}
\ No newline at end of file
Index: clang/lib/Frontend/CompilerInstance.cpp
===
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -2026,8 +2026,12 @@
   PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
   PrivPath.push_back(std::make_pair(, Path[0].second));
 
+  std::string FileName;
+  // If there is a modulemap module or prebuilt module, load it.
   if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, ImportLoc, true,
- !IsInclusionDirective))
+ !IsInclusionDirective) ||
+  selectModuleSource(nullptr, PrivateModule, FileName, BuiltModules,
+ PP->getHeaderSearchInfo()) != MS_ModuleNotFound)
 Sub = loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective);
   if (Sub) {
 MapPrivateSubModToTopLevel = true;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D147477: [clang][modules] Handle explicit modules when checking for .Private -> _Private

2023-04-03 Thread Ben Langmuir via Phabricator via cfe-commits
benlangmuir created this revision.
benlangmuir added reviewers: akyrtzi, jansvoboda11.
Herald added a project: All.
benlangmuir requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

While we eventually want to remove the mapping from .Private to _Private 
modules, until we do, ensure that it behaves the same for explicit modules.

rdar://107449872


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D147477

Files:
  clang/lib/Frontend/CompilerInstance.cpp
  clang/test/Modules/implicit-private-with-submodule-explicit.m


Index: clang/test/Modules/implicit-private-with-submodule-explicit.m
===
--- /dev/null
+++ clang/test/Modules/implicit-private-with-submodule-explicit.m
@@ -0,0 +1,26 @@
+// Checks that the use of .Private to refer to _Private modules works with an
+// explicit module.
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module 
-fmodule-name=A %t/module.modulemap -o %t/A.pcm
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module 
-fmodule-name=A_Private %t/module.modulemap -o %t/A_Private.pcm
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules 
-fno-implicit-module-maps -fmodule-file=A=%t/A.pcm 
-fmodule-file=A_Private=%t/A_Private.pcm -fsyntax-only %t/tu.m
+
+//--- module.modulemap
+module A { header "a.h" }
+module A_Private { header "priv.h" }
+
+//--- a.h
+
+//--- priv.h
+void priv(void);
+
+//--- tu.m
+@import A.Private; // expected-warning{{no submodule named 'Private' in module 
'A'; using top level 'A_Private'}}
+// expected-note@*:* {{defined here}}
+
+void tu(void) {
+  priv();
+}
\ No newline at end of file
Index: clang/lib/Frontend/CompilerInstance.cpp
===
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -2026,8 +2026,12 @@
   PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
   PrivPath.push_back(std::make_pair(, Path[0].second));
 
+  std::string FileName;
+  // If there is a modulemap module or prebuilt module, load it.
   if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, ImportLoc, 
true,
- !IsInclusionDirective))
+ !IsInclusionDirective) ||
+  selectModuleSource(nullptr, PrivateModule, FileName, BuiltModules,
+ PP->getHeaderSearchInfo()) != MS_ModuleNotFound)
 Sub = loadModule(ImportLoc, PrivPath, Visibility, 
IsInclusionDirective);
   if (Sub) {
 MapPrivateSubModToTopLevel = true;


Index: clang/test/Modules/implicit-private-with-submodule-explicit.m
===
--- /dev/null
+++ clang/test/Modules/implicit-private-with-submodule-explicit.m
@@ -0,0 +1,26 @@
+// Checks that the use of .Private to refer to _Private modules works with an
+// explicit module.
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module -fmodule-name=A %t/module.modulemap -o %t/A.pcm
+// RUN: %clang_cc1 -x objective-c -fmodules -fno-implicit-modules -emit-module -fmodule-name=A_Private %t/module.modulemap -o %t/A_Private.pcm
+// RUN: %clang_cc1 -x objective-c -verify -fmodules -fno-implicit-modules -fno-implicit-module-maps -fmodule-file=A=%t/A.pcm -fmodule-file=A_Private=%t/A_Private.pcm -fsyntax-only %t/tu.m
+
+//--- module.modulemap
+module A { header "a.h" }
+module A_Private { header "priv.h" }
+
+//--- a.h
+
+//--- priv.h
+void priv(void);
+
+//--- tu.m
+@import A.Private; // expected-warning{{no submodule named 'Private' in module 'A'; using top level 'A_Private'}}
+// expected-note@*:* {{defined here}}
+
+void tu(void) {
+  priv();
+}
\ No newline at end of file
Index: clang/lib/Frontend/CompilerInstance.cpp
===
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -2026,8 +2026,12 @@
   PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
   PrivPath.push_back(std::make_pair(, Path[0].second));
 
+  std::string FileName;
+  // If there is a modulemap module or prebuilt module, load it.
   if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, ImportLoc, true,
- !IsInclusionDirective))
+ !IsInclusionDirective) ||
+  selectModuleSource(nullptr, PrivateModule, FileName, BuiltModules,
+ PP->getHeaderSearchInfo()) != MS_ModuleNotFound)
 Sub = loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective);
   if (Sub) {