Template instantiation for constructors

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67623 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 89805a8..f21a462 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1654,6 +1654,8 @@
     return;
   }
 
+  // FIXME: Need to handle dependent types and expressions here.
+
   // We will treat direct-initialization as a copy-initialization:
   //    int x(1);  -as-> int x = 1;
   //    ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c);
@@ -1672,6 +1674,13 @@
   if (const ArrayType *Array = Context.getAsArrayType(DeclInitType))
     DeclInitType = Array->getElementType();
 
+  // FIXME: This isn't the right place to complete the type.
+  if (RequireCompleteType(VDecl->getLocation(), VDecl->getType(),
+                          diag::err_typecheck_decl_incomplete_type)) {
+    VDecl->setInvalidDecl();
+    return;
+  }
+
   if (VDecl->getType()->isRecordType()) {
     CXXConstructorDecl *Constructor
       = PerformInitializationByConstructor(DeclInitType,
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 685b9cf..4738dfb 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -44,6 +44,7 @@
     Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
     Decl *VisitEnumDecl(EnumDecl *D);
     Decl *VisitCXXMethodDecl(CXXMethodDecl *D);
+    Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D);
     Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
     Decl *VisitParmVarDecl(ParmVarDecl *D);
     Decl *VisitOriginalParmVarDecl(OriginalParmVarDecl *D);
@@ -247,6 +248,50 @@
   return Method;
 }
 
+Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+  llvm::SmallVector<ParmVarDecl *, 16> 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(ClassTy);
+  CXXConstructorDecl *Constructor
+    = CXXConstructorDecl::Create(SemaRef.Context, Record, D->getLocation(), 
+                                 Name, T, D->isExplicit(), D->isInline(), 
+                                 false);
+
+  // Attach the parameters
+  for (unsigned P = 0; P < Params.size(); ++P)
+    Params[P]->setOwningFunction(Constructor);
+  Constructor->setParams(SemaRef.Context, &Params[0], 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;
+  if (SemaRef.CheckFunctionDeclaration(Constructor, PrevDecl, Redeclaration,
+                                       /*FIXME:*/OverloadableAttrRequired))
+    Constructor->setInvalidDecl();
+
+  if (!Constructor->isInvalidDecl())
+    Owner->addDecl(Constructor);
+  return Constructor;
+}
+
 Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
   llvm::SmallVector<ParmVarDecl *, 16> Params;
   QualType T = InstantiateFunctionType(D, Params);