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.

Reply via email to