r183884 - C++11: If a class has a user-declared copy operation or destructor, the

Richard Smith richard-llvm at metafoo.co.uk
Wed Jun 12 20:23:43 PDT 2013


Author: rsmith
Date: Wed Jun 12 22:23:42 2013
New Revision: 183884

URL: http://llvm.org/viewvc/llvm-project?rev=183884&view=rev
Log:
C++11: If a class has a user-declared copy operation or destructor, the
implicit definition of a copy operation is deprecated. Add a warning for this
to -Wdeprecated. This warning is disabled by default for now, pending
investigation into how common this situation is.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/deprecated.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=183884&r1=183883&r2=183884&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Jun 12 22:23:42 2013
@@ -294,6 +294,11 @@ def warn_exception_spec_deprecated : War
   "dynamic exception specifications are deprecated">,
   InGroup<Deprecated>, DefaultIgnore;
 def note_exception_spec_deprecated : Note<"use '%0' instead">;
+def warn_deprecated_copy_operation : Warning<
+  "definition of implicit copy %select{constructor|assignment operator}1 "
+  "for %0 is deprecated because it has a user-declared "
+  "%select{copy %select{assignment operator|constructor}1|destructor}2">,
+  InGroup<Deprecated>, DefaultIgnore;
 
 def warn_global_constructor : Warning<
   "declaration requires a global constructor">,

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=183884&r1=183883&r2=183884&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Jun 12 22:23:42 2013
@@ -8808,6 +8808,58 @@ CXXMethodDecl *Sema::DeclareImplicitCopy
   return CopyAssignment;
 }
 
+/// Diagnose an implicit copy operation for a class which is odr-used, but
+/// which is deprecated because the class has a user-declared copy constructor,
+/// copy assignment operator, or destructor.
+static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp,
+                                            SourceLocation UseLoc) {
+  assert(CopyOp->isImplicit());
+
+  CXXRecordDecl *RD = CopyOp->getParent();
+  CXXMethodDecl *UserDeclaredOperation = 0;
+
+  // In Microsoft mode, assignment operations don't affect constructors and
+  // vice versa.
+  if (RD->hasUserDeclaredDestructor()) {
+    UserDeclaredOperation = RD->getDestructor();
+  } else if (!isa<CXXConstructorDecl>(CopyOp) &&
+             RD->hasUserDeclaredCopyConstructor() &&
+             !S.getLangOpts().MicrosoftMode) {
+    // Find any user-declared copy constructor.
+    for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(),
+                                      E = RD->ctor_end(); I != E; ++I) {
+      if (I->isCopyConstructor()) {
+        UserDeclaredOperation = *I;
+        break;
+      }
+    }
+    assert(UserDeclaredOperation);
+  } else if (isa<CXXConstructorDecl>(CopyOp) &&
+             RD->hasUserDeclaredCopyAssignment() &&
+             !S.getLangOpts().MicrosoftMode) {
+    // Find any user-declared move assignment operator.
+    for (CXXRecordDecl::method_iterator I = RD->method_begin(),
+                                        E = RD->method_end(); I != E; ++I) {
+      if (I->isCopyAssignmentOperator()) {
+        UserDeclaredOperation = *I;
+        break;
+      }
+    }
+    assert(UserDeclaredOperation);
+  }
+
+  if (UserDeclaredOperation) {
+    S.Diag(UserDeclaredOperation->getLocation(),
+         diag::warn_deprecated_copy_operation)
+      << RD << /*copy assignment*/!isa<CXXConstructorDecl>(CopyOp)
+      << /*destructor*/isa<CXXDestructorDecl>(UserDeclaredOperation);
+    S.Diag(UseLoc, diag::note_member_synthesized_at)
+      << (isa<CXXConstructorDecl>(CopyOp) ? Sema::CXXCopyConstructor
+                                          : Sema::CXXCopyAssignment)
+      << RD;
+  }
+}
+
 void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
                                         CXXMethodDecl *CopyAssignOperator) {
   assert((CopyAssignOperator->isDefaulted() && 
@@ -8823,7 +8875,14 @@ void Sema::DefineImplicitCopyAssignment(
     CopyAssignOperator->setInvalidDecl();
     return;
   }
-  
+
+  // C++11 [class.copy]p18:
+  //   The [definition of an implicitly declared copy assignment operator] is
+  //   deprecated if the class has a user-declared copy constructor or a
+  //   user-declared destructor.
+  if (getLangOpts().CPlusPlus11 && CopyAssignOperator->isImplicit())
+    diagnoseDeprecatedCopyOperation(*this, CopyAssignOperator, CurrentLocation);
+
   CopyAssignOperator->setUsed();
 
   SynthesizedFunctionScope Scope(*this, CopyAssignOperator);
@@ -9631,6 +9690,13 @@ void Sema::DefineImplicitCopyConstructor
   CXXRecordDecl *ClassDecl = CopyConstructor->getParent();
   assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
 
+  // C++11 [class.copy]p7:
+  //   The [definition of an implicitly declared copy constructro] is
+  //   deprecated if the class has a user-declared copy assignment operator
+  //   or a user-declared destructor.
+  if (getLangOpts().CPlusPlus11 && CopyConstructor->isImplicit())
+    diagnoseDeprecatedCopyOperation(*this, CopyConstructor, CurrentLocation);
+
   SynthesizedFunctionScope Scope(*this, CopyConstructor);
   DiagnosticErrorTrap Trap(Diags);
 

Modified: cfe/trunk/test/SemaCXX/deprecated.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/deprecated.cpp?rev=183884&r1=183883&r2=183884&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/deprecated.cpp (original)
+++ cfe/trunk/test/SemaCXX/deprecated.cpp Wed Jun 12 22:23:42 2013
@@ -33,3 +33,27 @@ struct T : private S {
   // expected-error at -4 {{ISO C++11 does not allow access declarations; use using declarations instead}}
 #endif
 };
+
+#if __cplusplus >= 201103L
+namespace DeprecatedCopy {
+  struct Assign {
+    Assign &operator=(const Assign&); // expected-warning {{definition of implicit copy constructor for 'Assign' is deprecated because it has a user-declared copy assignment operator}}
+  };
+  Assign a1, a2(a1); // expected-note {{implicit default copy constructor for 'Assign' first required here}}
+
+  struct Ctor {
+    Ctor();
+    Ctor(const Ctor&); // expected-warning {{definition of implicit copy assignment operator for 'Ctor' is deprecated because it has a user-declared copy constructor}}
+  };
+  Ctor b1, b2;
+  void f() { b1 = b2; } // expected-note {{implicit default copy assignment operator for 'Ctor' first required here}}
+
+  struct Dtor {
+    ~Dtor();
+    // expected-warning at -1 {{definition of implicit copy constructor for 'Dtor' is deprecated because it has a user-declared destructor}}
+    // expected-warning at -2 {{definition of implicit copy assignment operator for 'Dtor' is deprecated because it has a user-declared destructor}}
+  };
+  Dtor c1, c2(c1); // expected-note {{implicit default copy constructor for 'Dtor' first required here}}
+  void g() { c1 = c2; } // expected-note {{implicit default copy assignment operator for 'Dtor' first required here}}
+}
+#endif





More information about the cfe-commits mailing list