@@ -1808,14 +1808,14 @@ static std::string getScalaNodeText(llvm::yaml::Node *N) {
18081808 return cast<llvm::yaml::ScalarNode>(N)->getValue (Buffer).str ();
18091809}
18101810
1811- bool ClangImporter::canImportModule (ImportPath::Element moduleID ,
1811+ bool ClangImporter::canImportModule (ImportPath::Module modulePath ,
18121812 llvm::VersionTuple version,
18131813 bool underlyingVersion) {
18141814 // Look up the top-level module to see if it exists.
1815- // FIXME: This only works with top-level modules.
18161815 auto &clangHeaderSearch = Impl.getClangPreprocessor ().getHeaderSearchInfo ();
1816+ auto topModule = modulePath.front ();
18171817 clang::Module *clangModule = clangHeaderSearch.lookupModule (
1818- moduleID .Item .str (), /* ImportLoc=*/ clang::SourceLocation (),
1818+ topModule .Item .str (), /* ImportLoc=*/ clang::SourceLocation (),
18191819 /* AllowSearch=*/ true , /* AllowExtraModuleMapSearch=*/ true );
18201820 if (!clangModule) {
18211821 return false ;
@@ -1825,10 +1825,34 @@ bool ClangImporter::canImportModule(ImportPath::Element moduleID,
18251825 clang::Module::UnresolvedHeaderDirective mh;
18261826 clang::Module *m;
18271827 auto &ctx = Impl.getClangASTContext ();
1828- auto available = clangModule->isAvailable (ctx.getLangOpts (), getTargetInfo (),
1829- r, mh, m);
1828+ auto &lo = ctx.getLangOpts ();
1829+ auto &ti = getTargetInfo ();
1830+
1831+ auto available = clangModule->isAvailable (lo, ti, r, mh, m);
18301832 if (!available)
18311833 return false ;
1834+
1835+ if (modulePath.hasSubmodule ()) {
1836+ for (auto &component : modulePath.getSubmodulePath ()) {
1837+ clangModule = clangModule->findSubmodule (component.Item .str ());
1838+
1839+ // Special case: a submodule named "Foo.Private" can be moved to a
1840+ // top-level module named "Foo_Private". Clang has special support for
1841+ // this.
1842+ if (!clangModule && component.Item .str () == " Private" &&
1843+ (&component) == (&modulePath.getRaw ()[1 ])) {
1844+ clangModule = clangHeaderSearch.lookupModule (
1845+ (topModule.Item .str () + " _Private" ).str (),
1846+ /* ImportLoc=*/ clang::SourceLocation (),
1847+ /* AllowSearch=*/ true ,
1848+ /* AllowExtraModuleMapSearch=*/ true );
1849+ }
1850+ if (!clangModule || !clangModule->isAvailable (lo, ti, r, mh, m)) {
1851+ return false ;
1852+ }
1853+ }
1854+ }
1855+
18321856 if (version.empty ())
18331857 return true ;
18341858 assert (available);
@@ -1838,11 +1862,11 @@ bool ClangImporter::canImportModule(ImportPath::Element moduleID,
18381862 .getFilename (clangModule->DefinitionLoc );
18391863 // Look for the .tbd file inside .framework dir to get the project version
18401864 // number.
1841- std::string fwName = (llvm::Twine (moduleID .Item .str ()) + " .framework" ).str ();
1865+ std::string fwName = (llvm::Twine (topModule .Item .str ()) + " .framework" ).str ();
18421866 auto pos = path.find (fwName);
18431867 while (pos != StringRef::npos) {
18441868 llvm::SmallString<256 > buffer (path.substr (0 , pos + fwName.size ()));
1845- llvm::sys::path::append (buffer, llvm::Twine (moduleID .Item .str ()) + " .tbd" );
1869+ llvm::sys::path::append (buffer, llvm::Twine (topModule .Item .str ()) + " .tbd" );
18461870 auto tbdPath = buffer.str ();
18471871 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> tbdBufOrErr =
18481872 llvm::MemoryBuffer::getFile (tbdPath);
@@ -1877,8 +1901,8 @@ bool ClangImporter::canImportModule(ImportPath::Element moduleID,
18771901 }
18781902 // Diagnose unable to checking the current version.
18791903 if (currentVersion.empty ()) {
1880- Impl.diagnose (moduleID .Loc , diag::cannot_find_project_version, " Clang" ,
1881- moduleID .Item .str ());
1904+ Impl.diagnose (topModule .Loc , diag::cannot_find_project_version, " Clang" ,
1905+ topModule .Item .str ());
18821906 return true ;
18831907 }
18841908 assert (!currentVersion.empty ());
0 commit comments