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
This commit is contained in:
Jakub Jelinek 2019-03-02 09:06:57 +01:00 committed by Jakub Jelinek
parent 73ba6c7120
commit 574eaf0fda
10 changed files with 75 additions and 7 deletions

View File

@ -1,3 +1,18 @@
2019-03-02 Jakub Jelinek <jakub@redhat.com>
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 <polacek@redhat.com>
PR c++/89537 - missing location for error with non-static member fn.

View File

@ -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;

View File

@ -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) \

View File

@ -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;
}

View File

@ -2251,7 +2251,7 @@ static cp_expr cp_parser_initializer_clause
static cp_expr cp_parser_braced_list
(cp_parser*, bool*);
static vec<constructor_elt, va_gc> *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<constructor_elt, va_gc> *
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<constructor_elt, va_gc> *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;
}

View File

@ -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))
{

View File

@ -1,5 +1,10 @@
2019-03-02 Jakub Jelinek <jakub@redhat.com>
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.

View File

@ -0,0 +1,12 @@
// PR c++/71446
// { dg-do compile { target c++11 } }
// { dg-options "" }
#include <initializer_list>
struct S { int value; };
int foo (S);
char *foo (std::initializer_list<int>);
int x = foo ({.value = 0});

View File

@ -0,0 +1,14 @@
// PR c++/71446
// { dg-do compile { target c++11 } }
// { dg-options "" }
#include <initializer_list>
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>);
int z = baz ({.one = 1, .two = 2, .three = 3}); // { dg-error "could not convert" }

View File

@ -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 }