Declarators can now properly represent template-ids, e.g., for

  template void f<int>(int);
                ~~~~~~
Previously, we silently dropped the template arguments. With this
change, we now use the template arguments (when available) as the
explicitly-specified template arguments used to aid template argument
deduction for explicit template instantiations.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82806 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index c9983a8..074eb6e 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1587,6 +1587,17 @@
     assert(D.getIdentifier() == 0 && "operator names have no identifier");
     return Context.DeclarationNames.getCXXOperatorName(
                                                 D.getOverloadedOperator());
+      
+  case Declarator::DK_TemplateId: {
+    TemplateName Name
+      = TemplateName::getFromVoidPointer(D.getTemplateId()->Template);    
+    if (TemplateDecl *Template = Name.getAsTemplateDecl())
+      return Template->getDeclName();
+    if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl())
+      return Ovl->getDeclName();
+    
+    return DeclarationName();
+  }
   }
 
   assert(false && "Unknown name kind");
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 37fbf45..27e8edd 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -3409,23 +3409,38 @@
     return DeclPtrTy();
   }
   
+  // Translate the parser's template argument list in our AST format.
+  bool HasExplicitTemplateArgs = false;
+  llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+  if (D.getKind() == Declarator::DK_TemplateId) {
+    TemplateIdAnnotation *TemplateId = D.getTemplateId();
+    ASTTemplateArgsPtr TemplateArgsPtr(*this,
+                                       TemplateId->getTemplateArgs(),
+                                       TemplateId->getTemplateArgIsType(),
+                                       TemplateId->NumArgs);
+    translateTemplateArguments(TemplateArgsPtr,
+                               TemplateId->getTemplateArgLocations(),
+                               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 
   //  instantiated from the member definition associated with its class 
   //  template.
-  // FIXME: Implement this!
   llvm::SmallVector<FunctionDecl *, 8> Matches;
   for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
        P != PEnd; ++P) {
     NamedDecl *Prev = *P;
-    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
-      // FIXME: If there were any explicitly-specified template arguments, 
-      // don't look for Method declarations.
-      if (Context.hasSameUnqualifiedType(Method->getType(), R)) {
-        Matches.clear();
-        Matches.push_back(Method);
-        break;
+    if (!HasExplicitTemplateArgs) {
+      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
+        if (Context.hasSameUnqualifiedType(Method->getType(), R)) {
+          Matches.clear();
+          Matches.push_back(Method);
+          break;
+        }
       }
     }
     
@@ -3436,7 +3451,8 @@
     TemplateDeductionInfo Info(Context);
     FunctionDecl *Specialization = 0;
     if (TemplateDeductionResult TDK
-          = DeduceTemplateArguments(FunTmpl, /*FIXME:*/false, 0, 0, 
+          = DeduceTemplateArguments(FunTmpl, HasExplicitTemplateArgs,
+                                    TemplateArgs.data(), TemplateArgs.size(),
                                     R, Specialization, Info)) {
       // FIXME: Keep track of almost-matches?
       (void)TDK;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index c297694..d064e3c 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -842,7 +842,8 @@
   switch (D.getKind()) {
   case Declarator::DK_Abstract:
   case Declarator::DK_Normal:
-  case Declarator::DK_Operator: {
+  case Declarator::DK_Operator:
+  case Declarator::DK_TemplateId: {
     const DeclSpec &DS = D.getDeclSpec();
     if (OmittedReturnType) {
       // We default to a dependent type initially.  Can be modified by