re PR c++/9878 (error: non-lvalue in unary `&' wrongly issued)

PR c++/9878
	* call.c (convert_class_to_reference): Correct conversion
	sequences.
	(reference_binding): Add ref_bound_directly_to_rvalue_p parameter.
	(implicit_conversion): Adjust call to reference_binding.
	(add_candidate): Change type of candidates parameter.
	(add_function_candidate): Likewise.
	(add_conv_candidate): Likewise.
	(build_builtin_candidate): Likewise.
	(add_builtin_candidate): Likewise.
	(add_builtin_candidates): Likewise.
	(add_template_candidate_real): Likewise.
	(add_template_candidate): Likewise.
	(add_template_conv_candidate): Likewise.
	(build_user_type_conversion_1): Adjust accordingly.
	(build_object_call): Likewise.
	(build_conditional_expr): Likewise.
	(add_candidates): Likewise.
	(build_new_op): Likewise.
	(convert_like_real): Use USER_CONV_CAND.  Use build_nop.
	(build_new_method_call): Adjust calls to add_function_candidate.
	(make_temporary_var_for_ref_to_temp): New function.
	(initialize_reference): Add decl parameter.
	* class.c (build_rtti_vtbl_entries): Use build_address and
	build_nop.
	* cp-tree.h (initialize_reference): Change prototype.
	(make_temporary_var_for_ref_to_temp): New function.
	(build_type_conversion): Change prototype.
	(build_address): New function.
	(build_nop): Likewise.
	* cvt.c (cp_convert_to_pointer): Adjust call to
	build_type_conversion.  Avoid indicating redundant NOP_EXPRs.
	Use build_nop.
	(convert_to_pointer_force): Use build_nop.
	(build_up_reference): Use make_temporary_var_for_ref_to_temp.
	(convert_to_reference): Adjust call to build_type_conversion.
	(ocp_convert): Likewise.
	(build_type_conversion): Remove for_sure parameter.
	* decl.c (grok_reference_init): Use initialize_reference.
	* typeck.c (build_address): New function.
	(build_nop): Likewise.
	(build_unary_op): Use them.
	(build_ptrmemfunc): Tidy slightly.
	(convert_for_initialization): Adjust call to
	initialize_reference.
	* typeck2.c (store_init_value): Remove #if 0'd code.

	PR c++/9878
	* g++.dg/init/ref1.C: New test.

From-SVN: r63735
This commit is contained in:
Mark Mitchell 2003-03-03 21:55:25 +00:00 committed by Mark Mitchell
parent 03275f8132
commit 7993382ed0
10 changed files with 462 additions and 336 deletions

View File

@ -1,3 +1,52 @@
2003-03-03 Mark Mitchell <mark@codesourcery.com>
PR c++/9878
* call.c (convert_class_to_reference): Correct conversion
sequences.
(reference_binding): Add ref_bound_directly_to_rvalue_p parameter.
(implicit_conversion): Adjust call to reference_binding.
(add_candidate): Change type of candidates parameter.
(add_function_candidate): Likewise.
(add_conv_candidate): Likewise.
(build_builtin_candidate): Likewise.
(add_builtin_candidate): Likewise.
(add_builtin_candidates): Likewise.
(add_template_candidate_real): Likewise.
(add_template_candidate): Likewise.
(add_template_conv_candidate): Likewise.
(build_user_type_conversion_1): Adjust accordingly.
(build_object_call): Likewise.
(build_conditional_expr): Likewise.
(add_candidates): Likewise.
(build_new_op): Likewise.
(convert_like_real): Use USER_CONV_CAND. Use build_nop.
(build_new_method_call): Adjust calls to add_function_candidate.
(make_temporary_var_for_ref_to_temp): New function.
(initialize_reference): Add decl parameter.
* class.c (build_rtti_vtbl_entries): Use build_address and
build_nop.
* cp-tree.h (initialize_reference): Change prototype.
(make_temporary_var_for_ref_to_temp): New function.
(build_type_conversion): Change prototype.
(build_address): New function.
(build_nop): Likewise.
* cvt.c (cp_convert_to_pointer): Adjust call to
build_type_conversion. Avoid indicating redundant NOP_EXPRs.
Use build_nop.
(convert_to_pointer_force): Use build_nop.
(build_up_reference): Use make_temporary_var_for_ref_to_temp.
(convert_to_reference): Adjust call to build_type_conversion.
(ocp_convert): Likewise.
(build_type_conversion): Remove for_sure parameter.
* decl.c (grok_reference_init): Use initialize_reference.
* typeck.c (build_address): New function.
(build_nop): Likewise.
(build_unary_op): Use them.
(build_ptrmemfunc): Tidy slightly.
(convert_for_initialization): Adjust call to
initialize_reference.
* typeck2.c (store_init_value): Remove #if 0'd code.
2003-03-03 Jason Merrill <jason@redhat.com>
* decl.c (start_function): Clear DECL_NUM_STMTS.

File diff suppressed because it is too large Load Diff

View File

@ -7922,22 +7922,20 @@ build_rtti_vtbl_entries (tree binfo, vtbl_init_data* vid)
/* The second entry is the address of the typeinfo object. */
if (flag_rtti)
decl = build_unary_op (ADDR_EXPR, get_tinfo_decl (t), 0);
decl = build_address (get_tinfo_decl (t));
else
decl = integer_zero_node;
/* Convert the declaration to a type that can be stored in the
vtable. */
init = build1 (NOP_EXPR, vfunc_ptr_type_node, decl);
TREE_CONSTANT (init) = 1;
init = build_nop (vfunc_ptr_type_node, decl);
*vid->last_init = build_tree_list (NULL_TREE, init);
vid->last_init = &TREE_CHAIN (*vid->last_init);
/* Add the offset-to-top entry. It comes earlier in the vtable that
the the typeinfo entry. Convert the offset to look like a
function pointer, so that we can put it in the vtable. */
init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
TREE_CONSTANT (init) = 1;
init = build_nop (vfunc_ptr_type_node, offset);
*vid->last_init = build_tree_list (NULL_TREE, init);
vid->last_init = &TREE_CHAIN (*vid->last_init);
}

View File

@ -3576,7 +3576,8 @@ extern tree type_passed_as (tree);
extern tree convert_for_arg_passing (tree, tree);
extern tree cp_convert_parm_for_inlining (tree, tree, tree);
extern bool is_properly_derived_from (tree, tree);
extern tree initialize_reference (tree, tree);
extern tree initialize_reference (tree, tree, tree);
extern tree make_temporary_var_for_ref_to_temp (tree);
extern tree strip_top_quals (tree);
extern tree perform_implicit_conversion (tree, tree);
extern tree in_charge_arg_for_name (tree);
@ -3638,7 +3639,7 @@ extern tree ocp_convert (tree, tree, int, int);
extern tree cp_convert (tree, tree);
extern tree convert_to_void (tree, const char */*implicit context*/);
extern tree convert_force (tree, tree, int);
extern tree build_type_conversion (tree, tree, int);
extern tree build_type_conversion (tree, tree);
extern tree build_expr_type_conversion (int, tree, bool);
extern tree type_promotes_to (tree);
extern tree perform_qualification_conversions (tree, tree);
@ -4355,6 +4356,8 @@ extern tree check_return_expr (tree);
#define cxx_sizeof(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, true)
#define cxx_alignof(T) cxx_sizeof_or_alignof_type (T, ALIGNOF_EXPR, true)
extern tree build_ptrmemfunc_access_expr (tree, tree);
extern tree build_address (tree);
extern tree build_nop (tree, tree);
/* in typeck2.c */
extern void require_complete_eh_spec_types (tree, tree);

View File

@ -90,7 +90,7 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
return error_mark_node;
}
rval = build_type_conversion (type, expr, true);
rval = build_type_conversion (type, expr);
if (rval)
{
if (rval == error_mark_node)
@ -148,31 +148,33 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
{
enum tree_code code = PLUS_EXPR;
tree binfo;
tree intype_class;
tree type_class;
bool same_p;
intype_class = TREE_TYPE (intype);
type_class = TREE_TYPE (type);
same_p = same_type_p (TYPE_MAIN_VARIANT (intype_class),
TYPE_MAIN_VARIANT (type_class));
binfo = NULL_TREE;
/* Try derived to base conversion. */
binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type),
ba_check, NULL);
if (!binfo)
if (!same_p)
binfo = lookup_base (intype_class, type_class, ba_check, NULL);
if (!same_p && !binfo)
{
/* Try base to derived conversion. */
binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
ba_check, NULL);
binfo = lookup_base (type_class, intype_class, ba_check, NULL);
code = MINUS_EXPR;
}
if (binfo == error_mark_node)
return error_mark_node;
if (binfo)
if (binfo || same_p)
{
expr = build_base_path (code, expr, binfo, 0);
if (binfo)
expr = build_base_path (code, expr, binfo, 0);
/* Add any qualifier conversions. */
if (!same_type_p (TREE_TYPE (TREE_TYPE (expr)),
TREE_TYPE (type)))
{
expr = build1 (NOP_EXPR, type, expr);
TREE_CONSTANT (expr) =
TREE_CONSTANT (TREE_OPERAND (expr, 0));
}
return expr;
return build_nop (type, expr);
}
}
@ -225,9 +227,7 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
return error_mark_node;
}
rval = build1 (NOP_EXPR, type, expr);
TREE_CONSTANT (rval) = TREE_CONSTANT (expr);
return rval;
return build_nop (type, expr);
}
else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
@ -326,14 +326,9 @@ convert_to_pointer_force (tree type, tree expr)
/* Add any qualifier conversions. */
if (!same_type_p (TREE_TYPE (TREE_TYPE (expr)),
TREE_TYPE (type)))
{
expr = build1 (NOP_EXPR, type, expr);
TREE_CONSTANT (expr) =
TREE_CONSTANT (TREE_OPERAND (expr, 0));
}
expr = build_nop (type, expr);
return expr;
}
}
}
@ -354,7 +349,6 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
tree rval;
tree argtype = TREE_TYPE (arg);
tree target_type = TREE_TYPE (type);
tree stmt_expr = NULL_TREE;
my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187);
@ -364,26 +358,7 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
here because it needs to live as long as DECL. */
tree targ = arg;
arg = build_decl (VAR_DECL, NULL_TREE, argtype);
DECL_ARTIFICIAL (arg) = 1;
TREE_USED (arg) = 1;
TREE_STATIC (arg) = TREE_STATIC (decl);
if (TREE_STATIC (decl))
{
/* Namespace-scope or local static; give it a mangled name. */
tree name = mangle_ref_init_variable (decl);
DECL_NAME (arg) = name;
SET_DECL_ASSEMBLER_NAME (arg, name);
arg = pushdecl_top_level (arg);
}
else
{
/* Automatic; make sure we handle the cleanup properly. */
maybe_push_cleanup_level (argtype);
/* Don't push unnamed temps. Do set DECL_CONTEXT, though. */
DECL_CONTEXT (arg) = current_function_decl;
}
arg = make_temporary_var_for_ref_to_temp (decl);
/* Process the initializer for the declaration. */
DECL_INITIAL (arg) = targ;
@ -416,16 +391,7 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
else
rval
= convert_to_pointer_force (build_pointer_type (target_type), rval);
rval = build1 (NOP_EXPR, type, rval);
TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));
/* If we created and initialized a new temporary variable, add the
representation of that initialization to the RVAL. */
if (stmt_expr)
rval = build (COMPOUND_EXPR, TREE_TYPE (rval), stmt_expr, rval);
/* And return the result. */
return rval;
return build_nop (type, rval);
}
/* Subroutine of convert_to_reference. REFTYPE is the target reference type.
@ -500,7 +466,7 @@ convert_to_reference (tree reftype, tree expr, int convtype,
/* Look for a user-defined conversion to lvalue that we can use. */
rval_as_conversion
= build_type_conversion (reftype, expr, 1);
= build_type_conversion (reftype, expr);
if (rval_as_conversion && rval_as_conversion != error_mark_node
&& real_lvalue_p (rval_as_conversion))
@ -705,7 +671,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
if (IS_AGGR_TYPE (intype))
{
tree rval;
rval = build_type_conversion (type, e, 1);
rval = build_type_conversion (type, e);
if (rval)
return rval;
if (flags & LOOKUP_COMPLAIN)
@ -741,7 +707,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
if (IS_AGGR_TYPE (TREE_TYPE (e)))
{
tree rval;
rval = build_type_conversion (type, e, 1);
rval = build_type_conversion (type, e);
if (rval)
return rval;
else
@ -1015,24 +981,17 @@ convert_force (tree type, tree expr, int convtype)
allowed (references private members, etc).
If no conversion exists, NULL_TREE is returned.
If (FOR_SURE & 1) is nonzero, then we allow this type conversion
to take place immediately. Otherwise, we build a SAVE_EXPR
which can be evaluated if the results are ever needed.
Changes to this functions should be mirrored in user_harshness.
FIXME: Ambiguity checking is wrong. Should choose one by the implicit
object parameter, or by the second standard conversion sequence if
that doesn't do it. This will probably wait for an overloading rewrite.
(jason 8/9/95) */
tree
build_type_conversion (tree xtype, tree expr, int for_sure)
build_type_conversion (tree xtype, tree expr)
{
/* C++: check to see if we can convert this aggregate type
into the required type. */
return build_user_type_conversion
(xtype, expr, for_sure ? LOOKUP_NORMAL : 0);
return build_user_type_conversion (xtype, expr, LOOKUP_NORMAL);
}
/* Convert the given EXPR to one of a group of types suitable for use in an

View File

@ -7288,10 +7288,7 @@ grok_reference_init (tree decl, tree type, tree init)
DECL_INITIAL for local references (instead assigning to them
explicitly); we need to allow the temporary to be initialized
first. */
tmp = convert_to_reference
(type, init, CONV_IMPLICIT,
LOOKUP_ONLYCONVERTING|LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND,
decl);
tmp = initialize_reference (type, init, decl);
if (tmp == error_mark_node)
return NULL_TREE;

View File

@ -4089,7 +4089,45 @@ condition_conversion (expr)
t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t));
return t;
}
/* Return an ADDR_EXPR giving the address of T. This function
attempts no optimizations or simplifications; it is a low-level
primitive. */
tree
build_address (tree t)
{
tree addr;
if (error_operand_p (t) || !cxx_mark_addressable (t))
return error_mark_node;
addr = build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (t)),
t);
if (staticp (t))
TREE_CONSTANT (addr) = 1;
return addr;
}
/* Return a NOP_EXPR converting EXPR to TYPE. */
tree
build_nop (tree type, tree expr)
{
tree nop;
if (type == error_mark_node || error_operand_p (expr))
return expr;
nop = build1 (NOP_EXPR, type, expr);
if (TREE_CONSTANT (expr))
TREE_CONSTANT (nop) = 1;
return nop;
}
/* C++: Must handle pointers to members.
Perhaps type instantiation should be extended to handle conversion
@ -4479,9 +4517,6 @@ build_unary_op (code, xarg, noconvert)
if (argtype != error_mark_node)
argtype = build_pointer_type (argtype);
if (!cxx_mark_addressable (arg))
return error_mark_node;
{
tree addr;
@ -4515,12 +4550,7 @@ build_unary_op (code, xarg, noconvert)
cp_convert (argtype, byte_position (field))));
}
else
addr = build1 (ADDR_EXPR, argtype, arg);
/* Address of a static or external variable or
function counts as a constant */
if (staticp (arg))
TREE_CONSTANT (addr) = 1;
addr = build_address (arg);
if (TREE_CODE (argtype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
@ -5798,11 +5828,17 @@ build_ptrmemfunc (type, pfn, force)
int force;
{
tree fn;
tree pfn_type = TREE_TYPE (pfn);
tree to_type = build_ptrmemfunc_type (type);
tree pfn_type;
tree to_type;
if (error_operand_p (pfn))
return error_mark_node;
pfn_type = TREE_TYPE (pfn);
to_type = build_ptrmemfunc_type (type);
/* Handle multiple conversions of pointer to member functions. */
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn)))
if (TYPE_PTRMEMFUNC_P (pfn_type))
{
tree delta = NULL_TREE;
tree npfn = NULL_TREE;
@ -6183,7 +6219,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
if (fndecl)
savew = warningcount, savee = errorcount;
rhs = initialize_reference (type, rhs);
rhs = initialize_reference (type, rhs, /*decl=*/NULL_TREE);
if (fndecl)
{
if (warningcount > savew)

View File

@ -388,32 +388,8 @@ store_init_value (decl, init)
return value;
else if (TREE_STATIC (decl)
&& (! TREE_CONSTANT (value)
|| ! initializer_constant_valid_p (value, TREE_TYPE (value))
#if 0
/* A STATIC PUBLIC int variable doesn't have to be
run time inited when doing pic. (mrs) */
/* Since ctors and dtors are the only things that can
reference vtables, and they are always written down
the vtable definition, we can leave the
vtables in initialized data space.
However, other initialized data cannot be initialized
this way. Instead a global file-level initializer
must do the job. */
|| (flag_pic && !DECL_VIRTUAL_P (decl) && TREE_PUBLIC (decl))
#endif
))
|| ! initializer_constant_valid_p (value, TREE_TYPE (value))))
return value;
#if 0 /* No, that's C. jason 9/19/94 */
else
{
if (pedantic && TREE_CODE (value) == CONSTRUCTOR)
{
if (! TREE_CONSTANT (value) || ! TREE_STATIC (value))
pedwarn ("ISO C++ forbids non-constant aggregate initializer expressions");
}
}
#endif
/* Store the VALUE in DECL_INITIAL. If we're building a
statement-tree we will actually expand the initialization later

View File

@ -1,3 +1,8 @@
2003-03-03 Mark Mitchell <mark@codesourcery.com>
PR c++/9878
* g++.dg/init/ref1.C: New test.
Mon Mar 3 20:42:04 2003 J"orn Rennecke <joern.rennecke@superh.com>
* gcc.dg/sh-relax.c: New SH-only test.

View File

@ -0,0 +1,5 @@
void f(void)
{
short x = 0;
const int &y = x;
}