aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/expr.c21
2 files changed, 22 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3d6de0f..1f93ae7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2005-09-06 Olivier Hainque <hainque@adacore.com>
+ Eric Botcazou <ebotcazou@adacore.com>
+
+ PR middle-end/14997
+ * expr.c (expand_expr_real) <normal_inner_ref>: Force op0 to mem
+ when we would be extracting outside its bit span (bitpos+bitsize
+ larger than its mode), possible with some VIEW_CONVERT_EXPRs from
+ Ada unchecked conversions.
+
2005-09-06 Steven Bosscher <stevenb@suse.de>
* tree-ssa-pre.c (try_look_through_load): New function.
diff --git a/gcc/expr.c b/gcc/expr.c
index e5f5c3d..ff6adec 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -7178,25 +7178,30 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|| modifier == EXPAND_STACK_PARM)
? modifier : EXPAND_NORMAL);
- /* If this is a constant, put it into a register if it is a
- legitimate constant and OFFSET is 0 and memory if it isn't. */
+ /* If this is a constant, put it into a register if it is a legitimate
+ constant, OFFSET is 0, and we won't try to extract outside the
+ register (in case we were passed a partially uninitialized object
+ or a view_conversion to a larger size). Force the constant to
+ memory otherwise. */
if (CONSTANT_P (op0))
{
enum machine_mode mode = TYPE_MODE (TREE_TYPE (tem));
if (mode != BLKmode && LEGITIMATE_CONSTANT_P (op0)
- && offset == 0)
+ && offset == 0
+ && bitpos + bitsize <= GET_MODE_BITSIZE (mode))
op0 = force_reg (mode, op0);
else
op0 = validize_mem (force_const_mem (mode, op0));
}
- /* Otherwise, if this object not in memory and we either have an
- offset or a BLKmode result, put it there. This case can't occur in
- C, but can in Ada if we have unchecked conversion of an expression
- from a scalar type to an array or record type or for an
- ARRAY_RANGE_REF whose type is BLKmode. */
+ /* Otherwise, if this object not in memory and we either have an
+ offset, a BLKmode result, or a reference outside the object, put it
+ there. Such cases can occur in Ada if we have unchecked conversion
+ of an expression from a scalar type to an array or record type or
+ for an ARRAY_RANGE_REF whose type is BLKmode. */
else if (!MEM_P (op0)
&& (offset != 0
+ || (bitpos + bitsize > GET_MODE_BITSIZE (GET_MODE (op0)))
|| (code == ARRAY_RANGE_REF && mode == BLKmode)))
{
tree nt = build_qualified_type (TREE_TYPE (tem),