Hi,

as far as I can see this is just another case where we want to pass down more consistently the complain argument in order to avoid hard errors in sfinae contexts. In particular, we don't want hard errors from reshape_init itself (in order to fix 48737) and we want digest_init_r to forward complain to convert_for_initialization (to fix 48744). This requires some small adjustments elsewhere, not too much, in particular, earlier, finish_compound_literal forwards its complain argument to reshape_init and digest_init.

Tested x86_64-linux. Ok for mainline?

Thanks,
Paolo.

//////////////////
/cp
2011-05-08  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/48737
        PR c++/48744
        * decl.c (reshape_init): Take a complain parameter and do
        not call error if tf_error is not set.
        (check_initializer, reshape_init_r): Adjust.
        * typeck2.c (digest_init_r): Take a complain parameter and
        pass it to convert_for_initialization.
        (digest_init, digest_init_flags, process_init_constructor_array,
        process_init_constructor_record, process_init_constructor_union):
        Adjust.
        * init.c (expand_default_init, build_new_1): Likewise.
        * typeck.c (cp_build_modify_expr): Likewise.
        * decl2.c (grokfield): Likewise.
        * call.c (convert_like_real, convert_default_arg): Likewise.
        * semantics.c (finish_compound_literal): Pass complain to
        reshape_init and digest_init.
        * cp-tree.h: Adjust declarations.

/testsuite
2011-05-08  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/48737
        PR c++/48744
        * g++.dg/template/sfinae28.C: New.
        * g++.dg/template/sfinae29.C: Likewise.
Index: testsuite/g++.dg/template/sfinae28.C
===================================================================
--- testsuite/g++.dg/template/sfinae28.C        (revision 0)
+++ testsuite/g++.dg/template/sfinae28.C        (revision 0)
@@ -0,0 +1,13 @@
+// PR c++/48737
+// { dg-options "-std=c++0x" }
+
+template<class T>
+T&& create();
+
+template<class T, class... Args>
+decltype(T{create<Args>()...}, char()) f(int);
+
+template<class, class...>
+char (&f(...))[2];
+
+static_assert(sizeof(f<int[1], int, int>(0)) != 1, "Error");
Index: testsuite/g++.dg/template/sfinae29.C
===================================================================
--- testsuite/g++.dg/template/sfinae29.C        (revision 0)
+++ testsuite/g++.dg/template/sfinae29.C        (revision 0)
@@ -0,0 +1,23 @@
+// PR c++/48744
+// { dg-options "-std=c++0x" }
+
+template<class T>
+struct add_rval_ref {
+  typedef T&& type;
+};
+
+template<>
+struct add_rval_ref<void> {
+  typedef void type;
+};
+
+template<class T>
+typename add_rval_ref<T>::type create();
+
+template<class T, class Arg>
+decltype(T{create<Arg>()}, char()) f(int);
+
+template<class, class>
+char (&f(...))[2];
+
+static_assert(sizeof(f<int, void>(0)) != 1, "Error");
Index: cp/typeck.c
===================================================================
--- cp/typeck.c (revision 173549)
+++ cp/typeck.c (working copy)
@@ -6715,7 +6715,7 @@ cp_build_modify_expr (tree lhs, enum tree_code mod
            }
          if (check_array_initializer (lhs, lhstype, newrhs))
            return error_mark_node;
-         newrhs = digest_init (lhstype, newrhs);
+         newrhs = digest_init (lhstype, newrhs, complain);
        }
 
       else if (!same_or_base_type_p (TYPE_MAIN_VARIANT (lhstype),
Index: cp/init.c
===================================================================
--- cp/init.c   (revision 173549)
+++ cp/init.c   (working copy)
@@ -1435,7 +1435,7 @@ expand_default_init (tree binfo, tree true_exp, tr
     {
       /* A brace-enclosed initializer for an aggregate.  In C++0x this can
         happen for direct-initialization, too.  */
-      init = digest_init (type, init);
+      init = digest_init (type, init, complain);
       init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init);
       TREE_SIDE_EFFECTS (init) = 1;
       finish_expr_stmt (init);
@@ -2375,7 +2375,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type,
                             "verify length of initializer-list");
                }
              arraytype = build_cplus_array_type (type, domain);
-             vecinit = digest_init (arraytype, vecinit);
+             vecinit = digest_init (arraytype, vecinit, complain);
            }
          else if (*init)
             {
Index: cp/decl.c
===================================================================
--- cp/decl.c   (revision 173549)
+++ cp/decl.c   (working copy)
@@ -5203,7 +5203,7 @@ reshape_init_r (tree type, reshape_iter *d, bool f
            {
              ++d->cur;
              gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
-             return reshape_init (type, init);
+             return reshape_init (type, init, tf_warning_or_error);
            }
        }
 
@@ -5238,7 +5238,7 @@ reshape_init_r (tree type, reshape_iter *d, bool f
    revised CONSTRUCTOR node is returned.  */
 
 tree
-reshape_init (tree type, tree init)
+reshape_init (tree type, tree init, tsubst_flags_t complain)
 {
   VEC(constructor_elt, gc) *v;
   reshape_iter d;
@@ -5264,7 +5264,12 @@ tree
   /* Make sure all the element of the constructor were used. Otherwise,
      issue an error about exceeding initializers.  */
   if (d.cur != d.end)
-    error ("too many initializers for %qT", type);
+    {
+      if (complain & tf_error)
+       error ("too many initializers for %qT", type);
+      else
+       return error_mark_node;
+    }
 
   return new_init;
 }
@@ -5417,7 +5422,7 @@ check_initializer (tree decl, tree init, int flags
              init = error_mark_node;
            }
          else
-           init = reshape_init (type, init);       
+           init = reshape_init (type, init, tf_warning_or_error);          
        }
 
       /* If DECL has an array type without a specific bound, deduce the
Index: cp/typeck2.c
===================================================================
--- cp/typeck2.c        (revision 173549)
+++ cp/typeck2.c        (working copy)
@@ -797,7 +797,8 @@ check_narrowing (tree type, tree init)
    NESTED is true iff we are being called for an element of a CONSTRUCTOR.  */
 
 static tree
-digest_init_r (tree type, tree init, bool nested, int flags)
+digest_init_r (tree type, tree init, bool nested, int flags,
+              tsubst_flags_t complain)
 {
   enum tree_code code = TREE_CODE (type);
 
@@ -878,7 +879,7 @@ static tree
        check_narrowing (type, init);
       init = convert_for_initialization (0, type, init, flags,
                                         ICR_INIT, NULL_TREE, 0,
-                                        tf_warning_or_error);
+                                        complain);
       exp = &init;
 
       /* Skip any conversions since we'll be outputting the underlying
@@ -932,20 +933,20 @@ static tree
       return convert_for_initialization (NULL_TREE, type, init,
                                         flags,
                                         ICR_INIT, NULL_TREE, 0,
-                                         tf_warning_or_error);
+                                         complain);
     }
 }
 
 tree
-digest_init (tree type, tree init)
+digest_init (tree type, tree init, tsubst_flags_t complain)
 {
-  return digest_init_r (type, init, false, LOOKUP_IMPLICIT);
+  return digest_init_r (type, init, false, LOOKUP_IMPLICIT, complain);
 }
 
 tree
 digest_init_flags (tree type, tree init, int flags)
 {
-  return digest_init_r (type, init, false, flags);
+  return digest_init_r (type, init, false, flags, tf_warning_or_error);
 }
 
 /* Set of flags used within process_init_constructor to describe the
@@ -1017,7 +1018,8 @@ process_init_constructor_array (tree type, tree in
       else
        ce->index = size_int (i);
       gcc_assert (ce->value);
-      ce->value = digest_init_r (TREE_TYPE (type), ce->value, true, 
LOOKUP_IMPLICIT);
+      ce->value = digest_init_r (TREE_TYPE (type), ce->value, true,
+                                LOOKUP_IMPLICIT, tf_warning_or_error);
 
       if (ce->value != error_mark_node)
        gcc_assert (same_type_ignoring_top_level_qualifiers_p
@@ -1044,7 +1046,7 @@ process_init_constructor_array (tree type, tree in
                                             tf_warning_or_error);
            else
              next = build_constructor (init_list_type_node, NULL);
-           next = digest_init (TREE_TYPE (type), next);
+           next = digest_init (TREE_TYPE (type), next, tf_warning_or_error);
          }
        else if (!zero_init_p (TREE_TYPE (type)))
          next = build_zero_init (TREE_TYPE (type),
@@ -1124,7 +1126,8 @@ process_init_constructor_record (tree type, tree i
            }
 
          gcc_assert (ce->value);
-         next = digest_init_r (type, ce->value, true, LOOKUP_IMPLICIT);
+         next = digest_init_r (type, ce->value, true,
+                               LOOKUP_IMPLICIT, tf_warning_or_error);
          ++idx;
        }
       else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
@@ -1144,7 +1147,8 @@ process_init_constructor_record (tree type, tree i
                TARGET_EXPR_DIRECT_INIT_P (next) = true;
            }
 
-         next = digest_init_r (TREE_TYPE (field), next, true, LOOKUP_IMPLICIT);
+         next = digest_init_r (TREE_TYPE (field), next, true,
+                               LOOKUP_IMPLICIT, tf_warning_or_error);
 
          /* Warn when some struct elements are implicitly initialized.  */
          warning (OPT_Wmissing_field_initializers,
@@ -1254,7 +1258,8 @@ process_init_constructor_union (tree type, tree in
     }
 
   if (ce->value && ce->value != error_mark_node)
-    ce->value = digest_init_r (TREE_TYPE (ce->index), ce->value, true, 
LOOKUP_IMPLICIT);
+    ce->value = digest_init_r (TREE_TYPE (ce->index), ce->value,
+                              true, LOOKUP_IMPLICIT, tf_warning_or_error);
 
   return picflag_from_initializer (ce->value);
 }
Index: cp/semantics.c
===================================================================
--- cp/semantics.c      (revision 173549)
+++ cp/semantics.c      (working copy)
@@ -2369,7 +2369,7 @@ finish_compound_literal (tree type, tree compound_
   if (TREE_CODE (type) == ARRAY_TYPE
       && check_array_initializer (NULL_TREE, type, compound_literal))
     return error_mark_node;
-  compound_literal = reshape_init (type, compound_literal);
+  compound_literal = reshape_init (type, compound_literal, complain);
   if (TREE_CODE (type) == ARRAY_TYPE
       && TYPE_DOMAIN (type) == NULL_TREE)
     {
@@ -2378,7 +2378,7 @@ finish_compound_literal (tree type, tree compound_
       if (type == error_mark_node)
        return error_mark_node;
     }
-  compound_literal = digest_init (type, compound_literal);
+  compound_literal = digest_init (type, compound_literal, complain);
   /* Put static/constant array temporaries in static variables, but always
      represent class temporaries with TARGET_EXPR so we elide copies.  */
   if ((!at_function_scope_p () || CP_TYPE_CONST_P (type))
Index: cp/decl2.c
===================================================================
--- cp/decl2.c  (revision 173549)
+++ cp/decl2.c  (working copy)
@@ -924,7 +924,7 @@ grokfield (const cp_declarator *declarator,
       else if (!processing_template_decl)
        {
          if (TREE_CODE (init) == CONSTRUCTOR)
-           init = digest_init (TREE_TYPE (value), init);
+           init = digest_init (TREE_TYPE (value), init, tf_warning_or_error);
          init = maybe_constant_init (init);
 
          if (init != error_mark_node && !TREE_CONSTANT (init))
Index: cp/call.c
===================================================================
--- cp/call.c   (revision 173549)
+++ cp/call.c   (working copy)
@@ -5670,7 +5670,7 @@ convert_like_real (conversion *convs, tree expr, t
          expr = build2 (COMPLEX_EXPR, totype, real, imag);
          return fold_if_not_in_template (expr);
        }
-      return get_target_expr (digest_init (totype, expr));
+      return get_target_expr (digest_init (totype, expr, complain));
 
     default:
       break;
@@ -6032,7 +6032,7 @@ convert_default_arg (tree type, tree arg, tree fn,
   arg = break_out_target_exprs (arg);
   if (TREE_CODE (arg) == CONSTRUCTOR)
     {
-      arg = digest_init (type, arg);
+      arg = digest_init (type, arg, tf_warning_or_error);
       arg = convert_for_initialization (0, type, arg, LOOKUP_IMPLICIT,
                                        ICR_DEFAULT_ARGUMENT, fn, parmnum,
                                         tf_warning_or_error);
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h        (revision 173549)
+++ cp/cp-tree.h        (working copy)
@@ -4875,7 +4875,7 @@ extern tree cxx_comdat_group                      (tree);
 extern bool cp_missing_noreturn_ok_p           (tree);
 extern void initialize_artificial_var          (tree, VEC(constructor_elt,gc) 
*);
 extern tree check_var_type                     (tree, tree);
-extern tree reshape_init (tree, tree);
+extern tree reshape_init                        (tree, tree, tsubst_flags_t);
 extern tree next_initializable_field (tree);
 
 extern bool defer_mark_used_calls;
@@ -5641,7 +5641,7 @@ extern int abstract_virtuals_error_sfinae (tree, t
 
 extern tree store_init_value                   (tree, tree, int);
 extern void check_narrowing                    (tree, tree);
-extern tree digest_init                                (tree, tree);
+extern tree digest_init                                (tree, tree, 
tsubst_flags_t);
 extern tree digest_init_flags                  (tree, tree, int);
 extern tree build_scoped_ref                   (tree, tree, tree *);
 extern tree build_x_arrow                      (tree);

Reply via email to