re PR c++/52422 ([C++11][SFINAE] Hard errors with void or arithmetic expressions)

/cp
2012-04-18  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/52422
	* cp-tree.h (build_addr_func, decay_conversion,
	get_member_function_from_ptrfunc,
	build_m_component_ref, convert_member_func_to_ptr):
	Add tsubst_flags_t parameter.
	* typeck.c (cp_default_conversion): Add.
	(decay_conversion, default_conversion,
	get_member_function_from_ptrfunc, convert_member_func_to_ptr):
	Add tsubst_flags_t parameter and use it throughout.
	(cp_build_indirect_ref, cp_build_array_ref,
	cp_build_function_call_vec, convert_arguments, build_x_binary_op,
	cp_build_binary_op, cp_build_unary_op, build_reinterpret_cast_1,
	build_const_cast_1, expand_ptrmemfunc_cst,
	convert_for_initialization): Adjust.
	* init.c (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.
	* decl2.c (build_offset_ref_call_from_tree): 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 (cp_convert_to_pointer, force_rvalue,
	build_expr_type_conversion): Likewise.

/testsuite
2012-04-18  Paolo Carlini  <paolo.carlini@oracle.com>

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

From-SVN: r186565
This commit is contained in:
Paolo Carlini 2012-04-18 10:21:43 +00:00 committed by Paolo Carlini
parent 5932a4d411
commit 89fcabafa1
16 changed files with 288 additions and 108 deletions

View File

@ -1,3 +1,37 @@
2012-04-18 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/52422
* cp-tree.h (build_addr_func, decay_conversion,
get_member_function_from_ptrfunc,
build_m_component_ref, convert_member_func_to_ptr):
Add tsubst_flags_t parameter.
* typeck.c (cp_default_conversion): Add.
(decay_conversion, default_conversion,
get_member_function_from_ptrfunc, convert_member_func_to_ptr):
Add tsubst_flags_t parameter and use it throughout.
(cp_build_indirect_ref, cp_build_array_ref,
cp_build_function_call_vec, convert_arguments, build_x_binary_op,
cp_build_binary_op, cp_build_unary_op, build_reinterpret_cast_1,
build_const_cast_1, expand_ptrmemfunc_cst,
convert_for_initialization): Adjust.
* init.c (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.
* decl2.c (build_offset_ref_call_from_tree): 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 (cp_convert_to_pointer, force_rvalue,
build_expr_type_conversion): Likewise.
2012-04-17 Tom de Vries <tom@codesourcery.com>
* cp-gimplify.c (begin_bc_block): Add location parameter and use as

View File

@ -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);
@ -275,12 +275,13 @@ build_addr_func (tree function)
{
tree object = build_address (TREE_OPERAND (function, 0));
return get_member_function_from_ptrfunc (&object,
TREE_OPERAND (function, 1));
TREE_OPERAND (function, 1),
complain);
}
function = build_address (function);
}
else
function = decay_conversion (function);
function = decay_conversion (function, complain);
return function;
}
@ -341,7 +342,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));
@ -4373,9 +4374,9 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3,
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 (!VOID_TYPE_P (arg3_type))
arg3 = decay_conversion (arg3);
arg3 = decay_conversion (arg3, complain);
arg2_type = TREE_TYPE (arg2);
arg3_type = TREE_TYPE (arg3);
@ -5263,7 +5264,7 @@ build_new_op_1 (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
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:
@ -5807,7 +5808,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
/* 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);
@ -5844,7 +5845,10 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
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. */
@ -5970,7 +5974,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
}
case ck_lvalue:
return decay_conversion (expr);
return decay_conversion (expr, complain);
case ck_qual:
/* Warn about deprecated conversion if appropriate. */
@ -6014,7 +6018,7 @@ 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);
arg_type = TREE_TYPE (arg);
/* [expr.call]
@ -6341,7 +6345,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
errors will be deferred until the template is instantiated. */
if (processing_template_decl)
{
tree expr;
tree expr, addr;
tree return_type;
const tree *argarray;
unsigned int nargs;
@ -6363,9 +6367,12 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
alcarray[ix + 1] = arg;
argarray = alcarray;
}
expr = build_call_array_loc (input_location,
return_type, build_addr_func (fn), nargs,
argarray);
addr = build_addr_func (fn, complain);
if (addr == error_mark_node)
return error_mark_node;
expr = build_call_array_loc (input_location, return_type,
addr, nargs, argarray);
if (TREE_THIS_VOLATILE (fn) && cfun)
current_function_returns_abnormally = 1;
return convert_from_reference (expr);
@ -6782,7 +6789,11 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
TREE_TYPE (fn) = t;
}
else
fn = build_addr_func (fn);
{
fn = build_addr_func (fn, complain);
if (fn == error_mark_node)
return error_mark_node;
}
return build_cxx_call (fn, nargs, argarray);
}
@ -7003,7 +7014,9 @@ build_special_member_call (tree instance, tree name, VEC(tree,gc) **args,
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),

View File

@ -4854,7 +4854,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, ...);
@ -5782,7 +5782,7 @@ extern tree cxx_sizeof_or_alignof_type (tree, enum tree_code, bool);
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,
@ -5794,7 +5794,7 @@ extern tree cp_build_indirect_ref (tree, ref_operator,
extern tree build_array_ref (location_t, tree, tree);
extern tree cp_build_array_ref (location_t, tree, tree,
tsubst_flags_t);
extern tree get_member_function_from_ptrfunc (tree *, tree);
extern tree get_member_function_from_ptrfunc (tree *, tree, tsubst_flags_t);
extern tree cp_build_function_call (tree, tree, tsubst_flags_t);
extern tree cp_build_function_call_nary (tree, tsubst_flags_t, ...)
ATTRIBUTE_SENTINEL;
@ -5865,7 +5865,7 @@ extern tree build_nop (tree, tree);
extern tree non_reference (tree);
extern tree lookup_anon_field (tree, tree);
extern bool invalid_nonstatic_memfn_p (const_tree, tsubst_flags_t);
extern tree convert_member_func_to_ptr (tree, tree);
extern tree convert_member_func_to_ptr (tree, tree, tsubst_flags_t);
extern tree convert_ptrmem (tree, tree, bool, bool,
tsubst_flags_t);
extern int lvalue_or_else (tree, enum lvalue_use,
@ -5895,7 +5895,7 @@ 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, 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);

View File

@ -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.
@ -109,7 +109,7 @@ cp_convert_to_pointer (tree type, tree expr)
{
if (TYPE_PTRMEMFUNC_P (intype)
|| TREE_CODE (intype) == METHOD_TYPE)
return convert_member_func_to_ptr (type, expr);
return convert_member_func_to_ptr (type, expr, tf_warning_or_error);
if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
return build_nop (type, expr);
intype = TREE_TYPE (expr);
@ -188,7 +188,8 @@ cp_convert_to_pointer (tree type, tree expr)
{
tree object = TREE_OPERAND (expr, 0);
return get_member_function_from_ptrfunc (&object,
TREE_OPERAND (expr, 1));
TREE_OPERAND (expr, 1),
tf_warning_or_error);
}
}
error ("cannot convert %qE from type %qT to type %qT",
@ -550,7 +551,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 +1496,8 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
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:

View File

@ -4668,7 +4668,7 @@ grok_reference_init (tree decl, tree type, tree init, int flags)
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
@ -6535,7 +6535,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;
}

View File

@ -1,7 +1,7 @@
/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 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.
@ -4175,7 +4175,8 @@ build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args)
{
tree object_addr = cp_build_addr_expr (object, tf_warning_or_error);
fn = TREE_OPERAND (fn, 1);
fn = get_member_function_from_ptrfunc (&object_addr, fn);
fn = get_member_function_from_ptrfunc (&object_addr, fn,
tf_warning_or_error);
VEC_safe_insert (tree, gc, *args, 0, object_addr);
}

View File

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

View File

@ -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.
@ -3194,7 +3194,10 @@ build_vec_init (tree base, tree maxindex, tree init,
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;
@ -3243,7 +3246,9 @@ build_vec_init (tree base, tree maxindex, tree init,
{
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);

View File

@ -5692,7 +5692,11 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
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 (expr == error_mark_node)
return error_mark_node;
}
/* If we are in a template, EXPR may be non-dependent, but still
have a syntactic, rather than semantic, form. For example, EXPR
@ -5900,7 +5904,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
}
}
expr = decay_conversion (expr);
expr = decay_conversion (expr, complain);
if (expr == error_mark_node)
return error_mark_node;
@ -5985,7 +5989,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
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;
}

View File

@ -551,7 +551,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
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
@ -936,7 +936,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;

View File

@ -1382,7 +1382,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
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
@ -9365,7 +9365,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);

View File

@ -1818,7 +1818,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;
@ -1832,7 +1832,8 @@ decay_conversion (tree exp)
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;
}
@ -1851,13 +1852,14 @@ decay_conversion (tree exp)
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;
@ -1869,7 +1871,9 @@ decay_conversion (tree exp)
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);
}
@ -1877,7 +1881,8 @@ decay_conversion (tree exp)
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;
}
@ -1892,7 +1897,7 @@ decay_conversion (tree exp)
}
/* 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);
}
@ -1931,8 +1936,8 @@ decay_conversion (tree exp)
applied to both operands to a binary operator before determining
what additional conversions should apply. */
tree
default_conversion (tree exp)
static tree
cp_default_conversion (tree exp, tsubst_flags_t complain)
{
/* Check for target-specific promotions. */
tree promoted_type = targetm.promoted_type (TREE_TYPE (exp));
@ -1944,11 +1949,19 @@ 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, complain);
return exp;
}
/* C version. */
tree
default_conversion (tree exp)
{
return cp_default_conversion (exp, tf_warning_or_error);
}
/* EXPR is an expression with an integral or enumeration type.
Perform the integral promotions in [conv.prom], and return the
converted value. */
@ -2758,14 +2771,14 @@ cp_build_indirect_ref (tree ptr, ref_operator errorstring,
{
tree pointer, type;
if (ptr == error_mark_node)
return error_mark_node;
if (ptr == current_class_ptr)
return current_class_ref;
pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE
? ptr : decay_conversion (ptr));
? ptr : decay_conversion (ptr, complain));
if (pointer == error_mark_node)
return error_mark_node;
type = TREE_TYPE (pointer);
if (POINTER_TYPE_P (type))
@ -2982,8 +2995,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
}
{
tree ar = default_conversion (array);
tree ind = default_conversion (idx);
tree ar = cp_default_conversion (array, complain);
tree ind = cp_default_conversion (idx, complain);
/* Put the integer in IND to simplify error checking. */
if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE)
@ -2993,8 +3006,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
ind = temp;
}
if (ar == error_mark_node)
return ar;
if (ar == error_mark_node || ind == error_mark_node)
return error_mark_node;
if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE)
{
@ -3040,7 +3053,8 @@ build_array_ref (location_t loc, tree array, tree idx)
later has the right member. */
tree
get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
tsubst_flags_t complain)
{
if (TREE_CODE (function) == OFFSET_REF)
function = TREE_OPERAND (function, 1);
@ -3059,13 +3073,14 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
/* 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), complain);
e1 = convert (fntype, e1);
return e1;
}
else
{
error ("object missing in use of %qE", function);
if (complain & tf_error)
error ("object missing in use of %qE", function);
return error_mark_node;
}
}
@ -3085,25 +3100,32 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
case ptrmemfunc_vbit_in_pfn:
e1 = cp_build_binary_op (input_location,
BIT_AND_EXPR, idx, integer_one_node,
tf_warning_or_error);
complain);
idx = cp_build_binary_op (input_location,
MINUS_EXPR, idx, integer_one_node,
tf_warning_or_error);
complain);
if (idx == error_mark_node)
return error_mark_node;
break;
case ptrmemfunc_vbit_in_delta:
e1 = cp_build_binary_op (input_location,
BIT_AND_EXPR, delta, integer_one_node,
tf_warning_or_error);
complain);
delta = cp_build_binary_op (input_location,
RSHIFT_EXPR, delta, integer_one_node,
tf_warning_or_error);
complain);
if (delta == error_mark_node)
return error_mark_node;
break;
default:
gcc_unreachable ();
}
if (e1 == error_mark_node)
return error_mark_node;
/* Convert down to the right base before using the instance. A
special case is that in a pointer to member of class C, C may
be incomplete. In that case, the function will of course be
@ -3117,7 +3139,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
basetype, ba_check, NULL);
instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype,
1, tf_warning_or_error);
1, complain);
if (instance_ptr == error_mark_node)
return error_mark_node;
}
@ -3130,7 +3152,10 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
/* Next extract the vtable pointer from the object. */
vtbl = build1 (NOP_EXPR, build_pointer_type (vtbl_ptr_type_node),
instance_ptr);
vtbl = cp_build_indirect_ref (vtbl, RO_NULL, tf_warning_or_error);
vtbl = cp_build_indirect_ref (vtbl, RO_NULL, complain);
if (vtbl == error_mark_node)
return error_mark_node;
/* If the object is not dynamic the access invokes undefined
behavior. As it is not executed in this case silence the
spurious warnings it may provoke. */
@ -3138,17 +3163,21 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
/* Finally, extract the function pointer from the vtable. */
e2 = fold_build_pointer_plus_loc (input_location, vtbl, idx);
e2 = cp_build_indirect_ref (e2, RO_NULL, tf_warning_or_error);
e2 = cp_build_indirect_ref (e2, RO_NULL, complain);
if (e2 == error_mark_node)
return error_mark_node;
TREE_CONSTANT (e2) = 1;
/* When using function descriptors, the address of the
vtable entry is treated as a function pointer. */
if (TARGET_VTABLE_USES_DESCRIPTORS)
e2 = build1 (NOP_EXPR, TREE_TYPE (e2),
cp_build_addr_expr (e2, tf_warning_or_error));
cp_build_addr_expr (e2, complain));
e2 = fold_convert (TREE_TYPE (e3), e2);
e1 = build_conditional_expr (e1, e2, e3, tf_warning_or_error);
e1 = build_conditional_expr (e1, e2, e3, complain);
if (e1 == error_mark_node)
return error_mark_node;
/* Make sure this doesn't get evaluated first inside one of the
branches of the COND_EXPR. */
@ -3261,13 +3290,13 @@ cp_build_function_call_vec (tree function, VEC(tree,gc) **params,
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)
@ -3432,7 +3461,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl,
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)
@ -3559,7 +3588,7 @@ build_x_binary_op (enum tree_code code, tree arg1, enum tree_code arg1_code,
}
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);
@ -3723,16 +3752,16 @@ 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
{
if (!really_overloaded_fn (op0) && !VOID_TYPE_P (TREE_TYPE (op0)))
op0 = default_conversion (op0);
op0 = cp_default_conversion (op0, complain);
if (!really_overloaded_fn (op1) && !VOID_TYPE_P (TREE_TYPE (op1)))
op1 = default_conversion (op1);
op1 = cp_default_conversion (op1, complain);
}
/* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
@ -5129,7 +5158,11 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
{
code = CONJ_EXPR;
if (!noconvert)
arg = default_conversion (arg);
{
arg = cp_default_conversion (arg, complain);
if (arg == error_mark_node)
return error_mark_node;
}
}
else if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM
| WANT_VECTOR_OR_COMPLEX,
@ -5143,7 +5176,11 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, true)))
errstring = _("wrong type argument to abs");
else if (!noconvert)
arg = default_conversion (arg);
{
arg = cp_default_conversion (arg, complain);
if (arg == error_mark_node)
return error_mark_node;
}
break;
case CONJ_EXPR:
@ -5151,7 +5188,11 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, true)))
errstring = _("wrong type argument to conjugation");
else if (!noconvert)
arg = default_conversion (arg);
{
arg = cp_default_conversion (arg, complain);
if (arg == error_mark_node)
return error_mark_node;
}
break;
case TRUTH_NOT_EXPR:
@ -6129,7 +6170,7 @@ build_static_cast (tree type, tree expr, tsubst_flags_t complain)
converted expression. */
tree
convert_member_func_to_ptr (tree type, tree expr)
convert_member_func_to_ptr (tree type, tree expr, tsubst_flags_t complain)
{
tree intype;
tree decl;
@ -6138,21 +6179,27 @@ convert_member_func_to_ptr (tree type, tree expr)
gcc_assert (TYPE_PTRMEMFUNC_P (intype)
|| TREE_CODE (intype) == METHOD_TYPE);
if (!(complain & tf_warning_or_error))
return error_mark_node;
if (pedantic || warn_pmf2ptr)
pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpmf_conversions,
"converting from %qT to %qT", intype, type);
if (TREE_CODE (intype) == METHOD_TYPE)
expr = build_addr_func (expr);
expr = build_addr_func (expr, complain);
else if (TREE_CODE (expr) == PTRMEM_CST)
expr = build_address (PTRMEM_CST_MEMBER (expr));
else
{
decl = maybe_dummy_object (TYPE_PTRMEM_CLASS_TYPE (intype), 0);
decl = build_address (decl);
expr = get_member_function_from_ptrfunc (&decl, expr);
expr = get_member_function_from_ptrfunc (&decl, expr, complain);
}
if (expr == error_mark_node)
return error_mark_node;
return build_nop (type, expr);
}
@ -6230,12 +6277,12 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
&& TYPE_PTR_P (type)
&& (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
|| VOID_TYPE_P (TREE_TYPE (type))))
return convert_member_func_to_ptr (type, expr);
return convert_member_func_to_ptr (type, expr, complain);
/* 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. */
@ -6474,12 +6521,17 @@ build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain,
if (reference_type)
{
expr = cp_build_addr_expr (expr, complain);
if (expr == error_mark_node)
return error_mark_node;
expr = build_nop (reference_type, expr);
return convert_from_reference (expr);
}
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. */
@ -7333,7 +7385,8 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn)
/*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'
@ -7667,7 +7720,7 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
&& (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);

View File

@ -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)
@ -1528,7 +1529,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)
{
@ -1557,7 +1558,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;
@ -1574,18 +1575,18 @@ build_m_component_ref (tree datum, tree component)
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;
}
@ -1605,9 +1606,9 @@ build_m_component_ref (tree datum, tree component)
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)
@ -1631,14 +1632,20 @@ build_m_component_ref (tree datum, tree component)
/* 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);
if (datum == error_mark_node)
return error_mark_node;
}
/* 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 (datum == error_mark_node)
return error_mark_node;
/* If the object expression was an rvalue, return an rvalue. */
if (!is_lval)
datum = move (datum);

View File

@ -1,3 +1,9 @@
2012-04-18 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/52422
* g++.dg/cpp0x/sfinae33.C: New.
* g++.dg/cpp0x/sfinae34.C: Likewise.
2012-04-18 Joey Ye <joey.ye@arm.com>
* gcc.target/arm/thumb1-imm.c: Skip it in non-thumb1 target.

View File

@ -0,0 +1,27 @@
// PR c++/52422
// { dg-options -std=c++11 }
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, "");

View File

@ -0,0 +1,27 @@
// PR c++/52422
// { dg-options -std=c++11 }
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, "");