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.