diff mbox

[PING] Re: [4.8, C++ Patch] PR 52422

Message ID 4F55F883.9040607@oracle.com
State New
Headers show

Commit Message

Paolo Carlini March 6, 2012, 11:44 a.m. UTC
Hi

just rediffed and retested on x86_64-linux the new version of the patch. 
Is it Ok for mainline?

Thanks,
Paolo.

///////////////////////
/cp
2012-03-06  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/52422
	* cp-tree.h (build_addr_func, decay_conversion,
	build_m_component_ref): Add tsubst_flags_t parameter.
	* typeck.c (decay_conversion): Add tsubst_flags_t parameter and
	use it throughout.
	(default_conversion, cp_build_indirect_ref,
	get_member_function_from_ptrfunc, cp_build_function_call_vec,
	convert_arguments, build_x_binary_op, cp_build_binary_op,
	convert_member_func_to_ptr, build_reinterpret_cast_1,
	build_const_cast_1, expand_ptrmemfunc_cst,
	convert_for_initialization): Adjust.
	* init.c (build_vec_init, build_vec_init): Adjust.
	* decl.c (grok_reference_init, get_atexit_node): Likewise.
	* rtti.c (build_dynamic_cast_1, tinfo_base_init): Likewise.
	* except.c (build_throw): Likewise.
	* typeck2.c (build_x_arrow): Likewise.
	(build_m_component_ref): Add tsubst_flags_t parameter and
	use it throughout.
	* pt.c (convert_nontype_argument): Adjust.
	* semantics.c (finish_asm_stmt, maybe_add_lambda_conv_op): Likewise.
	* call.c (build_addr_func): Add tsubst_flags_t parameter and
	use it throughout.
	(build_call_a, build_conditional_expr_1, build_new_op_1,
	convert_like_real, convert_arg_to_ellipsis, build_over_call,
	build_special_member_call): Adjust.
	* cvt.c (force_rvalue, build_expr_type_conversion): Likewise.

/testsuite
2012-03-06  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/52422
	* g++.dg/cpp0x/sfinae33.C: New.
	* g++.dg/cpp0x/sfinae34.C: Likewise.
diff mbox

Patch

Index: testsuite/g++.dg/cpp0x/sfinae33.C
===================================================================
--- testsuite/g++.dg/cpp0x/sfinae33.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/sfinae33.C	(revision 0)
@@ -0,0 +1,27 @@ 
+// PR c++/52422
+// { 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 = decltype(create<T>()())
+>
+auto f(int) -> char(&)[1];
+
+template<class>
+auto f(...) -> char(&)[2];
+
+static_assert(sizeof(f<void>(0)) != 1, "");
Index: testsuite/g++.dg/cpp0x/sfinae34.C
===================================================================
--- testsuite/g++.dg/cpp0x/sfinae34.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/sfinae34.C	(revision 0)
@@ -0,0 +1,28 @@ 
+// PR c++/52422
+// { 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 U,
+  class = decltype( (create<T>().*create<U>())() )
+>
+auto f(int) -> char(&)[1];
+
+template<class, class>
+auto f(...) -> char(&)[2];
+
+static_assert(sizeof(f<void, void>(0)) != 1, "");
+
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 184985)
+++ cp/typeck.c	(working copy)
@@ -1813,7 +1813,7 @@  unlowered_expr_type (const_tree exp)
    that the return value is no longer an lvalue.  */
 
 tree
-decay_conversion (tree exp)
+decay_conversion (tree exp, tsubst_flags_t complain)
 {
   tree type;
   enum tree_code code;
@@ -1827,7 +1827,8 @@  tree
   exp = resolve_nondeduced_context (exp);
   if (type_unknown_p (exp))
     {
-      cxx_incomplete_type_error (exp, TREE_TYPE (exp));
+      if (complain & tf_error)
+	cxx_incomplete_type_error (exp, TREE_TYPE (exp));
       return error_mark_node;
     }
 
@@ -1846,13 +1847,14 @@  tree
   code = TREE_CODE (type);
   if (code == VOID_TYPE)
     {
-      error ("void value not ignored as it ought to be");
+      if (complain & tf_error)
+	error ("void value not ignored as it ought to be");
       return error_mark_node;
     }
-  if (invalid_nonstatic_memfn_p (exp, tf_warning_or_error))
+  if (invalid_nonstatic_memfn_p (exp, complain))
     return error_mark_node;
   if (code == FUNCTION_TYPE || is_overloaded_fn (exp))
-    return cp_build_addr_expr (exp, tf_warning_or_error);
+    return cp_build_addr_expr (exp, complain);
   if (code == ARRAY_TYPE)
     {
       tree adr;
@@ -1864,7 +1866,9 @@  tree
 
       if (TREE_CODE (exp) == COMPOUND_EXPR)
 	{
-	  tree op1 = decay_conversion (TREE_OPERAND (exp, 1));
+	  tree op1 = decay_conversion (TREE_OPERAND (exp, 1), complain);
+	  if (op1 == error_mark_node)
+            return error_mark_node;
 	  return build2 (COMPOUND_EXPR, TREE_TYPE (op1),
 			 TREE_OPERAND (exp, 0), op1);
 	}
@@ -1872,7 +1876,8 @@  tree
       if (!lvalue_p (exp)
 	  && ! (TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp)))
 	{
-	  error ("invalid use of non-lvalue array");
+	  if (complain & tf_error)
+	    error ("invalid use of non-lvalue array");
 	  return error_mark_node;
 	}
 
@@ -1887,7 +1892,7 @@  tree
 	}
       /* This way is better for a COMPONENT_REF since it can
 	 simplify the offset for a component.  */
-      adr = cp_build_addr_expr (exp, tf_warning_or_error);
+      adr = cp_build_addr_expr (exp, complain);
       return cp_convert (ptrtype, adr);
     }
 
@@ -1939,7 +1944,7 @@  default_conversion (tree exp)
   else if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (exp)))
     exp = perform_integral_promotions (exp);
   /* Perform the other conversions.  */
-  exp = decay_conversion (exp);
+  exp = decay_conversion (exp, tf_warning_or_error);
 
   return exp;
 }
@@ -2754,8 +2759,15 @@  cp_build_indirect_ref (tree ptr, ref_operator erro
   if (ptr == current_class_ptr)
     return current_class_ref;
 
-  pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE
-	     ? ptr : decay_conversion (ptr));
+  if (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE)
+    pointer = ptr;
+  else
+    {
+      pointer = decay_conversion (ptr, complain);
+      if (pointer == error_mark_node)
+	return error_mark_node;
+    }
+
   type = TREE_TYPE (pointer);
 
   if (POINTER_TYPE_P (type))
@@ -3049,7 +3061,8 @@  get_member_function_from_ptrfunc (tree *instance_p
 	      /* Extracting the function address from a pmf is only
 		 allowed with -Wno-pmf-conversions. It only works for
 		 pmf constants.  */
-	      e1 = build_addr_func (PTRMEM_CST_MEMBER (function));
+	      e1 = build_addr_func (PTRMEM_CST_MEMBER (function),
+				    tf_warning_or_error);
 	      e1 = convert (fntype, e1);
 	      return e1;
 	    }
@@ -3251,13 +3264,13 @@  cp_build_function_call_vec (tree function, VEC(tre
 	pedwarn (input_location, OPT_pedantic, 
 		 "ISO C++ forbids calling %<::main%> from within program");
 
-      function = build_addr_func (function);
+      function = build_addr_func (function, complain);
     }
   else
     {
       fndecl = NULL_TREE;
 
-      function = build_addr_func (function);
+      function = build_addr_func (function, complain);
     }
 
   if (function == error_mark_node)
@@ -3422,7 +3435,7 @@  convert_arguments (tree typelist, VEC(tree,gc) **v
 	  if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE
 	      || TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE
 	      || TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)
-	    val = decay_conversion (val);
+	    val = decay_conversion (val, complain);
 	}
 
       if (val == error_mark_node)
@@ -3549,7 +3562,7 @@  build_x_binary_op (enum tree_code code, tree arg1,
     }
 
   if (code == DOTSTAR_EXPR)
-    expr = build_m_component_ref (arg1, arg2);
+    expr = build_m_component_ref (arg1, arg2, complain);
   else
     expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE,
 			 overload, complain);
@@ -3713,9 +3726,9 @@  cp_build_binary_op (location_t location,
       || code == TRUTH_XOR_EXPR)
     {
       if (!really_overloaded_fn (op0) && !VOID_TYPE_P (TREE_TYPE (op0)))
-	op0 = decay_conversion (op0);
+	op0 = decay_conversion (op0, complain);
       if (!really_overloaded_fn (op1) && !VOID_TYPE_P (TREE_TYPE (op1)))
-	op1 = decay_conversion (op1);
+	op1 = decay_conversion (op1, complain);
     }
   else
     {
@@ -6107,7 +6120,7 @@  convert_member_func_to_ptr (tree type, tree expr)
 	     "converting from %qT to %qT", intype, type);
 
   if (TREE_CODE (intype) == METHOD_TYPE)
-    expr = build_addr_func (expr);
+    expr = build_addr_func (expr, tf_warning_or_error);
   else if (TREE_CODE (expr) == PTRMEM_CST)
     expr = build_address (PTRMEM_CST_MEMBER (expr));
   else
@@ -6199,7 +6212,7 @@  build_reinterpret_cast_1 (tree type, tree expr, bo
   /* If the cast is not to a reference type, the lvalue-to-rvalue,
      array-to-pointer, and function-to-pointer conversions are
      performed.  */
-  expr = decay_conversion (expr);
+  expr = decay_conversion (expr, complain);
 
   /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
      Strip such NOP_EXPRs if VALUE is being used in non-lvalue context.  */
@@ -6438,7 +6451,10 @@  build_const_cast_1 (tree dst_type, tree expr, tsub
 	    }
 	  else
 	    {
-	      expr = decay_conversion (expr);
+	      expr = decay_conversion (expr, complain);
+	      if (expr == error_mark_node)
+		return error_mark_node;
+
 	      /* build_c_cast puts on a NOP_EXPR to make the result not an
 		 lvalue.  Strip such NOP_EXPRs if VALUE is being used in
 		 non-lvalue context.  */
@@ -7282,7 +7298,8 @@  expand_ptrmemfunc_cst (tree cst, tree *delta, tree
 				 /*c_cast_p=*/0, tf_warning_or_error);
 
   if (!DECL_VIRTUAL_P (fn))
-    *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn));
+    *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type),
+		    build_addr_func (fn, tf_warning_or_error));
   else
     {
       /* If we're dealing with a virtual function, we have to adjust 'this'
@@ -7616,7 +7633,7 @@  convert_for_initialization (tree exp, tree type, t
 	  && (TREE_CODE (type) != REFERENCE_TYPE
 	      || TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE))
       || TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
-    rhs = decay_conversion (rhs);
+    rhs = decay_conversion (rhs, complain);
 
   rhstype = TREE_TYPE (rhs);
   coder = TREE_CODE (rhstype);
Index: cp/init.c
===================================================================
--- cp/init.c	(revision 184985)
+++ cp/init.c	(working copy)
@@ -1,7 +1,7 @@ 
 /* Handle initialization things in C++.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
    1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-   2011 Free Software Foundation, Inc.
+   2011, 2012 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -3192,7 +3192,10 @@  build_vec_init (tree base, tree maxindex, tree ini
   if (TREE_CODE (atype) == ARRAY_TYPE)
     {
       ptype = build_pointer_type (type);
-      base = cp_convert (ptype, decay_conversion (base));
+      base = decay_conversion (base, complain);
+      if (base == error_mark_node)
+	return error_mark_node;
+      base = cp_convert (ptype, base);
     }
   else
     ptype = atype;
@@ -3241,7 +3244,9 @@  build_vec_init (tree base, tree maxindex, tree ini
     {
       if (lvalue_kind (init) & clk_rvalueref)
 	xvalue = true;
-      base2 = decay_conversion (init);
+      base2 = decay_conversion (init, complain);
+      if (base2 == error_mark_node)
+	return error_mark_node;
       itype = TREE_TYPE (base2);
       base2 = get_temp_regvar (itype, base2);
       itype = TREE_TYPE (itype);
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 184985)
+++ cp/decl.c	(working copy)
@@ -4658,7 +4658,7 @@  grok_reference_init (tree decl, tree type, tree in
   if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE
       && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
     /* Note: default conversion is only called in very special cases.  */
-    init = decay_conversion (init);
+    init = decay_conversion (init, tf_warning_or_error);
 
   /* Convert INIT to the reference type TYPE.  This may involve the
      creation of a temporary, whose lifetime must be the same as that
@@ -6521,7 +6521,7 @@  get_atexit_node (void)
   atexit_fndecl = build_library_fn_ptr (name, fn_type);
   mark_used (atexit_fndecl);
   pop_lang_context ();
-  atexit_node = decay_conversion (atexit_fndecl);
+  atexit_node = decay_conversion (atexit_fndecl, tf_warning_or_error);
 
   return atexit_node;
 }
Index: cp/rtti.c
===================================================================
--- cp/rtti.c	(revision 184985)
+++ cp/rtti.c	(working copy)
@@ -1,6 +1,6 @@ 
 /* RunTime Type Identification
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008, 2009, 2010, 2011
+   2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
    Mostly written by Jason Merrill (jason@cygnus.com).
 
@@ -551,7 +551,7 @@  build_dynamic_cast_1 (tree type, tree expr, tsubst
 
   if (tc == POINTER_TYPE)
     {
-      expr = decay_conversion (expr);
+      expr = decay_conversion (expr, complain);
       exprtype = TREE_TYPE (expr);
 
       /* If T is a pointer type, v shall be an rvalue of a pointer to
@@ -931,7 +931,8 @@  tinfo_base_init (tinfo_s *ti, tree target)
 
   v = VEC_alloc (constructor_elt, gc, 2);
   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, vtable_ptr);
-  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, decay_conversion (name_decl));
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+			  decay_conversion (name_decl, tf_warning_or_error));
 
   init = build_constructor (init_list_type_node, v);
   TREE_CONSTANT (init) = 1;
Index: cp/except.c
===================================================================
--- cp/except.c	(revision 184985)
+++ cp/except.c	(working copy)
@@ -1,6 +1,6 @@ 
 /* Handle exceptional things in C++.
    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
+   2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2012
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann <tiemann@cygnus.com>
    Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
@@ -850,7 +850,7 @@  build_throw (tree exp)
 	}
       else
 	{
-	  tmp = decay_conversion (exp);
+	  tmp = decay_conversion (exp, tf_warning_or_error);
 	  if (tmp == error_mark_node)
 	    return error_mark_node;
 	  exp = build2 (INIT_EXPR, temp_type, object, tmp);
Index: cp/typeck2.c
===================================================================
--- cp/typeck2.c	(revision 184985)
+++ cp/typeck2.c	(working copy)
@@ -1,7 +1,8 @@ 
 /* Report error messages, build initializers, and perform
    some front-end optimizations for C++ compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+   1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
+   2012
    Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
@@ -1523,7 +1524,7 @@  build_x_arrow (tree expr, tsubst_flags_t complain)
 	last_rval = convert_from_reference (last_rval);
     }
   else
-    last_rval = decay_conversion (expr);
+    last_rval = decay_conversion (expr, complain);
 
   if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE)
     {
@@ -1552,7 +1553,7 @@  build_x_arrow (tree expr, tsubst_flags_t complain)
    already been checked out to be of aggregate type.  */
 
 tree
-build_m_component_ref (tree datum, tree component)
+build_m_component_ref (tree datum, tree component, tsubst_flags_t complain)
 {
   tree ptrmem_type;
   tree objtype;
@@ -1569,18 +1570,18 @@  tree
   ptrmem_type = TREE_TYPE (component);
   if (!TYPE_PTR_TO_MEMBER_P (ptrmem_type))
     {
-      error ("%qE cannot be used as a member pointer, since it is of "
-	     "type %qT",
-	     component, ptrmem_type);
+      if (complain & tf_error)
+	error ("%qE cannot be used as a member pointer, since it is of "
+	       "type %qT", component, ptrmem_type);
       return error_mark_node;
     }
 
   objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
   if (! MAYBE_CLASS_TYPE_P (objtype))
     {
-      error ("cannot apply member pointer %qE to %qE, which is of "
-	     "non-class type %qT",
-	     component, datum, objtype);
+      if (complain & tf_error)
+	error ("cannot apply member pointer %qE to %qE, which is of "
+	       "non-class type %qT", component, datum, objtype);
       return error_mark_node;
     }
 
@@ -1600,9 +1601,9 @@  tree
       if (!binfo)
 	{
 	mismatch:
-	  error ("pointer to member type %qT incompatible with object "
-		 "type %qT",
-		 type, objtype);
+	  if (complain & tf_error)
+	    error ("pointer to member type %qT incompatible with object "
+		   "type %qT", type, objtype);
 	  return error_mark_node;
 	}
       else if (binfo == error_mark_node)
@@ -1626,14 +1627,13 @@  tree
 
       /* Convert object to the correct base.  */
       if (binfo)
-	datum = build_base_path (PLUS_EXPR, datum, binfo, 1,
-				 tf_warning_or_error);
+	datum = build_base_path (PLUS_EXPR, datum, binfo, 1, complain);
 
       /* Build an expression for "object + offset" where offset is the
 	 value stored in the pointer-to-data-member.  */
       ptype = build_pointer_type (type);
       datum = fold_build_pointer_plus (fold_convert (ptype, datum), component);
-      datum = cp_build_indirect_ref (datum, RO_NULL, tf_warning_or_error);
+      datum = cp_build_indirect_ref (datum, RO_NULL, complain);
       /* If the object expression was an rvalue, return an rvalue.  */
       if (!is_lval)
 	datum = move (datum);
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 184985)
+++ cp/pt.c	(working copy)
@@ -5667,7 +5667,7 @@  convert_nontype_argument (tree type, tree expr, ts
      value_dependent_expression_p.  */
   if (TYPE_PTROBV_P (type)
       && TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE)
-    expr = decay_conversion (expr);
+    expr = decay_conversion (expr, complain);
 
   /* If we are in a template, EXPR may be non-dependent, but still
      have a syntactic, rather than semantic, form.  For example, EXPR
@@ -5875,7 +5875,7 @@  convert_nontype_argument (tree type, tree expr, ts
 	    }
 	}
 
-      expr = decay_conversion (expr);
+      expr = decay_conversion (expr, complain);
       if (expr == error_mark_node)
 	return error_mark_node;
 
@@ -5960,7 +5960,7 @@  convert_nontype_argument (tree type, tree expr, ts
 	 context information to decay the pointer.  */
       if (!type_unknown_p (expr_type))
 	{
-	  expr = decay_conversion (expr);
+	  expr = decay_conversion (expr, complain);
 	  if (expr == error_mark_node)
 	    return error_mark_node;
 	}
Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 184985)
+++ cp/semantics.c	(working copy)
@@ -1382,7 +1382,7 @@  finish_asm_stmt (int volatile_p, tree string, tree
       for (i = 0, t = input_operands; t; ++i, t = TREE_CHAIN (t))
 	{
 	  constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
-	  operand = decay_conversion (TREE_VALUE (t));
+	  operand = decay_conversion (TREE_VALUE (t), tf_warning_or_error);
 
 	  /* If the type of the operand hasn't been determined (e.g.,
 	     because it involves an overloaded function), then issue
@@ -9356,7 +9356,7 @@  maybe_add_lambda_conv_op (tree type)
   body = begin_function_body ();
   compound_stmt = begin_compound_stmt (0);
 
-  finish_return_stmt (decay_conversion (statfn));
+  finish_return_stmt (decay_conversion (statfn, tf_warning_or_error));
 
   finish_compound_stmt (compound_stmt);
   finish_function_body (body);
Index: cp/call.c
===================================================================
--- cp/call.c	(revision 184985)
+++ cp/call.c	(working copy)
@@ -263,7 +263,7 @@  check_dtor_name (tree basetype, tree name)
    pointer-to-member function.  */
 
 tree
-build_addr_func (tree function)
+build_addr_func (tree function, tsubst_flags_t complain)
 {
   tree type = TREE_TYPE (function);
 
@@ -280,7 +280,7 @@  tree
       function = build_address (function);
     }
   else
-    function = decay_conversion (function);
+    function = decay_conversion (function, complain);
 
   return function;
 }
@@ -341,7 +341,7 @@  build_call_a (tree function, int n, tree *argarray
   tree fntype;
   int i;
 
-  function = build_addr_func (function);
+  function = build_addr_func (function, tf_warning_or_error);
 
   gcc_assert (TYPE_PTR_P (TREE_TYPE (function)));
   fntype = TREE_TYPE (TREE_TYPE (function));
@@ -4346,9 +4346,19 @@  build_conditional_expr_1 (tree arg1, tree arg2, tr
 	 since it can't have any effect and since decay_conversion
 	 does not handle that case gracefully.  */
       if (!VOID_TYPE_P (arg2_type))
-	arg2 = decay_conversion (arg2);
+	{
+	  arg2 = decay_conversion (arg2, complain);
+	  if (arg2 == error_mark_node)
+	    return error_mark_node;
+	}
+
       if (!VOID_TYPE_P (arg3_type))
-	arg3 = decay_conversion (arg3);
+	{
+	  arg3 = decay_conversion (arg3, complain);
+	  if (arg3 == error_mark_node)
+	    return error_mark_node;
+	}
+
       arg2_type = TREE_TYPE (arg2);
       arg3_type = TREE_TYPE (arg3);
 
@@ -5236,7 +5246,7 @@  build_new_op_1 (enum tree_code code, int flags, tr
     case MEMBER_REF:
       return build_m_component_ref (cp_build_indirect_ref (arg1, RO_NULL, 
                                                            complain), 
-                                    arg2);
+                                    arg2, complain);
 
       /* The caller will deal with these.  */
     case ADDR_EXPR:
@@ -5780,7 +5790,7 @@  convert_like_real (conversion *convs, tree expr, t
 	/* Build up the initializer_list object.  */
 	totype = complete_type (totype);
 	field = next_initializable_field (TYPE_FIELDS (totype));
-	CONSTRUCTOR_APPEND_ELT (vec, field, decay_conversion (array));
+	CONSTRUCTOR_APPEND_ELT (vec, field, decay_conversion (array, complain));
 	field = next_initializable_field (DECL_CHAIN (field));
 	CONSTRUCTOR_APPEND_ELT (vec, field, size_int (len));
 	new_ctor = build_constructor (totype, vec);
@@ -5817,7 +5827,10 @@  convert_like_real (conversion *convs, tree expr, t
   switch (convs->kind)
     {
     case ck_rvalue:
-      expr = decay_conversion (expr);
+      expr = decay_conversion (expr, complain);
+      if (expr == error_mark_node)
+	return error_mark_node;
+
       if (! MAYBE_CLASS_TYPE_P (totype))
 	return expr;
       /* Else fall through.  */
@@ -5943,7 +5956,7 @@  convert_like_real (conversion *convs, tree expr, t
       }
 
     case ck_lvalue:
-      return decay_conversion (expr);
+      return decay_conversion (expr, complain);
 
     case ck_qual:
       /* Warn about deprecated conversion if appropriate.  */
@@ -5987,7 +6000,10 @@  convert_arg_to_ellipsis (tree arg)
 
      The lvalue-to-rvalue, array-to-pointer, and function-to-pointer
      standard conversions are performed.  */
-  arg = decay_conversion (arg);
+  arg = decay_conversion (arg, tf_warning_or_error);
+  if (arg == error_mark_node)
+    return error_mark_node;
+
   arg_type = TREE_TYPE (arg);
   /* [expr.call]
 
@@ -6336,9 +6352,9 @@  build_over_call (struct z_candidate *cand, int fla
 	    alcarray[ix + 1] = arg;
 	  argarray = alcarray;
 	}
-      expr = build_call_array_loc (input_location,
-				   return_type, build_addr_func (fn), nargs,
-				   argarray);
+      expr = build_call_array_loc (input_location, return_type,
+				   build_addr_func (fn, complain),
+				   nargs, argarray);
       if (TREE_THIS_VOLATILE (fn) && cfun)
 	current_function_returns_abnormally = 1;
       return convert_from_reference (expr);
@@ -6755,7 +6771,7 @@  build_over_call (struct z_candidate *cand, int fla
       TREE_TYPE (fn) = t;
     }
   else
-    fn = build_addr_func (fn);
+    fn = build_addr_func (fn, complain);
 
   return build_cxx_call (fn, nargs, argarray);
 }
@@ -6976,7 +6992,9 @@  build_special_member_call (tree instance, tree nam
 	 or destructor, then we fetch the VTT directly.
 	 Otherwise, we look it up using the VTT we were given.  */
       vtt = DECL_CHAIN (CLASSTYPE_VTABLES (current_class_type));
-      vtt = decay_conversion (vtt);
+      vtt = decay_conversion (vtt, complain);
+      if (vtt == error_mark_node)
+	return error_mark_node;
       vtt = build3 (COND_EXPR, TREE_TYPE (vtt),
 		    build2 (EQ_EXPR, boolean_type_node,
 			    current_in_charge_parm, integer_zero_node),
Index: cp/cvt.c
===================================================================
--- cp/cvt.c	(revision 184985)
+++ cp/cvt.c	(working copy)
@@ -1,7 +1,7 @@ 
 /* Language-level data type conversion for GNU C++.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
    1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-   2011 Free Software Foundation, Inc.
+   2011, 2012 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -550,7 +550,7 @@  force_rvalue (tree expr, tsubst_flags_t complain)
       expr = build_cplus_new (type, expr, complain);
     }
   else
-    expr = decay_conversion (expr);
+    expr = decay_conversion (expr, complain);
 
   return expr;
 }
@@ -1495,7 +1495,8 @@  build_expr_type_conversion (int desires, tree expr
 
       case FUNCTION_TYPE:
       case ARRAY_TYPE:
-	return (desires & WANT_POINTER) ? decay_conversion (expr)
+	return (desires & WANT_POINTER) ? decay_conversion (expr,
+							    tf_warning_or_error)
 					: NULL_TREE;
 
       case COMPLEX_TYPE:
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 184985)
+++ cp/cp-tree.h	(working copy)
@@ -4845,7 +4845,7 @@  extern bool check_dtor_name			(tree, tree);
 
 extern tree build_conditional_expr		(tree, tree, tree, 
                                                  tsubst_flags_t);
-extern tree build_addr_func			(tree);
+extern tree build_addr_func			(tree, tsubst_flags_t);
 extern void set_flags_from_callee		(tree);
 extern tree build_call_a			(tree, int, tree*);
 extern tree build_call_n			(tree, int, ...);
@@ -5769,7 +5769,7 @@  extern tree cxx_sizeof_or_alignof_type		(tree, enu
 extern tree cxx_sizeof_nowarn                   (tree);
 extern tree is_bitfield_expr_with_lowered_type  (const_tree);
 extern tree unlowered_expr_type                 (const_tree);
-extern tree decay_conversion			(tree);
+extern tree decay_conversion			(tree, tsubst_flags_t);
 extern tree build_class_member_access_expr      (tree, tree, tree, bool,
 						 tsubst_flags_t);
 extern tree finish_class_member_access_expr     (tree, tree, bool, 
@@ -5881,7 +5881,7 @@  extern tree digest_init				(tree, tree, tsubst_fla
 extern tree digest_init_flags			(tree, tree, int);
 extern tree build_scoped_ref			(tree, tree, tree *);
 extern tree build_x_arrow			(tree, tsubst_flags_t);
-extern tree build_m_component_ref		(tree, tree);
+extern tree build_m_component_ref		(tree, tree, tsubst_flags_t);
 extern tree build_functional_cast		(tree, tree, tsubst_flags_t);
 extern tree add_exception_specifier		(tree, tree, int);
 extern tree merge_exception_specifiers		(tree, tree, tree);