re PR c++/48737 ([C++0x][SFINAE] Hard errors with array list-construction with too...
authorPaolo Carlini <paolo.carlini@oracle.com>
Mon, 9 May 2011 19:24:50 +0000 (19:24 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Mon, 9 May 2011 19:24:50 +0000 (19:24 +0000)
/cp
2011-05-09  Paolo Carlini  <paolo.carlini@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, reshape_init_array,
reshape_init_array_1, reshape_init_vector, reshape_init_class):
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,
process_init_constructor, digest_init_r): 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-09  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/48737
PR c++/48744
* g++.dg/template/sfinae28.C: New.
* g++.dg/template/sfinae29.C: Likewise.

From-SVN: r173590

12 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/sfinae28.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/sfinae29.C [new file with mode: 0644]

index 04096deee9cda8e0b5b948134c152e030e37eae4..b89280dbda345d44426fcd0336f67e367bd4012a 100644 (file)
@@ -1,5 +1,27 @@
+2011-05-09  Paolo Carlini  <paolo.carlini@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, reshape_init_array,
+       reshape_init_array_1, reshape_init_vector, reshape_init_class):
+       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,
+       process_init_constructor, digest_init_r): 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.
+
 2011-05-07  Fabien ChĂȘne  <fabien@gcc.gnu.org>
-       
+
        PR c++/48859
        * init.c (diagnose_uninitialized_cst_or_ref_member_1): stop the
        recursion if there is user defined constructor.
index 3a71572b67dd2a066146186ad0894e74143097be..095d1b0cb294a6492069be1ef9b8e53a3f71cff9 100644 (file)
@@ -5670,7 +5670,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
          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, int parmnum)
   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 a03d6a11bcad877b92a2b305fe27171d83f4b845..53092ffc6e706a1eb792720b7d41034769ced2cf 100644 (file)
@@ -4903,7 +4903,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;
@@ -5669,7 +5669,7 @@ extern int abstract_virtuals_error_sfinae (tree, tree, tsubst_flags_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);
index c255e16c6dacca6c7c0f371d4e9d3ee8b9660897..ab36d18552ae7f9ce60fdd6efdc46fda094c1077 100644 (file)
@@ -4878,7 +4878,7 @@ typedef struct reshape_iterator_t
   constructor_elt *end;
 } reshape_iter;
 
-static tree reshape_init_r (tree, reshape_iter *, bool);
+static tree reshape_init_r (tree, reshape_iter *, bool, tsubst_flags_t);
 
 /* FIELD is a FIELD_DECL or NULL.  In the former case, the value
    returned is the next FIELD_DECL (possibly FIELD itself) that can be
@@ -4904,7 +4904,8 @@ next_initializable_field (tree field)
    the iterator within the constructor.  */
 
 static tree
-reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d)
+reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
+                     tsubst_flags_t complain)
 {
   tree new_init;
   bool sized_array_p = (max_index != NULL_TREE);
@@ -4936,7 +4937,8 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d)
       tree elt_init;
 
       check_array_designated_initializer (d->cur);
-      elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false);
+      elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false,
+                                complain);
       if (elt_init == error_mark_node)
        return error_mark_node;
       CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init),
@@ -4952,7 +4954,7 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d)
    Parameters are the same of reshape_init_r.  */
 
 static tree
-reshape_init_array (tree type, reshape_iter *d)
+reshape_init_array (tree type, reshape_iter *d, tsubst_flags_t complain)
 {
   tree max_index = NULL_TREE;
 
@@ -4961,14 +4963,14 @@ reshape_init_array (tree type, reshape_iter *d)
   if (TYPE_DOMAIN (type))
     max_index = array_type_nelts (type);
 
-  return reshape_init_array_1 (TREE_TYPE (type), max_index, d);
+  return reshape_init_array_1 (TREE_TYPE (type), max_index, d, complain);
 }
 
 /* Subroutine of reshape_init_r, processes the initializers for vectors.
    Parameters are the same of reshape_init_r.  */
 
 static tree
-reshape_init_vector (tree type, reshape_iter *d)
+reshape_init_vector (tree type, reshape_iter *d, tsubst_flags_t complain)
 {
   tree max_index = NULL_TREE;
 
@@ -4979,8 +4981,9 @@ reshape_init_vector (tree type, reshape_iter *d)
       tree value = d->cur->value;
       if (!same_type_p (TREE_TYPE (value), type))
        {
-         error ("invalid type %qT as initializer for a vector of type %qT",
-               TREE_TYPE (d->cur->value), type);
+         if (complain & tf_error)
+           error ("invalid type %qT as initializer for a vector of type %qT",
+                  TREE_TYPE (d->cur->value), type);
          value = error_mark_node;
        }
       ++d->cur;
@@ -4991,14 +4994,15 @@ reshape_init_vector (tree type, reshape_iter *d)
   if (TREE_CODE (type) == VECTOR_TYPE)
     max_index = size_int (TYPE_VECTOR_SUBPARTS (type) - 1);
 
-  return reshape_init_array_1 (TREE_TYPE (type), max_index, d);
+  return reshape_init_array_1 (TREE_TYPE (type), max_index, d, complain);
 }
 
 /* Subroutine of reshape_init_r, processes the initializers for classes
    or union. Parameters are the same of reshape_init_r.  */
 
 static tree
-reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p)
+reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
+                   tsubst_flags_t complain)
 {
   tree field;
   tree new_init;
@@ -5018,7 +5022,8 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p)
        initializer-list {}.  */
       if (!first_initializer_p)
        {
-         error ("initializer for %qT must be brace-enclosed", type);
+         if (complain & tf_error)
+           error ("initializer for %qT must be brace-enclosed", type);
          return error_mark_node;
        }
       return new_init;
@@ -5036,8 +5041,9 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p)
 
          if (!field || TREE_CODE (field) != FIELD_DECL)
            {
-             error ("%qT has no non-static data member named %qD", type,
-                   d->cur->index);
+             if (complain & tf_error)
+               error ("%qT has no non-static data member named %qD", type,
+                      d->cur->index);
              return error_mark_node;
            }
        }
@@ -5047,7 +5053,7 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p)
        break;
 
       field_init = reshape_init_r (TREE_TYPE (field), d,
-                                  /*first_initializer_p=*/false);
+                                  /*first_initializer_p=*/false, complain);
       if (field_init == error_mark_node)
        return error_mark_node;
 
@@ -5074,7 +5080,8 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p)
    outermost CONSTRUCTOR node.  */
 
 static tree
-reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
+reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
+               tsubst_flags_t complain)
 {
   tree init = d->cur->value;
 
@@ -5089,7 +5096,12 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
       if (BRACE_ENCLOSED_INITIALIZER_P (init))
        {
          if (CONSTRUCTOR_NELTS (init) > 2)
-           error ("too many initializers for %qT", type);
+           {
+             if (complain & tf_error)
+               error ("too many initializers for %qT", type);
+             else
+               return error_mark_node;
+           }
        }
       else if (first_initializer_p && d->cur != d->end)
        {
@@ -5116,7 +5128,8 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
        {
          if (SCALAR_TYPE_P (type))
            {
-             error ("braces around scalar initializer for type %qT", type);
+             if (complain & tf_error)
+               error ("braces around scalar initializer for type %qT", type);
              init = error_mark_node;
            }
          else
@@ -5203,7 +5216,7 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
            {
              ++d->cur;
              gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
-             return reshape_init (type, init);
+             return reshape_init (type, init, complain);
            }
        }
 
@@ -5213,11 +5226,11 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
 
   /* Dispatch to specialized routines.  */
   if (CLASS_TYPE_P (type))
-    return reshape_init_class (type, d, first_initializer_p);
+    return reshape_init_class (type, d, first_initializer_p, complain);
   else if (TREE_CODE (type) == ARRAY_TYPE)
-    return reshape_init_array (type, d);
+    return reshape_init_array (type, d, complain);
   else if (TREE_CODE (type) == VECTOR_TYPE)
-    return reshape_init_vector (type, d);
+    return reshape_init_vector (type, d, complain);
   else
     gcc_unreachable();
 }
@@ -5238,7 +5251,7 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
    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;
@@ -5257,14 +5270,19 @@ reshape_init (tree type, tree init)
   d.cur = VEC_index (constructor_elt, v, 0);
   d.end = d.cur + VEC_length (constructor_elt, v);
 
-  new_init = reshape_init_r (type, &d, true);
+  new_init = reshape_init_r (type, &d, true, complain);
   if (new_init == error_mark_node)
     return error_mark_node;
 
   /* 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 +5435,7 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
              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 2e08dd730d92bc5bc5aa9c8899837ed74b4111e9..91a66443bc8ad5579b2474ccca0ac937f7899c88 100644 (file)
@@ -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 3eb804dd56a4129d6667baa86477459bf16dd8fd..b71ddfc0f9f7b627a349b8458e5978c47fda87dc 100644 (file)
@@ -1435,7 +1435,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
     {
       /* 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);
@@ -2378,7 +2378,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
                             "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 d33f9fe16a9ffcfd3dfe6cc017b1ab8f7aead160..0ba0370833b74828ed6aa927929f27a29bb45991 100644 (file)
@@ -2369,7 +2369,7 @@ finish_compound_literal (tree type, tree compound_literal,
   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_literal,
       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 4d0c0d7b06befc2dbc9f5dc4db61ff32a1d4e7f2..d98c62bb940a75d68386156c2d6123b0d466110d 100644 (file)
@@ -6715,7 +6715,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
            }
          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 aec54f9d07f8d43891285986e2db714e4dc9d270..ec6b5d378504cb9fb103a8b86994d7bad6720121 100644 (file)
@@ -39,7 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-core.h"
 
 static tree
-process_init_constructor (tree type, tree init);
+process_init_constructor (tree type, tree init, tsubst_flags_t complain);
 
 
 /* Print an error message stemming from an attempt to use
@@ -783,8 +783,8 @@ check_narrowing (tree type, tree init)
     }
 
   if (!ok)
-    permerror (input_location, "narrowing conversion of %qE from %qT to %qT inside { }",
-              init, ftype, type);
+    permerror (input_location, "narrowing conversion of %qE from %qT "
+              "to %qT inside { }", init, ftype, type);
 }
 
 /* Process the initializer INIT for a variable of type TYPE, emitting
@@ -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);
 
@@ -833,7 +834,8 @@ digest_init_r (tree type, tree init, bool nested, int flags)
            {
              if (char_type != char_type_node)
                {
-                 error ("char-array initialized from wide string");
+                 if (complain & tf_error)
+                   error ("char-array initialized from wide string");
                  return error_mark_node;
                }
            }
@@ -841,12 +843,15 @@ digest_init_r (tree type, tree init, bool nested, int flags)
            {
              if (char_type == char_type_node)
                {
-                 error ("int-array initialized from non-wide string");
+                 if (complain & tf_error)
+                   error ("int-array initialized from non-wide string");
                  return error_mark_node;
                }
              else if (char_type != typ1)
                {
-                 error ("int-array initialized from incompatible wide string");
+                 if (complain & tf_error)
+                   error ("int-array initialized from incompatible "
+                          "wide string");
                  return error_mark_node;
                }
            }
@@ -861,7 +866,8 @@ digest_init_r (tree type, tree init, bool nested, int flags)
                 counted in the length of the constant, but in C++ this would
                 be invalid.  */
              if (size < TREE_STRING_LENGTH (init))
-               permerror (input_location, "initializer-string for array of chars is too long");
+               permerror (input_location, "initializer-string for array "
+                          "of chars is too long");
            }
          return init;
        }
@@ -878,7 +884,7 @@ digest_init_r (tree type, tree init, bool nested, int flags)
        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
@@ -902,13 +908,14 @@ digest_init_r (tree type, tree init, bool nested, int flags)
 
   if (BRACE_ENCLOSED_INITIALIZER_P (init)
       && !TYPE_NON_AGGREGATE_CLASS (type))
-    return process_init_constructor (type, init);
+    return process_init_constructor (type, init, complain);
   else
     {
       if (COMPOUND_LITERAL_P (init) && TREE_CODE (type) == ARRAY_TYPE)
        {
-         error ("cannot initialize aggregate of type %qT with "
-                "a compound literal", type);
+         if (complain & tf_error)
+           error ("cannot initialize aggregate of type %qT with "
+                  "a compound literal", type);
 
          return error_mark_node;
        }
@@ -924,28 +931,29 @@ digest_init_r (tree type, tree init, bool nested, int flags)
                  (type, TREE_TYPE (init))))
            return init;
 
-         error ("array must be initialized with a brace-enclosed"
-                " initializer");
+         if (complain & tf_error)
+           error ("array must be initialized with a brace-enclosed"
+                  " initializer");
          return error_mark_node;
        }
 
       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);
 }
 \f
 /* Set of flags used within process_init_constructor to describe the
@@ -974,7 +982,8 @@ picflag_from_initializer (tree init)
    which describe the initializers.  */
 
 static int
-process_init_constructor_array (tree type, tree init)
+process_init_constructor_array (tree type, tree init,
+                               tsubst_flags_t complain)
 {
   unsigned HOST_WIDE_INT i, len = 0;
   int flags = 0;
@@ -1001,7 +1010,12 @@ process_init_constructor_array (tree type, tree init)
 
   /* There must not be more initializers than needed.  */
   if (!unbounded && VEC_length (constructor_elt, v)  > len)
-    error ("too many initializers for %qT", type);
+    {
+      if (complain & tf_error)
+       error ("too many initializers for %qT", type);
+      else
+       return PICFLAG_ERRONEOUS;
+    }
 
   FOR_EACH_VEC_ELT (constructor_elt, v, i, ce)
     {
@@ -1017,7 +1031,8 @@ process_init_constructor_array (tree type, tree init)
       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, complain);
 
       if (ce->value != error_mark_node)
        gcc_assert (same_type_ignoring_top_level_qualifiers_p
@@ -1041,10 +1056,10 @@ process_init_constructor_array (tree type, tree init)
              one up; if it's an array, recurse.  */
            if (MAYBE_CLASS_TYPE_P (TREE_TYPE (type)))
               next = build_functional_cast (TREE_TYPE (type), NULL_TREE,
-                                            tf_warning_or_error);
+                                            complain);
            else
              next = build_constructor (init_list_type_node, NULL);
-           next = digest_init (TREE_TYPE (type), next);
+           next = digest_init (TREE_TYPE (type), next, complain);
          }
        else if (!zero_init_p (TREE_TYPE (type)))
          next = build_zero_init (TREE_TYPE (type),
@@ -1068,7 +1083,8 @@ process_init_constructor_array (tree type, tree init)
    the initializers.  */
 
 static int
-process_init_constructor_record (tree type, tree init)
+process_init_constructor_record (tree type, tree init,
+                                tsubst_flags_t complain)
 {
   VEC(constructor_elt,gc) *v = NULL;
   int flags = 0;
@@ -1124,7 +1140,8 @@ process_init_constructor_record (tree type, tree init)
            }
 
          gcc_assert (ce->value);
-         next = digest_init_r (type, ce->value, true, LOOKUP_IMPLICIT);
+         next = digest_init_r (type, ce->value, true,
+                               LOOKUP_IMPLICIT, complain);
          ++idx;
        }
       else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
@@ -1137,14 +1154,15 @@ process_init_constructor_record (tree type, tree init)
          if (MAYBE_CLASS_TYPE_P (TREE_TYPE (field)))
            {
              next = finish_compound_literal (TREE_TYPE (field), next,
-                                             tf_warning_or_error);
+                                             complain);
              /* direct-initialize the target. No temporary is going
                  to be involved.  */
              if (TREE_CODE (next) == TARGET_EXPR)
                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, complain);
 
          /* Warn when some struct elements are implicitly initialized.  */
          warning (OPT_Wmissing_field_initializers,
@@ -1153,11 +1171,26 @@ process_init_constructor_record (tree type, tree init)
       else
        {
          if (TREE_READONLY (field))
-           error ("uninitialized const member %qD", field);
+           {
+             if (complain & tf_error)
+               error ("uninitialized const member %qD", field);
+             else
+               return PICFLAG_ERRONEOUS;
+           }
          else if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field)))
-           error ("member %qD with uninitialized const fields", field);
+           {
+             if (complain & tf_error)
+               error ("member %qD with uninitialized const fields", field);
+             else
+               return PICFLAG_ERRONEOUS;
+           }
          else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
-           error ("member %qD is uninitialized reference", field);
+           {
+             if (complain & tf_error)
+               error ("member %qD is uninitialized reference", field);
+             else
+               return PICFLAG_ERRONEOUS;
+           }
 
          /* Warn when some struct elements are implicitly initialized
             to zero.  */
@@ -1181,8 +1214,13 @@ process_init_constructor_record (tree type, tree init)
     }
 
   if (idx < VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)))
-    error ("too many initializers for %qT", type);
-    
+    {
+      if (complain & tf_error)
+       error ("too many initializers for %qT", type);
+      else
+       return PICFLAG_ERRONEOUS;
+    }
+
   CONSTRUCTOR_ELTS (init) = v;
   return flags;
 }
@@ -1192,7 +1230,8 @@ process_init_constructor_record (tree type, tree init)
    which describe the initializer.  */
 
 static int
-process_init_constructor_union (tree type, tree init)
+process_init_constructor_union (tree type, tree init,
+                               tsubst_flags_t complain)
 {
   constructor_elt *ce;
   int len;
@@ -1204,6 +1243,8 @@ process_init_constructor_union (tree type, tree init)
   len = VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init));
   if (len > 1)
     {
+      if (!(complain & tf_error))
+       return PICFLAG_ERRONEOUS;
       error ("too many initializers for %qT", type);
       VEC_block_remove (constructor_elt, CONSTRUCTOR_ELTS (init), 1, len-1);
     }
@@ -1225,7 +1266,9 @@ process_init_constructor_union (tree type, tree init)
              break;
          if (!field)
            {
-             error ("no field %qD found in union being initialized", field);
+             if (complain & tf_error)
+               error ("no field %qD found in union being initialized",
+                      field);
              ce->value = error_mark_node;
            }
          ce->index = field;
@@ -1234,7 +1277,8 @@ process_init_constructor_union (tree type, tree init)
        {
          gcc_assert (TREE_CODE (ce->index) == INTEGER_CST
                      || TREE_CODE (ce->index) == RANGE_EXPR);
-         error ("index value instead of field name in union initializer");
+         if (complain & tf_error)
+           error ("index value instead of field name in union initializer");
          ce->value = error_mark_node;
        }
     }
@@ -1247,14 +1291,16 @@ process_init_constructor_union (tree type, tree init)
        field = TREE_CHAIN (field);
       if (field == NULL_TREE)
        {
-         error ("too many initializers for %qT", type);
+         if (complain & tf_error)
+           error ("too many initializers for %qT", type);
          ce->value = error_mark_node;
        }
       ce->index = field;
     }
 
   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, complain);
 
   return picflag_from_initializer (ce->value);
 }
@@ -1274,18 +1320,18 @@ process_init_constructor_union (tree type, tree init)
    of error.  */
 
 static tree
-process_init_constructor (tree type, tree init)
+process_init_constructor (tree type, tree init, tsubst_flags_t complain)
 {
   int flags;
 
   gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
 
   if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE)
-    flags = process_init_constructor_array (type, init);
+    flags = process_init_constructor_array (type, init, complain);
   else if (TREE_CODE (type) == RECORD_TYPE)
-    flags = process_init_constructor_record (type, init);
+    flags = process_init_constructor_record (type, init, complain);
   else if (TREE_CODE (type) == UNION_TYPE)
-    flags = process_init_constructor_union (type, init);
+    flags = process_init_constructor_union (type, init, complain);
   else
     gcc_unreachable ();
 
index 4b4bd93cd1129cc0640b85cbc2be7da46b83d9dc..82478ea5c0e0e6be8175fbfa07dcb2f8237f86b7 100644 (file)
@@ -1,3 +1,10 @@
+2011-05-09  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/48737
+       PR c++/48744
+       * g++.dg/template/sfinae28.C: New.
+       * g++.dg/template/sfinae29.C: Likewise.
+
 2011-05-09  Jason Merrill  <jason@redhat.com>
 
        * g++.dg/template/nontype23.C: New.
diff --git a/gcc/testsuite/g++.dg/template/sfinae28.C b/gcc/testsuite/g++.dg/template/sfinae28.C
new file mode 100644 (file)
index 0000000..be96983
--- /dev/null
@@ -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");
diff --git a/gcc/testsuite/g++.dg/template/sfinae29.C b/gcc/testsuite/g++.dg/template/sfinae29.C
new file mode 100644 (file)
index 0000000..486064c
--- /dev/null
@@ -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");