From f0103f7bb010405798fe14afc5972f327835ae57 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 4 Mar 2019 19:57:13 +0100 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 6 ++ gcc/cp/call.c | 83 ++++++++++++++++++++++++++-- gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/g++.dg/cpp2a/desig12.C | 15 +++++ gcc/testsuite/g++.dg/cpp2a/desig13.C | 16 ++++++ 5 files changed, 121 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig12.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig13.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e17537a52f0..8c0bfd994eb 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2019-03-04 Jakub Jelinek + + PR c++/71446 + * call.c (field_in_pset): New function. + (build_aggr_conv): Handle CONSTRUCTOR_IS_DESIGNATED_INIT correctly. + 2019-03-02 Jakub Jelinek PR c++/71446 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 1a9cf7e9abe..1a29eb7bb19 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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 *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 *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; + 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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3d883f6e83e..3186805c9cb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-03-04 Jakub Jelinek + + PR c++/71446 + * g++.dg/cpp2a/desig12.C: New test. + * g++.dg/cpp2a/desig13.C: New test. + 2019-03-04 Tamar Christina PR target/88530 diff --git a/gcc/testsuite/g++.dg/cpp2a/desig12.C b/gcc/testsuite/g++.dg/cpp2a/desig12.C new file mode 100644 index 00000000000..cfff9a79c63 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/desig12.C @@ -0,0 +1,15 @@ +// 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}); +} diff --git a/gcc/testsuite/g++.dg/cpp2a/desig13.C b/gcc/testsuite/g++.dg/cpp2a/desig13.C new file mode 100644 index 00000000000..442e8b74aa4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/desig13.C @@ -0,0 +1,16 @@ +// 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'" } +} -- 2.30.2