diff mbox

[C++] PRs 48737 & 48744

Message ID 4DC6CA14.60507@oracle.com
State New
Headers show

Commit Message

Paolo Carlini May 8, 2011, 4:51 p.m. UTC
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.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): 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.carlini@oracle.com>

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

Comments

Jason Merrill May 9, 2011, 4:32 a.m. UTC | #1
On 05/08/2011 12:51 PM, Paolo Carlini wrote:
> @@ -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);

Any reason not to SFINAEify reshape_init_r as well?  Same question for 
process_init_constructor*.

Jason
diff mbox

Patch

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);