When a special member is explicitly defaulted outside its class, and we reject

the defaulting because it would delete the member, produce additional notes
explaining why the member is implicitly deleted.

llvm-svn: 199829
This commit is contained in:
Richard Smith 2014-01-22 20:09:10 +00:00
parent 80429048db
commit 566184ac75
4 changed files with 25 additions and 18 deletions

View File

@ -4917,6 +4917,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
// [For a] user-provided explicitly-defaulted function [...] if such a // [For a] user-provided explicitly-defaulted function [...] if such a
// function is implicitly defined as deleted, the program is ill-formed. // function is implicitly defined as deleted, the program is ill-formed.
Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM; Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM;
ShouldDeleteSpecialMember(MD, CSM, /*Diagnose*/true);
HadError = true; HadError = true;
} }
} }

View File

@ -143,7 +143,7 @@ namespace PR13381 {
namespace Mutable { namespace Mutable {
struct A { struct A {
A(const A &); A(const A &);
A(A &) = delete; A(A &) = delete; // expected-note {{deleted here}}
}; };
struct B { struct B {
@ -153,7 +153,7 @@ namespace Mutable {
B::B(const B &) = default; B::B(const B &) = default;
struct C { struct C {
mutable A a; mutable A a; // expected-note {{deleted because field 'a' has a deleted copy constructor}}
C(const C &); C(const C &);
}; };
C::C(const C &) = default; // expected-error{{would delete}} C::C(const C &) = default; // expected-error{{would delete}}

View File

@ -2,21 +2,21 @@
struct Trivial {}; struct Trivial {};
struct NonTrivial { struct NonTrivial {
NonTrivial(NonTrivial&&); NonTrivial(NonTrivial&&); // expected-note{{copy constructor is implicitly deleted}}
}; };
// A defaulted move constructor for a class X is defined as deleted if X has: // A defaulted move constructor for a class X is defined as deleted if X has:
// -- a variant member with a non-trivial corresponding constructor // -- a variant member with a non-trivial corresponding constructor
union DeletedNTVariant { union DeletedNTVariant {
NonTrivial NT; NonTrivial NT; // expected-note{{deleted because variant field 'NT' has a non-trivial move constructor}}
DeletedNTVariant(DeletedNTVariant&&); DeletedNTVariant(DeletedNTVariant&&);
}; };
DeletedNTVariant::DeletedNTVariant(DeletedNTVariant&&) = default; // expected-error{{would delete}} DeletedNTVariant::DeletedNTVariant(DeletedNTVariant&&) = default; // expected-error{{would delete}}
struct DeletedNTVariant2 { struct DeletedNTVariant2 {
union { union {
NonTrivial NT; NonTrivial NT; // expected-note{{deleted because variant field 'NT' has a non-trivial move constructor}}
}; };
DeletedNTVariant2(DeletedNTVariant2&&); DeletedNTVariant2(DeletedNTVariant2&&);
}; };
@ -34,7 +34,7 @@ private:
}; };
struct HasNoAccess { struct HasNoAccess {
NoAccess NA; NoAccess NA; // expected-note{{deleted because field 'NA' has an inaccessible move constructor}}
HasNoAccess(HasNoAccess&&); HasNoAccess(HasNoAccess&&);
}; };
HasNoAccess::HasNoAccess(HasNoAccess&&) = default; // expected-error{{would delete}} HasNoAccess::HasNoAccess(HasNoAccess&&) = default; // expected-error{{would delete}}
@ -51,13 +51,16 @@ struct Ambiguity {
}; };
struct IsAmbiguous { struct IsAmbiguous {
Ambiguity A; Ambiguity A; // expected-note{{deleted because field 'A' has multiple move constructors}}
IsAmbiguous(IsAmbiguous&&); IsAmbiguous(IsAmbiguous&&); // expected-note{{copy constructor is implicitly deleted because 'IsAmbiguous' has a user-declared move constructor}}
}; };
IsAmbiguous::IsAmbiguous(IsAmbiguous&&) = default; // expected-error{{would delete}} IsAmbiguous::IsAmbiguous(IsAmbiguous&&) = default; // expected-error{{would delete}}
struct Deleted { struct Deleted {
IsAmbiguous IA; // FIXME: This diagnostic is slightly wrong: the constructor we select to move
// 'IA' is deleted, but we select the copy constructor (we ignore the move
// constructor, because it was defaulted and deleted).
IsAmbiguous IA; // expected-note{{deleted because field 'IA' has a deleted move constructor}}
Deleted(Deleted&&); Deleted(Deleted&&);
}; };
Deleted::Deleted(Deleted&&) = default; // expected-error{{would delete}} Deleted::Deleted(Deleted&&) = default; // expected-error{{would delete}}
@ -70,12 +73,15 @@ struct ConstMember {
}; };
ConstMember::ConstMember(ConstMember&&) = default; // ok, calls copy ctor ConstMember::ConstMember(ConstMember&&) = default; // ok, calls copy ctor
struct ConstMoveOnlyMember { struct ConstMoveOnlyMember {
const NonTrivial cnt; // FIXME: This diagnostic is slightly wrong: the constructor we select to move
// 'cnt' is deleted, but we select the copy constructor, because the object is
// const.
const NonTrivial cnt; // expected-note{{deleted because field 'cnt' has a deleted move constructor}}
ConstMoveOnlyMember(ConstMoveOnlyMember&&); ConstMoveOnlyMember(ConstMoveOnlyMember&&);
}; };
ConstMoveOnlyMember::ConstMoveOnlyMember(ConstMoveOnlyMember&&) = default; // expected-error{{would delete}} ConstMoveOnlyMember::ConstMoveOnlyMember(ConstMoveOnlyMember&&) = default; // expected-error{{would delete}}
struct VolatileMember { struct VolatileMember {
volatile Trivial vt; volatile Trivial vt; // expected-note{{deleted because field 'vt' has no move constructor}}
VolatileMember(VolatileMember&&); VolatileMember(VolatileMember&&);
}; };
VolatileMember::VolatileMember(VolatileMember&&) = default; // expected-error{{would delete}} VolatileMember::VolatileMember(VolatileMember&&) = default; // expected-error{{would delete}}
@ -83,17 +89,17 @@ VolatileMember::VolatileMember(VolatileMember&&) = default; // expected-error{{w
// -- a direct or virtual base class B that cannot be moved because overload // -- a direct or virtual base class B that cannot be moved because overload
// resolution results in an ambiguity or a function that is deleted or // resolution results in an ambiguity or a function that is deleted or
// inaccessible // inaccessible
struct AmbiguousMoveBase : Ambiguity { struct AmbiguousMoveBase : Ambiguity { // expected-note{{deleted because base class 'Ambiguity' has multiple move constructors}}
AmbiguousMoveBase(AmbiguousMoveBase&&); AmbiguousMoveBase(AmbiguousMoveBase&&); // expected-note{{copy constructor is implicitly deleted}}
}; };
AmbiguousMoveBase::AmbiguousMoveBase(AmbiguousMoveBase&&) = default; // expected-error{{would delete}} AmbiguousMoveBase::AmbiguousMoveBase(AmbiguousMoveBase&&) = default; // expected-error{{would delete}}
struct DeletedMoveBase : AmbiguousMoveBase { struct DeletedMoveBase : AmbiguousMoveBase { // expected-note{{deleted because base class 'AmbiguousMoveBase' has a deleted move constructor}}
DeletedMoveBase(DeletedMoveBase&&); DeletedMoveBase(DeletedMoveBase&&);
}; };
DeletedMoveBase::DeletedMoveBase(DeletedMoveBase&&) = default; // expected-error{{would delete}} DeletedMoveBase::DeletedMoveBase(DeletedMoveBase&&) = default; // expected-error{{would delete}}
struct InaccessibleMoveBase : NoAccess { struct InaccessibleMoveBase : NoAccess { // expected-note{{deleted because base class 'NoAccess' has an inaccessible move constructor}}
InaccessibleMoveBase(InaccessibleMoveBase&&); InaccessibleMoveBase(InaccessibleMoveBase&&);
}; };
InaccessibleMoveBase::InaccessibleMoveBase(InaccessibleMoveBase&&) = default; // expected-error{{would delete}} InaccessibleMoveBase::InaccessibleMoveBase(InaccessibleMoveBase&&) = default; // expected-error{{would delete}}
@ -108,7 +114,7 @@ private:
}; };
struct HasNoAccessDtor { struct HasNoAccessDtor {
NoAccessDtor NAD; NoAccessDtor NAD; // expected-note {{deleted because field 'NAD' has an inaccessible destructor}}
HasNoAccessDtor(HasNoAccessDtor&&); HasNoAccessDtor(HasNoAccessDtor&&);
}; };
HasNoAccessDtor::HasNoAccessDtor(HasNoAccessDtor&&) = default; // expected-error{{would delete}} HasNoAccessDtor::HasNoAccessDtor(HasNoAccessDtor&&) = default; // expected-error{{would delete}}

View File

@ -59,7 +59,7 @@ struct good_const {
good_const gc; good_const gc;
struct no_default { struct no_default {
no_default() = delete; // expected-note 3{{deleted here}} no_default() = delete; // expected-note 4{{deleted here}}
}; };
struct no_dtor { struct no_dtor {
~no_dtor() = delete; // expected-note 2{{deleted here}} ~no_dtor() = delete; // expected-note 2{{deleted here}}
@ -114,7 +114,7 @@ struct defaulted_delete {
defaulted_delete dd; // expected-error {{call to implicitly-deleted default constructor}} defaulted_delete dd; // expected-error {{call to implicitly-deleted default constructor}}
struct late_delete { struct late_delete {
no_default nd; no_default nd; // expected-note {{because field 'nd' has a deleted default constructor}}
late_delete(); late_delete();
}; };
late_delete::late_delete() = default; // expected-error {{would delete it}} late_delete::late_delete() = default; // expected-error {{would delete it}}