call.c (reference_binding): Remove REF_IS_VAR parameter.

* call.c (reference_binding): Remove REF_IS_VAR parameter.
	(implicit_conversion): Adjust call to reference_binding.
	(make_temporary_var_for_ref_to_type): Add TYPE parameter.
	(initialize_reference): Adjust handling for references bound to
	rvalues.
	* cp-tree.h (make_temporary_var_for_ref_to_temp): Change
	prototype.
	(real_non_cast_lvalue_p): New function.
	* cvt.c (build_up_reference): Adjust use of
	make_temporary_var_for_ref_to_temp.
	* tree.c (real_non_cast_lvalue_p): New function.

	* g++.dg/init/ref4.C: New test.

From-SVN: r63949
This commit is contained in:
Mark Mitchell 2003-03-07 21:19:38 +00:00 committed by Mark Mitchell
parent 5040d6912c
commit aa6e8ed33a
7 changed files with 121 additions and 46 deletions

View File

@ -1,3 +1,17 @@
2003-03-07 Mark Mitchell <mark@codesourcery.com>
* call.c (reference_binding): Remove REF_IS_VAR parameter.
(implicit_conversion): Adjust call to reference_binding.
(make_temporary_var_for_ref_to_type): Add TYPE parameter.
(initialize_reference): Adjust handling for references bound to
rvalues.
* cp-tree.h (make_temporary_var_for_ref_to_temp): Change
prototype.
(real_non_cast_lvalue_p): New method.
* cvt.c (build_up_reference): Adjust use of
make_temporary_var_for_ref_to_temp.
* tree.c (
2003-03-07 Gabriel Dos Reis <gdr@integrable-solutions.net>
* except.c (init_exception_processing): Use C90 prototype style.

View File

@ -85,7 +85,7 @@ static struct z_candidate *add_function_candidate
(struct z_candidate **, tree, tree, tree, tree, tree, int);
static tree implicit_conversion (tree, tree, tree, int);
static tree standard_conversion (tree, tree, tree);
static tree reference_binding (tree, tree, tree, int, bool);
static tree reference_binding (tree, tree, tree, int);
static tree non_reference (tree);
static tree build_conv (enum tree_code, tree, tree);
static bool is_subseq (tree, tree);
@ -1133,12 +1133,10 @@ direct_reference_binding (tree type, tree conv)
purposes of reference binding. For lvalue binding, either pass a
reference type to FROM or an lvalue expression to EXPR. If the
reference will be bound to a temporary, NEED_TEMPORARY_P is set for
the conversion returned. REF_IS_VAR is true iff the reference is
a variable (rather than, say, a parameter declaration). */
the conversion returned. */
static tree
reference_binding (tree rto, tree rfrom, tree expr, int flags,
bool ref_is_var)
reference_binding (tree rto, tree rfrom, tree expr, int flags)
{
tree conv = NULL_TREE;
tree to = TREE_TYPE (rto);
@ -1250,22 +1248,14 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags,
-- The reference is bound to the object represented by the rvalue
or to a sub-object within that object.
-- A temporary of type "cv1 T2" [sic] is created, and a
constructor is called to copy the entire rvalue object into
the temporary. The reference is bound to the temporary or to
a sub-object within the temporary
-- ...
In general, we choose the first alternative, since it avoids the
copy. However, if REF_IS_VAR is true, then we cannot do that; we
need to bind the reference to a temporary that wil live as long
as the reference itself.
In the first alternative, the implicit conversion sequence is
supposed to be same as we would obtain by generating a temporary.
Fortunately, if the types are reference compatible, then this is
either an identity conversion or the derived-to-base conversion,
just as for direct binding. */
if (CLASS_TYPE_P (from) && compatible_p && !ref_is_var)
We use the first alternative. The implicit conversion sequence
is supposed to be same as we would obtain by generating a
temporary. Fortunately, if the types are reference compatible,
then this is either an identity conversion or the derived-to-base
conversion, just as for direct binding. */
if (CLASS_TYPE_P (from) && compatible_p)
{
conv = build1 (IDENTITY_CONV, from, expr);
return direct_reference_binding (rto, conv);
@ -1321,7 +1311,7 @@ implicit_conversion (tree to, tree from, tree expr, int flags)
complete_type (to);
if (TREE_CODE (to) == REFERENCE_TYPE)
conv = reference_binding (to, from, expr, flags, /*ref_is_var=*/false);
conv = reference_binding (to, from, expr, flags);
else
conv = standard_conversion (to, from, expr);
@ -5849,19 +5839,14 @@ perform_implicit_conversion (tree type, tree expr)
/* DECL is a VAR_DECL whose type is a REFERENCE_TYPE. The reference
is being bound to a temporary. Create and return a new VAR_DECL
whose type is the underlying type of the reference. */
with the indicated TYPE; this variable will store the value to
which the reference is bound. */
tree
make_temporary_var_for_ref_to_temp (tree decl)
make_temporary_var_for_ref_to_temp (tree decl, tree type)
{
tree type;
tree var;
/* Get the type to which the reference refers. */
type = TREE_TYPE (decl);
my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 200302);
type = TREE_TYPE (type);
/* Create the variable. */
var = build_decl (VAR_DECL, NULL_TREE, type);
DECL_ARTIFICIAL (var) = 1;
@ -5905,8 +5890,7 @@ initialize_reference (tree type, tree expr, tree decl)
if (type == error_mark_node || error_operand_p (expr))
return error_mark_node;
conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL,
decl != NULL_TREE);
conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL);
if (!conv || ICS_BAD_FLAG (conv))
{
error ("could not convert `%E' to `%T'", expr, type);
@ -5918,7 +5902,7 @@ initialize_reference (tree type, tree expr, tree decl)
[class.temporary]
The temporary to which the reference is bound or the temporary
that is the complete object to which the temporary is bound
that is the complete object to which the reference is bound
persists for the lifetime of the reference.
The temporaries created during the evaluation of the expression
@ -5927,22 +5911,64 @@ initialize_reference (tree type, tree expr, tree decl)
full-expression in which they are created.
In that case, we store the converted expression into a new
VAR_DECL in a new scope. */
VAR_DECL in a new scope.
However, we want to be careful not to create temporaries when
they are not required. For example, given:
struct B {};
struct D : public B {};
D f();
const B& b = f();
there is no need to copy the return value from "f"; we can just
extend its lifetime. Similarly, given:
struct S {};
struct T { operator S(); };
T t;
const S& s = t;
we can extend the lifetime of the returnn value of the conversion
operator. */
my_friendly_assert (TREE_CODE (conv) == REF_BIND, 20030302);
if (decl && NEED_TEMPORARY_P (conv))
if (decl)
{
tree var;
/* Process the initializer for the declaration. */
expr = convert_like (TREE_OPERAND (conv, 0), expr);
/* Create the temporary variable. */
var = make_temporary_var_for_ref_to_temp (decl);
DECL_INITIAL (var) = expr;
cp_finish_decl (var, expr, NULL_TREE,
LOOKUP_ONLYCONVERTING|DIRECT_BIND);
tree base_conv_type;
/* Use its address to initialize the reference variable. */
return build_nop (type, build_address (var));
/* Skip over the REF_BIND. */
conv = TREE_OPERAND (conv, 0);
/* If the next conversion is a BASE_CONV, skip that too -- but
remember that the conversion was required. */
if (TREE_CODE (conv) == BASE_CONV)
{
my_friendly_assert (!NEED_TEMPORARY_P (conv), 20030307);
base_conv_type = TREE_TYPE (conv);
conv = TREE_OPERAND (conv, 0);
}
else
base_conv_type = NULL_TREE;
/* Perform the remainder of the conversion. */
expr = convert_like (conv, expr);
if (!real_non_cast_lvalue_p (expr))
{
/* Create the temporary variable. */
var = make_temporary_var_for_ref_to_temp (decl, TREE_TYPE (expr));
DECL_INITIAL (var) = expr;
cp_finish_decl (var, expr, NULL_TREE,
LOOKUP_ONLYCONVERTING|DIRECT_BIND);
/* Use its address to initialize the reference variable. */
expr = build_address (var);
}
else
/* Take the address of EXPR. */
expr = build_unary_op (ADDR_EXPR, expr, 0);
/* If a BASE_CONV was required, perform it now. */
if (base_conv_type)
expr = (perform_implicit_conversion
(build_pointer_type (base_conv_type), expr));
return build_nop (type, expr);
}
/* Perform the conversion. */

View File

@ -3581,7 +3581,7 @@ 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, tree);
extern tree make_temporary_var_for_ref_to_temp (tree);
extern tree make_temporary_var_for_ref_to_temp (tree, tree);
extern tree strip_top_quals (tree);
extern tree perform_implicit_conversion (tree, tree);
extern tree in_charge_arg_for_name (tree);
@ -4226,6 +4226,7 @@ extern tree copy_base_binfos (tree, tree, tree);
extern int member_p (tree);
extern cp_lvalue_kind real_lvalue_p (tree);
extern int non_cast_lvalue_p (tree);
extern cp_lvalue_kind real_non_cast_lvalue_p (tree);
extern int non_cast_lvalue_or_else (tree, const char *);
extern tree build_min (enum tree_code, tree,
...);

View File

@ -358,7 +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 = make_temporary_var_for_ref_to_temp (decl);
arg = make_temporary_var_for_ref_to_temp (decl, TREE_TYPE (arg));
/* Process the initializer for the declaration. */
DECL_INITIAL (arg) = targ;

View File

@ -212,6 +212,18 @@ real_lvalue_p (ref)
return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/ 0, /*cast*/ 1);
}
/* Returns the kind of lvalue that REF is, in the sense of
[basic.lval]. This function should really be named lvalue_p; it
computes the C++ definition of lvalue. */
cp_lvalue_kind
real_non_cast_lvalue_p (tree ref)
{
return lvalue_p_1 (ref,
/*treat_class_rvalues_as_lvalues=*/0,
/*allow_cast_as_lvalue=*/0);
}
/* This differs from real_lvalue_p in that class rvalues are
considered lvalues. */

View File

@ -1,3 +1,7 @@
2003-03-07 Mark Mitchell <mark@codesourcery.com>
* g++.dg/init/ref4.C: New test.
Fri Mar 7 17:41:07 CET 2003 Jan Hubicka <jh@suse.cz>
* gcc.dg/i386-local2.c: Fix problems with certain versions of dejagnu.

View File

@ -0,0 +1,18 @@
// { dg-do run }
int c;
struct Base {
Base() {}
Base(const Base &) { ++c; }
Base & operator = (const Base &);
};
struct Derived : public Base {};
const Base &b = Derived();
int main()
{
return c; // No copies should be required.
}