https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127765

            Bug ID: 127765
           Summary: `__builtin_stdc_rotate_left/right` with constant
                    operands is not a constant expression for `unsigned
                    _BitInt(N)` without a machine mode
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: bic60176 at gmail dot com
  Target Milestone: ---

With constant arguments, `__builtin_stdc_rotate_left` and
`__builtin_stdc_rotate_right` do not fold to a constant when
the first argument is an `unsigned _BitInt(N)` whose precision has no machine
mode and is not above
`MAX_FIXED_MODE_SIZE` (for example N = 2, 7, 9, 33, 100, 127 on x86_64). GCC
then rejects them in every
constant-expression context:

```c
typedef unsigned _BitInt(2) T;
static T v = __builtin_stdc_rotate_left ((T) 1, 1);   /* error: initializer
element is not constant */

_Static_assert (__builtin_stdc_rotate_left ((unsigned _BitInt(7)) 1, 1) == 2,
"");
                                           /* error: expression in static
assertion is not constant */
```

The same call is accepted for `unsigned int`, for `unsigned
_BitInt(8/16/32/64/128)` and for `unsigned _BitInt(129)`,
and the expression the manual gives as equivalent is accepted as a static
initializer for `unsigned _BitInt(2)`. The
other `__builtin_stdc_*` builtins fold for these types. The computed values are
correct at run time.

The shift-based expansion in `c_parser_postfix_expression` (gcc/c/c-parser.cc,
around line 13375) always wraps the
`COND_EXPR` condition in `COMPOUND_EXPR (arg1, arg2 != 0)`, and a comma
expression is never a constant expression,
so `c_fully_fold` cannot reduce it. Building the `COMPOUND_EXPR` only when
`TREE_SIDE_EFFECTS (arg1)` would keep the
sequencing where it is needed.

Reply via email to