Thu May 9 11:08:07 2024 UTC (24d)
lint: in C23 mode, support the nullptr constant


(rillig)
diff -r1.10 -r1.11 src/tests/usr.bin/xlint/lint1/c23.c
diff -r1.495 -r1.496 src/usr.bin/xlint/lint1/cgram.y
diff -r1.77 -r1.78 src/usr.bin/xlint/lint1/debug.c
diff -r1.224 -r1.225 src/usr.bin/xlint/lint1/externs1.h
diff -r1.224 -r1.225 src/usr.bin/xlint/lint1/lex.c
diff -r1.225 -r1.226 src/usr.bin/xlint/lint1/lint1.h

cvs diff -r1.10 -r1.11 src/tests/usr.bin/xlint/lint1/c23.c (expand / switch to unified diff)

--- src/tests/usr.bin/xlint/lint1/c23.c 2024/05/07 21:13:27 1.10
+++ src/tests/usr.bin/xlint/lint1/c23.c 2024/05/09 11:08:07 1.11
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: c23.c,v 1.10 2024/05/07 21:13:27 rillig Exp $ */ 1/* $NetBSD: c23.c,v 1.11 2024/05/09 11:08:07 rillig Exp $ */
2# 3 "c23.c" 2# 3 "c23.c"
3 3
4// Tests for the option -Ac23, which allows features from C23 and all earlier 4// Tests for the option -Ac23, which allows features from C23 and all earlier
5// ISO standards, but none of the GNU extensions. 5// ISO standards, but none of the GNU extensions.
6// 6//
7// See also: 7// See also:
8// c11.c 8// c11.c
9// msg_353.c for empty initializer braces 9// msg_353.c for empty initializer braces
10 10
11/* lint1-flags: -Ac23 -w -X 351 */ 11/* lint1-flags: -Ac23 -w -X 351 */
12 12
13 13
14int 14int
@@ -18,26 +18,40 @@ bool_is_predefined_in_c23(void) @@ -18,26 +18,40 @@ bool_is_predefined_in_c23(void)
18 bool f = false; 18 bool f = false;
19 return (t == true ? 20 : 0) + (f == false ? 3 : 0); 19 return (t == true ? 20 : 0) + (f == false ? 3 : 0);
20} 20}
21 21
22int 22int
23c99_bool_is_still_valid_in_c23(void) 23c99_bool_is_still_valid_in_c23(void)
24{ 24{
25 _Bool t = 1; 25 _Bool t = 1;
26 _Bool f = 0; 26 _Bool f = 0;
27 return (t == 1 ? 20 : 0) + (f == 0 ? 3 : 0); 27 return (t == 1 ? 20 : 0) + (f == 0 ? 3 : 0);
28} 28}
29 29
30 30
 31bool
 32null_pointer_constant(const char *p, double dbl)
 33{
 34 /* expect+1: error: operands of '!=' have incompatible types 'double' and 'pointer to void' [107] */
 35 if (dbl != nullptr)
 36 p++;
 37 if (dbl > 0.0)
 38 p++;
 39 if (*p == '\0')
 40 p = nullptr;
 41 return p == nullptr;
 42}
 43
 44
31int 45int
32empty_initializer_braces(void) 46empty_initializer_braces(void)
33{ 47{
34 struct s { 48 struct s {
35 int member; 49 int member;
36 } s; 50 } s;
37 51
38 // Empty initializer braces were introduced in C23. 52 // Empty initializer braces were introduced in C23.
39 s = (struct s){}; 53 s = (struct s){};
40 s = (struct s){s.member}; 54 s = (struct s){s.member};
41 return s.member; 55 return s.member;
42} 56}
43 57

cvs diff -r1.495 -r1.496 src/usr.bin/xlint/lint1/cgram.y (expand / switch to unified diff)

--- src/usr.bin/xlint/lint1/cgram.y 2024/05/03 04:04:17 1.495
+++ src/usr.bin/xlint/lint1/cgram.y 2024/05/09 11:08:07 1.496
@@ -1,15 +1,15 @@ @@ -1,15 +1,15 @@
1%{ 1%{
2/* $NetBSD: cgram.y,v 1.495 2024/05/03 04:04:17 rillig Exp $ */ 2/* $NetBSD: cgram.y,v 1.496 2024/05/09 11:08:07 rillig Exp $ */
3 3
4/* 4/*
5 * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. 5 * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved.
6 * Copyright (c) 1994, 1995 Jochen Pohl 6 * Copyright (c) 1994, 1995 Jochen Pohl
7 * All Rights Reserved. 7 * All Rights Reserved.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
@@ -25,27 +25,27 @@ @@ -25,27 +25,27 @@
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */ 34 */
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37#if defined(__RCSID) 37#if defined(__RCSID)
38__RCSID("$NetBSD: cgram.y,v 1.495 2024/05/03 04:04:17 rillig Exp $"); 38__RCSID("$NetBSD: cgram.y,v 1.496 2024/05/09 11:08:07 rillig Exp $");
39#endif 39#endif
40 40
41#include <limits.h> 41#include <limits.h>
42#include <stdlib.h> 42#include <stdlib.h>
43#include <string.h> 43#include <string.h>
44 44
45#include "lint1.h" 45#include "lint1.h"
46 46
47extern char *yytext; 47extern char *yytext;
48 48
49/* 49/*
50 * Contains the level of current declaration, used for symbol table entries. 50 * Contains the level of current declaration, used for symbol table entries.
51 * 0 is the top-level, > 0 is inside a function body. 51 * 0 is the top-level, > 0 is inside a function body.
@@ -130,26 +130,27 @@ is_either(const char *s, const char *a,  @@ -130,26 +130,27 @@ is_either(const char *s, const char *a,
130 function_specifier y_function_specifier; 130 function_specifier y_function_specifier;
131 parameter_list y_parameter_list; 131 parameter_list y_parameter_list;
132 function_call *y_arguments; 132 function_call *y_arguments;
133 type_t *y_type; 133 type_t *y_type;
134 tnode_t *y_tnode; 134 tnode_t *y_tnode;
135 range_t y_range; 135 range_t y_range;
136 buffer *y_string; 136 buffer *y_string;
137 qual_ptr *y_qual_ptr; 137 qual_ptr *y_qual_ptr;
138 bool y_seen_statement; 138 bool y_seen_statement;
139 struct generic_association *y_generic; 139 struct generic_association *y_generic;
140 array_size y_array_size; 140 array_size y_array_size;
141 bool y_in_system_header; 141 bool y_in_system_header;
142 designation y_designation; 142 designation y_designation;
 143 named_constant y_named_constant;
143}; 144};
144 145
145/* for Bison: 146/* for Bison:
146%printer { 147%printer {
147 if (is_integer($$->v_tspec)) 148 if (is_integer($$->v_tspec))
148 fprintf(yyo, "%lld", (long long)$$->u.integer); 149 fprintf(yyo, "%lld", (long long)$$->u.integer);
149 else 150 else
150 fprintf(yyo, "%Lg", $$->u.floating); 151 fprintf(yyo, "%Lg", $$->u.floating);
151} <y_val> 152} <y_val>
152%printer { fprintf(yyo, "'%s'", $$ != NULL ? $$->sb_name : "<null>"); } <y_name> 153%printer { fprintf(yyo, "'%s'", $$ != NULL ? $$->sb_name : "<null>"); } <y_name>
153%printer { 154%printer {
154 bool indented = debug_push_indented(true); 155 bool indented = debug_push_indented(true);
155 debug_sym("", $$, ""); 156 debug_sym("", $$, "");
@@ -189,26 +190,27 @@ is_either(const char *s, const char *a,  @@ -189,26 +190,27 @@ is_either(const char *s, const char *a,
189%printer { 190%printer {
190 if ($$.dn_len == 0) 191 if ($$.dn_len == 0)
191 fprintf(yyo, "(empty)"); 192 fprintf(yyo, "(empty)");
192 for (size_t i = 0; i < $$.dn_len; i++) { 193 for (size_t i = 0; i < $$.dn_len; i++) {
193 const designator *dr = $$.dn_items + i; 194 const designator *dr = $$.dn_items + i;
194 if (dr->dr_kind == DK_MEMBER) 195 if (dr->dr_kind == DK_MEMBER)
195 fprintf(yyo, ".%s", dr->dr_member->s_name); 196 fprintf(yyo, ".%s", dr->dr_member->s_name);
196 else if (dr->dr_kind == DK_SUBSCRIPT) 197 else if (dr->dr_kind == DK_SUBSCRIPT)
197 fprintf(yyo, "[%zu]", dr->dr_subscript); 198 fprintf(yyo, "[%zu]", dr->dr_subscript);
198 else 199 else
199 fprintf(yyo, "<scalar>"); 200 fprintf(yyo, "<scalar>");
200 } 201 }
201} <y_designation> 202} <y_designation>
 203%printer { fprintf(yyo, "%s", named_constant_name($$)); } <y_named_constant>
202*/ 204*/
203 205
204%token T_LBRACE T_RBRACE T_LBRACK T_RBRACK T_LPAREN T_RPAREN 206%token T_LBRACE T_RBRACE T_LBRACK T_RBRACK T_LPAREN T_RPAREN
205%token T_POINT T_ARROW 207%token T_POINT T_ARROW
206%token T_COMPLEMENT T_LOGNOT 208%token T_COMPLEMENT T_LOGNOT
207%token <y_inc> T_INCDEC 209%token <y_inc> T_INCDEC
208%token T_SIZEOF 210%token T_SIZEOF
209%token T_BUILTIN_OFFSETOF 211%token T_BUILTIN_OFFSETOF
210%token T_TYPEOF 212%token T_TYPEOF
211%token T_EXTENSION 213%token T_EXTENSION
212%token T_ALIGNAS 214%token T_ALIGNAS
213%token T_ALIGNOF 215%token T_ALIGNOF
214%token T_ASTERISK 216%token T_ASTERISK
@@ -277,26 +279,27 @@ is_either(const char *s, const char *a,  @@ -277,26 +279,27 @@ is_either(const char *s, const char *a,
277%left T_LOGAND 279%left T_LOGAND
278%left T_BITOR 280%left T_BITOR
279%left T_BITXOR 281%left T_BITXOR
280%left T_AMPER 282%left T_AMPER
281%left T_EQUALITY 283%left T_EQUALITY
282%left T_RELATIONAL 284%left T_RELATIONAL
283%left T_SHIFT 285%left T_SHIFT
284%left T_ADDITIVE 286%left T_ADDITIVE
285%left T_ASTERISK T_MULTIPLICATIVE 287%left T_ASTERISK T_MULTIPLICATIVE
286 288
287%token <y_name> T_NAME 289%token <y_name> T_NAME
288%token <y_name> T_TYPENAME 290%token <y_name> T_TYPENAME
289%token <y_val> T_CON 291%token <y_val> T_CON
 292%token <y_named_constant> T_NAMED_CONSTANT
290%token <y_string> T_STRING 293%token <y_string> T_STRING
291 294
292/* No type for program. */ 295/* No type for program. */
293%type <y_sym> identifier_sym 296%type <y_sym> identifier_sym
294%type <y_name> identifier 297%type <y_name> identifier
295%type <y_string> string 298%type <y_string> string
296%type <y_tnode> primary_expression 299%type <y_tnode> primary_expression
297%type <y_designation> member_designator 300%type <y_designation> member_designator
298%type <y_tnode> generic_selection 301%type <y_tnode> generic_selection
299%type <y_generic> generic_assoc_list 302%type <y_generic> generic_assoc_list
300%type <y_generic> generic_association 303%type <y_generic> generic_association
301%type <y_tnode> postfix_expression 304%type <y_tnode> postfix_expression
302%type <y_tnode> gcc_statement_expr_list 305%type <y_tnode> gcc_statement_expr_list
@@ -474,26 +477,45 @@ primary_expression: @@ -474,26 +477,45 @@ primary_expression:
474 T_NAME { 477 T_NAME {
475 bool sys_name, sys_next; 478 bool sys_name, sys_next;
476 sys_name = in_system_header; 479 sys_name = in_system_header;
477 if (yychar < 0) 480 if (yychar < 0)
478 yychar = yylex(); 481 yychar = yylex();
479 sys_next = in_system_header; 482 sys_next = in_system_header;
480 in_system_header = sys_name; 483 in_system_header = sys_name;
481 $$ = build_name(getsym($1), yychar == T_LPAREN); 484 $$ = build_name(getsym($1), yychar == T_LPAREN);
482 in_system_header = sys_next; 485 in_system_header = sys_next;
483 } 486 }
484| T_CON { 487| T_CON {
485 $$ = build_constant(gettyp($1->v_tspec), $1); 488 $$ = build_constant(gettyp($1->v_tspec), $1);
486 } 489 }
 490| T_NAMED_CONSTANT {
 491 if ($1 == NC_NULLPTR) {
 492 tnode_t *zero = expr_alloc_tnode();
 493 zero->tn_op = CON;
 494 zero->tn_type = gettyp(INT);
 495 zero->u.value.v_tspec = INT;
 496
 497 type_t *void_ptr = block_derive_type(gettyp(VOID), PTR);
 498 $$ = convert(CVT, 0, void_ptr, zero);
 499 $$->tn_sys = zero->tn_sys;
 500 } else {
 501 tnode_t *nc = expr_alloc_tnode();
 502 nc->tn_op = CON;
 503 nc->tn_type = gettyp(BOOL);
 504 nc->u.value.v_tspec = BOOL;
 505 nc->u.value.u.integer = $1 == NC_TRUE ? 1 : 0;
 506 $$ = nc;
 507 }
 508 }
487| string { 509| string {
488 $$ = build_string($1); 510 $$ = build_string($1);
489 } 511 }
490| T_LPAREN expression T_RPAREN { 512| T_LPAREN expression T_RPAREN {
491 if ($2 != NULL) 513 if ($2 != NULL)
492 $2->tn_parenthesized = true; 514 $2->tn_parenthesized = true;
493 $$ = $2; 515 $$ = $2;
494 } 516 }
495| generic_selection 517| generic_selection
496 /* GCC primary-expression, see c_parser_postfix_expression */ 518 /* GCC primary-expression, see c_parser_postfix_expression */
497| T_BUILTIN_OFFSETOF T_LPAREN type_name T_COMMA { 519| T_BUILTIN_OFFSETOF T_LPAREN type_name T_COMMA {
498 set_sym_kind(SK_MEMBER); 520 set_sym_kind(SK_MEMBER);
499 } member_designator T_RPAREN { 521 } member_designator T_RPAREN {

cvs diff -r1.77 -r1.78 src/usr.bin/xlint/lint1/debug.c (expand / switch to unified diff)

--- src/usr.bin/xlint/lint1/debug.c 2024/05/03 04:04:17 1.77
+++ src/usr.bin/xlint/lint1/debug.c 2024/05/09 11:08:07 1.78
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: debug.c,v 1.77 2024/05/03 04:04:17 rillig Exp $ */ 1/* $NetBSD: debug.c,v 1.78 2024/05/09 11:08:07 rillig Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2021 The NetBSD Foundation, Inc. 4 * Copyright (c) 2021 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Roland Illig <rillig@NetBSD.org>. 8 * by Roland Illig <rillig@NetBSD.org>.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -25,27 +25,27 @@ @@ -25,27 +25,27 @@
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#if HAVE_NBTOOL_CONFIG_H 32#if HAVE_NBTOOL_CONFIG_H
33#include "nbtool_config.h" 33#include "nbtool_config.h"
34#endif 34#endif
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37#if defined(__RCSID) 37#if defined(__RCSID)
38__RCSID("$NetBSD: debug.c,v 1.77 2024/05/03 04:04:17 rillig Exp $"); 38__RCSID("$NetBSD: debug.c,v 1.78 2024/05/09 11:08:07 rillig Exp $");
39#endif 39#endif
40 40
41#include <stdlib.h> 41#include <stdlib.h>
42#include <string.h> 42#include <string.h>
43 43
44#include "lint1.h" 44#include "lint1.h"
45#include "cgram.h" 45#include "cgram.h"
46 46
47 47
48#ifdef DEBUG 48#ifdef DEBUG
49 49
50static int debug_indentation = 0; 50static int debug_indentation = 0;
51static bool did_indentation; 51static bool did_indentation;
@@ -351,26 +351,38 @@ type_qualifiers_string(type_qualifiers t @@ -351,26 +351,38 @@ type_qualifiers_string(type_qualifiers t
351} 351}
352 352
353const char * 353const char *
354function_specifier_name(function_specifier spec) 354function_specifier_name(function_specifier spec)
355{ 355{
356 static const char *const name[] = { 356 static const char *const name[] = {
357 "inline", 357 "inline",
358 "_Noreturn", 358 "_Noreturn",
359 }; 359 };
360 360
361 return name[spec]; 361 return name[spec];
362} 362}
363 363
 364const char *
 365named_constant_name(named_constant nc)
 366{
 367 static const char *const name[] = {
 368 "false",
 369 "true",
 370 "nullptr",
 371 };
 372
 373 return name[nc];
 374}
 375
364static void 376static void
365debug_word(bool flag, const char *name) 377debug_word(bool flag, const char *name)
366{ 378{
367 379
368 if (flag) 380 if (flag)
369 debug_printf(" %s", name); 381 debug_printf(" %s", name);
370} 382}
371 383
372void 384void
373debug_sym(const char *prefix, const sym_t *sym, const char *suffix) 385debug_sym(const char *prefix, const sym_t *sym, const char *suffix)
374{ 386{
375 387
376 debug_printf("%s%s", prefix, sym->s_name); 388 debug_printf("%s%s", prefix, sym->s_name);

cvs diff -r1.224 -r1.225 src/usr.bin/xlint/lint1/externs1.h (expand / switch to unified diff)

--- src/usr.bin/xlint/lint1/externs1.h 2024/05/03 04:04:18 1.224
+++ src/usr.bin/xlint/lint1/externs1.h 2024/05/09 11:08:07 1.225
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: externs1.h,v 1.224 2024/05/03 04:04:18 rillig Exp $ */ 1/* $NetBSD: externs1.h,v 1.225 2024/05/09 11:08:07 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1994, 1995 Jochen Pohl 4 * Copyright (c) 1994, 1995 Jochen Pohl
5 * All Rights Reserved. 5 * All Rights Reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -126,26 +126,27 @@ void expr_free_all(void); @@ -126,26 +126,27 @@ void expr_free_all(void);
126memory_pool expr_save_memory(void); 126memory_pool expr_save_memory(void);
127void expr_restore_memory(memory_pool); 127void expr_restore_memory(memory_pool);
128 128
129/* 129/*
130 * debug.c 130 * debug.c
131 */ 131 */
132 132
133#ifdef DEBUG 133#ifdef DEBUG
134const char *decl_level_kind_name(decl_level_kind); 134const char *decl_level_kind_name(decl_level_kind);
135const char *scl_name(scl_t); 135const char *scl_name(scl_t);
136const char *symbol_kind_name(symbol_kind); 136const char *symbol_kind_name(symbol_kind);
137const char *type_qualifiers_string(type_qualifiers); 137const char *type_qualifiers_string(type_qualifiers);
138const char *function_specifier_name(function_specifier); 138const char *function_specifier_name(function_specifier);
 139const char *named_constant_name(named_constant);
139void debug_dcs(void); 140void debug_dcs(void);
140void debug_dcs_all(void); 141void debug_dcs_all(void);
141void debug_node(const tnode_t *); 142void debug_node(const tnode_t *);
142void debug_type(const type_t *); 143void debug_type(const type_t *);
143void debug_sym(const char *, const sym_t *, const char *); 144void debug_sym(const char *, const sym_t *, const char *);
144void debug_symtab(void); 145void debug_symtab(void);
145void debug_printf(const char *fmt, ...) __printflike(1, 2); 146void debug_printf(const char *fmt, ...) __printflike(1, 2);
146void debug_skip_indent(void); 147void debug_skip_indent(void);
147void debug_indent_inc(void); 148void debug_indent_inc(void);
148void debug_indent_dec(void); 149void debug_indent_dec(void);
149bool debug_push_indented(bool); 150bool debug_push_indented(bool);
150void debug_pop_indented(bool); 151void debug_pop_indented(bool);
151void debug_enter_func(const char *); 152void debug_enter_func(const char *);

cvs diff -r1.224 -r1.225 src/usr.bin/xlint/lint1/lex.c (expand / switch to unified diff)

--- src/usr.bin/xlint/lint1/lex.c 2024/05/07 21:13:26 1.224
+++ src/usr.bin/xlint/lint1/lex.c 2024/05/09 11:08:07 1.225
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: lex.c,v 1.224 2024/05/07 21:13:26 rillig Exp $ */ 1/* $NetBSD: lex.c,v 1.225 2024/05/09 11:08:07 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. 4 * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved.
5 * Copyright (c) 1994, 1995 Jochen Pohl 5 * Copyright (c) 1994, 1995 Jochen Pohl
6 * All Rights Reserved. 6 * All Rights Reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -28,27 +28,27 @@ @@ -28,27 +28,27 @@
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */ 33 */
34 34
35#if HAVE_NBTOOL_CONFIG_H 35#if HAVE_NBTOOL_CONFIG_H
36#include "nbtool_config.h" 36#include "nbtool_config.h"
37#endif 37#endif
38 38
39#include <sys/cdefs.h> 39#include <sys/cdefs.h>
40#if defined(__RCSID) 40#if defined(__RCSID)
41__RCSID("$NetBSD: lex.c,v 1.224 2024/05/07 21:13:26 rillig Exp $"); 41__RCSID("$NetBSD: lex.c,v 1.225 2024/05/09 11:08:07 rillig Exp $");
42#endif 42#endif
43 43
44#include <ctype.h> 44#include <ctype.h>
45#include <errno.h> 45#include <errno.h>
46#include <float.h> 46#include <float.h>
47#include <limits.h> 47#include <limits.h>
48#include <math.h> 48#include <math.h>
49#include <stdlib.h> 49#include <stdlib.h>
50#include <string.h> 50#include <string.h>
51 51
52#include "lint1.h" 52#include "lint1.h"
53#include "cgram.h" 53#include "cgram.h"
54 54
@@ -87,44 +87,45 @@ bool in_system_header; @@ -87,44 +87,45 @@ bool in_system_header;
87 (since) == 99 || (since) == 11, \ 87 (since) == 99 || (since) == 11, \
88 (since) == 23, \ 88 (since) == 23, \
89 (gcc) > 0, \ 89 (gcc) > 0, \
90 ((deco) & 1) != 0, ((deco) & 2) != 0, ((deco) & 4) != 0, \ 90 ((deco) & 1) != 0, ((deco) & 2) != 0, ((deco) & 4) != 0, \
91 } 91 }
92#define kwdef_token(name, token, since, gcc, deco) \ 92#define kwdef_token(name, token, since, gcc, deco) \
93 kwdef(name, token, {false}, since, gcc, deco) 93 kwdef(name, token, {false}, since, gcc, deco)
94#define kwdef_sclass(name, sclass, since, gcc, deco) \ 94#define kwdef_sclass(name, sclass, since, gcc, deco) \
95 kwdef(name, T_SCLASS, .u.kw_scl = (sclass), since, gcc, deco) 95 kwdef(name, T_SCLASS, .u.kw_scl = (sclass), since, gcc, deco)
96#define kwdef_type(name, tspec, since) \ 96#define kwdef_type(name, tspec, since) \
97 kwdef(name, T_TYPE, .u.kw_tspec = (tspec), since, 0, 1) 97 kwdef(name, T_TYPE, .u.kw_tspec = (tspec), since, 0, 1)
98#define kwdef_tqual(name, tqual, since, gcc, deco) \ 98#define kwdef_tqual(name, tqual, since, gcc, deco) \
99 kwdef(name, T_QUAL, .u.kw_tqual = {.tqual = true}, since, gcc, deco) 99 kwdef(name, T_QUAL, .u.kw_tqual = {.tqual = true}, since, gcc, deco)
100#define kwdef_const(name, constant, since, gcc, deco) \ 100#define kwdef_const(name, named_constant, since, gcc, deco) \
101 kwdef(name, T_CON, .u.kw_const = (constant), since, gcc, deco) 101 kwdef(name, T_NAMED_CONSTANT, \
 102 .u.kw_named_constant = (named_constant), since, gcc, deco)
102#define kwdef_keyword(name, token) \ 103#define kwdef_keyword(name, token) \
103 kwdef(name, token, {false}, 78, 0, 1) 104 kwdef(name, token, {false}, 78, 0, 1)
104 105
105/* During initialization, these keywords are written to the symbol table. */ 106/* During initialization, these keywords are written to the symbol table. */
106static const struct keyword { 107static const struct keyword {
107 const char kw_name[20]; 108 const char kw_name[20];
108 int kw_token; /* token to be returned by yylex() */ 109 int kw_token; /* token to be returned by yylex() */
109 union { 110 union {
110 bool kw_dummy; 111 bool kw_dummy;
111 scl_t kw_scl; /* if kw_token is T_SCLASS */ 112 scl_t kw_scl; /* if kw_token is T_SCLASS */
112 tspec_t kw_tspec; /* if kw_token is T_TYPE or 113 tspec_t kw_tspec; /* if kw_token is T_TYPE or
113 * T_STRUCT_OR_UNION */ 114 * T_STRUCT_OR_UNION */
114 type_qualifiers kw_tqual; /* if kw_token is T_QUAL */ 115 type_qualifiers kw_tqual; /* if kw_token is T_QUAL */
115 function_specifier kw_fs; /* if kw_token is 116 function_specifier kw_fs; /* if kw_token is
116 * T_FUNCTION_SPECIFIER */ 117 * T_FUNCTION_SPECIFIER */
117 named_constant kw_const; /* if kw_token is T_CON */ 118 named_constant kw_named_constant;
118 } u; 119 } u;
119 bool kw_added_in_c90:1; 120 bool kw_added_in_c90:1;
120 bool kw_added_in_c99_or_c11:1; 121 bool kw_added_in_c99_or_c11:1;
121 bool kw_added_in_c23:1; 122 bool kw_added_in_c23:1;
122 bool kw_gcc:1; /* available in GCC mode */ 123 bool kw_gcc:1; /* available in GCC mode */
123 bool kw_plain:1; /* 'name' */ 124 bool kw_plain:1; /* 'name' */
124 bool kw_leading:1; /* '__name' */ 125 bool kw_leading:1; /* '__name' */
125 bool kw_both:1; /* '__name__' */ 126 bool kw_both:1; /* '__name__' */
126} keywords[] = { 127} keywords[] = {
127 // TODO: _Alignas is not available in C99. 128 // TODO: _Alignas is not available in C99.
128 kwdef_keyword( "_Alignas", T_ALIGNAS), 129 kwdef_keyword( "_Alignas", T_ALIGNAS),
129 // TODO: _Alignof is not available in C99. 130 // TODO: _Alignof is not available in C99.
130 kwdef_keyword( "_Alignof", T_ALIGNOF), 131 kwdef_keyword( "_Alignof", T_ALIGNOF),
@@ -155,26 +156,27 @@ static const struct keyword { @@ -155,26 +156,27 @@ static const struct keyword {
155 kwdef_type( "float", FLOAT, 78), 156 kwdef_type( "float", FLOAT, 78),
156 kwdef_keyword( "for", T_FOR), 157 kwdef_keyword( "for", T_FOR),
157 kwdef_token( "_Generic", T_GENERIC, 11,0,1), 158 kwdef_token( "_Generic", T_GENERIC, 11,0,1),
158 kwdef_keyword( "goto", T_GOTO), 159 kwdef_keyword( "goto", T_GOTO),
159 kwdef_keyword( "if", T_IF), 160 kwdef_keyword( "if", T_IF),
160 kwdef_token( "__imag__", T_IMAG, 78,1,1), 161 kwdef_token( "__imag__", T_IMAG, 78,1,1),
161 kwdef("inline", T_FUNCTION_SPECIFIER, .u.kw_fs = FS_INLINE, 99,0,7), 162 kwdef("inline", T_FUNCTION_SPECIFIER, .u.kw_fs = FS_INLINE, 99,0,7),
162 kwdef_type( "int", INT, 78), 163 kwdef_type( "int", INT, 78),
163#ifdef INT128_SIZE 164#ifdef INT128_SIZE
164 kwdef_type( "__int128_t", INT128, 99), 165 kwdef_type( "__int128_t", INT128, 99),
165#endif 166#endif
166 kwdef_type( "long", LONG, 78), 167 kwdef_type( "long", LONG, 78),
167 kwdef("_Noreturn", T_FUNCTION_SPECIFIER, .u.kw_fs = FS_NORETURN, 11,0,1), 168 kwdef("_Noreturn", T_FUNCTION_SPECIFIER, .u.kw_fs = FS_NORETURN, 11,0,1),
 169 kwdef_const( "nullptr", NC_NULLPTR, 23,0,1),
168 // XXX: __packed is GCC-specific. 170 // XXX: __packed is GCC-specific.
169 kwdef_token( "__packed", T_PACKED, 78,0,1), 171 kwdef_token( "__packed", T_PACKED, 78,0,1),
170 kwdef_token( "__real__", T_REAL, 78,1,1), 172 kwdef_token( "__real__", T_REAL, 78,1,1),
171 kwdef_sclass( "register", REG, 78,0,1), 173 kwdef_sclass( "register", REG, 78,0,1),
172 kwdef_tqual( "restrict", tq_restrict, 99,0,7), 174 kwdef_tqual( "restrict", tq_restrict, 99,0,7),
173 kwdef_keyword( "return", T_RETURN), 175 kwdef_keyword( "return", T_RETURN),
174 kwdef_type( "short", SHORT, 78), 176 kwdef_type( "short", SHORT, 78),
175 kwdef( "signed", T_TYPE, .u.kw_tspec = SIGNED, 90,0,3), 177 kwdef( "signed", T_TYPE, .u.kw_tspec = SIGNED, 90,0,3),
176 kwdef_keyword( "sizeof", T_SIZEOF), 178 kwdef_keyword( "sizeof", T_SIZEOF),
177 kwdef_sclass( "static", STATIC, 78,0,1), 179 kwdef_sclass( "static", STATIC, 78,0,1),
178 // XXX: _Static_assert was added in C11. 180 // XXX: _Static_assert was added in C11.
179 kwdef_keyword( "_Static_assert", T_STATIC_ASSERT), 181 kwdef_keyword( "_Static_assert", T_STATIC_ASSERT),
180 kwdef("struct", T_STRUCT_OR_UNION, .u.kw_tspec = STRUCT, 78,0,1), 182 kwdef("struct", T_STRUCT_OR_UNION, .u.kw_tspec = STRUCT, 78,0,1),
@@ -364,28 +366,28 @@ register_keyword(const struct keyword *k @@ -364,28 +366,28 @@ register_keyword(const struct keyword *k
364 sym_t *sym = block_zero_alloc(sizeof(*sym), "sym"); 366 sym_t *sym = block_zero_alloc(sizeof(*sym), "sym");
365 sym->s_name = name; 367 sym->s_name = name;
366 sym->s_keyword = kw; 368 sym->s_keyword = kw;
367 int tok = kw->kw_token; 369 int tok = kw->kw_token;
368 sym->u.s_keyword.sk_token = tok; 370 sym->u.s_keyword.sk_token = tok;
369 if (tok == T_TYPE || tok == T_STRUCT_OR_UNION) 371 if (tok == T_TYPE || tok == T_STRUCT_OR_UNION)
370 sym->u.s_keyword.u.sk_tspec = kw->u.kw_tspec; 372 sym->u.s_keyword.u.sk_tspec = kw->u.kw_tspec;
371 if (tok == T_SCLASS) 373 if (tok == T_SCLASS)
372 sym->s_scl = kw->u.kw_scl; 374 sym->s_scl = kw->u.kw_scl;
373 if (tok == T_QUAL) 375 if (tok == T_QUAL)
374 sym->u.s_keyword.u.sk_type_qualifier = kw->u.kw_tqual; 376 sym->u.s_keyword.u.sk_type_qualifier = kw->u.kw_tqual;
375 if (tok == T_FUNCTION_SPECIFIER) 377 if (tok == T_FUNCTION_SPECIFIER)
376 sym->u.s_keyword.u.function_specifier = kw->u.kw_fs; 378 sym->u.s_keyword.u.function_specifier = kw->u.kw_fs;
377 if (tok == T_CON) 379 if (tok == T_NAMED_CONSTANT)
378 sym->u.s_keyword.u.constant = kw->u.kw_const; 380 sym->u.s_keyword.u.named_constant = kw->u.kw_named_constant;
379 381
380 symtab_add(sym); 382 symtab_add(sym);
381} 383}
382 384
383static bool 385static bool
384is_keyword_known(const struct keyword *kw) 386is_keyword_known(const struct keyword *kw)
385{ 387{
386 388
387 if (kw->kw_added_in_c23 && !allow_c23) 389 if (kw->kw_added_in_c23 && !allow_c23)
388 return false; 390 return false;
389 if ((kw->kw_added_in_c90 || kw->kw_added_in_c99_or_c11) && !allow_c90) 391 if ((kw->kw_added_in_c90 || kw->kw_added_in_c99_or_c11) && !allow_c90)
390 return false; 392 return false;
391 393
@@ -445,32 +447,28 @@ lex_keyword(sym_t *sym) @@ -445,32 +447,28 @@ lex_keyword(sym_t *sym)
445{ 447{
446 int tok = sym->u.s_keyword.sk_token; 448 int tok = sym->u.s_keyword.sk_token;
447 449
448 if (tok == T_SCLASS) 450 if (tok == T_SCLASS)
449 yylval.y_scl = sym->s_scl; 451 yylval.y_scl = sym->s_scl;
450 if (tok == T_TYPE || tok == T_STRUCT_OR_UNION) 452 if (tok == T_TYPE || tok == T_STRUCT_OR_UNION)
451 yylval.y_tspec = sym->u.s_keyword.u.sk_tspec; 453 yylval.y_tspec = sym->u.s_keyword.u.sk_tspec;
452 if (tok == T_QUAL) 454 if (tok == T_QUAL)
453 yylval.y_type_qualifiers = 455 yylval.y_type_qualifiers =
454 sym->u.s_keyword.u.sk_type_qualifier; 456 sym->u.s_keyword.u.sk_type_qualifier;
455 if (tok == T_FUNCTION_SPECIFIER) 457 if (tok == T_FUNCTION_SPECIFIER)
456 yylval.y_function_specifier = 458 yylval.y_function_specifier =
457 sym->u.s_keyword.u.function_specifier; 459 sym->u.s_keyword.u.function_specifier;
458 if (tok == T_CON) { 460 if (tok == T_NAMED_CONSTANT)
459 val_t *v = xcalloc(1, sizeof(*v)); 461 yylval.y_named_constant = sym->u.s_keyword.u.named_constant;
460 v->v_tspec = BOOL; 
461 v->u.integer = sym->u.s_keyword.u.constant == NC_TRUE ? 1 : 0; 
462 yylval.y_val = v; 
463 } 
464 return tok; 462 return tok;
465} 463}
466 464
467/* 465/*
468 * Look up the definition of a name in the symbol table. This symbol must 466 * Look up the definition of a name in the symbol table. This symbol must
469 * either be a keyword or a symbol of the type required by sym_kind (label, 467 * either be a keyword or a symbol of the type required by sym_kind (label,
470 * member, tag, ...). 468 * member, tag, ...).
471 */ 469 */
472extern int 470extern int
473lex_name(const char *yytext, size_t yyleng) 471lex_name(const char *yytext, size_t yyleng)
474{ 472{
475 473
476 sym_t *sym = symtab_search(yytext); 474 sym_t *sym = symtab_search(yytext);

cvs diff -r1.225 -r1.226 src/usr.bin/xlint/lint1/lint1.h (expand / switch to unified diff)

--- src/usr.bin/xlint/lint1/lint1.h 2024/05/07 21:13:26 1.225
+++ src/usr.bin/xlint/lint1/lint1.h 2024/05/09 11:08:07 1.226
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: lint1.h,v 1.225 2024/05/07 21:13:26 rillig Exp $ */ 1/* $NetBSD: lint1.h,v 1.226 2024/05/09 11:08:07 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. 4 * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved.
5 * Copyright (c) 1994, 1995 Jochen Pohl 5 * Copyright (c) 1994, 1995 Jochen Pohl
6 * All Rights Reserved. 6 * All Rights Reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -180,27 +180,27 @@ typedef enum { @@ -180,27 +180,27 @@ typedef enum {
180 ABSTRACT, /* abstract symbol (sizeof, casts, unnamed 180 ABSTRACT, /* abstract symbol (sizeof, casts, unnamed
181 * argument) */ 181 * argument) */
182} scl_t; 182} scl_t;
183 183
184/* C23 6.7.4 */ 184/* C23 6.7.4 */
185typedef enum { 185typedef enum {
186 FS_INLINE, /* since C99 */ 186 FS_INLINE, /* since C99 */
187 FS_NORETURN, /* since C11 */ 187 FS_NORETURN, /* since C11 */
188} function_specifier; 188} function_specifier;
189 189
190typedef enum { 190typedef enum {
191 NC_FALSE, /* since C23 */ 191 NC_FALSE, /* since C23 */
192 NC_TRUE, /* since C23 */ 192 NC_TRUE, /* since C23 */
193 // TODO: null_ptr 193 NC_NULLPTR, /* since C23 */
194} named_constant; 194} named_constant;
195 195
196/* A type, variable, keyword; basically anything that has a name. */ 196/* A type, variable, keyword; basically anything that has a name. */
197struct sym { 197struct sym {
198 const char *s_name; 198 const char *s_name;
199 const char *s_rename; /* renamed symbol's given name */ 199 const char *s_rename; /* renamed symbol's given name */
200 pos_t s_def_pos; /* position of last (prototype) definition, 200 pos_t s_def_pos; /* position of last (prototype) definition,
201 * prototype declaration, no-prototype-def., 201 * prototype declaration, no-prototype-def.,
202 * tentative definition or declaration, in this 202 * tentative definition or declaration, in this
203 * order */ 203 * order */
204 pos_t s_set_pos; /* position of first initialization */ 204 pos_t s_set_pos; /* position of first initialization */
205 pos_t s_use_pos; /* position of first use */ 205 pos_t s_use_pos; /* position of first use */
206 symbol_kind s_kind; 206 symbol_kind s_kind;
@@ -230,27 +230,27 @@ struct sym { @@ -230,27 +230,27 @@ struct sym {
230 struct_or_union *sm_containing_type; 230 struct_or_union *sm_containing_type;
231 unsigned int sm_offset_in_bits; 231 unsigned int sm_offset_in_bits;
232 } s_member; 232 } s_member;
233 struct { 233 struct {
234 int sk_token; 234 int sk_token;
235 union { 235 union {
236 /* if T_TYPE or T_STRUCT_OR_UNION */ 236 /* if T_TYPE or T_STRUCT_OR_UNION */
237 tspec_t sk_tspec; 237 tspec_t sk_tspec;
238 /* if T_QUAL */ 238 /* if T_QUAL */
239 type_qualifiers sk_type_qualifier; 239 type_qualifiers sk_type_qualifier;
240 /* if T_FUNCTION_SPECIFIER */ 240 /* if T_FUNCTION_SPECIFIER */
241 function_specifier function_specifier; 241 function_specifier function_specifier;
242 /* if T_CON */ 242 /* if T_CON */
243 named_constant constant; 243 named_constant named_constant;
244 } u; 244 } u;
245 } s_keyword; 245 } s_keyword;
246 sym_t *s_old_style_params; /* parameters in an old-style 246 sym_t *s_old_style_params; /* parameters in an old-style
247 * function definition */ 247 * function definition */
248 } u; 248 } u;
249 sym_t *s_symtab_next; /* next symbol in the same symtab bucket */ 249 sym_t *s_symtab_next; /* next symbol in the same symtab bucket */
250 sym_t **s_symtab_ref; /* pointer to s_symtab_next of the previous 250 sym_t **s_symtab_ref; /* pointer to s_symtab_next of the previous
251 * symbol */ 251 * symbol */
252 sym_t *s_next; /* next struct/union member, enumerator, 252 sym_t *s_next; /* next struct/union member, enumerator,
253 * parameter */ 253 * parameter */
254 sym_t *s_level_next; /* next symbol declared on the same level */ 254 sym_t *s_level_next; /* next symbol declared on the same level */
255}; 255};
256 256