Summary: | Brace initialization of array sometimes fails if no copy constructor | ||
---|---|---|---|
Product: | gcc | Reporter: | John Lindgren <john> |
Component: | c++ | Assignee: | Jason Merrill <jason> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | daniel.kruegler, eyalroz1, jason, jason, jlame646, l2m, mpolacek, pdimov, richard-gccbugzilla, ville.voutilainen, webrown.cpp |
Priority: | P3 | Keywords: | rejects-valid |
Version: | 4.9.1 | ||
Target Milestone: | 9.4 | ||
See Also: |
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59238 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96743 |
||
Host: | Target: | ||
Build: | Known to work: | 10.3.0, 11.0, 11.1.0, 9.4.0 | |
Known to fail: | 10.2.0, 4.8.2, 4.9.1, 5.0, 6.1.1 | Last reconfirmed: | 2020-12-07 00:00:00 |
Attachments: |
Test case 1
Test case 2 Test case 3 Test case 4 Corrected test case 2 |
Description
John Lindgren
2014-11-01 18:44:27 UTC
Created attachment 33860 [details]
Test case 2
Created attachment 33861 [details]
Test case 3
Created attachment 33862 [details]
Test case 4
Created attachment 33863 [details]
Corrected test case 2
Corrected test case 2 (previous was identical to test case 1).
The member array case only fails when the array element has a user-defined destructor Here's the failing testcase repeated from the attachment and reduced slightly: struct Child { Child (int); ~Child (); Child (const Child &) = delete; }; struct Parent { Parent () : children {{5}, {7}} {} Child children[2]; }; i.cc: In constructor ‘Parent::Parent()’: i.cc:12:35: error: use of deleted function ‘Child::Child(const Child&)’ Parent () : children {{5}, {7}} {} ^ i.cc:6:5: note: declared here Child (const Child &) = delete; ^ Commenting out the destructor declaration allows it to compile. *** Bug 64887 has been marked as a duplicate of this bug. *** Reduced from PR 64887: struct string { string(const char*) { } ~string(); // make this type non-trivial }; struct A { string s; A() = delete; A(const A&) = delete; A(A&&) = delete; A(const char*); }; A arr[2] = {{"a"}, {"b"}}; // ok struct Aggr { A arr[2]; Aggr() : arr{{"a"}, {"b"}} {} // error }; The member of non-trivial type is required to trigger the error, presumably because it makes the destructor non-trivial. Just ran into this bug again with GCC 6.1.1. Any hope of this ever getting fixed? *** Bug 70395 has been marked as a duplicate of this bug. *** Testcase from PR 70395 struct NonCopyable { NonCopyable(const NonCopyable&) = delete; NonCopyable(NonCopyable&&) = delete; NonCopyable& operator=(const NonCopyable&) = delete; NonCopyable& operator=(NonCopyable&&) = delete; NonCopyable() {} ~NonCopyable() {} // to make it non-trivial }; struct A { A(): _a{} {} ~A() {} NonCopyable _a[5]; } a; *** Bug 92393 has been marked as a duplicate of this bug. *** Rejection valid code, especially valid code which is not contrived and can well occur in people's real-life work, seems like a high-priority bug. The last substantive comment here, other than dupe-marking-related comments two years ago, is comment #8, asking for this to be fixed - four and a half years ago. Jonathan and others - please try to prioritize fixing this, and even if you can't for some reason - at least explain which this can't be fixed promptly. See also: https://stackoverflow.com/q/65138048/1593077 At least for #c5 the important difference between that testcase and // ~Child (); which is accepted is I think since r0-113052-ge2df21bfc6c81b4bc410a42002c8427454ffa628 in the cp/init.c (perform_member_init) code: 888 /* A FIELD_DECL doesn't really have a suitable lifetime, but 889 make_temporary_var_for_ref_to_temp will treat it as automatic and 890 set_up_extended_ref_temp wants to use the decl in a warning. */ 891 init = extend_ref_init_temps (member, init, &cleanups); 892 if (TREE_CODE (type) == ARRAY_TYPE 893 && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type))) 894 init = build_vec_init_expr (type, init, tf_warning_or_error); If it has trivial destructor, nothing calls build_vec_init_expr and the copy ctor isn't needed, but when it is called, it is needed. I think in this case extend_ref_init_temps doesn't do anything at all, so it is unclear if build_vec_init_expr is needed too or not. FWIW, I just hit this problem as well when trying to make changes to Boost.Variant2. My reduced test case is https://godbolt.org/z/zG6ddP; I was going to submit that as a bug but found this one. I support the petition to have this fixed. Looking. Mine. The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:cd09079cfd50d289cbb05eadb728a0713f6bae8a commit r11-6733-gcd09079cfd50d289cbb05eadb728a0713f6bae8a Author: Jason Merrill <jason@redhat.com> Date: Fri Jan 15 11:42:00 2021 -0500 c++: Fix list-init of array of no-copy type [PR63707] build_vec_init_elt models initialization from some arbitrary object of the type, i.e. copy, but in the case of list-initialization we don't do a copy from the elements, we initialize them directly. gcc/cp/ChangeLog: PR c++/63707 * tree.c (build_vec_init_expr): Don't call build_vec_init_elt if we got a CONSTRUCTOR. gcc/testsuite/ChangeLog: PR c++/63707 * g++.dg/cpp0x/initlist-array13.C: New test. Fixed for GCC 11 so far. The releases/gcc-10 branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:81fd2df5911c4b2c31960fa5ef1407d20f1ca50c commit r10-9311-g81fd2df5911c4b2c31960fa5ef1407d20f1ca50c Author: Jason Merrill <jason@redhat.com> Date: Fri Jan 15 11:42:00 2021 -0500 c++: Fix list-init of array of no-copy type [PR63707] build_vec_init_elt models initialization from some arbitrary object of the type, i.e. copy, but in the case of list-initialization we don't do a copy from the elements, we initialize them directly. gcc/cp/ChangeLog: PR c++/63707 * tree.c (build_vec_init_expr): Don't call build_vec_init_elt if we got a CONSTRUCTOR. gcc/testsuite/ChangeLog: PR c++/63707 * g++.dg/cpp0x/initlist-array13.C: New test. The releases/gcc-9 branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:ca02f0a0eb0fbeb3c1e01c3a55a95b0690ecfabc commit r9-9212-gca02f0a0eb0fbeb3c1e01c3a55a95b0690ecfabc Author: Jason Merrill <jason@redhat.com> Date: Fri Jan 15 11:42:00 2021 -0500 c++: Fix list-init of array of no-copy type [PR63707] build_vec_init_elt models initialization from some arbitrary object of the type, i.e. copy, but in the case of list-initialization we don't do a copy from the elements, we initialize them directly. gcc/cp/ChangeLog: PR c++/63707 * tree.c (build_vec_init_expr): Don't call build_vec_init_elt if we got a CONSTRUCTOR. gcc/testsuite/ChangeLog: PR c++/63707 * g++.dg/cpp0x/initlist-array13.C: New test. Also fixed for 9.4 and 10.3. Thank you, Jason and others, for your attentiveness to interest in the bug and prioritizing its fix. (Now if you could just fix all the other bugs I'm interested in... :-P) *** Bug 68709 has been marked as a duplicate of this bug. *** *** Bug 91499 has been marked as a duplicate of this bug. *** *** Bug 106788 has been marked as a duplicate of this bug. *** |