diff options
author | Mark Mitchell <mark@codesourcery.com> | 2003-03-07 21:19:38 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2003-03-07 21:19:38 +0000 |
commit | aa6e8ed33a18a6185f852b6d07a2168638c7cf39 (patch) | |
tree | d541d77effe4c2a0317c197fe33a09d83658f481 /gcc | |
parent | 5040d6912ccf32e1b3baed1e0a2d9dd475bbf853 (diff) | |
download | gcc-aa6e8ed33a18a6185f852b6d07a2168638c7cf39.zip gcc-aa6e8ed33a18a6185f852b6d07a2168638c7cf39.tar.gz gcc-aa6e8ed33a18a6185f852b6d07a2168638c7cf39.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/cp/call.c | 114 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 3 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 2 | ||||
-rw-r--r-- | gcc/cp/tree.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/ref4.C | 18 |
7 files changed, 121 insertions, 46 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index afb3436..f11bba8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 15dbbe1..a25da46 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 447fd57..53a4db6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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, ...); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index ba5fbba..88e802e 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -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; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 520aa16..94fe9fb 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2a95e09..27c6197 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/g++.dg/init/ref4.C b/gcc/testsuite/g++.dg/init/ref4.C new file mode 100644 index 0000000..6b65d99 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/ref4.C @@ -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. +} |