Hi!

The following testcase ICEs, because we have *pbitsize 65 and
lang_hooks.types.type_for_size returns NULL for that.  The following patch
punts in that case, but makes sure we punt before overwriting *exp_, because
the caller uses it regardless of whether decode_field_reference returns NULL
or not.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

David has proposed to also change c_common_type_for_size to handle the 65 to
127 bit bitsizes, but that looks too risky for me for GCC 9, although if you
think it can go in now, David has a patch for that.

2019-02-20  Jakub Jelinek  <ja...@redhat.com>
            David Malcolm  <dmalc...@redhat.com>

        PR middle-end/89091
        * fold-const.c (decode_field_reference): Return NULL_TREE if
        lang_hooks.types.type_for_size returns NULL.  Check it before
        overwriting *exp_.  Use return NULL_TREE instead of return 0.

        * gcc.dg/torture/pr89091.c: New test.

--- gcc/fold-const.c.jj 2019-02-14 10:24:16.300632811 +0100
+++ gcc/fold-const.c    2019-02-20 15:52:35.476932131 +0100
@@ -4280,7 +4280,7 @@ decode_field_reference (location_t loc,
      There are problems with FP fields since the type_for_size call
      below can fail for, e.g., XFmode.  */
   if (! INTEGRAL_TYPE_P (TREE_TYPE (exp)))
-    return 0;
+    return NULL_TREE;
 
   /* We are interested in the bare arrangement of bits, so strip everything
      that doesn't affect the machine mode.  However, record the type of the
@@ -4296,7 +4296,7 @@ decode_field_reference (location_t loc,
       exp = TREE_OPERAND (exp, 0);
       STRIP_NOPS (exp); STRIP_NOPS (and_mask);
       if (TREE_CODE (and_mask) != INTEGER_CST)
-       return 0;
+       return NULL_TREE;
     }
 
   poly_int64 poly_bitsize, poly_bitpos;
@@ -4312,7 +4312,11 @@ decode_field_reference (location_t loc,
       || (! AGGREGATE_TYPE_P (TREE_TYPE (inner))
          && compare_tree_int (TYPE_SIZE (TREE_TYPE (inner)),
                               *pbitpos + *pbitsize) < 0))
-    return 0;
+    return NULL_TREE;
+
+  unsigned_type = lang_hooks.types.type_for_size (*pbitsize, 1);
+  if (unsigned_type == NULL_TREE)
+    return NULL_TREE;
 
   *exp_ = exp;
 
@@ -4323,7 +4327,6 @@ decode_field_reference (location_t loc,
     *punsignedp = TYPE_UNSIGNED (outer_type);
 
   /* Compute the mask to access the bitfield.  */
-  unsigned_type = lang_hooks.types.type_for_size (*pbitsize, 1);
   precision = TYPE_PRECISION (unsigned_type);
 
   mask = build_int_cst_type (unsigned_type, -1);
--- gcc/testsuite/gcc.dg/torture/pr89091.c.jj   2019-02-20 15:55:54.604694453 
+0100
+++ gcc/testsuite/gcc.dg/torture/pr89091.c      2019-02-20 15:55:18.186294196 
+0100
@@ -0,0 +1,10 @@
+/* PR middle-end/89091 */
+/* { dg-do compile { target int128 } } */
+
+struct S { unsigned __int128 s : 65; };
+
+int
+foo (struct S *x, int y)
+{
+  return y && x->s;
+}

        Jakub

Reply via email to