commit 3320d8bc6ec44fefbdd0d8b2951b773fa3181aad
Author: Ben Langmuir <blangmuir@apple.com>
Date:   Fri Jan 23 16:45:24 2015

    PR16909

diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index f6d185e..c39e2b1 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -1439,6 +1439,8 @@ public:
                                CXXScopeSpec *SS,
                                ParsedType &SuggestedType,
                                bool AllowClassTemplates = false);
+  void diagnoseMissingTypename(IdentifierInfo *II, SourceLocation IILoc,
+                               Scope *S, CXXScopeSpec *SS);
 
   /// \brief For compatibility with MSVC, we delay parsing of some default
   /// template type arguments until instantiation time.  Emits a warning and
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index cd6ff6c..5d4fb9e 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -590,14 +590,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
     Diag(IILoc, diag::err_typename_nested_not_found) 
       << II << DC << SS->getRange();
   else if (isDependentScopeSpecifier(*SS)) {
-    unsigned DiagID = diag::err_typename_missing;
-    if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S))
-      DiagID = diag::ext_typename_missing;
-
-    Diag(SS->getRange().getBegin(), DiagID)
-      << SS->getScopeRep() << II->getName()
-      << SourceRange(SS->getRange().getBegin(), IILoc)
-      << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename ");
+    diagnoseMissingTypename(II, IILoc, S, SS);
     SuggestedType = ActOnTypenameType(S, SourceLocation(),
                                       *SS, *II, IILoc).get();
   } else {
@@ -606,6 +599,18 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
   }
 }
 
+void Sema::diagnoseMissingTypename(IdentifierInfo *II, SourceLocation IILoc,
+                                   Scope *S, CXXScopeSpec *SS) {
+  unsigned DiagID = diag::err_typename_missing;
+  if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S))
+    DiagID = diag::ext_typename_missing;
+
+  Diag(SS->getRange().getBegin(), DiagID)
+      << SS->getScopeRep() << II->getName()
+      << SourceRange(SS->getRange().getBegin(), IILoc)
+      << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename ");
+}
+
 /// \brief Determine whether the given result set contains either a type name
 /// or 
 static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) {
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 7451497..9940d93 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2166,6 +2166,19 @@ Sema::ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
   TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
   translateTemplateArguments(TemplateArgsIn, TemplateArgs);
 
+  if (isDependentScopeSpecifier(SS) &&
+      !getCurrentInstantiationOf(SS.getScopeRep()) &&
+      !Template.getAsDependentTemplateName()) {
+    IdentifierInfo *TemplateII = Template.getAsTemplateDecl()->getIdentifier();
+
+    // This can happen if we are missing the 'typename' keyword in a type
+    // specifier A<T>::B<U>.
+    diagnoseMissingTypename(TemplateII, TemplateLoc, getCurScope(), &SS);
+    // Recover by replacing Template with a DependentTemplateName.
+    Template = TemplateName(
+        Context.getDependentTemplateName(SS.getScopeRep(), TemplateII));
+  }
+
   if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
     QualType T
       = Context.getDependentTemplateSpecializationType(ETK_None,
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp b/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
index d1562d4..c4a230f 100644
--- a/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
+++ b/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
@@ -24,7 +24,9 @@ X0::X0 X0::f1() { return X0(); } // expected-error{{qualified reference to 'X0'
 struct X0::X0 X0::f2() { return X0(); }
 
 template<typename T> X1<T>::X1<T> X1<T>::f2() { } // expected-error{{qualified reference to 'X1' is a constructor name rather than a template name wherever a constructor can be declared}}
+// expected-error@-1{{missing 'typename'}}
 template<typename T> X1<T>::X1<T> (X1<T>::f2)(int) { } // expected-error{{qualified reference to 'X1' is a constructor name rather than a template name wherever a constructor can be declared}}
+// expected-error@-1{{missing 'typename'}}
 template<typename T> struct X1<T>::X1<T> (X1<T>::f2)(float) { }
 
 // We have a special case for lookup within using-declarations that are
diff --git a/test/CXX/temp/temp.decls/temp.variadic/sizeofpack.cpp b/test/CXX/temp/temp.decls/temp.variadic/sizeofpack.cpp
index 4960a2b..87c22a0 100644
--- a/test/CXX/temp/temp.decls/temp.variadic/sizeofpack.cpp
+++ b/test/CXX/temp/temp.decls/temp.variadic/sizeofpack.cpp
@@ -61,7 +61,7 @@ struct X {
 
 template<class... Members>
 template<int i>
-X<Members...>::get_t<i> X<Members...>::get()
+typename X<Members...>::template get_t<i> X<Members...>::get()
 {
   return 0;
 }
diff --git a/test/SemaTemplate/typename-specifier.cpp b/test/SemaTemplate/typename-specifier.cpp
index 602e903..de6a71f 100644
--- a/test/SemaTemplate/typename-specifier.cpp
+++ b/test/SemaTemplate/typename-specifier.cpp
@@ -240,3 +240,13 @@ void j() {
   h<B>();
 }
 } // namespace pointer_vs_multiply
+
+namespace PR16909 {
+template <typename T>
+struct A {
+  template <typename U>
+  struct B {};
+};
+template <typename T, typename U>
+A<T>::B<U> get(); // expected-error {{missing 'typename'}}
+}
