https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772
--- Comment #5 from Roland Illig <roland.illig at gmx dot de> --- Sorry for the confusing description. Let me try again. NetBSD lint includes a yacc parser for C code. This parser contains the rules 'block_item_list' and 'block_item': https://github.com/NetBSD/src/blob/7ebcd1679b455e619909ec9c128e8ad7f103ded9/usr.bin/xlint/lint1/cgram.y#L1804 > block_item_list: /* C99 6.8.2 */ > block_item > | block_item_list block_item { > if ($1 && !$2) > /* declarations after statements is a C99 feature */ > c99ism(327); > $$ = $1 || $2; > } The rule 'block_item' remembers in 'y_seen_statement' whether the item was a statement, so that the parser rule 'block_item_list' can warn in C90 mode. In another part of the parser, the rule 'gcc_attribute' handles the keyword 'const', by accessing 'y_type_qualifiers.tq_const', which on 2023-07-15 was a _Bool bit-field member in 'struct type_qualifiers'. https://github.com/NetBSD/src/blob/7ebcd1679b455e619909ec9c128e8ad7f103ded9/usr.bin/xlint/lint1/cgram.y#L2197 > gcc_attribute: > | type_qualifier { > if (!$1.tq_const) > yyerror("Bad attribute"); > } On big-endian arm and powerpc, the code that GCC 10.5.0 generates for the 'block_item_list' parser rule depends on whether the 'gcc_attribute' parser rule accesses a bit-field member or not. This does not make sense to me, as I expect the parser rules to be independent. When I compile this parser on arm with -O2 and run lint in C90 mode, it not only warns about declarations after statements, but also about statements after statements. $ gcc -O2 -ftrapv -fPIE -std=gnu99 -S cgram.c -o cgram.casmv -fverbose-asm The code that is generated for the condition '$1 && !$2' is: > @ cgram.y:1802: if ($1 && !$2) > ldr r6, .L580+796 > add r6, pc, r6 > ldr r4, [r6, #20] > ldrb r3, [r4, #-8] @ $1.y_seen_statement > cmp r3, #0 > beq .L368 > @ cgram.y:550: $$ = build_unary($2 == INC ? INCAFT : DECAFT, $3, $1); > ldrb r3, [r4] > @ cgram.y:1802: > lsrs r3, r3, #7 @ $2.y_type_qualifiers.tq_const > beq .L562 (Annotations hand-edited by me.) Two strange things happen here: 1. The code from cgram.y:550 is completely unrelated, so it should not have been mentioned here. The 'ldrb' is correct, so maybe it's just the attribution that is wrong. 2. The expressions '$1' and '$2' both have type _Bool. Nevertheless, the second bool is accessed as if it were a bit-field. Due to this access, no matter whether '$2 as bool' is 1 or 0, the the expression '($2 as bit-field) >> 7' always evaluates to 0, so the condition '$1 && !$2' evaluates to true, which results in the additional warnings from lint. Instead of lsrs, GCC should have generated a cmp instruction. I don't have any other GCC version installed on the machine, so I cannot test whether GCC 11.4.0 behaves differently.