]> granicus.if.org Git - clang/commitdiff
Clang modules: collect exports recursively
authorDmitri Gribenko <gribozavr@gmail.com>
Thu, 31 Oct 2013 22:24:10 +0000 (22:24 +0000)
committerDmitri Gribenko <gribozavr@gmail.com>
Thu, 31 Oct 2013 22:24:10 +0000 (22:24 +0000)
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

include/clang/Basic/Module.h
lib/Basic/Module.cpp

index 027e217d108a997a10b9c7e01ce79976941ff0c7..3d8b75b471f6089383882d6cf679781ea253f2ec 100644 (file)
@@ -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<Module *> &Exported) const;
 
   static StringRef getModuleInputBufferName() {
index 481537788e9ec3d5504813183d9eb53849d70ea3..ccf7077d6fb88e60068718ef4892b592f46e566f 100644 (file)
@@ -252,15 +252,23 @@ void Module::buildVisibleModulesCache() const {
   // This module is visible to itself.
   VisibleModulesCache.insert(this);
 
-  llvm::SmallVector<Module*, 4> 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<Module *, 4> Visited;
+  llvm::SmallVector<Module *, 4> Exports;
+  SmallVector<Module *, 4> Stack(Imports.begin(), Imports.end());
+  while (!Stack.empty()) {
+    Module *CurrModule = Stack.pop_back_val();
+    VisibleModulesCache.insert(CurrModule);
+
+    CurrModule->getExportedModules(Exports);
+    for (SmallVectorImpl<Module *>::iterator I = Exports.begin(),
+                                             E = Exports.end();
+         I != E; ++I) {
+      Module *Exported = *I;
+      if (Visited.insert(Exported))
+        Stack.push_back(Exported);
+    }
   }
 }