re PR c++/160 (Reference variables not initialized correctly in constructor initializer list using , operator)
cp: PR c++/160 * typeck.c (build_modify_expr): Remove old unreachable code & tidy up. Don't stabilize_references when initializing a reference. testsuite: * g++.dg/other/init2.C: New test. From-SVN: r48307
This commit is contained in:
parent
fdfc290b94
commit
a56ca89955
@ -1,3 +1,9 @@
|
|||||||
|
2001-12-24 Nathan Sidwell <nathan@codesourcery.com>
|
||||||
|
|
||||||
|
PR c++/160
|
||||||
|
* typeck.c (build_modify_expr): Remove old unreachable code & tidy
|
||||||
|
up. Don't stabilize_references when initializing a reference.
|
||||||
|
|
||||||
2001-12-23 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
2001-12-23 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
||||||
|
|
||||||
* decl2.c (lang_f_options): Const-ify.
|
* decl2.c (lang_f_options): Const-ify.
|
||||||
|
204
gcc/cp/typeck.c
204
gcc/cp/typeck.c
@ -5494,13 +5494,7 @@ build_modify_expr (lhs, modifycode, rhs)
|
|||||||
if (lhs == error_mark_node || rhs == error_mark_node)
|
if (lhs == error_mark_node || rhs == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
/* Types that aren't fully specified cannot be used in assignments. */
|
|
||||||
lhs = require_complete_type (lhs);
|
|
||||||
|
|
||||||
newrhs = rhs;
|
|
||||||
|
|
||||||
/* Handle control structure constructs used as "lvalues". */
|
/* Handle control structure constructs used as "lvalues". */
|
||||||
|
|
||||||
switch (TREE_CODE (lhs))
|
switch (TREE_CODE (lhs))
|
||||||
{
|
{
|
||||||
/* Handle --foo = 5; as these are valid constructs in C++ */
|
/* Handle --foo = 5; as these are valid constructs in C++ */
|
||||||
@ -5532,13 +5526,14 @@ build_modify_expr (lhs, modifycode, rhs)
|
|||||||
|
|
||||||
/* Handle (a ? b : c) used as an "lvalue". */
|
/* Handle (a ? b : c) used as an "lvalue". */
|
||||||
case COND_EXPR:
|
case COND_EXPR:
|
||||||
rhs = save_expr (rhs);
|
|
||||||
{
|
{
|
||||||
/* Produce (a ? (b = rhs) : (c = rhs))
|
/* Produce (a ? (b = rhs) : (c = rhs))
|
||||||
except that the RHS goes through a save-expr
|
except that the RHS goes through a save-expr
|
||||||
so the code to compute it is only emitted once. */
|
so the code to compute it is only emitted once. */
|
||||||
tree cond;
|
tree cond;
|
||||||
|
|
||||||
|
rhs = save_expr (rhs);
|
||||||
|
|
||||||
/* Check this here to avoid odd errors when trying to convert
|
/* Check this here to avoid odd errors when trying to convert
|
||||||
a throw to the type of the COND_EXPR. */
|
a throw to the type of the COND_EXPR. */
|
||||||
if (!lvalue_or_else (lhs, "assignment"))
|
if (!lvalue_or_else (lhs, "assignment"))
|
||||||
@ -5558,54 +5553,27 @@ build_modify_expr (lhs, modifycode, rhs)
|
|||||||
/* Make sure the code to compute the rhs comes out
|
/* Make sure the code to compute the rhs comes out
|
||||||
before the split. */
|
before the split. */
|
||||||
return build (COMPOUND_EXPR, TREE_TYPE (lhs),
|
return build (COMPOUND_EXPR, TREE_TYPE (lhs),
|
||||||
/* Case to void to suppress warning
|
/* Cast to void to suppress warning
|
||||||
from warn_if_unused_value. */
|
from warn_if_unused_value. */
|
||||||
cp_convert (void_type_node, rhs), cond);
|
cp_convert (void_type_node, rhs), cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case OFFSET_REF:
|
||||||
|
lhs = resolve_offset_ref (lhs);
|
||||||
|
if (lhs == error_mark_node)
|
||||||
|
return error_mark_node;
|
||||||
|
olhstype = lhstype = TREE_TYPE (lhs);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TREE_CODE (lhs) == OFFSET_REF)
|
|
||||||
{
|
|
||||||
if (TREE_OPERAND (lhs, 0) == NULL_TREE)
|
|
||||||
{
|
|
||||||
/* Static class member? */
|
|
||||||
tree member = TREE_OPERAND (lhs, 1);
|
|
||||||
if (TREE_CODE (member) == VAR_DECL)
|
|
||||||
lhs = member;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
compiler_error ("invalid static class member");
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
lhs = resolve_offset_ref (lhs);
|
|
||||||
|
|
||||||
olhstype = lhstype = TREE_TYPE (lhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lhs == error_mark_node)
|
|
||||||
return lhs;
|
|
||||||
|
|
||||||
if (TREE_CODE (lhstype) == REFERENCE_TYPE
|
|
||||||
&& modifycode != INIT_EXPR)
|
|
||||||
{
|
|
||||||
lhs = convert_from_reference (lhs);
|
|
||||||
olhstype = lhstype = TREE_TYPE (lhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If a binary op has been requested, combine the old LHS value with the RHS
|
|
||||||
producing the value we should actually store into the LHS. */
|
|
||||||
|
|
||||||
if (modifycode == INIT_EXPR)
|
if (modifycode == INIT_EXPR)
|
||||||
{
|
{
|
||||||
if (TREE_CODE (rhs) == CONSTRUCTOR)
|
if (TREE_CODE (rhs) == CONSTRUCTOR)
|
||||||
{
|
{
|
||||||
if (! same_type_p (TREE_TYPE (rhs), lhstype))
|
my_friendly_assert (same_type_p (TREE_TYPE (rhs), lhstype),
|
||||||
abort ();
|
20011220);
|
||||||
result = build (INIT_EXPR, lhstype, lhs, rhs);
|
result = build (INIT_EXPR, lhstype, lhs, rhs);
|
||||||
TREE_SIDE_EFFECTS (result) = 1;
|
TREE_SIDE_EFFECTS (result) = 1;
|
||||||
return result;
|
return result;
|
||||||
@ -5622,35 +5590,55 @@ build_modify_expr (lhs, modifycode, rhs)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (modifycode == NOP_EXPR)
|
|
||||||
{
|
|
||||||
/* `operator=' is not an inheritable operator. */
|
|
||||||
if (! IS_AGGR_TYPE (lhstype))
|
|
||||||
/* Do the default thing */;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
|
|
||||||
lhs, rhs, make_node (NOP_EXPR));
|
|
||||||
if (result == NULL_TREE)
|
|
||||||
return error_mark_node;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
lhstype = olhstype;
|
|
||||||
}
|
|
||||||
else if (PROMOTES_TO_AGGR_TYPE (lhstype, REFERENCE_TYPE))
|
|
||||||
{
|
|
||||||
my_friendly_abort (978652);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lhs = stabilize_reference (lhs);
|
if (TREE_CODE (lhstype) == REFERENCE_TYPE)
|
||||||
newrhs = cp_build_binary_op (modifycode, lhs, rhs);
|
|
||||||
if (newrhs == error_mark_node)
|
|
||||||
{
|
{
|
||||||
error (" in evaluation of `%Q(%#T, %#T)'", modifycode,
|
lhs = convert_from_reference (lhs);
|
||||||
TREE_TYPE (lhs), TREE_TYPE (rhs));
|
olhstype = lhstype = TREE_TYPE (lhs);
|
||||||
return error_mark_node;
|
|
||||||
}
|
}
|
||||||
|
lhs = require_complete_type (lhs);
|
||||||
|
if (lhs == error_mark_node)
|
||||||
|
return error_mark_node;
|
||||||
|
|
||||||
|
if (modifycode == NOP_EXPR)
|
||||||
|
{
|
||||||
|
/* `operator=' is not an inheritable operator. */
|
||||||
|
if (! IS_AGGR_TYPE (lhstype))
|
||||||
|
/* Do the default thing */;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
|
||||||
|
lhs, rhs, make_node (NOP_EXPR));
|
||||||
|
if (result == NULL_TREE)
|
||||||
|
return error_mark_node;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
lhstype = olhstype;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* A binary op has been requested. Combine the old LHS
|
||||||
|
value with the RHS producing the value we should actually
|
||||||
|
store into the LHS. */
|
||||||
|
|
||||||
|
my_friendly_assert (!PROMOTES_TO_AGGR_TYPE (lhstype, REFERENCE_TYPE),
|
||||||
|
978652);
|
||||||
|
lhs = stabilize_reference (lhs);
|
||||||
|
newrhs = cp_build_binary_op (modifycode, lhs, rhs);
|
||||||
|
if (newrhs == error_mark_node)
|
||||||
|
{
|
||||||
|
error (" in evaluation of `%Q(%#T, %#T)'", modifycode,
|
||||||
|
TREE_TYPE (lhs), TREE_TYPE (rhs));
|
||||||
|
return error_mark_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now it looks like a plain assignment. */
|
||||||
|
modifycode = NOP_EXPR;
|
||||||
|
}
|
||||||
|
my_friendly_assert (TREE_CODE (lhstype) != REFERENCE_TYPE, 20011220);
|
||||||
|
my_friendly_assert (TREE_CODE (TREE_TYPE (newrhs)) != REFERENCE_TYPE,
|
||||||
|
20011220);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle a cast used as an "lvalue".
|
/* Handle a cast used as an "lvalue".
|
||||||
@ -5669,15 +5657,16 @@ build_modify_expr (lhs, modifycode, rhs)
|
|||||||
case FIX_FLOOR_EXPR:
|
case FIX_FLOOR_EXPR:
|
||||||
case FIX_ROUND_EXPR:
|
case FIX_ROUND_EXPR:
|
||||||
case FIX_CEIL_EXPR:
|
case FIX_CEIL_EXPR:
|
||||||
if (TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
|
|
||||||
|| TREE_CODE (TREE_TYPE (newrhs)) == FUNCTION_TYPE
|
|
||||||
|| TREE_CODE (TREE_TYPE (newrhs)) == METHOD_TYPE
|
|
||||||
|| TREE_CODE (TREE_TYPE (newrhs)) == OFFSET_TYPE)
|
|
||||||
newrhs = default_conversion (newrhs);
|
|
||||||
{
|
{
|
||||||
tree inner_lhs = TREE_OPERAND (lhs, 0);
|
tree inner_lhs = TREE_OPERAND (lhs, 0);
|
||||||
tree result;
|
tree result;
|
||||||
|
|
||||||
|
if (TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
|
||||||
|
|| TREE_CODE (TREE_TYPE (newrhs)) == FUNCTION_TYPE
|
||||||
|
|| TREE_CODE (TREE_TYPE (newrhs)) == METHOD_TYPE
|
||||||
|
|| TREE_CODE (TREE_TYPE (newrhs)) == OFFSET_TYPE)
|
||||||
|
newrhs = default_conversion (newrhs);
|
||||||
|
|
||||||
/* ISO C++ 5.4/1: The result is an lvalue if T is a reference
|
/* ISO C++ 5.4/1: The result is an lvalue if T is a reference
|
||||||
type, otherwise the result is an rvalue. */
|
type, otherwise the result is an rvalue. */
|
||||||
if (! lvalue_p (lhs))
|
if (! lvalue_p (lhs))
|
||||||
@ -5703,23 +5692,23 @@ build_modify_expr (lhs, modifycode, rhs)
|
|||||||
|
|
||||||
GNU_xref_assign (lhs);
|
GNU_xref_assign (lhs);
|
||||||
|
|
||||||
/* Warn about storing in something that is `const'. */
|
/* Warn about modifying something that is `const'. Don't warn if
|
||||||
/* For C++, don't warn if this is initialization. */
|
this is initialization. */
|
||||||
if (modifycode != INIT_EXPR
|
if (modifycode != INIT_EXPR
|
||||||
&& (TREE_READONLY (lhs) || CP_TYPE_CONST_P (lhstype)
|
&& (TREE_READONLY (lhs) || CP_TYPE_CONST_P (lhstype)
|
||||||
/* Functions are not modifiable, even though they are
|
/* Functions are not modifiable, even though they are
|
||||||
lvalues. */
|
lvalues. */
|
||||||
|| TREE_CODE (TREE_TYPE (lhs)) == FUNCTION_TYPE
|
|| TREE_CODE (TREE_TYPE (lhs)) == FUNCTION_TYPE
|
||||||
|
|| TREE_CODE (TREE_TYPE (lhs)) == METHOD_TYPE
|
||||||
|
/* If it's an aggregate and any field is const, then it is
|
||||||
|
effectively const. */
|
||||||
|| (IS_AGGR_TYPE_CODE (TREE_CODE (lhstype))
|
|| (IS_AGGR_TYPE_CODE (TREE_CODE (lhstype))
|
||||||
&& C_TYPE_FIELDS_READONLY (lhstype))
|
&& C_TYPE_FIELDS_READONLY (lhstype))))
|
||||||
|| (TREE_CODE (lhstype) == REFERENCE_TYPE
|
|
||||||
&& CP_TYPE_CONST_P (TREE_TYPE (lhstype)))))
|
|
||||||
readonly_error (lhs, "assignment", 0);
|
readonly_error (lhs, "assignment", 0);
|
||||||
|
|
||||||
/* If storing into a structure or union member,
|
/* If storing into a structure or union member, it has probably been
|
||||||
it has probably been given type `int'.
|
given type `int'. Compute the type that would go with the actual
|
||||||
Compute the type that would go with
|
amount of storage the member occupies. */
|
||||||
the actual amount of storage the member occupies. */
|
|
||||||
|
|
||||||
if (TREE_CODE (lhs) == COMPONENT_REF
|
if (TREE_CODE (lhs) == COMPONENT_REF
|
||||||
&& (TREE_CODE (lhstype) == INTEGER_TYPE
|
&& (TREE_CODE (lhstype) == INTEGER_TYPE
|
||||||
@ -5738,40 +5727,14 @@ build_modify_expr (lhs, modifycode, rhs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modifycode != INIT_EXPR)
|
if (TREE_CODE (lhstype) != REFERENCE_TYPE)
|
||||||
{
|
{
|
||||||
/* Make modifycode now either a NOP_EXPR or an INIT_EXPR. */
|
if (TREE_SIDE_EFFECTS (lhs))
|
||||||
modifycode = NOP_EXPR;
|
lhs = stabilize_reference (lhs);
|
||||||
/* Reference-bashing */
|
if (TREE_SIDE_EFFECTS (newrhs))
|
||||||
if (TREE_CODE (lhstype) == REFERENCE_TYPE)
|
newrhs = stabilize_reference (newrhs);
|
||||||
{
|
|
||||||
tree tmp = convert_from_reference (lhs);
|
|
||||||
lhstype = TREE_TYPE (tmp);
|
|
||||||
if (!COMPLETE_TYPE_P (lhstype))
|
|
||||||
{
|
|
||||||
incomplete_type_error (lhs, lhstype);
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
lhs = tmp;
|
|
||||||
olhstype = lhstype;
|
|
||||||
}
|
|
||||||
if (TREE_CODE (TREE_TYPE (newrhs)) == REFERENCE_TYPE)
|
|
||||||
{
|
|
||||||
tree tmp = convert_from_reference (newrhs);
|
|
||||||
if (!COMPLETE_TYPE_P (TREE_TYPE (tmp)))
|
|
||||||
{
|
|
||||||
incomplete_type_error (newrhs, TREE_TYPE (tmp));
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
newrhs = tmp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TREE_SIDE_EFFECTS (lhs))
|
|
||||||
lhs = stabilize_reference (lhs);
|
|
||||||
if (TREE_SIDE_EFFECTS (newrhs))
|
|
||||||
newrhs = stabilize_reference (newrhs);
|
|
||||||
|
|
||||||
/* Convert new value to destination type. */
|
/* Convert new value to destination type. */
|
||||||
|
|
||||||
if (TREE_CODE (lhstype) == ARRAY_TYPE)
|
if (TREE_CODE (lhstype) == ARRAY_TYPE)
|
||||||
@ -5795,17 +5758,8 @@ build_modify_expr (lhs, modifycode, rhs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (modifycode == INIT_EXPR)
|
if (modifycode == INIT_EXPR)
|
||||||
{
|
newrhs = convert_for_initialization (lhs, lhstype, newrhs, LOOKUP_NORMAL,
|
||||||
newrhs = convert_for_initialization (lhs, lhstype, newrhs, LOOKUP_NORMAL,
|
"initialization", NULL_TREE, 0);
|
||||||
"initialization", NULL_TREE, 0);
|
|
||||||
if (current_function_decl &&
|
|
||||||
lhs == DECL_RESULT (current_function_decl))
|
|
||||||
{
|
|
||||||
if (DECL_INITIAL (lhs))
|
|
||||||
warning ("return value from function receives multiple initializations");
|
|
||||||
DECL_INITIAL (lhs) = newrhs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Avoid warnings on enum bit fields. */
|
/* Avoid warnings on enum bit fields. */
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2001-12-24 Nathan Sidwell <nathan@codesourcery.com>
|
||||||
|
|
||||||
|
* g++.dg/other/init2.C: New test.
|
||||||
|
|
||||||
2001-12-24 Richard Henderson <rth@redhat.com>
|
2001-12-24 Richard Henderson <rth@redhat.com>
|
||||||
|
|
||||||
* gcc.dg/20011223-1.c: New.
|
* gcc.dg/20011223-1.c: New.
|
||||||
|
49
gcc/testsuite/g++.dg/other/init2.C
Normal file
49
gcc/testsuite/g++.dg/other/init2.C
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// { dg-do run }
|
||||||
|
|
||||||
|
// Copyright (C) 2001 Free Software Foundation, Inc.
|
||||||
|
// Contributed by Nathan Sidwell 20 Dec 2001 <nathan@nathan@codesourcery.com>
|
||||||
|
|
||||||
|
// PR 160. Wrong code emitted for some reference initializers.
|
||||||
|
|
||||||
|
void Foo ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int fail;
|
||||||
|
|
||||||
|
class C
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int m;
|
||||||
|
int &r;
|
||||||
|
|
||||||
|
C () ;
|
||||||
|
};
|
||||||
|
|
||||||
|
C::C ()
|
||||||
|
: m (1), r ((Foo (), m))
|
||||||
|
{
|
||||||
|
m = 10;
|
||||||
|
|
||||||
|
if (r != m)
|
||||||
|
fail = 1;
|
||||||
|
else if (&m != &r)
|
||||||
|
fail = 2;
|
||||||
|
}
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
int m (1);
|
||||||
|
int &r ((Foo (),m));
|
||||||
|
|
||||||
|
m = 10;
|
||||||
|
if (r != m)
|
||||||
|
fail = 3;
|
||||||
|
else if (&r != &m)
|
||||||
|
fail = 4;
|
||||||
|
|
||||||
|
if (!fail)
|
||||||
|
{
|
||||||
|
C c;
|
||||||
|
}
|
||||||
|
return fail;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user