Module Name: src Committed By: rillig Date: Thu Jul 13 20:30:22 UTC 2023
Modified Files: src/tests/usr.bin/xlint/lint1: c11.c c23.c src/usr.bin/xlint/lint1: decl.c lex.c Log Message: lint: in C23 mode, recognize the keyword 'thread_local' To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/tests/usr.bin/xlint/lint1/c11.c cvs rdiff -u -r1.1 -r1.2 src/tests/usr.bin/xlint/lint1/c23.c cvs rdiff -u -r1.352 -r1.353 src/usr.bin/xlint/lint1/decl.c cvs rdiff -u -r1.183 -r1.184 src/usr.bin/xlint/lint1/lex.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/usr.bin/xlint/lint1/c11.c diff -u src/tests/usr.bin/xlint/lint1/c11.c:1.2 src/tests/usr.bin/xlint/lint1/c11.c:1.3 --- src/tests/usr.bin/xlint/lint1/c11.c:1.2 Wed Jul 12 18:26:04 2023 +++ src/tests/usr.bin/xlint/lint1/c11.c Thu Jul 13 20:30:21 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: c11.c,v 1.2 2023/07/12 18:26:04 rillig Exp $ */ +/* $NetBSD: c11.c,v 1.3 2023/07/13 20:30:21 rillig Exp $ */ # 3 "c11.c" /* @@ -42,6 +42,12 @@ three_times(void) exit(0); } +// In C11 mode, 'thread_local' is not yet known, but '_Thread_local' is. +/* expect+2: error: old-style declaration; add 'int' [1] */ +/* expect+1: error: syntax error 'int' [249] */ +thread_local int thread_local_variable_c23; +_Thread_local int thread_local_variable_c11; + /* The '_Noreturn' must not appear after the declarator. */ void _Noreturn exit(int) _Noreturn; /* expect-1: error: formal parameter #1 lacks name [59] */ Index: src/tests/usr.bin/xlint/lint1/c23.c diff -u src/tests/usr.bin/xlint/lint1/c23.c:1.1 src/tests/usr.bin/xlint/lint1/c23.c:1.2 --- src/tests/usr.bin/xlint/lint1/c23.c:1.1 Sun Jul 2 23:45:10 2023 +++ src/tests/usr.bin/xlint/lint1/c23.c Thu Jul 13 20:30:21 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: c23.c,v 1.1 2023/07/02 23:45:10 rillig Exp $ */ +/* $NetBSD: c23.c,v 1.2 2023/07/13 20:30:21 rillig Exp $ */ # 3 "c23.c" // Tests for the option -Ac23, which allows features from C23 and all earlier @@ -16,7 +16,27 @@ c23(void) int member; } s; + // Empty initializer braces were introduced in C23. s = (struct s){}; s = (struct s){s.member}; return s.member; } + +// The keyword 'thread_local' was introduced in C23. +thread_local int globally_visible; + +// Thread-local functions don't make sense; they are syntactically allowed, +// though. +thread_local void +thread_local_function(void) +{ +} + +void +function(void) +{ + // Not sure whether it makes sense to have a function-scoped + // thread-local variable. Don't warn for now, let the compilers handle + // this case. + thread_local int function_scoped_thread_local; +} Index: src/usr.bin/xlint/lint1/decl.c diff -u src/usr.bin/xlint/lint1/decl.c:1.352 src/usr.bin/xlint/lint1/decl.c:1.353 --- src/usr.bin/xlint/lint1/decl.c:1.352 Thu Jul 13 19:59:08 2023 +++ src/usr.bin/xlint/lint1/decl.c Thu Jul 13 20:30:21 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: decl.c,v 1.352 2023/07/13 19:59:08 rillig Exp $ */ +/* $NetBSD: decl.c,v 1.353 2023/07/13 20:30:21 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -38,7 +38,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: decl.c,v 1.352 2023/07/13 19:59:08 rillig Exp $"); +__RCSID("$NetBSD: decl.c,v 1.353 2023/07/13 20:30:21 rillig Exp $"); #endif #include <sys/param.h> @@ -1514,7 +1514,8 @@ declarator_name(sym_t *sym) */ sc = AUTO; sym->s_def = DEF; - } else if (sc == AUTO || sc == STATIC || sc == TYPEDEF) + } else if (sc == AUTO || sc == STATIC || sc == TYPEDEF + || sc == THREAD_LOCAL) sym->s_def = DEF; else if (sc == REG) { sym->s_register = true; Index: src/usr.bin/xlint/lint1/lex.c diff -u src/usr.bin/xlint/lint1/lex.c:1.183 src/usr.bin/xlint/lint1/lex.c:1.184 --- src/usr.bin/xlint/lint1/lex.c:1.183 Thu Jul 13 19:59:08 2023 +++ src/usr.bin/xlint/lint1/lex.c Thu Jul 13 20:30:21 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: lex.c,v 1.183 2023/07/13 19:59:08 rillig Exp $ */ +/* $NetBSD: lex.c,v 1.184 2023/07/13 20:30:21 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -38,7 +38,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: lex.c,v 1.183 2023/07/13 19:59:08 rillig Exp $"); +__RCSID("$NetBSD: lex.c,v 1.184 2023/07/13 20:30:21 rillig Exp $"); #endif #include <ctype.h> @@ -68,18 +68,22 @@ bool in_gcc_attribute; bool in_system_header; /* - * Valid values for 'since' are 78, 90, 99, 11. + * Valid values for 'since' are 78, 90, 99, 11, 23. * - * The C11 keywords are added in C99 mode as well, to provide good error - * messages instead of a simple parse error. If the keyword '_Generic' were - * not defined, it would be interpreted as an implicit function call, leading - * to a parse error. + * The C11 keywords are all taken from the reserved namespace. They are added + * in C99 mode as well, to make the parse error messages more useful. For + * example, if the keyword '_Generic' were not defined, it would be interpreted + * as an implicit function call, leading to a parse error. + * + * The C23 keywords are not made available in earlier modes, as they may + * conflict with user-defined identifiers. */ #define kwdef(name, token, detail, since, gcc, deco) \ - { \ + { /* CONSTCOND */ \ name, token, detail, \ (since) == 90, \ - /* CONSTCOND */ (since) == 99 || (since) == 11, \ + (since) == 99 || (since) == 11, \ + (since) == 23, \ (gcc) > 0, \ ((deco) & 1) != 0, ((deco) & 2) != 0, ((deco) & 4) != 0, \ } @@ -107,8 +111,9 @@ static const struct keyword { function_specifier kw_fs; /* if kw_token is * T_FUNCTION_SPECIFIER */ } u; - bool kw_c90:1; /* available in C90 mode */ - bool kw_c99_or_c11:1; /* available in C99 or C11 mode */ + bool kw_added_in_c90:1; + bool kw_added_in_c99_or_c11:1; + bool kw_added_in_c23:1; bool kw_gcc:1; /* available in GCC mode */ bool kw_plain:1; /* 'name' */ bool kw_leading:1; /* '__name' */ @@ -164,6 +169,7 @@ static const struct keyword { kwdef_token( "__symbolrename", T_SYMBOLRENAME, 78,0,1), kwdef_sclass( "__thread", THREAD_LOCAL, 78,1,1), kwdef_sclass( "_Thread_local", THREAD_LOCAL, 11,0,1), + kwdef_sclass( "thread_local", THREAD_LOCAL, 23,0,1), kwdef_sclass( "typedef", TYPEDEF, 78,0,1), kwdef_token( "typeof", T_TYPEOF, 78,1,7), #ifdef INT128_SIZE @@ -364,7 +370,9 @@ static bool is_keyword_known(const struct keyword *kw) { - if ((kw->kw_c90 || kw->kw_c99_or_c11) && !allow_c90) + if (kw->kw_added_in_c23 && !allow_c23) + return false; + if ((kw->kw_added_in_c90 || kw->kw_added_in_c99_or_c11) && !allow_c90) return false; /* @@ -378,7 +386,7 @@ is_keyword_known(const struct keyword *k if (kw->kw_gcc) return false; - if (kw->kw_c99_or_c11 && !allow_c99) + if (kw->kw_added_in_c99_or_c11 && !allow_c99) return false; return true; }