Use explicitly-specified template argument lists to help naming
explicit template specializations, when available.

llvm-svn: 82824
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 56f4693..a992fb1 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -403,6 +403,7 @@
       // deduction, and that error is one of the SFINAE errors,
       // suppress the diagnostic.
       ++NumSFINAEErrors;
+      Diags.setLastDiagnosticIgnored();
       return SemaDiagnosticBuilder(*this);
     }
 
@@ -2444,6 +2445,10 @@
                                 TemplateParameterList *TemplateParams,
                                 AccessSpecifier AS);
 
+  void translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
+                                  SourceLocation *TemplateArgLocs,
+                        llvm::SmallVector<TemplateArgument, 16> &TemplateArgs);
+    
   QualType CheckTemplateIdType(TemplateName Template,
                                SourceLocation TemplateLoc,
                                SourceLocation LAngleLoc,
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 074eb6e..1f53cde 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2693,15 +2693,49 @@
         isOutOfScopePreviousDeclaration(PrevDecl, DC, Context)))
     PrevDecl = 0;
 
-  // FIXME: If the declarator has a template argument list but 
-  // isFunctionTemplateSpecialization is false, this is a function template 
-  // specialization but the user forgot the "template<>" header. Complain about
-  // the missing template<> header and set isFunctionTemplateSpecialization.
-
+  // If the declarator is a template-id, translate the parser's template 
+  // argument list into our AST format.
+  bool HasExplicitTemplateArgs = false;
+  llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+  SourceLocation LAngleLoc, RAngleLoc;
+  if (D.getKind() == Declarator::DK_TemplateId) {
+    TemplateIdAnnotation *TemplateId = D.getTemplateId();
+    ASTTemplateArgsPtr TemplateArgsPtr(*this,
+                                       TemplateId->getTemplateArgs(),
+                                       TemplateId->getTemplateArgIsType(),
+                                       TemplateId->NumArgs);
+    translateTemplateArguments(TemplateArgsPtr,
+                               TemplateId->getTemplateArgLocations(),
+                               TemplateArgs);
+    TemplateArgsPtr.release();
+    
+    HasExplicitTemplateArgs = true;
+    LAngleLoc = TemplateId->LAngleLoc;
+    RAngleLoc = TemplateId->RAngleLoc;
+    
+    if (FunctionTemplate) {
+      // FIXME: Diagnostic function template with explicit template
+      // arguments.
+      HasExplicitTemplateArgs = false;
+    } else if (!isFunctionTemplateSpecialization && 
+               !D.getDeclSpec().isFriendSpecified()) {
+      // We have encountered something that the user meant to be a 
+      // specialization (because it has explicitly-specified template
+      // arguments) but that was not introduced with a "template<>" (or had
+      // too few of them).
+      Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
+        << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
+        << CodeModificationHint::CreateInsertion(
+                                   D.getDeclSpec().getSourceRange().getBegin(),
+                                                 "template<> ");
+      isFunctionTemplateSpecialization = true;
+    }
+  }
+  
   if (isFunctionTemplateSpecialization &&
-      CheckFunctionTemplateSpecialization(NewFD, 
-                                          /*FIXME:*/false, SourceLocation(),
-                                          0, 0, SourceLocation(), 
+      CheckFunctionTemplateSpecialization(NewFD, HasExplicitTemplateArgs,
+                                          LAngleLoc, TemplateArgs.data(),
+                                          TemplateArgs.size(), RAngleLoc,
                                           PrevDecl))
     NewFD->setInvalidDecl();
   
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 27e8edd..e0c1afbf 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1037,9 +1037,8 @@
 
 /// \brief Translates template arguments as provided by the parser
 /// into template arguments used by semantic analysis.
-static void
-translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
-                           SourceLocation *TemplateArgLocs,
+void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
+                                      SourceLocation *TemplateArgLocs,
                      llvm::SmallVector<TemplateArgument, 16> &TemplateArgs) {
   TemplateArgs.reserve(TemplateArgsIn.size());
 
@@ -3409,7 +3408,8 @@
     return DeclPtrTy();
   }
   
-  // Translate the parser's template argument list in our AST format.
+  // If the declarator is a template-id, translate the parser's template 
+  // argument list into our AST format.
   bool HasExplicitTemplateArgs = false;
   llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
   if (D.getKind() == Declarator::DK_TemplateId) {
@@ -3423,8 +3423,7 @@
                                TemplateArgs);
     HasExplicitTemplateArgs = true;
   }
-  
-  
+    
   // C++ [temp.explicit]p1:
   //   A [...] function [...] can be explicitly instantiated from its template. 
   //   A member function [...] of a class template can be explicitly