Implement conversion function templates, along with the ability to use
template argument deduction from a conversion function (C++
[temp.deduct.conv]) with implicit conversions.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79693 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index ff97631..ded49b3 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -505,6 +505,17 @@
     Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
                                        Destructor->getLocation(), Name,
                                        T, Destructor->isInline(), false);
+  } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
+    CanQualType ConvTy 
+      = SemaRef.Context.getCanonicalType(
+                                      T->getAsFunctionType()->getResultType());
+    Name = SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
+                                                                      ConvTy);
+    Method = CXXConversionDecl::Create(SemaRef.Context, Record,
+                                       Conversion->getLocation(), Name,
+                                       T, Conversion->getDeclaratorInfo(),
+                                       Conversion->isInline(), 
+                                       Conversion->isExplicit());
   } else {
     Method = CXXMethodDecl::Create(SemaRef.Context, Record, D->getLocation(), 
                                    D->getDeclName(), T, D->getDeclaratorInfo(),
@@ -541,11 +552,6 @@
     if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag)
       PrevDecl = 0;
   }
-  
-  bool Redeclaration = false;
-  bool OverloadableAttrRequired = false;
-  SemaRef.CheckFunctionDeclaration(Method, PrevDecl, Redeclaration,
-                                   /*FIXME:*/OverloadableAttrRequired);
 
   if (FunctionTemplate)
     // Record this function template specialization.
@@ -553,7 +559,13 @@
                                               FunctionTemplate,
                                               &TemplateArgs,
                                               InsertPos);
-  else if (!Method->isInvalidDecl() || !PrevDecl)
+  
+  bool Redeclaration = false;
+  bool OverloadableAttrRequired = false;
+  SemaRef.CheckFunctionDeclaration(Method, PrevDecl, Redeclaration,
+                                   /*FIXME:*/OverloadableAttrRequired);
+
+  if (!FunctionTemplate && (!Method->isInvalidDecl() || !PrevDecl))
     Owner->addDecl(Method);
   
   return Method;
@@ -568,37 +580,7 @@
 }
 
 Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
-  // FIXME: Look for existing, explicit specializations.
-  Sema::LocalInstantiationScope Scope(SemaRef);
-
-  llvm::SmallVector<ParmVarDecl *, 4> Params;
-  QualType T = InstantiateFunctionType(D, Params);
-  if (T.isNull())
-    return 0;
-  assert(Params.size() == 0 && "Destructor with parameters?");
-
-  // Build the instantiated conversion declaration.
-  CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
-  QualType ClassTy = SemaRef.Context.getTypeDeclType(Record);
-  CanQualType ConvTy 
-    = SemaRef.Context.getCanonicalType(T->getAsFunctionType()->getResultType());
-  CXXConversionDecl *Conversion
-    = CXXConversionDecl::Create(SemaRef.Context, Record,
-                                D->getLocation(),
-         SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(ConvTy),
-                                T, D->getDeclaratorInfo(),
-                                D->isInline(), D->isExplicit());
-  Conversion->setInstantiationOfMemberFunction(D);
-  if (InitMethodInstantiation(Conversion, D))
-    Conversion->setInvalidDecl();
-
-  bool Redeclaration = false;
-  bool OverloadableAttrRequired = false;
-  NamedDecl *PrevDecl = 0;
-  SemaRef.CheckFunctionDeclaration(Conversion, PrevDecl, Redeclaration,
-                                   /*FIXME:*/OverloadableAttrRequired);
-  Owner->addDecl(Conversion);
-  return Conversion;  
+  return VisitCXXMethodDecl(D);
 }
 
 ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {