Introduce support for constructor templates, which can now be declared
and will participate in overload resolution. Unify the instantiation
of CXXMethodDecls and CXXConstructorDecls, which had already gotten
out-of-sync.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79658 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 078c32b..9e05b32 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -485,10 +485,25 @@
 
   // Build the instantiated method declaration.
   CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
-  CXXMethodDecl *Method
-    = CXXMethodDecl::Create(SemaRef.Context, Record, D->getLocation(), 
-                            D->getDeclName(), T, D->getDeclaratorInfo(),
-                            D->isStatic(), D->isInline());
+  CXXMethodDecl *Method = 0;
+  
+  DeclarationName Name = D->getDeclName();
+  CXXConstructorDecl *ConstructorD = dyn_cast<CXXConstructorDecl>(D);
+  if (ConstructorD) {
+    QualType ClassTy = SemaRef.Context.getTypeDeclType(Record);
+    Name = SemaRef.Context.DeclarationNames.getCXXConstructorName(
+                                    SemaRef.Context.getCanonicalType(ClassTy));
+    Method = CXXConstructorDecl::Create(SemaRef.Context, Record, 
+                                        ConstructorD->getLocation(), 
+                                        Name, T, 
+                                        ConstructorD->getDeclaratorInfo(),
+                                        ConstructorD->isExplicit(), 
+                                        ConstructorD->isInline(), false);
+  } else {
+    Method = CXXMethodDecl::Create(SemaRef.Context, Record, D->getLocation(), 
+                                   D->getDeclName(), T, D->getDeclaratorInfo(),
+                                   D->isStatic(), D->isInline());
+  }
 
   if (!FunctionTemplate)
     Method->setInstantiationOfMemberFunction(D);
@@ -507,15 +522,20 @@
   if (InitMethodInstantiation(Method, D))
     Method->setInvalidDecl();
 
-  NamedDecl *PrevDecl 
-    = SemaRef.LookupQualifiedName(Owner, Method->getDeclName(), 
-                                  Sema::LookupOrdinaryName, true);
-  // In C++, the previous declaration we find might be a tag type
-  // (class or enum). In this case, the new declaration will hide the
-  // tag type. Note that this does does not apply if we're declaring a
-  // typedef (C++ [dcl.typedef]p4).
-  if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag)
-    PrevDecl = 0;
+  NamedDecl *PrevDecl = 0;
+  
+  if (!FunctionTemplate) {
+    PrevDecl = SemaRef.LookupQualifiedName(Owner, Name, 
+                                           Sema::LookupOrdinaryName, true);
+  
+    // In C++, the previous declaration we find might be a tag type
+    // (class or enum). In this case, the new declaration will hide the
+    // tag type. Note that this does does not apply if we're declaring a
+    // typedef (C++ [dcl.typedef]p4).
+    if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag)
+      PrevDecl = 0;
+  }
+  
   bool Redeclaration = false;
   bool OverloadableAttrRequired = false;
   SemaRef.CheckFunctionDeclaration(Method, PrevDecl, Redeclaration,
@@ -528,60 +548,16 @@
                                               &TemplateArgs,
                                               InsertPos);
   else if (!Method->isInvalidDecl() || !PrevDecl)
-      Owner->addDecl(Method);
+    Owner->addDecl(Method);
+  
   return Method;
 }
 
 Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *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;
-
-  // Build the instantiated method declaration.
-  CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
-  QualType ClassTy = SemaRef.Context.getTypeDeclType(Record);
-  DeclarationName Name
-    = SemaRef.Context.DeclarationNames.getCXXConstructorName(
-                                 SemaRef.Context.getCanonicalType(ClassTy));
-  CXXConstructorDecl *Constructor
-    = CXXConstructorDecl::Create(SemaRef.Context, Record, D->getLocation(), 
-                                 Name, T, D->getDeclaratorInfo(),
-                                 D->isExplicit(), D->isInline(), false);
-  Constructor->setInstantiationOfMemberFunction(D);
-
-  // Attach the parameters
-  for (unsigned P = 0; P < Params.size(); ++P)
-    Params[P]->setOwningFunction(Constructor);
-  Constructor->setParams(SemaRef.Context, Params.data(), Params.size());
-
-  if (InitMethodInstantiation(Constructor, D))
-    Constructor->setInvalidDecl();
-
-  NamedDecl *PrevDecl 
-    = SemaRef.LookupQualifiedName(Owner, Name, Sema::LookupOrdinaryName, true);
-
-  // In C++, the previous declaration we find might be a tag type
-  // (class or enum). In this case, the new declaration will hide the
-  // tag type. Note that this does does not apply if we're declaring a
-  // typedef (C++ [dcl.typedef]p4).
-  if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag)
-    PrevDecl = 0;
-  bool Redeclaration = false;
-  bool OverloadableAttrRequired = false;
-  SemaRef.CheckFunctionDeclaration(Constructor, PrevDecl, Redeclaration,
-                                   /*FIXME:*/OverloadableAttrRequired);
-
-  Record->addedConstructor(SemaRef.Context, Constructor);
-  Owner->addDecl(Constructor);
-  return Constructor;
+  return VisitCXXMethodDecl(D);
 }
 
 Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
-  // FIXME: Look for existing, explicit specializations.
   Sema::LocalInstantiationScope Scope(SemaRef);
 
   llvm::SmallVector<ParmVarDecl *, 4> Params;