forked from OSchip/llvm-project
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. llvm-svn: 183884
This commit is contained in:
parent
4055de40ab
commit
d577fbbd1c
|
@ -294,6 +294,11 @@ def warn_exception_spec_deprecated : Warning<
|
|||
"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">,
|
||||
|
|
|
@ -8808,6 +8808,58 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
|
|||
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(SourceLocation CurrentLocation,
|
|||
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(SourceLocation CurrentLocation,
|
|||
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);
|
||||
|
||||
|
|
|
@ -33,3 +33,27 @@ struct T : private S {
|
|||
// expected-error@-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@-1 {{definition of implicit copy constructor for 'Dtor' is deprecated because it has a user-declared destructor}}
|
||||
// expected-warning@-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
|
||||
|
|
Loading…
Reference in New Issue