This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix shorten_compare (PR c/48197)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: "Joseph S. Myers" <joseph at codesourcery dot com>, Jason Merrill <jason at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Sun, 20 Mar 2011 13:49:34 +0100
- Subject: [PATCH] Fix shorten_compare (PR c/48197)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
As this testcase shows, shorten_compare misbehaves if *restype_ptr
is wider than one of the operands and get_narrower returns something even
narrower than opN. If primopN is sign-extended to opN, but opN is unsigned,
unsignedpN is zero, but the mixed extension behaves differently from
sign-extension only.
This patch fixes it by ignoring what get_narrower did in that case.
For first zero-extending to opN and then sign-extending this isn't a
problem, as zero-extension means the sign-extension will fill bits with zero
anyway.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.6.1?
2011-03-20 Jakub Jelinek <jakub@redhat.com>
PR c/48197
* c-common.c (shorten_compare): If primopN is first sign-extended
to opN and then zero-extended to result type, set primopN to opN.
* gcc.c-torture/execute/pr48197.c: New test.
--- gcc/c-family/c-common.c.jj 2011-03-16 18:29:52.000000000 +0100
+++ gcc/c-family/c-common.c 2011-03-19 15:52:10.000000000 +0100
@@ -3303,6 +3303,20 @@ shorten_compare (tree *op0_ptr, tree *op
primop0 = get_narrower (op0, &unsignedp0);
primop1 = get_narrower (op1, &unsignedp1);
+ /* If primopN is first sign-extended from primopN's precision to opN's
+ precision, then zero-extended from opN's precision to
+ *restype_ptr precision, shortenings might be invalid. */
+ if (TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (TREE_TYPE (op0))
+ && TYPE_PRECISION (TREE_TYPE (op0)) < TYPE_PRECISION (*restype_ptr)
+ && !unsignedp0
+ && TYPE_UNSIGNED (TREE_TYPE (op0)))
+ primop0 = op0;
+ if (TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (TREE_TYPE (op1))
+ && TYPE_PRECISION (TREE_TYPE (op1)) < TYPE_PRECISION (*restype_ptr)
+ && !unsignedp1
+ && TYPE_UNSIGNED (TREE_TYPE (op1)))
+ primop1 = op1;
+
/* Handle the case that OP0 does not *contain* a conversion
but it *requires* conversion to FINAL_TYPE. */
--- gcc/testsuite/gcc.c-torture/execute/pr48197.c.jj 2011-03-19 14:11:53.000000000 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr48197.c 2011-03-19 14:11:05.000000000 +0100
@@ -0,0 +1,25 @@
+/* PR c/48197 */
+
+extern void abort (void);
+static int y = 0x8000;
+
+int
+main ()
+{
+ unsigned int x = (short)y;
+ if (sizeof (0LL) == sizeof (0U))
+ return 0;
+ if (0LL > (0U ^ (short)-0x8000))
+ abort ();
+ if (0LL > (0U ^ x))
+ abort ();
+ if (0LL > (0U ^ (short)y))
+ abort ();
+ if ((0U ^ (short)-0x8000) < 0LL)
+ abort ();
+ if ((0U ^ x) < 0LL)
+ abort ();
+ if ((0U ^ (short)y) < 0LL)
+ abort ();
+ return 0;
+}
Jakub