From 574eaf0fda98b795daf6b588e3c0e878987f9769 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 2 Mar 2019 09:06:57 +0100 Subject: [PATCH] re PR c++/71446 (Incorrect overload resolution when using designated initializers) PR c++/71446 * cp-tree.h (CONSTRUCTOR_IS_DESIGNATED_INIT): Define. * parser.c (cp_parser_braced_list): Adjust cp_parser_initializer_list caller, set CONSTRUCTOR_IS_DESIGNATED_INIT. (cp_parser_initializer_list): Add designated parameter, set *designated to a bool whether any designators were parsed. * decl.c (reshape_init): Copy over CONSTRUCTOR_IS_DESIGNATED_INIT if needed. * pt.c (tsubst_copy_and_build): Likewise. * call.c (implicit_conversion): If CONSTRUCTOR_IS_DESIGNATED_INIT, don't call build_list_conv, nor build_complex_conv, nor attempt to convert a single element initializer to scalar. * g++.dg/cpp2a/desig10.C: New test. * g++.dg/cpp2a/desig11.C: New test. * g++.dg/ext/desig4.C: Expect 4 new errors. From-SVN: r269340 --- gcc/cp/ChangeLog | 15 +++++++++++++++ gcc/cp/call.c | 7 ++++--- gcc/cp/cp-tree.h | 7 +++++++ gcc/cp/decl.c | 3 +++ gcc/cp/parser.c | 13 +++++++++---- gcc/cp/pt.c | 2 ++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/cpp2a/desig10.C | 12 ++++++++++++ gcc/testsuite/g++.dg/cpp2a/desig11.C | 14 ++++++++++++++ gcc/testsuite/g++.dg/ext/desig4.C | 4 ++++ 10 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig10.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig11.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bc6754ec819..e17537a52f0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +2019-03-02 Jakub Jelinek + + PR c++/71446 + * cp-tree.h (CONSTRUCTOR_IS_DESIGNATED_INIT): Define. + * parser.c (cp_parser_braced_list): Adjust cp_parser_initializer_list + caller, set CONSTRUCTOR_IS_DESIGNATED_INIT. + (cp_parser_initializer_list): Add designated parameter, set *designated + to a bool whether any designators were parsed. + * decl.c (reshape_init): Copy over CONSTRUCTOR_IS_DESIGNATED_INIT if + needed. + * pt.c (tsubst_copy_and_build): Likewise. + * call.c (implicit_conversion): If CONSTRUCTOR_IS_DESIGNATED_INIT, + don't call build_list_conv, nor build_complex_conv, nor attempt to + convert a single element initializer to scalar. + 2019-03-01 Marek Polacek PR c++/89537 - missing location for error with non-static member fn. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index d9073d7c23d..1a9cf7e9abe 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -1876,11 +1876,12 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p, if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr)) { - if (is_std_init_list (to)) + if (is_std_init_list (to) && !CONSTRUCTOR_IS_DESIGNATED_INIT (expr)) return build_list_conv (to, expr, flags, complain); /* As an extension, allow list-initialization of _Complex. */ - if (TREE_CODE (to) == COMPLEX_TYPE) + if (TREE_CODE (to) == COMPLEX_TYPE + && !CONSTRUCTOR_IS_DESIGNATED_INIT (expr)) { conv = build_complex_conv (to, expr, flags, complain); if (conv) @@ -1896,7 +1897,7 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p, if (nelts == 0) elt = build_value_init (to, tf_none); - else if (nelts == 1) + else if (nelts == 1 && !CONSTRUCTOR_IS_DESIGNATED_INIT (expr)) elt = CONSTRUCTOR_ELT (expr, 0)->value; else elt = error_mark_node; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 91bc82b85e5..663a23b4043 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -471,6 +471,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; TYPE_MARKED_P (in _TYPE) RANGE_FOR_IVDEP (in RANGE_FOR_STMT) CALL_EXPR_OPERATOR_SYNTAX (in CALL_EXPR, AGGR_INIT_EXPR) + CONSTRUCTOR_IS_DESIGNATED_INIT (in CONSTRUCTOR) Usage of TYPE_LANG_FLAG_?: 0: TYPE_DEPENDENT_P @@ -4235,6 +4236,12 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define DIRECT_LIST_INIT_P(NODE) \ (BRACE_ENCLOSED_INITIALIZER_P (NODE) && CONSTRUCTOR_IS_DIRECT_INIT (NODE)) +/* True if this is a designated initializer (when we allow initializer-clauses + mixed with designated-initializer-clauses set whenever there is at least + one designated-initializer-clause), or a C99 designator. */ +#define CONSTRUCTOR_IS_DESIGNATED_INIT(NODE) \ + (TREE_LANG_FLAG_6 (CONSTRUCTOR_CHECK (NODE))) + /* True if NODE represents a conversion for direct-initialization in a template. Set by perform_implicit_conversion_flags. */ #define IMPLICIT_CONV_EXPR_DIRECT_INIT(NODE) \ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c5b5bd3ce08..173758feddf 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -6278,6 +6278,9 @@ reshape_init (tree type, tree init, tsubst_flags_t complain) if (CONSTRUCTOR_IS_DIRECT_INIT (init) && BRACE_ENCLOSED_INITIALIZER_P (new_init)) CONSTRUCTOR_IS_DIRECT_INIT (new_init) = true; + if (CONSTRUCTOR_IS_DESIGNATED_INIT (init) + && BRACE_ENCLOSED_INITIALIZER_P (new_init)) + CONSTRUCTOR_IS_DESIGNATED_INIT (new_init) = true; return new_init; } diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 2edd685fb3d..580426780ea 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2251,7 +2251,7 @@ static cp_expr cp_parser_initializer_clause static cp_expr cp_parser_braced_list (cp_parser*, bool*); static vec *cp_parser_initializer_list - (cp_parser *, bool *); + (cp_parser *, bool *, bool *); static void cp_parser_ctor_initializer_opt_and_function_body (cp_parser *, bool); @@ -22768,9 +22768,11 @@ cp_parser_braced_list (cp_parser* parser, bool* non_constant_p) /* If it's not a `}', then there is a non-trivial initializer. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE)) { + bool designated; /* Parse the initializer list. */ CONSTRUCTOR_ELTS (initializer) - = cp_parser_initializer_list (parser, non_constant_p); + = cp_parser_initializer_list (parser, non_constant_p, &designated); + CONSTRUCTOR_IS_DESIGNATED_INIT (initializer) = designated; /* A trailing `,' token is allowed. */ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) cp_lexer_consume_token (parser->lexer); @@ -22890,10 +22892,12 @@ cp_parser_array_designator_p (cp_parser *parser) Returns a vec of constructor_elt. The VALUE of each elt is an expression for the initializer. If the INDEX of the elt is non-NULL, it is the IDENTIFIER_NODE naming the field to initialize. NON_CONSTANT_P is - as for cp_parser_initializer. */ + as for cp_parser_initializer. Set *DESIGNATED to a boolean whether there + are any designators. */ static vec * -cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) +cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p, + bool *designated) { vec *v = NULL; bool first_p = true; @@ -23070,6 +23074,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) IDENTIFIER_MARKED (designator) = 0; } + *designated = first_designator != NULL_TREE; return v; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7295839ebd2..8a5a0b38b2d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -19359,6 +19359,8 @@ tsubst_copy_and_build (tree t, r = build_constructor (init_list_type_node, n); CONSTRUCTOR_IS_DIRECT_INIT (r) = CONSTRUCTOR_IS_DIRECT_INIT (t); + CONSTRUCTOR_IS_DESIGNATED_INIT (r) + = CONSTRUCTOR_IS_DESIGNATED_INIT (t); if (TREE_HAS_CONSTRUCTOR (t)) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8701bc1d642..e6a83b083c8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2019-03-02 Jakub Jelinek + PR c++/71446 + * g++.dg/cpp2a/desig10.C: New test. + * g++.dg/cpp2a/desig11.C: New test. + * g++.dg/ext/desig4.C: Expect 4 new errors. + PR target/89506 * gcc.dg/pr89506.c: New test. diff --git a/gcc/testsuite/g++.dg/cpp2a/desig10.C b/gcc/testsuite/g++.dg/cpp2a/desig10.C new file mode 100644 index 00000000000..7fb68683853 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/desig10.C @@ -0,0 +1,12 @@ +// PR c++/71446 +// { dg-do compile { target c++11 } } +// { dg-options "" } + +#include + +struct S { int value; }; + +int foo (S); +char *foo (std::initializer_list); + +int x = foo ({.value = 0}); diff --git a/gcc/testsuite/g++.dg/cpp2a/desig11.C b/gcc/testsuite/g++.dg/cpp2a/desig11.C new file mode 100644 index 00000000000..d6895a7be56 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/desig11.C @@ -0,0 +1,14 @@ +// PR c++/71446 +// { dg-do compile { target c++11 } } +// { dg-options "" } + +#include + +int foo (int); // { dg-message "initializing argument 1 of" } +int x = foo ({.foo = 0}); // { dg-error "cannot convert" } + +int bar (_Complex int); // { dg-message "initializing argument 1 of" } +int y = bar ({.real = 0, .imag = 1}); // { dg-error "cannot convert" } + +int baz (std::initializer_list); +int z = baz ({.one = 1, .two = 2, .three = 3}); // { dg-error "could not convert" } diff --git a/gcc/testsuite/g++.dg/ext/desig4.C b/gcc/testsuite/g++.dg/ext/desig4.C index 33be2582be2..62c3c581b59 100644 --- a/gcc/testsuite/g++.dg/ext/desig4.C +++ b/gcc/testsuite/g++.dg/ext/desig4.C @@ -6,9 +6,13 @@ int a = { .foo = 6 }; // { dg-error "designator" } int b = { [0] = 1 }; // { dg-error "designator" } _Complex float c = { .foo = 0, 1 }; // { dg-error "designator" } // { dg-error "either all initializer clauses should be designated or none of them should be" "" { target c++2a } .-1 } + // { dg-error "cannot convert" "" { target *-*-* } .-2 } _Complex float d = { [0] = 0, 1 }; // { dg-error "designator" } // { dg-error "either all initializer clauses should be designated or none of them should be" "" { target c++2a } .-1 } + // { dg-error "cannot convert" "" { target *-*-* } .-2 } _Complex float e = { 0, .foo = 1 }; // { dg-error "designator" } // { dg-error "either all initializer clauses should be designated or none of them should be" "" { target c++2a } .-1 } + // { dg-error "cannot convert" "" { target *-*-* } .-2 } _Complex float f = { 0, [0] = 1 }; // { dg-error "designator" } // { dg-error "either all initializer clauses should be designated or none of them should be" "" { target c++2a } .-1 } + // { dg-error "cannot convert" "" { target *-*-* } .-2 } -- 2.30.2