OSDN Git Service

PR middle-end/19689
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 30 Jan 2005 02:33:27 +0000 (02:33 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 30 Jan 2005 02:33:27 +0000 (02:33 +0000)
        * expr.c (store_field): Don't strip sub-mode cast when the input
        data is even smaller.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@94429 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/expr.c
gcc/testsuite/gcc.c-torture/execute/pr19689.c [new file with mode: 0644]

index f3bcde3..c56c728 100644 (file)
@@ -1,5 +1,11 @@
 2005-01-29  Richard Henderson  <rth@redhat.com>
 
+       PR middle-end/19689
+       * expr.c (store_field): Don't strip sub-mode cast when the input
+       data is even smaller.
+
+2005-01-29  Richard Henderson  <rth@redhat.com>
+
        PR middle-end/19687
        * expr.c (categorize_ctor_elements_1): Check for CONSTRUCTOR of a
        union being empty.
index 29acbba..ab7cf93 100644 (file)
@@ -5226,12 +5226,18 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
         the field we're storing into, that mask is redundant.  This is
         particularly common with bit field assignments generated by the
         C front end.  */
-      if (TREE_CODE (exp) == NOP_EXPR
-         && INTEGRAL_TYPE_P (TREE_TYPE (exp))
-         && (TYPE_PRECISION (TREE_TYPE (exp))
-             < GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (exp))))
-         && bitsize == TYPE_PRECISION (TREE_TYPE (exp)))
-       exp = TREE_OPERAND (exp, 0);
+      if (TREE_CODE (exp) == NOP_EXPR)
+       {
+         tree type = TREE_TYPE (exp);
+         if (INTEGRAL_TYPE_P (type)
+             && TYPE_PRECISION (type) < GET_MODE_BITSIZE (TYPE_MODE (type))
+             && bitsize == TYPE_PRECISION (type))
+           {
+             type = TREE_TYPE (TREE_OPERAND (exp, 0));
+             if (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) >= bitsize)
+               exp = TREE_OPERAND (exp, 0);
+           }
+       }
 
       temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
 
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr19689.c b/gcc/testsuite/gcc.c-torture/execute/pr19689.c
new file mode 100644 (file)
index 0000000..608415f
--- /dev/null
@@ -0,0 +1,19 @@
+extern void abort (void);
+
+struct
+{
+  int b : 29;
+} f;
+
+void foo (short j)
+{
+  f.b = j;
+}
+
+int main()
+{
+  foo (-55);
+  if (f.b != -55)
+    abort ();
+  return 0;
+}