aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2019-03-02 09:06:57 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2019-03-02 09:06:57 +0100
commit574eaf0fda98b795daf6b588e3c0e878987f9769 (patch)
tree999a0ff1961dfb213965506f95467552114d19cb /gcc
parent73ba6c712005892fbddb3e4dd7160d218e1b8c50 (diff)
downloadgcc-574eaf0fda98b795daf6b588e3c0e878987f9769.zip
gcc-574eaf0fda98b795daf6b588e3c0e878987f9769.tar.gz
gcc-574eaf0fda98b795daf6b588e3c0e878987f9769.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog15
-rw-r--r--gcc/cp/call.c7
-rw-r--r--gcc/cp/cp-tree.h7
-rw-r--r--gcc/cp/decl.c3
-rw-r--r--gcc/cp/parser.c13
-rw-r--r--gcc/cp/pt.c2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/desig10.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/desig11.C14
-rw-r--r--gcc/testsuite/g++.dg/ext/desig4.C4
10 files changed, 75 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bc6754e..e17537a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index d9073d7..1a9cf7e 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 91bc82b..663a23b 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 c5b5bd3c..173758f 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 2edd685..5804267 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<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;
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7295839..8a5a0b3 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 8701bc1..e6a83b0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig10.C b/gcc/testsuite/g++.dg/cpp2a/desig10.C
new file mode 100644
index 0000000..7fb6868
--- /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 <initializer_list>
+
+struct S { int value; };
+
+int foo (S);
+char *foo (std::initializer_list<int>);
+
+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 0000000..d6895a7
--- /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 <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" }
diff --git a/gcc/testsuite/g++.dg/ext/desig4.C b/gcc/testsuite/g++.dg/ext/desig4.C
index 33be258..62c3c58 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 }