Implement explicit specialization of explicitly-defaulted constructors.
The general out-of-line case (including explicit instantiation mostly
works except that the definition is being lost somewhere between the AST
and CodeGen, so the definition is never emitted.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131933 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 9d8ab64..e8f2f57 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -6011,7 +6011,8 @@
 void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
                                             CXXConstructorDecl *Constructor) {
   assert((Constructor->isDefaulted() && Constructor->isDefaultConstructor() &&
-          !Constructor->isUsed(false) && !Constructor->isDeleted()) &&
+          !Constructor->doesThisDeclarationHaveABody() &&
+          !Constructor->isDeleted()) &&
     "DefineImplicitDefaultConstructor - call it for implicit default ctor");
 
   CXXRecordDecl *ClassDecl = Constructor->getParent();
@@ -6303,7 +6304,8 @@
 
 void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
                                     CXXDestructorDecl *Destructor) {
-  assert((Destructor->isDefaulted() && !Destructor->isUsed(false)) &&
+  assert((Destructor->isDefaulted() &&
+          !Destructor->doesThisDeclarationHaveABody()) &&
          "DefineImplicitDestructor - call it for implicit default dtor");
   CXXRecordDecl *ClassDecl = Destructor->getParent();
   assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
@@ -6750,7 +6752,7 @@
   assert((CopyAssignOperator->isDefaulted() && 
           CopyAssignOperator->isOverloadedOperator() &&
           CopyAssignOperator->getOverloadedOperator() == OO_Equal &&
-          !CopyAssignOperator->isUsed(false)) &&
+          !CopyAssignOperator->doesThisDeclarationHaveABody()) &&
          "DefineImplicitCopyAssignment called for wrong function");
 
   CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent();
@@ -7228,7 +7230,7 @@
                                    CXXConstructorDecl *CopyConstructor) {
   assert((CopyConstructor->isDefaulted() &&
           CopyConstructor->isCopyConstructor() &&
-          !CopyConstructor->isUsed(false)) &&
+          !CopyConstructor->doesThisDeclarationHaveABody()) &&
          "DefineImplicitCopyConstructor - call it for implicit copy ctor");
 
   CXXRecordDecl *ClassDecl = CopyConstructor->getParent();
@@ -8673,8 +8675,15 @@
     MD->setDefaulted();
     MD->setExplicitlyDefaulted();
 
-    // We'll check it when the record is done
-    if (MD == MD->getCanonicalDecl())
+    // If this definition appears within the record, do the checking when
+    // the record is complete.
+    const FunctionDecl *Primary = MD;
+    if (MD->getTemplatedKind() != FunctionDecl::TK_NonTemplate)
+      // Find the uninstantiated declaration that actually had the '= default'
+      // on it.
+      MD->getTemplateInstantiationPattern()->isDefined(Primary);
+
+    if (Primary == Primary->getCanonicalDecl())
       return;
 
     switch (Member) {
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index fb34d9f..2481bd0 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2320,6 +2320,9 @@
   Stmt *Pattern = 0;
   if (PatternDecl)
     Pattern = PatternDecl->getBody(PatternDecl);
+  if (!Pattern)
+    // Try to find a defaulted definition
+    PatternDecl->isDefined(PatternDecl);
 
   // Postpone late parsed template instantiations.
   if (PatternDecl && PatternDecl->isLateTemplateParsed() &&
@@ -2337,7 +2340,7 @@
     Pattern = PatternDecl->getBody(PatternDecl);
   }
 
-  if (!Pattern) {
+  if (!Pattern && !PatternDecl->isDefaulted()) {
     if (DefinitionRequired) {
       if (Function->getPrimaryTemplate())
         Diag(PointOfInstantiation, 
@@ -2432,22 +2435,30 @@
   MultiLevelTemplateArgumentList TemplateArgs =
     getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
 
-  // If this is a constructor, instantiate the member initializers.
-  if (const CXXConstructorDecl *Ctor =
-        dyn_cast<CXXConstructorDecl>(PatternDecl)) {
-    InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor,
-                               TemplateArgs);
+  if (PatternDecl->isDefaulted()) {
+    ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true);
+
+    SetDeclDefaulted(Function, PatternDecl->getLocation());
+
+    return;
+  } else {
+    // If this is a constructor, instantiate the member initializers.
+    if (const CXXConstructorDecl *Ctor =
+          dyn_cast<CXXConstructorDecl>(PatternDecl)) {
+      InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor,
+                                 TemplateArgs);
+    }
+
+    // Instantiate the function body.
+    StmtResult Body = SubstStmt(Pattern, TemplateArgs);
+
+    if (Body.isInvalid())
+      Function->setInvalidDecl();
+    
+    ActOnFinishFunctionBody(Function, Body.get(),
+                            /*IsInstantiation=*/true);
   }
 
-  // Instantiate the function body.
-  StmtResult Body = SubstStmt(Pattern, TemplateArgs);
-
-  if (Body.isInvalid())
-    Function->setInvalidDecl();
-  
-  ActOnFinishFunctionBody(Function, Body.get(),
-                          /*IsInstantiation=*/true);
-
   PerformDependentDiagnostics(PatternDecl, TemplateArgs);
 
   savedContext.pop();