https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128596
Bug ID: 128596
Summary: c_parser_attribute_arguments requires id_kind ==
C_ID_ID for identifier attribute arguments, rejecting
__attribute__((access(read_only, ...))) when a typedef
of the same name is visible in C
Product: gcc
Version: 16.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: 220245569 at seu dot edu.cn
CC: 220255623 at seu dot edu.cn, jianhao.xu at seu dot edu.cn
Target Milestone: ---
Target: *-*-*
Reproducer
----------
$ cat trigger.c
typedef int read_only;
__attribute__((access(read_only, 1)))
int read_first(const int *p) {
return *p;
}
Compile command / flags:
podman exec defuzz-toolchain-daemon /opt/gcc16/bin/x86_64-linux-gnu-gcc -O2 -S
-o /dev/null /tmp/t39.c
Observed output (GCC 16.2.0):
/tmp/t39.c:3:23: error: expected expression before 'read_only'
3 | __attribute__((access(read_only, 1)))
| ^~~~~~~~~
Expected behavior:
Attribute mode identifiers (which live in the attribute's own argument grammar,
not the ordinary identifier/type namespace) should be accepted when token->type
== CPP_NAME regardless of whether token->id_kind is C_ID_ID or C_ID_TYPENAME
(matching C++ and c_parser_gnu_attribute's attribute-name handling).
Root cause
----------
Source location: gcc/c/c-parser.cc:5694-5708 (c_parser_attribute_arguments)
In c_parser_attribute_arguments (gcc/c/c-parser.cc:5694-5708), when
takes_identifier is true for an attribute (such as 'access', 'mode', 'section',
etc.) and the first argument token is a CPP_NAME, line 5696 checks 'if
(c_parser_next_token_is (parser, CPP_NAME) && c_parser_peek_token
(parser)->id_kind == C_ID_ID)'. If the user or a header has declared 'typedef
int read_only;' in an enclosing scope, the lexer classifies the token
'read_only' as C_ID_TYPENAME rather than C_ID_ID! As a result,
c_parser_attribute_arguments refuses to parse the identifier, falls through to
c_parser_expr_list (which rejects a type name as an expression), and aborts
compilation with 'error: expected expression before read_only' (whereas C++
accepts it without issue).
Impact:
Valid hardening annotations such as __attribute__((access(read_only, ...)))
fail to compile in C translation units whenever a typedef with the same
spelling is visible.
Suggested Fix
-------------
In gcc/c/c-parser.cc:5696 (c_parser_attribute_arguments), accept C_ID_TYPENAME
(and C_ID_CLASSNAME) in addition to C_ID_ID when takes_identifier is true and
the token is CPP_NAME.