Hi,
On 02/29/2012 06:53 AM, Paolo Carlini wrote:
Daniel noticed a couple other SFINAE issues, which I'm fixing in the
usual straightforward way. Tested x86_64-linux.
When fixing these things, please add checking for error_mark_node
return as well. For instance, in this patch the calls to
decay_conversion from build_conditional_expr_1 could return
error_mark_node, in which case we want to return out of
build_conditional_expr_1 as well. Similarly with the call in
convert_like_real, and so on.
I see. Thus I added many of those checks, essentially all I could see
besides some special cases like we call decay_conversion with an
explicit tf_warning_or_error (thus we have the status quo behavior
anyway) or when there are already checks, just a few lines below. In the
feature I'll keep an eye to that.
Does the below look better? (booted and tested x86_64-linux)
PS: while working on the patch, I noticed that a few functions, which in
the meanwhile acquired a tsubst_flags_t parameter, aren't fully
propagating it, are still passing tf_warning_or_error. Apparently a
clean-up is in order.
Please. :)
Ok, will do (and in case more error_mark_node checks too, of course)
Thanks,
Paolo.
//////////////////////
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 184739)
+++ 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 184739)
+++ 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 (tiem...@cygnus.com)
This file is part of GCC.
@@ -3186,7 +3186,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;
@@ -3235,7 +3238,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 184739)
+++ cp/decl.c (working copy)
@@ -4650,7 +4650,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
@@ -6513,7 +6513,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 184739)
+++ 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 (ja...@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 184739)
+++ 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 <tiem...@cygnus.com>
Rewritten by Mike Stump <m...@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 184739)
+++ 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 (tiem...@cygnus.com)
@@ -1518,7 +1519,7 @@ build_x_arrow (tree expr)
last_rval = convert_from_reference (last_rval);
}
else
- last_rval = decay_conversion (expr);
+ last_rval = decay_conversion (expr, tf_warning_or_error);
if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE)
{
@@ -1544,7 +1545,7 @@ build_x_arrow (tree expr)
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;
@@ -1561,18 +1562,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;
}
@@ -1592,9 +1593,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)
@@ -1618,14 +1619,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 184739)
+++ cp/pt.c (working copy)
@@ -5688,7 +5688,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
@@ -5896,7 +5896,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;
@@ -5981,7 +5981,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 184739)
+++ 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 184739)
+++ 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));
@@ -4342,9 +4342,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);
@@ -5232,7 +5242,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:
@@ -5776,7 +5786,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);
@@ -5812,7 +5822,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. */
@@ -5938,7 +5951,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. */
@@ -5982,7 +5995,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]
@@ -6331,9 +6347,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);
@@ -6750,7 +6766,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);
}
@@ -6971,7 +6987,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 184739)
+++ 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 (tiem...@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 184739)
+++ 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);
-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);