When we perform dependent name lookup during template instantiation, it's not
sufficient to only consider names visible at the point of instantiation,
because that may not include names that were visible when the template was
defined. More generally, if the instantiation backtrace goes through a module
M, then every declaration visible within M should be available to the
instantiation. Any of those declarations might be part of the interface that M
intended to export to a template that it instantiates.

The fix here has two parts:

1) If we find a non-visible declaration during name lookup during template
instantiation, check whether the declaration was visible from the defining
module of all entities on the active template instantiation stack. The defining
module is not the owning module in all cases: we look at the module in which a
template was defined, not the module in which it was first instantiated.

2) Perform pending instantiations at the end of a module, not at the end of the
translation unit. This is general goodness, since it significantly cuts down
the amount of redundant work that is performed in every TU importing a module,
and also implicitly adds the module containing the point of instantiation to
the set of modules checked for declarations in a lookup within a template
instantiation.

There's a known issue here with template instantiations performed while
building a module, if additional imports are added later on. I'll fix that
in a subsequent commit.

llvm-svn: 187167
diff --git a/clang/test/Modules/Inputs/cxx-templates-a.h b/clang/test/Modules/Inputs/cxx-templates-a.h
index 7770d34..cc83d7b 100644
--- a/clang/test/Modules/Inputs/cxx-templates-a.h
+++ b/clang/test/Modules/Inputs/cxx-templates-a.h
@@ -14,3 +14,9 @@
 template<typename T> struct SomeTemplate<T*>;
 template<typename T> struct SomeTemplate<T*> {};
 typedef SomeTemplate<int*> SomeTemplateIntPtr;
+
+template<typename T> void PerformDelayedLookup(T &t) {
+  t.f();
+  typename T::Inner inner;
+  FoundByADL(t);
+}
diff --git a/clang/test/Modules/Inputs/cxx-templates-b-impl.h b/clang/test/Modules/Inputs/cxx-templates-b-impl.h
new file mode 100644
index 0000000..fdf4a4f
--- /dev/null
+++ b/clang/test/Modules/Inputs/cxx-templates-b-impl.h
@@ -0,0 +1,5 @@
+struct DefinedInBImpl {
+  void f();
+  struct Inner {};
+  friend void FoundByADL(DefinedInBImpl);
+};
diff --git a/clang/test/Modules/Inputs/cxx-templates-b.h b/clang/test/Modules/Inputs/cxx-templates-b.h
index e0f67d0..36d7d78 100644
--- a/clang/test/Modules/Inputs/cxx-templates-b.h
+++ b/clang/test/Modules/Inputs/cxx-templates-b.h
@@ -14,3 +14,26 @@
 template<typename T> struct SomeTemplate<T&> {};
 template<typename T> struct SomeTemplate<T&>;
 typedef SomeTemplate<int&> SomeTemplateIntRef;
+
+extern DefinedInCommon &defined_in_common;
+
+@import cxx_templates_b_impl;
+
+template<typename T, typename> struct Identity { typedef T type; };
+template<typename T> void UseDefinedInBImpl() {
+  typename Identity<DefinedInBImpl, T>::type dependent;
+  FoundByADL(dependent);
+  typename Identity<DefinedInBImpl, T>::type::Inner inner;
+  dependent.f();
+}
+
+extern DefinedInBImpl &defined_in_b_impl;
+
+@import cxx_templates_a;
+template<typename T> void UseDefinedInBImplIndirectly(T &v) {
+  PerformDelayedLookup(v);
+}
+
+void TriggerInstantiation() {
+  UseDefinedInBImpl<void>();
+}
diff --git a/clang/test/Modules/Inputs/cxx-templates-common.h b/clang/test/Modules/Inputs/cxx-templates-common.h
index 950a2a6..6993da8 100644
--- a/clang/test/Modules/Inputs/cxx-templates-common.h
+++ b/clang/test/Modules/Inputs/cxx-templates-common.h
@@ -1 +1,7 @@
 template<typename T> struct SomeTemplate {};
+
+struct DefinedInCommon {
+  void f();
+  struct Inner {};
+  friend void FoundByADL(DefinedInCommon);
+};
diff --git a/clang/test/Modules/Inputs/module.map b/clang/test/Modules/Inputs/module.map
index 0a84f88..7be8b79 100644
--- a/clang/test/Modules/Inputs/module.map
+++ b/clang/test/Modules/Inputs/module.map
@@ -196,6 +196,10 @@
   header "cxx-templates-a.h"
 }
 
+module cxx_templates_b_impl {
+  header "cxx-templates-b-impl.h"
+}
+
 module cxx_templates_b {
   header "cxx-templates-b.h"
 }
diff --git a/clang/test/Modules/cxx-templates.cpp b/clang/test/Modules/cxx-templates.cpp
index 5715999..bb8ba03 100644
--- a/clang/test/Modules/cxx-templates.cpp
+++ b/clang/test/Modules/cxx-templates.cpp
@@ -24,8 +24,8 @@
   N::f<double>(1.0);
   N::f<int>();
   N::f(); // expected-error {{no matching function}}
-  // expected-note@Inputs/cxx-templates-a.h:6 {{couldn't infer template argument}}
-  // expected-note@Inputs/cxx-templates-a.h:7 {{requires 1 argument, but 0 were provided}}
+  // expected-note@Inputs/cxx-templates-b.h:6 {{couldn't infer template argument}}
+  // expected-note@Inputs/cxx-templates-b.h:7 {{requires single argument 't'}}
 
   template_param_kinds_1<0>(); // ok, from cxx-templates-a.h
   template_param_kinds_1<int>(); // ok, from cxx-templates-b.h
@@ -46,6 +46,26 @@
   template_param_kinds_3<Tmpl_T_T_B>(); // expected-error {{ambiguous}}
   // expected-note@Inputs/cxx-templates-a.h:12 {{candidate}}
   // expected-note@Inputs/cxx-templates-b.h:12 {{candidate}}
+
+  // Trigger the instantiation of a template in 'a' that uses a type defined in
+  // 'common'. That type is not visible here.
+  PerformDelayedLookup(defined_in_common);
+
+  // Trigger the instantiation of a template in 'b' that uses a type defined in
+  // 'b_impl'. That type is not visible here.
+  UseDefinedInBImpl<int>();
+
+  // Trigger the instantiation of a template in 'a' that uses a type defined in
+  // 'b_impl', via a template defined in 'b'. Since the type is visible from
+  // within 'b', the instantiation succeeds.
+  UseDefinedInBImplIndirectly(defined_in_b_impl);
+
+  // Trigger the instantiation of a template in 'a' that uses a type defined in
+  // 'b_impl'. That type is not visible here, nor in 'a'. This fails; there is
+  // no reason why DefinedInBImpl should be visible here.
+  // expected-error@Inputs/cxx-templates-a.h:19 {{definition of 'DefinedInBImpl' must be imported}}
+  // expected-note@Inputs/cxx-templates-b-impl.h:1 {{definition is here}}
+  PerformDelayedLookup(defined_in_b_impl); // expected-note {{in instantiation of}}
 }
 
 @import cxx_templates_common;
@@ -62,9 +82,6 @@
 // CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f'
 // CHECK-GLOBAL-NEXT: `-FunctionTemplate {{.*}} 'f'
 
-// FIXME: There should only be two 'f's here.
 // CHECK-NAMESPACE-N:      DeclarationName 'f'
 // CHECK-NAMESPACE-N-NEXT: |-FunctionTemplate {{.*}} 'f'
-// CHECK-NAMESPACE-N-NEXT: |-FunctionTemplate {{.*}} 'f'
-// CHECK-NAMESPACE-N-NEXT: |-FunctionTemplate {{.*}} 'f'
 // CHECK-NAMESPACE-N-NEXT: `-FunctionTemplate {{.*}} 'f'