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