Author: James Y Knight Date: 2022-05-25T14:20:11-04:00 New Revision: 997b072e10d2be09c0e1a5bf4d6b92e2da3b8cc6
URL: https://github.com/llvm/llvm-project/commit/997b072e10d2be09c0e1a5bf4d6b92e2da3b8cc6 DIFF: https://github.com/llvm/llvm-project/commit/997b072e10d2be09c0e1a5bf4d6b92e2da3b8cc6.diff LOG: C++ DR2394: Const-default-constructible for members. Const class members may be initialized with a defaulted default constructor under the same conditions it would be allowed for a const object elsewhere. Differential Revision: https://reviews.llvm.org/D126170 Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaDeclCXX.cpp clang/test/CXX/drs/dr23xx.cpp clang/test/CXX/special/class.ctor/p5-0x.cpp clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp clang/www/cxx_dr_status.html Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a457a8fb2efe4..c34d29c8762d4 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -155,6 +155,9 @@ Bug Fixes a coroutine will no longer generate a call to a global allocation function with the signature (std::size_t, p0, ..., pn). This fixes Issue `Issue 54881 <https://github.com/llvm/llvm-project/issues/54881>`_. +- Implement `CWG 2394 <https://wg21.link/cwg2394>`_: Const class members + may be initialized with a defaulted default constructor under the same + conditions it would be allowed for a const object elsewhere. Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index a16fe0b1b72a4..c470a46f58477 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -9213,13 +9213,12 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { << !!ICI << MD->getParent() << FD << FieldType << /*Reference*/0; return true; } - // C++11 [class.ctor]p5: any non-variant non-static data member of - // const-qualified type (or array thereof) with no - // brace-or-equal-initializer does not have a user-provided default - // constructor. + // C++11 [class.ctor]p5 (modified by DR2394): any non-variant non-static + // data member of const-qualified type (or array thereof) with no + // brace-or-equal-initializer is not const-default-constructible. if (!inUnion() && FieldType.isConstQualified() && !FD->hasInClassInitializer() && - (!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor())) { + (!FieldRecord || !FieldRecord->allowConstDefaultInit())) { if (Diagnose) S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field) << !!ICI << MD->getParent() << FD << FD->getType() << /*Const*/1; diff --git a/clang/test/CXX/drs/dr23xx.cpp b/clang/test/CXX/drs/dr23xx.cpp index a7ff2a5813ed0..8d6b4a5dc16ea 100644 --- a/clang/test/CXX/drs/dr23xx.cpp +++ b/clang/test/CXX/drs/dr23xx.cpp @@ -158,3 +158,14 @@ void g() { } } //namespace dr2303 #endif + +namespace dr2394 { // dr2394: 15 + +struct A {}; +const A a; + +// Now allowed to default-init B. +struct B { const A a; }; +B b; + +} diff --git a/clang/test/CXX/special/class.ctor/p5-0x.cpp b/clang/test/CXX/special/class.ctor/p5-0x.cpp index 67f0d2a935744..c433df64a7cf4 100644 --- a/clang/test/CXX/special/class.ctor/p5-0x.cpp +++ b/clang/test/CXX/special/class.ctor/p5-0x.cpp @@ -2,6 +2,8 @@ struct DefaultedDefCtor1 {}; struct DefaultedDefCtor2 { DefaultedDefCtor2() = default; }; +struct DefaultedDefCtorUninitialized1 { int x; }; +struct DefaultedDefCtorUninitialized2 { int x; DefaultedDefCtorUninitialized2() = default; }; struct DeletedDefCtor { DeletedDefCtor() = delete; DeletedDefCtor(int); }; // expected-note {{explicitly marked deleted here}} class PrivateDefCtor { PrivateDefCtor() = default; public: PrivateDefCtor(int); }; struct DeletedDtor { ~DeletedDtor() = delete; }; // expected-note 4{{explicitly marked deleted here}} @@ -51,21 +53,20 @@ class NotDeleted2d { int &&a = 0; }; // expected-error {{reference member 'a' bi NotDeleted2d nd2d; // expected-note {{first required here}} // - any non-variant non-static data member of const qualified type (or array -// thereof) with no brace-or-equal-initializer does not have a user-provided -// default constructor, +// thereof) with no brace-or-equal-initializer is not const-default-constructible class Deleted3a { const int a; }; // expected-note {{because field 'a' of const-qualified type 'const int' would not be initialized}} \ 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[42]' would not be initialized}} +class Deleted3b { const DefaultedDefCtorUninitialized1 a[42]; }; // expected-note {{because field 'a' of const-qualified type 'const DefaultedDefCtorUninitialized1[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}} +class Deleted3c { const DefaultedDefCtorUninitialized2 a; }; // expected-note {{because field 'a' of const-qualified type 'const DefaultedDefCtorUninitialized2' would not be initialized}} Deleted3c d3c; // expected-error {{implicitly-deleted default constructor}} class NotDeleted3a { const int a = 0; }; NotDeleted3a nd3a; -class NotDeleted3b { const DefaultedDefCtor1 a[42] = {}; }; +class NotDeleted3b { const DefaultedDefCtorUninitialized1 a[42] = {}; }; NotDeleted3b nd3b; -class NotDeleted3c { const DefaultedDefCtor2 a = DefaultedDefCtor2(); }; +class NotDeleted3c { const DefaultedDefCtorUninitialized2 a = DefaultedDefCtorUninitialized2(); }; NotDeleted3c nd3c; union NotDeleted3d { const int a; int b; }; NotDeleted3d nd3d; @@ -75,6 +76,10 @@ union NotDeleted3f { const DefaultedDefCtor2 a; int b; }; NotDeleted3f nd3f; struct NotDeleted3g { union { const int a; int b; }; }; NotDeleted3g nd3g; +struct NotDeleted3h { const DefaultedDefCtor1 a[42]; }; +NotDeleted3h nd3h; +struct NotDeleted3i { const DefaultedDefCtor2 a; }; +NotDeleted3i nd3i; // - X is a union and all of its variant members are of const-qualified type (or // array thereof), diff --git a/clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp index feb483546c3eb..f8a40f97c9791 100644 --- a/clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp +++ b/clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp @@ -48,8 +48,12 @@ struct good : non_trivial { }; good g; +struct bad_const_inner { + int x; +}; + struct bad_const { - const good g; // expected-note {{field 'g' of const-qualified type 'const good' would not be initialized}} + const bad_const_inner g; // expected-note {{field 'g' of const-qualified type 'const bad_const_inner' would not be initialized}} }; bad_const bc; // expected-error {{call to implicitly-deleted default constructor}} diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index e193d37c09598..b9a38150063bc 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -14178,7 +14178,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://wg21.link/cwg2394">2394</a></td> <td>CD5</td> <td>Const-default-constructible for members</td> - <td class="none" align="center">Unknown</td> + <td class="unreleased" align="center">Clang 15</td> </tr> <tr class="open" id="2395"> <td><a href="https://wg21.link/cwg2395">2395</a></td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits