aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/typeck.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/typeck.c')
-rw-r--r--gcc/cp/typeck.c380
1 files changed, 190 insertions, 190 deletions
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 6ca524233d8..82867eba0b3 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -285,7 +285,7 @@ commonparms (p1, p2)
if (TREE_VALUE (p1) != TREE_VALUE (p2))
{
any_change = 1;
- TREE_VALUE (n) = common_type (TREE_VALUE (p1), TREE_VALUE (p2));
+ TREE_VALUE (n) = merge_types (TREE_VALUE (p1), TREE_VALUE (p2));
}
else
TREE_VALUE (n) = TREE_VALUE (p1);
@@ -330,16 +330,38 @@ type_after_usual_arithmetic_conversions (t1, t2)
/* FIXME: Attributes. */
my_friendly_assert (ARITHMETIC_TYPE_P (t1)
+ || TREE_CODE (t1) == COMPLEX_TYPE
|| TREE_CODE (t1) == ENUMERAL_TYPE,
19990725);
my_friendly_assert (ARITHMETIC_TYPE_P (t2)
+ || TREE_CODE (t2) == COMPLEX_TYPE
|| TREE_CODE (t2) == ENUMERAL_TYPE,
19990725);
- /* In what follows, we slightly generalize the rules given in [expr]
- so as to deal with `long long'. First, merge the attributes. */
+ /* In what follows, we slightly generalize the rules given in [expr] so
+ as to deal with `long long' and `complex'. First, merge the
+ attributes. */
attributes = (*targetm.merge_type_attributes) (t1, t2);
+ /* If one type is complex, form the common type of the non-complex
+ components, then make that complex. Use T1 or T2 if it is the
+ required type. */
+ if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
+ {
+ tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
+ tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
+ tree subtype
+ = type_after_usual_arithmetic_conversions (subtype1, subtype2);
+
+ if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
+ return build_type_attribute_variant (t1, attributes);
+ else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
+ return build_type_attribute_variant (t2, attributes);
+ else
+ return build_type_attribute_variant (build_complex_type (subtype),
+ attributes);
+ }
+
/* If only one is real, use it as the result. */
if (code1 == REAL_TYPE && code2 != REAL_TYPE)
return build_type_attribute_variant (t1, attributes);
@@ -359,6 +381,10 @@ type_after_usual_arithmetic_conversions (t1, t2)
else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
return build_type_attribute_variant (t2, attributes);
+ /* The types are the same; no need to do anything fancy. */
+ if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+ return build_type_attribute_variant (t1, attributes);
+
if (code1 != REAL_TYPE)
{
/* If one is a sizetype, use it so size_binop doesn't blow up. */
@@ -420,9 +446,17 @@ type_after_usual_arithmetic_conversions (t1, t2)
|| same_type_p (TYPE_MAIN_VARIANT (t2), double_type_node))
return build_type_attribute_variant (double_type_node,
attributes);
- else
+ if (same_type_p (TYPE_MAIN_VARIANT (t1), float_type_node)
+ || same_type_p (TYPE_MAIN_VARIANT (t2), float_type_node))
return build_type_attribute_variant (float_type_node,
attributes);
+
+ /* Two floating-point types whose TYPE_MAIN_VARIANTs are none of
+ the standard C++ floating-point types. Logic earlier in this
+ function has already eliminated the possibility that
+ TYPE_PRECISION (t2) != TYPE_PRECISION (t1), so there's no
+ compelling reason to choose one or the other. */
+ return build_type_attribute_variant (t1, attributes);
}
}
@@ -439,6 +473,7 @@ composite_pointer_type (t1, t2, arg1, arg2, location)
const char* location;
{
tree result_type;
+ tree attributes;
/* [expr.rel]
@@ -456,6 +491,9 @@ composite_pointer_type (t1, t2, arg1, arg2, location)
if (TYPE_PTRMEMFUNC_P (t2))
t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
+ /* Merge the attributes. */
+ attributes = (*targetm.merge_type_attributes) (t1, t2);
+
/* We have:
[expr.rel]
@@ -504,21 +542,18 @@ composite_pointer_type (t1, t2, arg1, arg2, location)
}
}
- return result_type;
+ return build_type_attribute_variant (result_type, attributes);
}
-/* Return the common type of two types.
+/* Return the merged type of two types.
We assume that comptypes has already been done and returned 1;
if that isn't so, this may crash.
- This is the type for the result of most arithmetic operations
- if the operands have the given two types.
-
- We do not deal with enumeral types here because they have already been
- converted to integer types. */
+ This just combines attributes and default arguments; any other
+ differences would cause the two types to compare unalike. */
tree
-common_type (t1, t2)
+merge_types (t1, t2)
tree t1, t2;
{
register enum tree_code code1;
@@ -528,9 +563,7 @@ common_type (t1, t2)
/* Save time if the two types are the same. */
if (t1 == t2)
return t1;
- t1 = original_type (t1);
- t2 = original_type (t2);
- if (t1 == t2)
+ if (original_type (t1) == original_type (t2))
return t1;
/* If one type is nonsense, use the other. */
@@ -539,20 +572,11 @@ common_type (t1, t2)
if (t2 == error_mark_node)
return t1;
- if ((ARITHMETIC_TYPE_P (t1) || TREE_CODE (t1) == ENUMERAL_TYPE)
- && (ARITHMETIC_TYPE_P (t2) || TREE_CODE (t2) == ENUMERAL_TYPE))
- return type_after_usual_arithmetic_conversions (t1, t2);
-
/* Merge the attributes. */
attributes = (*targetm.merge_type_attributes) (t1, t2);
/* Treat an enum type as the unsigned integer type of the same width. */
- if (TREE_CODE (t1) == ENUMERAL_TYPE)
- t1 = type_for_size (TYPE_PRECISION (t1), 1);
- if (TREE_CODE (t2) == ENUMERAL_TYPE)
- t2 = type_for_size (TYPE_PRECISION (t2), 1);
-
if (TYPE_PTRMEMFUNC_P (t1))
t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
if (TYPE_PTRMEMFUNC_P (t2))
@@ -561,88 +585,21 @@ common_type (t1, t2)
code1 = TREE_CODE (t1);
code2 = TREE_CODE (t2);
- /* If one type is complex, form the common type of the non-complex
- components, then make that complex. Use T1 or T2 if it is the
- required type. */
- if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
- {
- tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
- tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
- tree subtype = common_type (subtype1, subtype2);
-
- if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
- return build_type_attribute_variant (t1, attributes);
- else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
- return build_type_attribute_variant (t2, attributes);
- else
- return build_type_attribute_variant (build_complex_type (subtype),
- attributes);
- }
-
switch (code1)
{
- case INTEGER_TYPE:
- case REAL_TYPE:
- /* We should have called type_after_usual_arithmetic_conversions
- above. */
- abort ();
- break;
-
case POINTER_TYPE:
case REFERENCE_TYPE:
- /* For two pointers, do this recursively on the target type,
- and combine the qualifiers of the two types' targets. */
- /* This code was turned off; I don't know why.
- But ISO C++ specifies doing this with the qualifiers.
- So I turned it on again. */
+ /* For two pointers, do this recursively on the target type. */
{
- tree tt1 = TREE_TYPE (t1);
- tree tt2 = TREE_TYPE (t2);
- tree b1, b2;
- int type_quals;
- tree target;
-
- if (TREE_CODE (tt1) == OFFSET_TYPE)
- {
- b1 = TYPE_OFFSET_BASETYPE (tt1);
- b2 = TYPE_OFFSET_BASETYPE (tt2);
- tt1 = TREE_TYPE (tt1);
- tt2 = TREE_TYPE (tt2);
- }
- else
- b1 = b2 = NULL_TREE;
-
- type_quals = (cp_type_quals (tt1) | cp_type_quals (tt2));
- tt1 = TYPE_MAIN_VARIANT (tt1);
- tt2 = TYPE_MAIN_VARIANT (tt2);
-
- if (tt1 == tt2)
- target = tt1;
- else if (VOID_TYPE_P (tt1) || VOID_TYPE_P (tt2))
- target = void_type_node;
- else if (tt1 == unknown_type_node)
- target = tt2;
- else if (tt2 == unknown_type_node)
- target = tt1;
- else
- target = common_type (tt1, tt2);
-
- target = cp_build_qualified_type (target, type_quals);
-
- if (b1)
- {
- if (same_type_p (b1, b2)
- || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))
- target = build_offset_type (b2, target);
- else if (binfo_or_else (b2, b1))
- target = build_offset_type (b1, target);
- }
+ tree target = merge_types (TREE_TYPE (t1), TREE_TYPE (t2));
+ int quals = cp_type_quals (t1);
if (code1 == POINTER_TYPE)
t1 = build_pointer_type (target);
else
t1 = build_reference_type (target);
t1 = build_type_attribute_variant (t1, attributes);
+ t1 = cp_build_qualified_type (t1, quals);
if (TREE_CODE (target) == METHOD_TYPE)
t1 = build_ptrmemfunc_type (t1);
@@ -650,9 +607,17 @@ common_type (t1, t2)
return t1;
}
+ case OFFSET_TYPE:
+ {
+ tree base = TYPE_OFFSET_BASETYPE (t1);
+ tree target = merge_types (TREE_TYPE (t1), TREE_TYPE (t2));
+ t1 = build_offset_type (base, target);
+ break;
+ }
+
case ARRAY_TYPE:
{
- tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
+ tree elt = merge_types (TREE_TYPE (t1), TREE_TYPE (t2));
/* Save space: see if the result is identical to one of the args. */
if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
return build_type_attribute_variant (t1, attributes);
@@ -661,14 +626,14 @@ common_type (t1, t2)
/* Merge the element types, and have a size if either arg has one. */
t1 = build_cplus_array_type
(elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
- return build_type_attribute_variant (t1, attributes);
+ break;
}
case FUNCTION_TYPE:
/* Function types: prefer the one that specified arg types.
If both do, merge the arg types. Also merge the return types. */
{
- tree valtype = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
+ tree valtype = merge_types (TREE_TYPE (t1), TREE_TYPE (t2));
tree p1 = TYPE_ARG_TYPES (t1);
tree p2 = TYPE_ARG_TYPES (t2);
tree rval, raises;
@@ -697,73 +662,72 @@ common_type (t1, t2)
}
rval = build_function_type (valtype, commonparms (p1, p2));
- rval = build_exception_variant (rval, raises);
- return build_type_attribute_variant (rval, attributes);
+ t1 = build_exception_variant (rval, raises);
+ break;
}
- case RECORD_TYPE:
- case UNION_TYPE:
- t1 = TYPE_MAIN_VARIANT (t1);
- t2 = TYPE_MAIN_VARIANT (t2);
+ case METHOD_TYPE:
+ {
+ /* Get this value the long way, since TYPE_METHOD_BASETYPE
+ is just the main variant of this. */
+ tree basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2)));
+ tree raises = TYPE_RAISES_EXCEPTIONS (t1);
+ tree t3;
+
+ /* If this was a member function type, get back to the
+ original type of type member function (i.e., without
+ the class instance variable up front. */
+ t1 = build_function_type (TREE_TYPE (t1),
+ TREE_CHAIN (TYPE_ARG_TYPES (t1)));
+ t2 = build_function_type (TREE_TYPE (t2),
+ TREE_CHAIN (TYPE_ARG_TYPES (t2)));
+ t3 = merge_types (t1, t2);
+ t3 = build_cplus_method_type (basetype, TREE_TYPE (t3),
+ TYPE_ARG_TYPES (t3));
+ t1 = build_exception_variant (t3, raises);
+ break;
+ }
- if (DERIVED_FROM_P (t1, t2) && binfo_or_else (t1, t2))
- return build_type_attribute_variant (t1, attributes);
- else if (binfo_or_else (t2, t1))
- return build_type_attribute_variant (t2, attributes);
- else
- {
- compiler_error ("common_type called with uncommon aggregate types");
- return error_mark_node;
- }
+ default:;
+ }
+ return build_type_attribute_variant (t1, attributes);
+}
- case METHOD_TYPE:
- if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)))
- {
- /* Get this value the long way, since TYPE_METHOD_BASETYPE
- is just the main variant of this. */
- tree basetype;
- tree raises, t3;
+/* Return the common type of two types.
+ We assume that comptypes has already been done and returned 1;
+ if that isn't so, this may crash.
- tree b1 = TYPE_OFFSET_BASETYPE (t1);
- tree b2 = TYPE_OFFSET_BASETYPE (t2);
+ This is the type for the result of most arithmetic operations
+ if the operands have the given two types. */
- if (same_type_p (b1, b2)
- || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))
- basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2)));
- else
- {
- if (binfo_or_else (b2, b1) == NULL_TREE)
- compiler_error ("common_type called with uncommon method types");
- basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t1)));
- }
+tree
+common_type (t1, t2)
+ tree t1, t2;
+{
+ enum tree_code code1;
+ enum tree_code code2;
- raises = TYPE_RAISES_EXCEPTIONS (t1);
-
- /* If this was a member function type, get back to the
- original type of type member function (i.e., without
- the class instance variable up front. */
- t1 = build_function_type (TREE_TYPE (t1),
- TREE_CHAIN (TYPE_ARG_TYPES (t1)));
- t2 = build_function_type (TREE_TYPE (t2),
- TREE_CHAIN (TYPE_ARG_TYPES (t2)));
- t3 = common_type (t1, t2);
- t3 = build_cplus_method_type (basetype, TREE_TYPE (t3),
- TYPE_ARG_TYPES (t3));
- t1 = build_exception_variant (t3, raises);
- }
- else
- compiler_error ("common_type called with uncommon method types");
+ /* If one type is nonsense, bail. */
+ if (t1 == error_mark_node || t2 == error_mark_node)
+ return error_mark_node;
- return build_type_attribute_variant (t1, attributes);
+ code1 = TREE_CODE (t1);
+ code2 = TREE_CODE (t2);
- case OFFSET_TYPE:
- /* Pointers to members should now be handled by the POINTER_TYPE
- case above. */
- abort ();
+ if ((ARITHMETIC_TYPE_P (t1) || code1 == ENUMERAL_TYPE
+ || code1 == COMPLEX_TYPE)
+ && (ARITHMETIC_TYPE_P (t2) || code2 == ENUMERAL_TYPE
+ || code2 == COMPLEX_TYPE))
+ return type_after_usual_arithmetic_conversions (t1, t2);
- default:
- return build_type_attribute_variant (t1, attributes);
- }
+ else if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2))
+ || (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2))
+ || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2)))
+ return composite_pointer_type (t1, t2, error_mark_node, error_mark_node,
+ "conversion");
+
+ else
+ abort ();
}
/* Compare two exception specifier types for exactness or subsetness, if
@@ -1037,20 +1001,6 @@ comptypes (t1, t2, strict)
&& comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict));
break;
- case METHOD_TYPE:
- if (! comp_except_specs (TYPE_RAISES_EXCEPTIONS (t1),
- TYPE_RAISES_EXCEPTIONS (t2), 1))
- return 0;
-
- /* This case is anti-symmetrical!
- One can pass a base member (or member function)
- to something expecting a derived member (or member function),
- but not vice-versa! */
-
- val = (comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)
- && compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2)));
- break;
-
case POINTER_TYPE:
case REFERENCE_TYPE:
t1 = TREE_TYPE (t1);
@@ -1065,11 +1015,8 @@ comptypes (t1, t2, strict)
goto look_hard;
break;
+ case METHOD_TYPE:
case FUNCTION_TYPE:
- if (! comp_except_specs (TYPE_RAISES_EXCEPTIONS (t1),
- TYPE_RAISES_EXCEPTIONS (t2), 1))
- return 0;
-
val = ((TREE_TYPE (t1) == TREE_TYPE (t2)
|| comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict))
&& compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2)));
@@ -1597,7 +1544,7 @@ c_sizeof (type)
TYPE_IS_SIZETYPE means that certain things (like overflow) will
never happen. However, this node should really have type
`size_t', which is just a typedef for an ordinary integer type. */
- size = fold (build1 (NOP_EXPR, c_size_type_node, size));
+ size = fold (build1 (NOP_EXPR, size_type_node, size));
my_friendly_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (size)),
20001021);
return size;
@@ -1666,7 +1613,7 @@ c_sizeof_nowarn (type)
TYPE_IS_SIZETYPE means that certain things (like overflow) will
never happen. However, this node should really have type
`size_t', which is just a typedef for an ordinary integer type. */
- size = fold (build1 (NOP_EXPR, c_size_type_node, size));
+ size = fold (build1 (NOP_EXPR, size_type_node, size));
my_friendly_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (size)),
20001021);
return size;
@@ -2926,19 +2873,18 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
load-with-sign-extend, while the second used normal load then
shift to sign-extend. An optimizer flaw, perhaps, but it's
easier to make this change. */
+ idx = cp_build_binary_op (TRUNC_DIV_EXPR,
+ build1 (NOP_EXPR, vtable_index_type, e3),
+ TYPE_SIZE_UNIT (vtable_entry_type));
switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
{
case ptrmemfunc_vbit_in_pfn:
- idx = cp_build_binary_op (TRUNC_DIV_EXPR,
- build1 (NOP_EXPR, vtable_index_type, e3),
- TYPE_SIZE_UNIT (vtable_entry_type));
e1 = cp_build_binary_op (BIT_AND_EXPR,
build1 (NOP_EXPR, vtable_index_type, e3),
integer_one_node);
break;
case ptrmemfunc_vbit_in_delta:
- idx = build1 (NOP_EXPR, vtable_index_type, e3);
e1 = cp_build_binary_op (BIT_AND_EXPR,
delta, integer_one_node);
delta = cp_build_binary_op (RSHIFT_EXPR,
@@ -4076,8 +4022,14 @@ cp_pointer_int_sum (resultcode, ptrop, intop)
enum tree_code resultcode;
register tree ptrop, intop;
{
- if (!complete_type_or_else (TREE_TYPE (ptrop), ptrop))
- return error_mark_node;
+ tree res_type = TREE_TYPE (ptrop);
+
+ /* pointer_int_sum() uses size_in_bytes() on the TREE_TYPE(res_type)
+ in certain circumstance (when it's valid to do so). So we need
+ to make sure it's complete. We don't need to check here, if we
+ can actually complete it at all, as those checks will be done in
+ pointer_int_sum() anyway. */
+ complete_type (TREE_TYPE (res_type));
return pointer_int_sum (resultcode, ptrop, fold (intop));
}
@@ -4215,6 +4167,25 @@ build_x_unary_op (code, xarg)
}
if (code == ADDR_EXPR)
{
+ /* A pointer to member-function can be formed only by saying
+ &X::mf. */
+ if (!flag_ms_extensions && TREE_CODE (TREE_TYPE (xarg)) == METHOD_TYPE
+ && (TREE_CODE (xarg) != OFFSET_REF || !PTRMEM_OK_P (xarg)))
+ {
+ if (TREE_CODE (xarg) != OFFSET_REF)
+ {
+ error ("invalid use of '%E' to form a pointer-to-member-function. Use a qualified-id.",
+ xarg);
+ return error_mark_node;
+ }
+ else
+ {
+ error ("parenthesis around '%E' cannot be used to form a pointer-to-member-function",
+ xarg);
+ PTRMEM_OK_P (xarg) = 1;
+ }
+ }
+
if (TREE_CODE (xarg) == OFFSET_REF)
{
ptrmem = PTRMEM_OK_P (xarg);
@@ -4854,9 +4825,6 @@ mark_addressable (exp)
{
register tree x = exp;
- if (TREE_ADDRESSABLE (x) == 1)
- return 1;
-
while (1)
switch (TREE_CODE (x))
{
@@ -4875,6 +4843,8 @@ mark_addressable (exp)
TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */
return 1;
}
+ /* FALLTHRU */
+
case VAR_DECL:
/* Caller should not be trying to mark initialized
constant fields addressable. */
@@ -4882,6 +4852,7 @@ mark_addressable (exp)
|| DECL_IN_AGGR_P (x) == 0
|| TREE_STATIC (x)
|| DECL_EXTERNAL (x), 314);
+ /* FALLTHRU */
case CONST_DECL:
case RESULT_DECL:
@@ -4890,6 +4861,7 @@ mark_addressable (exp)
warning ("address requested for `%D', which is declared `register'",
x);
TREE_ADDRESSABLE (x) = 1;
+ put_var_into_stack (x);
return 1;
case FUNCTION_DECL:
@@ -5072,6 +5044,22 @@ build_static_cast (type, expr)
&& kind != bk_via_virtual)
ok = 1;
}
+ else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+ {
+ /* They're pointers to members. The pointed to objects must be
+ the same (ignoring CV qualifiers), and the containing classes
+ must be related non-virtually. */
+ base_kind kind;
+
+ if (same_type_p
+ (strip_all_pointer_quals (TREE_TYPE (TREE_TYPE (type))),
+ strip_all_pointer_quals (TREE_TYPE (TREE_TYPE (intype))))
+ && (lookup_base (TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)),
+ TYPE_OFFSET_BASETYPE (TREE_TYPE (type)),
+ ba_ignore | ba_quiet, &kind))
+ && kind != bk_via_virtual)
+ ok = 1;
+ }
else if (TREE_CODE (intype) != BOOLEAN_TYPE
&& TREE_CODE (type) != ARRAY_TYPE
&& TREE_CODE (type) != FUNCTION_TYPE
@@ -5481,7 +5469,10 @@ build_modify_expr (lhs, modifycode, rhs)
so the code to compute it is only emitted once. */
tree cond;
- rhs = save_expr (rhs);
+ if (lvalue_p (rhs))
+ rhs = stabilize_reference (rhs);
+ else
+ rhs = save_expr (rhs);
/* Check this here to avoid odd errors when trying to convert
a throw to the type of the COND_EXPR. */
@@ -5688,15 +5679,16 @@ build_modify_expr (lhs, modifycode, rhs)
{
int from_array;
- if (!same_or_base_type_p (lhstype, TREE_TYPE (rhs)))
+ if (!same_or_base_type_p (TYPE_MAIN_VARIANT (lhstype),
+ TYPE_MAIN_VARIANT (TREE_TYPE (rhs))))
{
error ("incompatible types in assignment of `%T' to `%T'",
- TREE_TYPE (rhs), lhstype);
+ TREE_TYPE (rhs), lhstype);
return error_mark_node;
}
/* Allow array assignment in compiler-generated code. */
- if (pedantic && ! DECL_ARTIFICIAL (current_function_decl))
+ if (! DECL_ARTIFICIAL (current_function_decl))
pedwarn ("ISO C++ forbids assignment of arrays");
from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
@@ -6203,8 +6195,16 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
/* Simplify the RHS if possible. */
if (TREE_CODE (rhs) == CONST_DECL)
rhs = DECL_INITIAL (rhs);
- else if (coder != ARRAY_TYPE)
- rhs = decl_constant_value (rhs);
+
+ /* We do not use decl_constant_value here because of this case:
+
+ const char* const s = "s";
+
+ The conversion rules for a string literal are more lax than for a
+ variable; in particular, a string literal can be converted to a
+ "char *" but the variable "s" cannot be converted in the same
+ way. If the conversion is allowed, the optimization should be
+ performed while creating the converted expression. */
/* [expr.ass]