]> granicus.if.org Git - clang/commitdiff
Implement deletion of explicitly defaulted default constructors.
authorSean Hunt <scshunt@csclub.uwaterloo.ca>
Thu, 12 May 2011 03:51:48 +0000 (03:51 +0000)
committerSean Hunt <scshunt@csclub.uwaterloo.ca>
Thu, 12 May 2011 03:51:48 +0000 (03:51 +0000)
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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp

index c8ab2392bfdbabb3714cbaf00ad2c484d3d2e80e..2ab02d60e19d534fb6263694ccda27796822d0a5 100644 (file)
@@ -3632,6 +3632,10 @@ def err_defaulted_default_ctor_params : Error<
   "an explicitly-defaulted default constructor must have no parameters">;
 def err_incorrect_defaulted_exception_spec : Error<
   "exception specification of explicitly defaulted function is incorrect">;
+def err_out_of_line_default_deletes : Error<
+  "defaulting this %select{default constructor|copy constructor|copy "
+  "assignment operator|destructor}0 would delete it after its first "
+  "declaration">;
 
 def warn_array_index_precedes_bounds : Warning<
   "array index of '%0' indexes before the beginning of the array">,
index 9a4afde05784fc98181192f2a2c0ce9e2d8c0597..972d080fc967490a048b4dd01376973d5d8114da 100644 (file)
@@ -1518,7 +1518,6 @@ Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) {
   if (MD->isCopyAssignmentOperator())
     return Sema::CXXCopyAssignment;
 
-  llvm_unreachable("getSpecialMember on non-special member");
   return Sema::CXXInvalid;
 }
 
@@ -4220,9 +4219,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
 
       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 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
         }
       }
 
-  // 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);
     }
   }
 
index b00d73d93c8ed724d7843b35ebbb7ed1e92e414d..8ef3463f424fd768d494525749ea904647fbf726 100644 (file)
@@ -3057,6 +3057,14 @@ void Sema::CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *CD) {
     // 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) {