Implement deletion of explicitly defaulted default constructors.

We still don't parse out-of-line defaults correctly, which is needed to
get the full effect out of this patch.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131223 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 9a4afde..972d080 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1518,7 +1518,6 @@
   if (MD->isCopyAssignmentOperator())
     return Sema::CXXCopyAssignment;
 
-  llvm_unreachable("getSpecialMember on non-special member");
   return Sema::CXXInvalid;
 }
 
@@ -4220,9 +4219,6 @@
 
       isVirtualOkay = !isStatic;
     } else {
-      if (DefaultLoc.isValid())
-        Diag(DefaultLoc, diag::err_default_special_members);
-
       // Determine whether the function was written with a
       // prototype. This true when:
       //   - we're in C++ (where every function has a prototype),
@@ -4778,33 +4774,13 @@
         }
       }
 
-  // Check explicitly defaulted methods
-  // FIXME: This could be made better through CXXSpecialMember if it did
-  // default constructors (which it should rather than any constructor).
-  if (NewFD && DefaultLoc.isValid() && getLangOptions().CPlusPlus) {
-    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD)) {
-      if (CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(MD)) {
-        if (CD->isDefaultConstructor() || CD->isCopyOrMoveConstructor()) {
-          CD->setDefaulted();
-          CD->setExplicitlyDefaulted();
-          if (CD != CD->getCanonicalDecl() && CD->isDefaultConstructor())
-            CheckExplicitlyDefaultedDefaultConstructor(CD);
-          // FIXME: Do copy/move ctors here.
-        } else {
-          Diag(DefaultLoc, diag::err_default_special_members);
-        }
-      } else if (CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
-        DD->setDefaulted();
-        DD->setExplicitlyDefaulted();
-        // FIXME: Add a checking method
-      } else if (MD->isCopyAssignmentOperator() /* ||
-                 MD->isMoveAssignmentOperator() */) {
-        MD->setDefaulted();
-        MD->setExplicitlyDefaulted();
-        // FIXME: Add a checking method
-      } else {
-        Diag(DefaultLoc, diag::err_default_special_members);
-      }
+  if (DefaultLoc.isValid()) {
+    CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
+    if (MD && getSpecialMember(MD) != CXXInvalid) {
+      MD->setExplicitlyDefaulted();
+      MD->setDefaulted();
+    } else {
+      Diag(DefaultLoc, diag::err_default_special_members);
     }
   }
 
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index b00d73d..8ef3463 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3057,6 +3057,14 @@
     // We know there are no parameters.
     CD->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI));
   }
+
+  if (ShouldDeleteDefaultConstructor(CD)) {
+    if (First)
+      CD->setDeletedAsWritten();
+    else
+      Diag(CD->getLocation(), diag::err_out_of_line_default_deletes)
+        << getSpecialMember(CD);
+  }
 }
 
 bool Sema::ShouldDeleteDefaultConstructor(CXXConstructorDecl *CD) {