From: Dmitri Gribenko Date: Thu, 31 Oct 2013 22:24:10 +0000 (+0000) Subject: Clang modules: collect exports recursively X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bc64d35c4151dc34c21d0fc971b3aee0d28d83a3;p=clang Clang modules: collect exports recursively This change makes Module::buildVisibleModulesCache() collect exported modules recursively. While computing a set of exports, getExportedModules() iterates over the set of imported modules and filters it. But it does not consider the set of exports of those modules -- it is the responsibility of the caller to do this. Here is a certain instance of this issue. Module::isModuleVisible says that CoreFoundation.CFArray submodule is not visible from Cocoa. Why? - Cocoa imports Foundation. - Foundation has an export restriction: "export *". - Foundation imports CoreFoundation. (Just the top-level module.) - CoreFoundation exports CoreFoundation.CFArray. To decide which modules are visible from Cocoa, we collect all exported modules from immediate imports in Cocoa: > visibleModulesFro(Cocoa) = exported(Foundation) + exported(CoreData) + exported(AppKit) To find out which modules are exported, we filter imports according to restrictions: > exported(Foundation) = filterByModuleMapRestrictions(imports(Foundation)) Because Foundation imports CoreFoundation (not CoreFoundation.CFArray), the CFArray submodule is considered not exported from Foundation, and is not visible from Cocoa (according to Module::isModuleVisible). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@193815 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index 027e217d10..3d8b75b471 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -404,6 +404,9 @@ public: submodule_const_iterator submodule_end() const { return SubModules.end(); } /// \brief Returns the exported modules based on the wildcard restrictions. + /// + /// This returns a subset of immediately imported modules (the ones that are + /// exported), not the complete set of exported modules. void getExportedModules(SmallVectorImpl &Exported) const; static StringRef getModuleInputBufferName() { diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp index 481537788e..ccf7077d6f 100644 --- a/lib/Basic/Module.cpp +++ b/lib/Basic/Module.cpp @@ -252,15 +252,23 @@ void Module::buildVisibleModulesCache() const { // This module is visible to itself. VisibleModulesCache.insert(this); - llvm::SmallVector Exported; - for (unsigned I = 0, N = Imports.size(); I != N; ++I) { - // Every imported module is visible. - VisibleModulesCache.insert(Imports[I]); - - // Every module exported by an imported module is visible. - Imports[I]->getExportedModules(Exported); - VisibleModulesCache.insert(Exported.begin(), Exported.end()); - Exported.clear(); + // Every imported module is visible. + // Every module exported by an imported module is visible. + llvm::SmallPtrSet Visited; + llvm::SmallVector Exports; + SmallVector Stack(Imports.begin(), Imports.end()); + while (!Stack.empty()) { + Module *CurrModule = Stack.pop_back_val(); + VisibleModulesCache.insert(CurrModule); + + CurrModule->getExportedModules(Exports); + for (SmallVectorImpl::iterator I = Exports.begin(), + E = Exports.end(); + I != E; ++I) { + Module *Exported = *I; + if (Visited.insert(Exported)) + Stack.push_back(Exported); + } } }