diff --git a/clang/include/clang/Lex/DirectoryLookup.h b/clang/include/clang/Lex/DirectoryLookup.h index 0539018e66ff..261dfabc0fd2 100644 --- a/clang/include/clang/Lex/DirectoryLookup.h +++ b/clang/include/clang/Lex/DirectoryLookup.h @@ -56,6 +56,10 @@ private: /// \brief Whether this is a header map used when building a framework. unsigned IsIndexHeaderMap : 1; + + /// \brief Whether we've performed an exhaustive search for module maps + /// within the subdirectories of this directory. + unsigned SearchedAllModuleMaps : 1; public: /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of @@ -64,7 +68,7 @@ public: bool isFramework) : DirCharacteristic(DT), LookupType(isFramework ? LT_Framework : LT_NormalDir), - IsIndexHeaderMap(false) { + IsIndexHeaderMap(false), SearchedAllModuleMaps(false) { u.Dir = dir; } @@ -73,7 +77,7 @@ public: DirectoryLookup(const HeaderMap *map, SrcMgr::CharacteristicKind DT, bool isIndexHeaderMap) : DirCharacteristic(DT), LookupType(LT_HeaderMap), - IsIndexHeaderMap(isIndexHeaderMap) { + IsIndexHeaderMap(isIndexHeaderMap), SearchedAllModuleMaps(false) { u.Map = map; } @@ -109,6 +113,16 @@ public: /// isHeaderMap - Return true if this is a header map, not a normal directory. bool isHeaderMap() const { return getLookupType() == LT_HeaderMap; } + /// \brief Determine whether we have already searched this entire + /// directory for module maps. + bool haveSearchedAllModuleMaps() const { return SearchedAllModuleMaps; } + + /// \brief Specify whether we have already searched all of the subdirectories + /// for module maps. + void setSearchedAllModuleMaps(bool SAMM) { + SearchedAllModuleMaps = SAMM; + } + /// DirCharacteristic - The type of directory this is, one of the DirType enum /// values. SrcMgr::CharacteristicKind getDirCharacteristic() const { diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h index a0ce1399937b..8a5a798560de 100644 --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -505,7 +505,11 @@ private: Module *loadFrameworkModule(StringRef Name, const DirectoryEntry *Dir, bool IsSystem); - + + /// \brief Load all of the module maps within the immediate subdirectories + /// of the given search directory. + void loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir); + public: /// \brief Retrieve the module map. ModuleMap &getModuleMap() { return ModMap; } diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 9e4b68232a14..304bd6969a68 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -181,8 +181,22 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { if (Module) break; } + + // If we've already performed the exhaustive search for module maps in this + // search directory, don't do it again. + if (SearchDirs[Idx].haveSearchedAllModuleMaps()) + continue; + + // Load all module maps in the immediate subdirectories of this search + // directory. + loadSubdirectoryModuleMaps(SearchDirs[Idx]); + + // Look again for the module. + Module = ModMap.findModule(ModuleName); + if (Module) + break; } - + return Module; } @@ -1126,13 +1140,7 @@ void HeaderSearch::collectAllModules(SmallVectorImpl &Modules) { // Try to load module map files for immediate subdirectories of this search // directory. - llvm::error_code EC; - SmallString<128> DirNative; - llvm::sys::path::native(SearchDirs[Idx].getDir()->getName(), DirNative); - for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd; - Dir != DirEnd && !EC; Dir.increment(EC)) { - loadModuleMapFile(Dir->path()); - } + loadSubdirectoryModuleMaps(SearchDirs[Idx]); } // Populate the list of modules. @@ -1142,3 +1150,18 @@ void HeaderSearch::collectAllModules(SmallVectorImpl &Modules) { Modules.push_back(M->getValue()); } } + +void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) { + if (SearchDir.haveSearchedAllModuleMaps()) + return; + + llvm::error_code EC; + SmallString<128> DirNative; + llvm::sys::path::native(SearchDir.getDir()->getName(), DirNative); + for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd; + Dir != DirEnd && !EC; Dir.increment(EC)) { + loadModuleMapFile(Dir->path()); + } + + SearchDir.setSearchedAllModuleMaps(true); +} diff --git a/clang/test/Modules/Inputs/Modified/B.h b/clang/test/Modules/Inputs/Modified/B.h index f50dd80ca4e8..52526b7f3ab0 100644 --- a/clang/test/Modules/Inputs/Modified/B.h +++ b/clang/test/Modules/Inputs/Modified/B.h @@ -1,3 +1,3 @@ -@import A; +@import ModA; int getB(); diff --git a/clang/test/Modules/Inputs/Modified/module.map b/clang/test/Modules/Inputs/Modified/module.map index 50aaebc5c752..27b0d7062c76 100644 --- a/clang/test/Modules/Inputs/Modified/module.map +++ b/clang/test/Modules/Inputs/Modified/module.map @@ -1,5 +1,5 @@ -module A { header "A.h" } -module B { +module ModA { header "A.h" } +module ModB { header "B.h" export * } diff --git a/clang/test/Modules/Inputs/oldname/module.map b/clang/test/Modules/Inputs/oldname/module.map new file mode 100644 index 000000000000..5812f869b342 --- /dev/null +++ b/clang/test/Modules/Inputs/oldname/module.map @@ -0,0 +1,4 @@ +module NewName { + header "new_name.h" + export * +} diff --git a/clang/test/Modules/Inputs/oldname/new_name.h b/clang/test/Modules/Inputs/oldname/new_name.h new file mode 100644 index 000000000000..8bf2f1c8c312 --- /dev/null +++ b/clang/test/Modules/Inputs/oldname/new_name.h @@ -0,0 +1 @@ +int same_api; diff --git a/clang/test/Modules/modify-module.m b/clang/test/Modules/modify-module.m index decd07de080d..953c917cddcc 100644 --- a/clang/test/Modules/modify-module.m +++ b/clang/test/Modules/modify-module.m @@ -11,9 +11,9 @@ // RUN: %clang_cc1 -fdisable-module-hash -fmodules-cache-path=%t/cache -fmodules -I %t/include %s -verify // RUN: echo 'int getA(); int getA2();' > %t/include/A.h // RUN: %clang_cc1 -fdisable-module-hash -fmodules-cache-path=%t/cache -fmodules -I %t/include %s -verify -// RUN: rm %t/cache/A.pcm +// RUN: rm %t/cache/ModA.pcm // RUN: %clang_cc1 -fdisable-module-hash -fmodules-cache-path=%t/cache -fmodules -I %t/include %s -verify -// RUN: touch %t/cache/A.pcm +// RUN: touch %t/cache/ModA.pcm // RUN: %clang_cc1 -fdisable-module-hash -fmodules-cache-path=%t/cache -fmodules -I %t/include %s -verify // expected-no-diagnostics @@ -21,7 +21,7 @@ // FIXME: It is intended to suppress this on win32. // REQUIRES: ansi-escape-sequences -@import B; +@import ModB; int getValue() { return getA() + getB(); } diff --git a/clang/test/Modules/renamed.m b/clang/test/Modules/renamed.m new file mode 100644 index 000000000000..4e8f5329bb0f --- /dev/null +++ b/clang/test/Modules/renamed.m @@ -0,0 +1,8 @@ +@import NewName; + +int f() { return same_api; } + +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -I %S/Inputs -fmodules-cache-path=%t %s -verify + +// expected-no-diagnostics