Commit f0103f7b by Jakub Jelinek Committed by Jakub Jelinek

re PR c++/71446 (Incorrect overload resolution when using designated initializers)

	PR c++/71446
	* call.c (field_in_pset): New function.
	(build_aggr_conv): Handle CONSTRUCTOR_IS_DESIGNATED_INIT correctly.

	* g++.dg/cpp2a/desig12.C: New test.
	* g++.dg/cpp2a/desig13.C: New test.

From-SVN: r269371
parent 209cd3bd
2019-03-04 Jakub Jelinek <jakub@redhat.com>
PR c++/71446
* call.c (field_in_pset): New function.
(build_aggr_conv): Handle CONSTRUCTOR_IS_DESIGNATED_INIT correctly.
2019-03-02 Jakub Jelinek <jakub@redhat.com>
PR c++/71446
......
......@@ -902,6 +902,28 @@ can_convert_array (tree atype, tree ctor, int flags, tsubst_flags_t complain)
return true;
}
/* Helper for build_aggr_conv. Return true if FIELD is in PSET, or if
FIELD has ANON_AGGR_TYPE_P and any initializable field in there recursively
is in PSET. */
static bool
field_in_pset (hash_set<tree> *pset, tree field)
{
if (pset->contains (field))
return true;
if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
for (field = TYPE_FIELDS (TREE_TYPE (field));
field; field = DECL_CHAIN (field))
{
field = next_initializable_field (field);
if (field == NULL_TREE)
break;
if (field_in_pset (pset, field))
return true;
}
return false;
}
/* Represent a conversion from CTOR, a braced-init-list, to TYPE, an
aggregate class, if such a conversion is possible. */
......@@ -912,6 +934,7 @@ build_aggr_conv (tree type, tree ctor, int flags, tsubst_flags_t complain)
conversion *c;
tree field = next_initializable_field (TYPE_FIELDS (type));
tree empty_ctor = NULL_TREE;
hash_set<tree> *pset = NULL;
/* We already called reshape_init in implicit_conversion. */
......@@ -919,26 +942,69 @@ build_aggr_conv (tree type, tree ctor, int flags, tsubst_flags_t complain)
context; they're always simple copy-initialization. */
flags = LOOKUP_IMPLICIT|LOOKUP_NO_NARROWING;
/* For designated initializers, verify that each initializer is convertible
to corresponding TREE_TYPE (ce->index) and mark those FIELD_DECLs as
visited. In the following loop then ignore already visited
FIELD_DECLs. */
if (CONSTRUCTOR_IS_DESIGNATED_INIT (ctor))
{
tree idx, val;
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, idx, val)
{
if (idx && TREE_CODE (idx) == FIELD_DECL)
{
tree ftype = TREE_TYPE (idx);
bool ok;
if (TREE_CODE (ftype) == ARRAY_TYPE
&& TREE_CODE (val) == CONSTRUCTOR)
ok = can_convert_array (ftype, val, flags, complain);
else
ok = can_convert_arg (ftype, TREE_TYPE (val), val, flags,
complain);
if (!ok)
goto fail;
/* For unions, there should be just one initializer. */
if (TREE_CODE (type) == UNION_TYPE)
{
field = NULL_TREE;
i = 1;
break;
}
if (pset == NULL)
pset = new hash_set<tree>;
pset->add (idx);
}
else
goto fail;
}
}
for (; field; field = next_initializable_field (DECL_CHAIN (field)))
{
tree ftype = TREE_TYPE (field);
tree val;
bool ok;
if (pset && field_in_pset (pset, field))
continue;
if (i < CONSTRUCTOR_NELTS (ctor))
val = CONSTRUCTOR_ELT (ctor, i)->value;
{
val = CONSTRUCTOR_ELT (ctor, i)->value;
++i;
}
else if (DECL_INITIAL (field))
val = get_nsdmi (field, /*ctor*/false, complain);
else if (TYPE_REF_P (ftype))
/* Value-initialization of reference is ill-formed. */
return NULL;
goto fail;
else
{
if (empty_ctor == NULL_TREE)
empty_ctor = build_constructor (init_list_type_node, NULL);
val = empty_ctor;
}
++i;
if (TREE_CODE (ftype) == ARRAY_TYPE
&& TREE_CODE (val) == CONSTRUCTOR)
......@@ -948,15 +1014,22 @@ build_aggr_conv (tree type, tree ctor, int flags, tsubst_flags_t complain)
complain);
if (!ok)
return NULL;
goto fail;
if (TREE_CODE (type) == UNION_TYPE)
break;
}
if (i < CONSTRUCTOR_NELTS (ctor))
return NULL;
{
fail:
if (pset)
delete pset;
return NULL;
}
if (pset)
delete pset;
c = alloc_conversion (ck_aggr);
c->type = type;
c->rank = cr_exact;
......
2019-03-04 Jakub Jelinek <jakub@redhat.com>
PR c++/71446
* g++.dg/cpp2a/desig12.C: New test.
* g++.dg/cpp2a/desig13.C: New test.
2019-03-04 Tamar Christina <tamar.christina@arm.com>
PR target/88530
......
// PR c++/71446
// { dg-do compile { target c++11 } }
// { dg-options "" }
struct T { void *a; int b; };
struct U { int a; union { int b; union { long c; short d; }; }; int e; };
void bar (T);
void baz (U);
void
foo ()
{
bar ({.b = 1});
baz ({.c = 5L, .e = 6});
}
// PR c++/71446
// { dg-do compile { target c++11 } }
// { dg-options "" }
struct S { int a, b, c, d, e; };
struct T { int a, b; };
void foo (S);
void bar (T);
void
baz ()
{
foo ({.d = 5, 6, .b = 2, 3}); // { dg-error "designator order for field 'S::b' does not match declaration order in 'S'" }
// { dg-error "either all initializer clauses should be designated or none of them should be" "" { target c++2a } .-1 }
bar ({.b = 1, .a = 2}); // { dg-error "designator order for field 'T::a' does not match declaration order in 'T'" }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment