re PR c++/71446 (Incorrect overload resolution when using designated initializers)
authorJakub Jelinek <jakub@redhat.com>
Sat, 2 Mar 2019 08:06:57 +0000 (09:06 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sat, 2 Mar 2019 08:06:57 +0000 (09:06 +0100)
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
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp2a/desig10.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/desig11.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/desig4.C

index bc6754e..e17537a 100644 (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.
index d9073d7..1a9cf7e 100644 (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;
index 91bc82b..663a23b 100644 (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) \
index c5b5bd3..173758f 100644 (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;
 }
index 2edd685..5804267 100644 (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;
 }
 
index 7295839..8a5a0b3 100644 (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))
          {
index 8701bc1..e6a83b0 100644 (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.
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig10.C b/gcc/testsuite/g++.dg/cpp2a/desig10.C
new file mode 100644 (file)
index 0000000..7fb6868
--- /dev/null
@@ -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 (file)
index 0000000..d6895a7
--- /dev/null
@@ -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" }
index 33be258..62c3c58 100644 (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 }