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:
parent
5932a4d411
commit
89fcabafa1
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
12
gcc/cp/cvt.c
12
gcc/cp/cvt.c
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
10
gcc/cp/pt.c
10
gcc/cp/pt.c
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
153
gcc/cp/typeck.c
153
gcc/cp/typeck.c
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
27
gcc/testsuite/g++.dg/cpp0x/sfinae33.C
Normal file
27
gcc/testsuite/g++.dg/cpp0x/sfinae33.C
Normal 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, "");
|
27
gcc/testsuite/g++.dg/cpp0x/sfinae34.C
Normal file
27
gcc/testsuite/g++.dg/cpp0x/sfinae34.C
Normal 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, "");
|
Loading…
Reference in New Issue
Block a user