From 86250895597e288c86ef08c2e824956ea9835fed Mon Sep 17 00:00:00 2001
From: Dmitri Gribenko <gribozavr@gmail.com>
Date: Mon, 4 Nov 2013 21:51:33 +0000
Subject: [PATCH] Include non-explicit submodules in exported module list

This change fixes Richard's testcase for r193815.  Now we include non-explicit
submodules into the list of exports.

The test failed previously because:
- recursive_visibility_a1.inner is not imported (only recursive_visibility_a1 is),
- thus the 'inner' submodule is not showing up in any of the import lists,
- and because of this getExportedModules() is not returning the
  correct module set -- it only considers modules that are imported.

The fix is to make Module::getExportedModules() include non-explicit submodules
into the list of exports.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194018 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Basic/Module.cpp                           | 10 ++++++++++
 lib/Serialization/ASTReader.cpp                | 11 +----------
 test/Modules/Inputs/module.map                 | 18 ++++++++++++++++++
 .../Inputs/recursive_visibility_a1_inner.h     |  4 ++++
 .../recursive_visibility_a2_more_inner.h       |  4 ++++
 test/Modules/Inputs/recursive_visibility_b.h   |  2 ++
 test/Modules/Inputs/recursive_visibility_c.h   |  5 +++++
 test/Modules/recursive_visibility.mm           |  9 +++++++++
 8 files changed, 53 insertions(+), 10 deletions(-)
 create mode 100644 test/Modules/Inputs/recursive_visibility_a1_inner.h
 create mode 100644 test/Modules/Inputs/recursive_visibility_a2_more_inner.h
 create mode 100644 test/Modules/Inputs/recursive_visibility_b.h
 create mode 100644 test/Modules/Inputs/recursive_visibility_c.h
 create mode 100644 test/Modules/recursive_visibility.mm

diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp
index 4818e8d173..d08cef1a15 100644
--- a/lib/Basic/Module.cpp
+++ b/lib/Basic/Module.cpp
@@ -194,6 +194,16 @@ static void printModuleId(raw_ostream &OS, const ModuleId &Id) {
 }
 
 void Module::getExportedModules(SmallVectorImpl<Module *> &Exported) const {
+  // All non-explicit submodules are exported.
+  for (std::vector<Module *>::const_iterator I = SubModules.begin(),
+                                             E = SubModules.end();
+       I != E; ++I) {
+    Module *Mod = *I;
+    if (!Mod->IsExplicit)
+      Exported.push_back(Mod);
+  }
+
+  // Find re-exported modules by filtering the list of imported modules.
   bool AnyWildcard = false;
   bool UnrestrictedWildcard = false;
   SmallVector<Module *, 4> WildcardRestrictions;
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 57278d5620..4d1b4b90b6 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -2845,16 +2845,7 @@ void ASTReader::makeModuleVisible(Module *Mod,
       makeNamesVisible(Hidden->second, Hidden->first);
       HiddenNamesMap.erase(Hidden);
     }
-    
-    // Push any non-explicit submodules onto the stack to be marked as
-    // visible.
-    for (Module::submodule_iterator Sub = Mod->submodule_begin(),
-                                 SubEnd = Mod->submodule_end();
-         Sub != SubEnd; ++Sub) {
-      if (!(*Sub)->IsExplicit && Visited.insert(*Sub))
-        Stack.push_back(*Sub);
-    }
-    
+
     // Push any exported modules onto the stack to be marked as visible.
     SmallVector<Module *, 16> Exports;
     Mod->getExportedModules(Exports);
diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map
index cb4d339f7e..cf8a298cce 100644
--- a/test/Modules/Inputs/module.map
+++ b/test/Modules/Inputs/module.map
@@ -263,3 +263,21 @@ module using_decl {
   module a { header "using-decl-a.h" export * }
   module b { header "using-decl-b.h" export * }
 }
+
+module recursive_visibility_a1 {
+  module inner { header "recursive_visibility_a1_inner.h" }
+}
+module recursive_visibility_a2 {
+  module inner {
+    module more_inner {
+      header "recursive_visibility_a2_more_inner.h"
+    }
+  }
+}
+module recursive_visibility_b {
+  header "recursive_visibility_b.h"
+  export *
+}
+module recursive_visibility_c {
+  header "recursive_visibility_c.h"
+}
diff --git a/test/Modules/Inputs/recursive_visibility_a1_inner.h b/test/Modules/Inputs/recursive_visibility_a1_inner.h
new file mode 100644
index 0000000000..0f9fdf709b
--- /dev/null
+++ b/test/Modules/Inputs/recursive_visibility_a1_inner.h
@@ -0,0 +1,4 @@
+namespace A1_Inner {
+  struct X {};
+  void f(X);
+}
diff --git a/test/Modules/Inputs/recursive_visibility_a2_more_inner.h b/test/Modules/Inputs/recursive_visibility_a2_more_inner.h
new file mode 100644
index 0000000000..a9ff9d90af
--- /dev/null
+++ b/test/Modules/Inputs/recursive_visibility_a2_more_inner.h
@@ -0,0 +1,4 @@
+namespace A2_More_Inner {
+  struct X {};
+  void f(X);
+}
diff --git a/test/Modules/Inputs/recursive_visibility_b.h b/test/Modules/Inputs/recursive_visibility_b.h
new file mode 100644
index 0000000000..2c5d4effe3
--- /dev/null
+++ b/test/Modules/Inputs/recursive_visibility_b.h
@@ -0,0 +1,2 @@
+@import recursive_visibility_a1.inner;
+@import recursive_visibility_a2;
diff --git a/test/Modules/Inputs/recursive_visibility_c.h b/test/Modules/Inputs/recursive_visibility_c.h
new file mode 100644
index 0000000000..a978a3c0a5
--- /dev/null
+++ b/test/Modules/Inputs/recursive_visibility_c.h
@@ -0,0 +1,5 @@
+@import recursive_visibility_b;
+template<template<typename T> class Y> void g() {
+  f(typename Y<A1_Inner::X>::type{});
+  f(typename Y<A2_More_Inner::X>::type{});
+}
diff --git a/test/Modules/recursive_visibility.mm b/test/Modules/recursive_visibility.mm
new file mode 100644
index 0000000000..f37410aa44
--- /dev/null
+++ b/test/Modules/recursive_visibility.mm
@@ -0,0 +1,9 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -verify -std=c++11
+
+// expected-no-diagnostics
+
+@import recursive_visibility_c;
+
+template<typename T> struct Z { typedef T type; };
+template void g<Z>();
-- 
2.40.0