c++: desig init in presence of list ctor [PR109871]

add_list_candidates has logic to reject designated initialization of a
non-aggregate type, but this is inadvertently being suppressed if the type
has a list constructor due to the order of case analysis, which in the
below testcase leads to us incorrectly treating the initializer list as if
it's non-designated.  This patch fixes this by making us check for invalid
designated initialization sooner.

	PR c++/109871

gcc/cp/ChangeLog:

	* call.cc (add_list_candidates): Check for invalid designated
	initialization sooner and even for types that have a list
	constructor.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp2a/desig27.C: New test.

(cherry picked from commit d5e5007c4b534391c0a97be56f6024fde1a88682)
This commit is contained in:
Patrick Palka 2023-05-16 12:39:16 -04:00
parent ae2c80c65e
commit efdcb731bb
2 changed files with 24 additions and 8 deletions

View File

@ -4128,6 +4128,14 @@ add_list_candidates (tree fns, tree first_arg,
if (CONSTRUCTOR_NELTS (init_list) == 0
&& TYPE_HAS_DEFAULT_CONSTRUCTOR (totype))
;
else if (CONSTRUCTOR_IS_DESIGNATED_INIT (init_list)
&& !CP_AGGREGATE_TYPE_P (totype))
{
if (complain & tf_error)
error ("designated initializers cannot be used with a "
"non-aggregate type %qT", totype);
return;
}
/* If the class has a list ctor, try passing the list as a single
argument first, but only consider list ctors. */
else if (TYPE_HAS_LIST_CTOR (totype))
@ -4139,14 +4147,6 @@ add_list_candidates (tree fns, tree first_arg,
if (any_strictly_viable (*candidates))
return;
}
else if (CONSTRUCTOR_IS_DESIGNATED_INIT (init_list)
&& !CP_AGGREGATE_TYPE_P (totype))
{
if (complain & tf_error)
error ("designated initializers cannot be used with a "
"non-aggregate type %qT", totype);
return;
}
/* Expand the CONSTRUCTOR into a new argument vec. */
vec<tree, va_gc> *new_args;

View File

@ -0,0 +1,16 @@
// PR c++/109871
// { dg-do compile { target c++11 } }
// { dg-options "" }
#include <initializer_list>
struct vector {
vector(std::initializer_list<int>); // #1
vector(int); // #2
};
void f(vector);
int main() {
f({.blah = 42}); // { dg-error "designated" } previously incorrectly selected #2
}