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;
 }

Reply via email to