minified reproducer, reduced from the original (https://git.sr.ht/~nabijaczleweli/voreutils/tree/5781698e96ad3a085a2f3d712dc61b020ae287ad/item/cmd/df.cpp#L80): #include <vector> template <class T> struct field { field(T &&) {} }; std::vector<field<int>> fields_normal{2}; // Error std::vector<field<int>> fields_workaround{{2}}; // OK All Clangs I cared to try and GCCs <=13 accept this and do the expected thing. GCC 14 (and trunk according to godbolt) explode with <source>:6:40: error: binding reference of type 'int&&' to 'const int' discards qualifiers 6 | std::vector<field<int>> fields_normal{2}; // Error | ^ <source>:4:11: note: initializing argument 1 of 'field<T>::field(T&&) [with T = int]' 4 | field(T &&) {} | ^~~~ <source>: In function 'void __static_initialization_and_destruction_0()': <source>:6:40: error: cannot bind rvalue reference of type 'int&&' to lvalue of type 'const int' 6 | std::vector<field<int>> fields_normal{2}; // Error | ^ <source>:4:11: note: initializing argument 1 of 'field<T>::field(T&&) [with T = int]' 4 | field(T &&) {} | ^~~~ Compiler returned: 1 which feels nonsensical to me.
Reduced further: #include <initializer_list> template <class T> struct field { field(T &&) {} }; struct vector { vector(std::initializer_list<field<int>>) { } }; vector fields_normal{2}; // Error init.cc:11:23: error: binding reference of type 'int&&' to 'const int' discards qualifiers 11 | vector fields_normal{2}; // Error | ^ init.cc:5:11: note: initializing argument 1 of 'field<T>::field(T&&) [with T = int]' 5 | field(T &&) {} | ^~~~ init.cc: In function 'void __static_initialization_and_destruction_0()': init.cc:11:23: error: cannot bind rvalue reference of type 'int&&' to lvalue of type 'const int' 11 | vector fields_normal{2}; // Error | ^ init.cc:5:11: note: initializing argument 1 of 'field<T>::field(T&&) [with T = int]' 5 | field(T &&) {} | ^~~~ Regression started with r14-1705: c++: build initializer_list<string> in a loop [PR105838]
I have a patch.
The trunk branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>: https://gcc.gnu.org/g:9f79c7ddff5f1b004803931406ad17eaba095fff commit r15-3274-g9f79c7ddff5f1b004803931406ad17eaba095fff Author: Marek Polacek <polacek@redhat.com> Date: Wed Aug 28 15:45:49 2024 -0400 c++: wrong error due to std::initializer_list opt [PR116476] Here maybe_init_list_as_array gets elttype=field, init={NON_LVALUE_EXPR <2>} and it tries to convert the init's element type (int) to field using implicit_conversion, which works, so overall maybe_init_list_as_array is successful. But it constifies init_elttype so we end up with "const int". Later, when we actually perform the conversion and invoke field::field(T&&), we end up with this error: error: binding reference of type 'int&&' to 'const int' discards qualifiers So I think maybe_init_list_as_array should try to perform the conversion, like it does below with fc. PR c++/116476 gcc/cp/ChangeLog: * call.cc (maybe_init_list_as_array): Try convert_like and see if it worked. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/initlist-opt2.C: New test. Reviewed-by: Jason Merrill <jason@redhat.com>
Fixed on trunk so far.
The releases/gcc-14 branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>: https://gcc.gnu.org/g:0784e8934e96187e17c1b02dce1e0ed35d2229dd commit r14-10799-g0784e8934e96187e17c1b02dce1e0ed35d2229dd Author: Marek Polacek <polacek@redhat.com> Date: Wed Aug 28 15:45:49 2024 -0400 c++: wrong error due to std::initializer_list opt [PR116476] Here maybe_init_list_as_array gets elttype=field, init={NON_LVALUE_EXPR <2>} and it tries to convert the init's element type (int) to field using implicit_conversion, which works, so overall maybe_init_list_as_array is successful. But it constifies init_elttype so we end up with "const int". Later, when we actually perform the conversion and invoke field::field(T&&), we end up with this error: error: binding reference of type 'int&&' to 'const int' discards qualifiers So I think maybe_init_list_as_array should try to perform the conversion, like it does below with fc. PR c++/116476 gcc/cp/ChangeLog: * call.cc (maybe_init_list_as_array): Try convert_like and see if it worked. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/initlist-opt2.C: New test. Reviewed-by: Jason Merrill <jason@redhat.com> (cherry picked from commit 9f79c7ddff5f1b004803931406ad17eaba095fff)
Fixed.