From: Richard Smith Date: Sun, 29 Apr 2012 06:32:34 +0000 (+0000) Subject: [class.copy]p23: Fix an assertion caused by incorrect argument numbering in a X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a2e76f56c60dbd4de3dc0fed02bb01bea4dcff81;p=clang [class.copy]p23: Fix an assertion caused by incorrect argument numbering in a diagnostic, add a test for this paragraph, and tighten up the diagnostic wording a little. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155784 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 887f908de8..2fc9d9a0aa 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2897,8 +2897,8 @@ def note_deleted_dtor_no_operator_delete : Note< def note_deleted_special_member_class_subobject : Note< "%select{default constructor|copy constructor|move constructor|" "copy assignment operator|move assignment operator|destructor}0 of " - "%select{||||union }4%1 is implicitly deleted because " - "%select{base class %3|field %3}2 has " + "%1 is implicitly deleted because " + "%select{base class %3|%select{||||variant }4field %3}2 has " "%select{no|a deleted|multiple|an inaccessible|a non-trivial}4 " "%select{%select{default constructor|copy constructor|move constructor|copy " "assignment operator|move assignment operator|destructor}0|destructor}5" @@ -2917,8 +2917,8 @@ def note_deleted_copy_user_declared_move : Note< "copy %select{constructor|assignment operator}0 is implicitly deleted because" " %1 has a user-declared move %select{constructor|assignment operator}2">; def note_deleted_assign_field : Note< - "%select{copy|move}0 assignment operator of %0 is implicitly deleted " - "because field %1 is of %select{reference|const-qualified}3 type %2">; + "%select{copy|move}0 assignment operator of %1 is implicitly deleted " + "because field %2 is of %select{reference|const-qualified}4 type %3">; // This should eventually be an error. def warn_undefined_internal : Warning< diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 6183942893..7312dbde28 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4549,7 +4549,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { (!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor())) { if (Diagnose) S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field) - << MD->getParent() << FD << FieldType << /*Const*/1; + << MD->getParent() << FD << FD->getType() << /*Const*/1; return true; } @@ -4577,7 +4577,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { // -- a non-static data member of const non-class type (or array thereof) if (Diagnose) S.Diag(FD->getLocation(), diag::note_deleted_assign_field) - << IsMove << MD->getParent() << FD << FieldType << /*Const*/1; + << IsMove << MD->getParent() << FD << FD->getType() << /*Const*/1; return true; } } diff --git a/test/CXX/special/class.copy/p11.0x.copy.cpp b/test/CXX/special/class.copy/p11.0x.copy.cpp index b2b4f6a87f..2274700c5b 100644 --- a/test/CXX/special/class.copy/p11.0x.copy.cpp +++ b/test/CXX/special/class.copy/p11.0x.copy.cpp @@ -8,7 +8,7 @@ struct NonTrivial { // -- a variant member with a non-trivial corresponding constructor union DeletedNTVariant { - NonTrivial NT; // expected-note{{copy constructor of union 'DeletedNTVariant' is implicitly deleted because field 'NT' has a non-trivial copy constructor}} + NonTrivial NT; // expected-note{{copy constructor of 'DeletedNTVariant' is implicitly deleted because variant field 'NT' has a non-trivial copy constructor}} DeletedNTVariant(); }; DeletedNTVariant DVa; @@ -16,7 +16,7 @@ DeletedNTVariant DVb(DVa); // expected-error{{call to implicitly-deleted copy co struct DeletedNTVariant2 { union { - NonTrivial NT; // expected-note{{copy constructor of union 'DeletedNTVariant2' is implicitly deleted because field 'NT' has a non-trivial copy constructor}} + NonTrivial NT; // expected-note{{copy constructor of 'DeletedNTVariant2' is implicitly deleted because variant field 'NT' has a non-trivial copy constructor}} }; DeletedNTVariant2(); }; diff --git a/test/CXX/special/class.copy/p23-cxx11.cpp b/test/CXX/special/class.copy/p23-cxx11.cpp new file mode 100644 index 0000000000..62a0843bfa --- /dev/null +++ b/test/CXX/special/class.copy/p23-cxx11.cpp @@ -0,0 +1,134 @@ +// RUN: %clang_cc1 -verify %s -std=c++11 + +template struct CopyAssign { + static T t; + void test() { + t = t; // expected-error +{{deleted}} + } +}; +template struct MoveAssign { + static T t; + void test() { + t = static_cast(t); // expected-error +{{deleted}} + } +}; + +struct NonTrivialCopyAssign { + NonTrivialCopyAssign &operator=(const NonTrivialCopyAssign &); +}; +struct NonTrivialMoveAssign { + NonTrivialMoveAssign &operator=(NonTrivialMoveAssign &&); +}; +struct AmbiguousCopyAssign { + AmbiguousCopyAssign &operator=(const AmbiguousCopyAssign &); + AmbiguousCopyAssign &operator=(volatile AmbiguousCopyAssign &); +}; +struct AmbiguousMoveAssign { + AmbiguousMoveAssign &operator=(const AmbiguousMoveAssign &&); + AmbiguousMoveAssign &operator=(volatile AmbiguousMoveAssign &&); +}; +struct DeletedCopyAssign { + DeletedCopyAssign &operator=(const DeletedCopyAssign &) = delete; // expected-note 2{{deleted}} +}; +struct DeletedMoveAssign { + DeletedMoveAssign &operator=(DeletedMoveAssign &&) = delete; // expected-note 2{{deleted}} +}; +class InaccessibleCopyAssign { + InaccessibleCopyAssign &operator=(const InaccessibleCopyAssign &); +}; +class InaccessibleMoveAssign { + InaccessibleMoveAssign &operator=(InaccessibleMoveAssign &&); +}; + +// A defaulted copy/move assignment operator for class X is defined as deleted +// if X has: + +// -- a variant member with a non-trivial corresponding assignment operator +// and X is a union-like class +struct A1 { + union { + NonTrivialCopyAssign x; // expected-note {{variant field 'x' has a non-trivial copy assign}} + }; +}; +template struct CopyAssign; // expected-note {{here}} + +struct A2 { + A2 &operator=(A2 &&) = default; // expected-note {{here}} + union { + NonTrivialMoveAssign x; // expected-note {{variant field 'x' has a non-trivial move assign}} + }; +}; +template struct MoveAssign; // expected-note {{here}} + +// -- a non-static const data member of (array of) non-class type +struct B1 { + const int a; // expected-note 2{{field 'a' is of const-qualified type}} +}; +struct B2 { + const void *const a[3][9][2]; // expected-note 2{{field 'a' is of const-qualified type 'const void *const [3][9][2]'}} +}; +struct B3 { + const void *a[3]; +}; +template struct CopyAssign; // expected-note {{here}} +template struct MoveAssign; // expected-note {{here}} +template struct CopyAssign; // expected-note {{here}} +template struct MoveAssign; // expected-note {{here}} +template struct CopyAssign; +template struct MoveAssign; + +// -- a non-static data member of reference type +struct C1 { + int &a; // expected-note 2{{field 'a' is of reference type 'int &'}} +}; +template struct CopyAssign; // expected-note {{here}} +template struct MoveAssign; // expected-note {{here}} + +// -- a non-static data member of class type M that cannot be copied/moved +struct D1 { + AmbiguousCopyAssign a; // expected-note {{field 'a' has multiple copy}} +}; +struct D2 { + D2 &operator=(D2 &&) = default; // expected-note {{here}} + AmbiguousMoveAssign a; // expected-note {{field 'a' has multiple move}} +}; +struct D3 { + DeletedCopyAssign a; // expected-note {{field 'a' has a deleted copy}} +}; +struct D4 { + D4 &operator=(D4 &&) = default; // expected-note {{here}} + DeletedMoveAssign a; // expected-note {{field 'a' has a deleted move}} +}; +struct D5 { + InaccessibleCopyAssign a; // expected-note {{field 'a' has an inaccessible copy}} +}; +struct D6 { + D6 &operator=(D6 &&) = default; // expected-note {{here}} + InaccessibleMoveAssign a; // expected-note {{field 'a' has an inaccessible move}} +}; +template struct CopyAssign; // expected-note {{here}} +template struct MoveAssign; // expected-note {{here}} +template struct CopyAssign; // expected-note {{here}} +template struct MoveAssign; // expected-note {{here}} +template struct CopyAssign; // expected-note {{here}} +template struct MoveAssign; // expected-note {{here}} + +// -- a direct or virtual base that cannot be copied/moved +struct E1 : AmbiguousCopyAssign {}; // expected-note {{base class 'AmbiguousCopyAssign' has multiple copy}} +struct E2 : AmbiguousMoveAssign { // expected-note {{base class 'AmbiguousMoveAssign' has multiple move}} + E2 &operator=(E2 &&) = default; // expected-note {{here}} +}; +struct E3 : DeletedCopyAssign {}; // expected-note {{base class 'DeletedCopyAssign' has a deleted copy}} +struct E4 : DeletedMoveAssign { // expected-note {{base class 'DeletedMoveAssign' has a deleted move}} + E4 &operator=(E4 &&) = default; // expected-note {{here}} +}; +struct E5 : InaccessibleCopyAssign {}; // expected-note {{base class 'InaccessibleCopyAssign' has an inaccessible copy}} +struct E6 : InaccessibleMoveAssign { // expected-note {{base class 'InaccessibleMoveAssign' has an inaccessible move}} + E6 &operator=(E6 &&) = default; // expected-note {{here}} +}; +template struct CopyAssign; // expected-note {{here}} +template struct MoveAssign; // expected-note {{here}} +template struct CopyAssign; // expected-note {{here}} +template struct MoveAssign; // expected-note {{here}} +template struct CopyAssign; // expected-note {{here}} +template struct MoveAssign; // expected-note {{here}} diff --git a/test/CXX/special/class.ctor/p5-0x.cpp b/test/CXX/special/class.ctor/p5-0x.cpp index 694ab5b175..1aaeef282a 100644 --- a/test/CXX/special/class.ctor/p5-0x.cpp +++ b/test/CXX/special/class.ctor/p5-0x.cpp @@ -21,7 +21,7 @@ int n; // - X is a union-like class that has a variant member with a non-trivial // default constructor, -union Deleted1a { UserProvidedDefCtor u; }; // expected-note {{default constructor of union 'Deleted1a' is implicitly deleted because field 'u' has a non-trivial default constructor}} +union Deleted1a { UserProvidedDefCtor u; }; // expected-note {{default constructor of 'Deleted1a' is implicitly deleted because variant field 'u' has a non-trivial default constructor}} Deleted1a d1a; // expected-error {{implicitly-deleted default constructor}} union NotDeleted1a { DefaultedDefCtor1 nu; }; NotDeleted1a nd1a; @@ -53,7 +53,7 @@ class Deleted3a { const int a; }; // expected-note {{because field 'a' of const- expected-warning {{does not declare any constructor}} \ expected-note {{will never be initialized}} Deleted3a d3a; // expected-error {{implicitly-deleted default constructor}} -class Deleted3b { const DefaultedDefCtor1 a[42]; }; // expected-note {{because field 'a' of const-qualified type 'const DefaultedDefCtor1' would not be initialized}} +class Deleted3b { const DefaultedDefCtor1 a[42]; }; // expected-note {{because field 'a' of const-qualified type 'const DefaultedDefCtor1 [42]' would not be initialized}} Deleted3b d3b; // expected-error {{implicitly-deleted default constructor}} class Deleted3c { const DefaultedDefCtor2 a; }; // expected-note {{because field 'a' of const-qualified type 'const DefaultedDefCtor2' would not be initialized}} Deleted3c d3c; // expected-error {{implicitly-deleted default constructor}} @@ -77,7 +77,7 @@ NotDeleted3g nd3g; union Deleted4a { const int a; const int b; - const UserProvidedDefCtor c; // expected-note {{because field 'c' has a non-trivial default constructor}} + const UserProvidedDefCtor c; // expected-note {{because variant field 'c' has a non-trivial default constructor}} }; Deleted4a d4a; // expected-error {{implicitly-deleted default constructor}} union NotDeleted4a { const int a; int b; }; diff --git a/test/CXX/special/class.dtor/p5-0x.cpp b/test/CXX/special/class.dtor/p5-0x.cpp index dbfa004440..0d073cea52 100644 --- a/test/CXX/special/class.dtor/p5-0x.cpp +++ b/test/CXX/special/class.dtor/p5-0x.cpp @@ -16,25 +16,25 @@ class InaccessibleDtor { // destructor. union A1 { A1(); - NonTrivDtor n; // expected-note {{destructor of union 'A1' is implicitly deleted because field 'n' has a non-trivial destructor}} + NonTrivDtor n; // expected-note {{destructor of 'A1' is implicitly deleted because variant field 'n' has a non-trivial destructor}} }; A1 a1; // expected-error {{deleted function}} struct A2 { A2(); union { - NonTrivDtor n; // expected-note {{because field 'n' has a non-trivial destructor}} + NonTrivDtor n; // expected-note {{because variant field 'n' has a non-trivial destructor}} }; }; A2 a2; // expected-error {{deleted function}} union A3 { A3(); - NonTrivDtor n[3]; // expected-note {{because field 'n' has a non-trivial destructor}} + NonTrivDtor n[3]; // expected-note {{because variant field 'n' has a non-trivial destructor}} }; A3 a3; // expected-error {{deleted function}} struct A4 { A4(); union { - NonTrivDtor n[3]; // expected-note {{because field 'n' has a non-trivial destructor}} + NonTrivDtor n[3]; // expected-note {{because variant field 'n' has a non-trivial destructor}} }; }; A4 a4; // expected-error {{deleted function}}