+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.
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)
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;
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
#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) \
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;
}
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);
/* 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);
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;
IDENTIFIER_MARKED (designator) = 0;
}
+ *designated = first_designator != NULL_TREE;
return v;
}
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))
{
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.
--- /dev/null
+// 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});
--- /dev/null
+// 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" }
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 }