Implement name lookup for conversion function template specializations
(C++ [temp.mem]p5-6), which involves template argument deduction based
on the type named, e.g., given

  struct X { template<typename T> operator T*(); } x;

when we call

  x.operator int*();

we perform template argument deduction to determine that T=int. This
template argument deduction is needed for template specialization and
explicit instantiation, e.g.,

  template<> X::operator float*() { /* ... */ }

and when calling or otherwise naming a conversion function (as in the
first example). 

This fixes PR5742 and PR5762, although there's some remaining ugliness
that's causing out-of-line definitions of conversion function
templates to fail. I'll look into that separately.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93162 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index ec08658..f463cbb 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1178,8 +1178,14 @@
     LookupObjCImplementationName
   };
 
+  /// \brief Specifies whether (or how) name lookup is being performed for a
+  /// redeclaration (vs. a reference).
   enum RedeclarationKind {
-    NotForRedeclaration,
+    /// \brief The lookup is a reference to this name that is not for the
+    /// purpose of redeclaring the name.
+    NotForRedeclaration = 0,
+    /// \brief The lookup results will be used for redeclaration of a name,
+    /// if an entity by that name already exists.
     ForRedeclaration
   };
 
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 8965199..41f0886 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2743,7 +2743,9 @@
       << ClassType << ConvType;
   }
 
-  if (Conversion->getPreviousDeclaration()) {
+  if (Conversion->getPrimaryTemplate()) {
+    // ignore specializations
+  } else if (Conversion->getPreviousDeclaration()) {
     const NamedDecl *ExpectedPrevDecl = Conversion->getPreviousDeclaration();
     if (FunctionTemplateDecl *ConversionTemplate
           = Conversion->getDescribedFunctionTemplate())
@@ -2754,7 +2756,7 @@
   } else if (FunctionTemplateDecl *ConversionTemplate
                = Conversion->getDescribedFunctionTemplate())
     ClassDecl->addConversionFunction(ConversionTemplate);
-  else if (!Conversion->getPrimaryTemplate()) // ignore specializations
+  else 
     ClassDecl->addConversionFunction(Conversion);
 
   return DeclPtrTy::make(Conversion);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index bf9d099..02af661 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1010,11 +1010,18 @@
 
   // C++ [temp.dep.expr]p3:
   //   An id-expression is type-dependent if it contains:
+  //     -- an identifier that was declared with a dependent type,
+  //        (note: handled after lookup)
+  //     -- a template-id that is dependent,
+  //        (note: handled in BuildTemplateIdExpr)
+  //     -- a conversion-function-id that specifies a dependent type,
   //     -- a nested-name-specifier that contains a class-name that
   //        names a dependent type.
   // Determine whether this is a member of an unknown specialization;
   // we need to handle these differently.
-  if (SS.isSet() && IsDependentIdExpression(*this, SS)) {
+  if ((Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
+       Name.getCXXNameType()->isDependentType()) ||
+      (SS.isSet() && IsDependentIdExpression(*this, SS))) {
     return ActOnDependentIdExpression(SS, Name, NameLoc,
                                       isAddressOfOperand,
                                       TemplateArgs);
@@ -2281,7 +2288,7 @@
     }
   }
 
-  assert(BaseType->isDependentType());
+  assert(BaseType->isDependentType() || Name.isDependentName());
 
   // Get the type being accessed in BaseType.  If this is an arrow, the BaseExpr
   // must have pointer type, and the accessed type is the pointee.
@@ -3170,7 +3177,7 @@
 
   Expr *Base = BaseArg.takeAs<Expr>();
   OwningExprResult Result(*this);
-  if (Base->getType()->isDependentType()) {
+  if (Base->getType()->isDependentType() || Name.isDependentName()) {
     Result = ActOnDependentMemberExpr(ExprArg(*this, Base), Base->getType(),
                                       IsArrow, OpLoc,
                                       SS, FirstQualifierInScope,
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 897ce20..a8c2366 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -444,10 +444,81 @@
   bool Found = false;
 
   DeclContext::lookup_const_iterator I, E;
-  for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I)
-    if (R.isAcceptableDecl(*I))
-      R.addDecl(*I), Found = true;
+  for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) {
+    if (R.isAcceptableDecl(*I)) {
+      R.addDecl(*I);
+      Found = true;
+    }
+  }
 
+  if (R.getLookupName().getNameKind()
+        == DeclarationName::CXXConversionFunctionName &&
+      !R.getLookupName().getCXXNameType()->isDependentType() &&
+      isa<CXXRecordDecl>(DC)) {
+    // C++ [temp.mem]p6:
+    //   A specialization of a conversion function template is not found by 
+    //   name lookup. Instead, any conversion function templates visible in the
+    //   context of the use are considered. [...]
+    const CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
+    
+    const UnresolvedSet *Unresolved = Record->getConversionFunctions();
+    for (UnresolvedSet::iterator U = Unresolved->begin(), 
+                              UEnd = Unresolved->end();
+         U != UEnd; ++U) {
+      FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U);
+      if (!ConvTemplate)
+        continue;
+      
+      // When we're performing lookup for the purposes of redeclaration, just
+      // add the conversion function template. When we deduce template 
+      // arguments for specializations, we'll end up unifying the return 
+      // type of the new declaration with the type of the function template.
+      if (R.isForRedeclaration()) {
+        R.addDecl(ConvTemplate);
+        Found = true;
+        continue;
+      }
+      
+      // C++ [temp.mem]p6:
+      //   [...] For each such operator, if argument deduction succeeds 
+      //   (14.9.2.3), the resulting specialization is used as if found by 
+      //   name lookup.
+      //
+      // When referencing a conversion function for any purpose other than
+      // a redeclaration (such that we'll be building an expression with the
+      // result), perform template argument deduction and place the 
+      // specialization into the result set. We do this to avoid forcing all
+      // callers to perform special deduction for conversion functions.
+      Sema::TemplateDeductionInfo Info(R.getSema().Context);
+      FunctionDecl *Specialization = 0;
+      
+      const FunctionProtoType *ConvProto        
+        = ConvTemplate->getTemplatedDecl()->getType()
+                                                  ->getAs<FunctionProtoType>();
+      assert(ConvProto && "Nonsensical conversion function template type");
+
+      // Compute the type of the function that we would expect the conversion
+      // function to have, if it were to match the name given.
+      // FIXME: Calling convention!
+      QualType ExpectedType
+        = R.getSema().Context.getFunctionType(
+                                            R.getLookupName().getCXXNameType(),
+                                              0, 0, ConvProto->isVariadic(),
+                                              ConvProto->getTypeQuals(),
+                                              false, false, 0, 0,
+                                              ConvProto->getNoReturnAttr());
+      
+      // Perform template argument deduction against the type that we would
+      // expect the function to have.
+      if (R.getSema().DeduceTemplateArguments(ConvTemplate, 0, ExpectedType,
+                                              Specialization, Info)
+            == Sema::TDK_Success) {
+        R.addDecl(Specialization);
+        Found = true;
+      }
+    }
+  }
+  
   return Found;
 }
 
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 825dabf..3dd85d9 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -2307,8 +2307,6 @@
   const FunctionProtoType* Proto
     = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
   assert(Proto && "Functions without a prototype cannot be overloaded");
-  assert(!isa<CXXConversionDecl>(Function) &&
-         "Use AddConversionCandidate for conversion functions");
   assert(!Function->getDescribedFunctionTemplate() &&
          "Use AddTemplateOverloadCandidate for function templates");
 
@@ -2509,8 +2507,6 @@
   const FunctionProtoType* Proto
     = dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
   assert(Proto && "Methods without a prototype cannot be overloaded");
-  assert(!isa<CXXConversionDecl>(Method) &&
-         "Use AddConversionCandidate for conversion functions");
   assert(!isa<CXXConstructorDecl>(Method) &&
          "Use AddOverloadCandidate for constructors");
 
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index ecb89ed..5ca8bfd 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -4540,8 +4540,10 @@
       if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
         if (Context.hasSameUnqualifiedType(Method->getType(), R)) {
           Matches.clear();
+
           Matches.push_back(Method);
-          break;
+          if (Method->getTemplateSpecializationKind() == TSK_Undeclared)
+            break;
         }
       }
     }
@@ -4553,7 +4555,7 @@
     TemplateDeductionInfo Info(Context);
     FunctionDecl *Specialization = 0;
     if (TemplateDeductionResult TDK
-          = DeduceTemplateArguments(FunTmpl,
+          = DeduceTemplateArguments(FunTmpl, 
                                (HasExplicitTemplateArgs ? &TemplateArgs : 0),
                                     R, Specialization, Info)) {
       // FIXME: Keep track of almost-matches?
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 40f3507..ea79d9f 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -1312,20 +1312,18 @@
 /// \param FunctionTemplate the function template for which we are performing
 /// template argument deduction.
 ///
-/// \param HasExplicitTemplateArgs whether any template arguments were
-/// explicitly specified.
-///
-/// \param ExplicitTemplateArguments when @p HasExplicitTemplateArgs is true,
-/// the explicitly-specified template arguments.
-///
-/// \param NumExplicitTemplateArguments when @p HasExplicitTemplateArgs is true,
-/// the number of explicitly-specified template arguments in
-/// @p ExplicitTemplateArguments. This value may be zero.
+/// \param ExplicitTemplateArguments the explicit template arguments provided
+/// for this call.
 ///
 /// \param Args the function call arguments
 ///
 /// \param NumArgs the number of arguments in Args
 ///
+/// \param Name the name of the function being called. This is only significant
+/// when the function template is a conversion function template, in which
+/// case this routine will also perform template argument deduction based on
+/// the function to which 
+///
 /// \param Specialization if template argument deduction was successful,
 /// this will be set to the function template specialization produced by
 /// template argument deduction.
@@ -1336,7 +1334,7 @@
 /// \returns the result of template argument deduction.
 Sema::TemplateDeductionResult
 Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
-                              const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                          const TemplateArgumentListInfo *ExplicitTemplateArgs,
                               Expr **Args, unsigned NumArgs,
                               FunctionDecl *&Specialization,
                               TemplateDeductionInfo &Info) {
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 86ad0a0..499160d 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -897,12 +897,16 @@
 
   case UnqualifiedId::IK_ConstructorName:
   case UnqualifiedId::IK_DestructorName:
-  case UnqualifiedId::IK_ConversionFunctionId:
     // Constructors and destructors don't have return types. Use
-    // "void" instead. Conversion operators will check their return
-    // types separately.
+    // "void" instead. 
     T = Context.VoidTy;
     break;
+
+  case UnqualifiedId::IK_ConversionFunctionId:
+    // The result type of a conversion function is the type that it
+    // converts to.
+    T = GetTypeFromParser(D.getName().ConversionFunctionId);
+    break;
   }
   
   if (T.isNull())
@@ -1041,7 +1045,8 @@
       const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
 
       // C99 6.7.5.3p1: The return type may not be a function or array type.
-      if (T->isArrayType() || T->isFunctionType()) {
+      if ((T->isArrayType() || T->isFunctionType()) &&
+          (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) {
         Diag(DeclType.Loc, diag::err_func_returning_array_function) << T;
         T = Context.IntTy;
         D.setInvalidType(true);