From b454a471ee33efa50fb367b2a81cd00f4e7b9ed3 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 22 Jan 2014 20:09:10 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@199829 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDeclCXX.cpp | 1 + test/CXX/special/class.copy/p11.0x.copy.cpp | 4 +-- test/CXX/special/class.copy/p11.0x.move.cpp | 34 ++++++++++++--------- test/SemaCXX/cxx0x-deleted-default-ctor.cpp | 4 +-- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 3fe6337d50..019b1c189c 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4917,6 +4917,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // [For a] user-provided explicitly-defaulted function [...] if such a // function is implicitly defined as deleted, the program is ill-formed. Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM; + ShouldDeleteSpecialMember(MD, CSM, /*Diagnose*/true); HadError = true; } } diff --git a/test/CXX/special/class.copy/p11.0x.copy.cpp b/test/CXX/special/class.copy/p11.0x.copy.cpp index 19e7683608..1ca0143d09 100644 --- a/test/CXX/special/class.copy/p11.0x.copy.cpp +++ b/test/CXX/special/class.copy/p11.0x.copy.cpp @@ -143,7 +143,7 @@ namespace PR13381 { namespace Mutable { struct A { A(const A &); - A(A &) = delete; + A(A &) = delete; // expected-note {{deleted here}} }; struct B { @@ -153,7 +153,7 @@ namespace Mutable { B::B(const B &) = default; struct C { - mutable A a; + mutable A a; // expected-note {{deleted because field 'a' has a deleted copy constructor}} C(const C &); }; C::C(const C &) = default; // expected-error{{would delete}} diff --git a/test/CXX/special/class.copy/p11.0x.move.cpp b/test/CXX/special/class.copy/p11.0x.move.cpp index 1dce27a832..514817d2b7 100644 --- a/test/CXX/special/class.copy/p11.0x.move.cpp +++ b/test/CXX/special/class.copy/p11.0x.move.cpp @@ -2,21 +2,21 @@ struct Trivial {}; 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 variant member with a non-trivial corresponding constructor union DeletedNTVariant { - NonTrivial NT; + NonTrivial NT; // expected-note{{deleted because variant field 'NT' has a non-trivial move constructor}} DeletedNTVariant(DeletedNTVariant&&); }; DeletedNTVariant::DeletedNTVariant(DeletedNTVariant&&) = default; // expected-error{{would delete}} struct DeletedNTVariant2 { union { - NonTrivial NT; + NonTrivial NT; // expected-note{{deleted because variant field 'NT' has a non-trivial move constructor}} }; DeletedNTVariant2(DeletedNTVariant2&&); }; @@ -34,7 +34,7 @@ private: }; struct HasNoAccess { - NoAccess NA; + NoAccess NA; // expected-note{{deleted because field 'NA' has an inaccessible move constructor}} HasNoAccess(HasNoAccess&&); }; HasNoAccess::HasNoAccess(HasNoAccess&&) = default; // expected-error{{would delete}} @@ -51,13 +51,16 @@ struct Ambiguity { }; struct IsAmbiguous { - Ambiguity A; - IsAmbiguous(IsAmbiguous&&); + Ambiguity A; // expected-note{{deleted because field 'A' has multiple move constructors}} + 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}} 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&&) = default; // expected-error{{would delete}} @@ -70,12 +73,15 @@ struct ConstMember { }; ConstMember::ConstMember(ConstMember&&) = default; // ok, calls copy ctor 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&&) = default; // expected-error{{would delete}} struct VolatileMember { - volatile Trivial vt; + volatile Trivial vt; // expected-note{{deleted because field 'vt' has no move constructor}} VolatileMember(VolatileMember&&); }; 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 // resolution results in an ambiguity or a function that is deleted or // inaccessible -struct AmbiguousMoveBase : Ambiguity { - AmbiguousMoveBase(AmbiguousMoveBase&&); +struct AmbiguousMoveBase : Ambiguity { // expected-note{{deleted because base class 'Ambiguity' has multiple move constructors}} + AmbiguousMoveBase(AmbiguousMoveBase&&); // expected-note{{copy constructor is implicitly deleted}} }; 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&&) = 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&&) = default; // expected-error{{would delete}} @@ -108,7 +114,7 @@ private: }; struct HasNoAccessDtor { - NoAccessDtor NAD; + NoAccessDtor NAD; // expected-note {{deleted because field 'NAD' has an inaccessible destructor}} HasNoAccessDtor(HasNoAccessDtor&&); }; HasNoAccessDtor::HasNoAccessDtor(HasNoAccessDtor&&) = default; // expected-error{{would delete}} diff --git a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp index 0cebc10ade..b9af67948b 100644 --- a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp +++ b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp @@ -59,7 +59,7 @@ struct good_const { good_const gc; struct no_default { - no_default() = delete; // expected-note 3{{deleted here}} + no_default() = delete; // expected-note 4{{deleted here}} }; struct no_dtor { ~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}} 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() = default; // expected-error {{would delete it}} -- 2.40.0