diff options
author | David Malcolm <dmalcolm@redhat.com> | 2025-01-02 15:10:15 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2025-01-02 15:10:15 -0500 |
commit | 321983033d621e3f75e11d380c4463956a3f6e1e (patch) | |
tree | f4ed1961d8858dbf05bad2e3cb4111f9a73e941a /gcc/c/c-parser.cc | |
parent | 99d5ef700619c28904846399a6f6692af4c56b1b (diff) | |
download | gcc-321983033d621e3f75e11d380c4463956a3f6e1e.zip gcc-321983033d621e3f75e11d380c4463956a3f6e1e.tar.gz gcc-321983033d621e3f75e11d380c4463956a3f6e1e.tar.bz2 |
c: special-case some "bool" errors with C23 (v2) [PR117629]
Changed in v2:
- distinguish between "bool" and "_Bool" when determining
standard version
This patch attempts to provide better error messages for
code compiled with C23 that hasn't been updated for
"bool", "true", and "false" becoming keywords.
Specifically:
(1) with "typedef int bool;" previously we emitted:
t1.c:7:13: error: two or more data types in declaration specifiers
7 | typedef int bool;
| ^~~~
t1.c:7:1: warning: useless type name in empty declaration
7 | typedef int bool;
| ^~~~~~~
whereas with this patch we emit:
t1.c:7:13: error: 'bool' cannot be defined via 'typedef'
7 | typedef int bool;
| ^~~~
t1.c:7:13: note: 'bool' is a keyword with '-std=c23' onwards
t1.c:7:1: warning: useless type name in empty declaration
7 | typedef int bool;
| ^~~~~~~
(2) with "int bool;" previously we emitted:
t2.c:7:5: error: two or more data types in declaration specifiers
7 | int bool;
| ^~~~
t2.c:7:1: warning: useless type name in empty declaration
7 | int bool;
| ^~~
whereas with this patch we emit:
t2.c:7:5: error: 'bool' cannot be used here
7 | int bool;
| ^~~~
t2.c:7:5: note: 'bool' is a keyword with '-std=c23' onwards
t2.c:7:1: warning: useless type name in empty declaration
7 | int bool;
| ^~~
(3) with "typedef enum { false = 0, true = 1 } _Bool;" previously we
emitted:
t3.c:7:16: error: expected identifier before 'false'
7 | typedef enum { false = 0, true = 1 } _Bool;
| ^~~~~
t3.c:7:38: error: expected ';', identifier or '(' before '_Bool'
7 | typedef enum { false = 0, true = 1 } _Bool;
| ^~~~~
t3.c:7:38: warning: useless type name in empty declaration
whereas with this patch we emit:
t3.c:7:16: error: cannot use keyword 'false' as enumeration constant
7 | typedef enum { false = 0, true = 1 } _Bool;
| ^~~~~
t3.c:7:16: note: 'false' is a keyword with '-std=c23' onwards
t3.c:7:38: error: expected ';', identifier or '(' before '_Bool'
7 | typedef enum { false = 0, true = 1 } _Bool;
| ^~~~~
t3.c:7:38: warning: useless type name in empty declaration
gcc/c/ChangeLog:
PR c/117629
* c-decl.cc (declspecs_add_type): Special-case attempts to use
bool as a typedef name or declaration name.
* c-errors.cc (get_std_for_keyword): New.
(add_note_about_new_keyword): New.
* c-parser.cc (report_bad_enum_name): New, split out from...
(c_parser_enum_specifier): ...here, adding handling for RID_FALSE
and RID_TRUE.
* c-tree.h (add_note_about_new_keyword): New decl.
gcc/testsuite/ChangeLog:
PR c/117629
* gcc.dg/auto-type-2.c: Update expected output with _Bool.
* gcc.dg/c23-bool-errors-1.c: New test.
* gcc.dg/c23-bool-errors-2.c: New test.
* gcc.dg/c23-bool-errors-3.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/c/c-parser.cc')
-rw-r--r-- | gcc/c/c-parser.cc | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index d289af6..f72b0f0 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -3785,6 +3785,47 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, specs->postfix_attrs = c_parser_std_attribute_specifier_sequence (parser); } +/* Complain about a non-CPP_NAME within an enumerator list. */ + +static void +report_bad_enum_name (c_parser *parser) +{ + if (!parser->error) + { + c_token *token = c_parser_peek_token (parser); + switch (token->type) + { + default: + break; + case CPP_CLOSE_BRACE: + /* Give a nicer error for "enum {}". */ + error_at (token->location, + "empty enum is invalid"); + parser->error = true; + return; + case CPP_KEYWORD: + /* Give a nicer error for attempts to use "true" and "false" + in enums with C23 onwards. */ + if (token->keyword == RID_FALSE + || token->keyword == RID_TRUE) + { + auto_diagnostic_group d; + error_at (token->location, + "cannot use keyword %qs as enumeration constant", + IDENTIFIER_POINTER (token->value)); + add_note_about_new_keyword (token->location, + token->value); + parser->error = true; + return; + } + break; + } + } + + /* Otherwise, a more generic error message. */ + c_parser_error (parser, "expected identifier"); +} + /* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2, C11 6.7.2.2). enum-specifier: @@ -3952,16 +3993,7 @@ c_parser_enum_specifier (c_parser *parser) location_t decl_loc, value_loc; if (c_parser_next_token_is_not (parser, CPP_NAME)) { - /* Give a nicer error for "enum {}". */ - if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE) - && !parser->error) - { - error_at (c_parser_peek_token (parser)->location, - "empty enum is invalid"); - parser->error = true; - } - else - c_parser_error (parser, "expected identifier"); + report_bad_enum_name (parser); c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); values = error_mark_node; break; |