class base { public: base(void) {}; base(base &&) = delete; }; class foo : public base { }; template<typename C> inline C &bar(void) { static C c{}; return c; } const foo &baz(void) { return bar<const foo>(); } is rejected since r11-2704 in C++17. clang++/EDG accept this.
$ ./cc1plus -quiet 98642.C 98642.C: In instantiation of ‘C& bar() [with C = const foo]’: 98642.C:19:25: required from here 98642.C:13:12: error: use of deleted function ‘base::base(base&&)’ 13 | static C c{}; | ^ 98642.C:4:3: note: declared here 4 | base(base &&) = delete; | ^~~~
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:d75199f782348bfc401f925b60f33ffc9822b7cc commit r11-6736-gd75199f782348bfc401f925b60f33ffc9822b7cc Author: Jason Merrill <jason@redhat.com> Date: Wed Jan 13 13:27:06 2021 -0500 c++: Avoid redundant copy in {} init [PR98642] Here, initializing from { } implies a call to the default constructor for base. We were then seeing that we're initializing a base subobject, so we tried to copy the result of that call. This is clearly wrong; we should initialize the base directly from its default constructor. This patch does a lot of refactoring of unsafe_copy_elision_p and adds make_safe_copy_elision that will also try to do the base constructor rewriting from the last patch. gcc/cp/ChangeLog: PR c++/98642 * call.c (unsafe_return_slot_p): Return int. (init_by_return_slot_p): Split out from... (unsafe_copy_elision_p): ...here. (unsafe_copy_elision_p_opt): New name for old meaning. (build_over_call): Adjust. (make_safe_copy_elision): New. * typeck2.c (split_nonconstant_init_1): Elide copy from safe list-initialization. * cp-tree.h: Adjust. gcc/testsuite/ChangeLog: PR c++/98642 * g++.dg/cpp1z/elide5.C: New test.
Created attachment 49977 [details] possible patch to elide more copies This implements a suggestion I made in https://github.com/itanium-cxx-abi/cxx-abi/issues/107
Confirmed it broke on the GCC 10 branch after the GCC 10.2 release which worked, thus indeed P1 but only is rejected with -std=c++17 not with the default -std level. What broke it on the branch? (maybe reversion is a better fix there?)
So obviously that was 2020-12-23 Jason Merrill <jason@redhat.com> PR c++/90254 PR c++/93711 * cp-tree.h (unsafe_return_slot_p): Declare. * call.c (is_base_field_ref): Rename to unsafe_return_slot_p. (build_over_call): Check unsafe_return_slot_p. (build_special_member_call): Likewise. * init.c (expand_default_init): Likewise. * typeck2.c (split_nonconstant_init_1): Likewise.
The releases/gcc-10 branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:506fcfdb12562e829448e2b2eff475c65986e26b commit r10-9312-g506fcfdb12562e829448e2b2eff475c65986e26b Author: Jason Merrill <jason@redhat.com> Date: Wed Jan 13 13:27:06 2021 -0500 c++: Avoid redundant copy in {} init [PR98642] Here, initializing from { } implies a call to the default constructor for base. We were then seeing that we're initializing a base subobject, so we tried to copy the result of that call. This is clearly wrong; we should initialize the base directly from its default constructor. gcc/cp/ChangeLog: PR c++/98642 * typeck2.c (split_nonconstant_init_1): Don't copy a list-init constructor call. gcc/testsuite/ChangeLog: PR c++/98642 * g++.dg/cpp1z/elide5.C: New test.
So is this now fixed even for 10.3?
The reported testcase is now accepted.