aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/c-parser.cc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2025-01-02 15:10:15 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2025-01-02 15:10:15 -0500
commit321983033d621e3f75e11d380c4463956a3f6e1e (patch)
treef4ed1961d8858dbf05bad2e3cb4111f9a73e941a /gcc/c/c-parser.cc
parent99d5ef700619c28904846399a6f6692af4c56b1b (diff)
downloadgcc-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.cc52
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;