aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2003-03-06 22:46:10 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2003-03-06 22:46:10 +0000
commit5e2569964b62e695056d601d225589ba01348ff8 (patch)
tree1d244e8b7aa4d71995d155f1b8bc28dc30e5f960 /gcc
parenta9aa7083edffef0a326154cc39f429e55a12d846 (diff)
downloadgcc-5e2569964b62e695056d601d225589ba01348ff8.zip
gcc-5e2569964b62e695056d601d225589ba01348ff8.tar.gz
gcc-5e2569964b62e695056d601d225589ba01348ff8.tar.bz2
re PR c++/9965 (ICE in cp_expr_size)
PR c++/9965 * call.c (reference_binding): Add ref_is_var parameter. (implicit_conversion): Adjust call to reference_binding. (initialize_reference): Likewise. PR c++/9965 * g++.dg/init/ref2.C: New test. From-SVN: r63909
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/call.c45
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/init/ref2.C10
4 files changed, 41 insertions, 22 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 94fb884..25bba1b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
2003-03-06 Mark Mitchell <mark@codesourcery.com>
+ PR c++/9965
+ * call.c (reference_binding): Add ref_is_var parameter.
+ (implicit_conversion): Adjust call to reference_binding.
+ (initialize_reference): Likewise.
+
PR c++/9400
* decl.c (pushdecl): Don't check for shadowing of DECL_ARTIFICIAL
PARM_DECLs.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index fe26866..45cb23b 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, bool);
static tree non_reference (tree);
static tree build_conv (enum tree_code, tree, tree);
static bool is_subseq (tree, tree);
@@ -1111,14 +1111,12 @@ 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. If non-NULL,
- *REF_BOUND_DIRECTLY_TO_RVALUE_P is set to true if and only if the
- conversion sequence returned binds the reference directly to an
- rvalue. */
+ the conversion returned. REF_IS_VAR is true iff the reference is
+ a variable (rather than, say, a parameter declaration). */
static tree
reference_binding (tree rto, tree rfrom, tree expr, int flags,
- bool *ref_bound_directly_to_rvalue_p)
+ bool ref_is_var)
{
tree conv = NULL_TREE;
tree to = TREE_TYPE (rto);
@@ -1127,10 +1125,6 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags,
bool compatible_p;
cp_lvalue_kind lvalue_p = clk_none;
- /* Assume that the reference is not bound directly to an rvalue. */
- if (ref_bound_directly_to_rvalue_p)
- *ref_bound_directly_to_rvalue_p = false;
-
if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr))
{
expr = instantiate_type (to, expr, tf_none);
@@ -1234,15 +1228,23 @@ 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.
- In this case, 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)
+ -- 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)
{
- if (ref_bound_directly_to_rvalue_p)
- *ref_bound_directly_to_rvalue_p = true;
conv = build1 (IDENTITY_CONV, from, expr);
return direct_reference_binding (rto, conv);
}
@@ -1297,8 +1299,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_bound_directly_to_rvalue_p=*/NULL);
+ conv = reference_binding (to, from, expr, flags, /*ref_is_var=*/false);
else
conv = standard_conversion (to, from, expr);
@@ -5847,13 +5848,13 @@ tree
initialize_reference (tree type, tree expr, tree decl)
{
tree conv;
- bool ref_bound_directly_to_rvalue_p;
+ bool ref_bound_directly_to_rvalue_p = false;
if (type == error_mark_node || error_operand_p (expr))
return error_mark_node;
conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL,
- &ref_bound_directly_to_rvalue_p);
+ decl != NULL_TREE);
if (!conv || ICS_BAD_FLAG (conv))
{
error ("could not convert `%E' to `%T'", expr, type);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 964228f..9fabfd1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
2003-03-06 Mark Mitchell <mark@codesourcery.com>
+ PR c++/9965
+ * g++.dg/init/ref2.C: New test.
+
PR c++/9400
* g++.dg/warn/Wshadow-2.C: New test.
diff --git a/gcc/testsuite/g++.dg/init/ref2.C b/gcc/testsuite/g++.dg/init/ref2.C
new file mode 100644
index 0000000..231ea04
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/ref2.C
@@ -0,0 +1,10 @@
+struct Base {
+ Base();
+ Base(const Base &);
+ Base & operator = (const Base &);
+};
+
+struct Derived : public Base {};
+
+Derived derived();
+const Base &b = derived();