Thu May 9 20:56:41 2024 UTC (23d)
lint: in C23 mode, allow storage classes in compound literals


(rillig)
diff -r1.11 -r1.12 src/tests/usr.bin/xlint/lint1/c23.c
diff -r1.498 -r1.499 src/usr.bin/xlint/lint1/cgram.y

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

--- src/tests/usr.bin/xlint/lint1/c23.c 2024/05/09 11:08:07 1.11
+++ src/tests/usr.bin/xlint/lint1/c23.c 2024/05/09 20:56:41 1.12
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: c23.c,v 1.11 2024/05/09 11:08:07 rillig Exp $ */ 1/* $NetBSD: c23.c,v 1.12 2024/05/09 20:56:41 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
@@ -32,26 +32,49 @@ bool @@ -32,26 +32,49 @@ bool
32null_pointer_constant(const char *p, double dbl) 32null_pointer_constant(const char *p, double dbl)
33{ 33{
34 /* expect+1: error: operands of '!=' have incompatible types 'double' and 'pointer to void' [107] */ 34 /* expect+1: error: operands of '!=' have incompatible types 'double' and 'pointer to void' [107] */
35 if (dbl != nullptr) 35 if (dbl != nullptr)
36 p++; 36 p++;
37 if (dbl > 0.0) 37 if (dbl > 0.0)
38 p++; 38 p++;
39 if (*p == '\0') 39 if (*p == '\0')
40 p = nullptr; 40 p = nullptr;
41 return p == nullptr; 41 return p == nullptr;
42} 42}
43 43
44 44
 45void *
 46storage_class_in_compound_literal(void)
 47{
 48 typedef struct node node;
 49 struct node {
 50 node *left;
 51 int value;
 52 node *right;
 53 };
 54
 55 node *tree;
 56 tree = &(static node){
 57 &(static node){
 58 nullptr,
 59 3,
 60 nullptr,
 61 },
 62 5,
 63 nullptr,
 64 };
 65 return tree->left;
 66}
 67
45int 68int
46empty_initializer_braces(void) 69empty_initializer_braces(void)
47{ 70{
48 struct s { 71 struct s {
49 int member; 72 int member;
50 } s; 73 } s;
51 74
52 // Empty initializer braces were introduced in C23. 75 // Empty initializer braces were introduced in C23.
53 s = (struct s){}; 76 s = (struct s){};
54 s = (struct s){s.member}; 77 s = (struct s){s.member};
55 return s.member; 78 return s.member;
56} 79}
57 80

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

--- src/usr.bin/xlint/lint1/cgram.y 2024/05/09 20:22:20 1.498
+++ src/usr.bin/xlint/lint1/cgram.y 2024/05/09 20:56:41 1.499
@@ -1,15 +1,15 @@ @@ -1,15 +1,15 @@
1%{ 1%{
2/* $NetBSD: cgram.y,v 1.498 2024/05/09 20:22:20 rillig Exp $ */ 2/* $NetBSD: cgram.y,v 1.499 2024/05/09 20:56:41 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.498 2024/05/09 20:22:20 rillig Exp $"); 38__RCSID("$NetBSD: cgram.y,v 1.499 2024/05/09 20:56:41 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.
@@ -296,52 +296,54 @@ is_either(const char *s, const char *a,  @@ -296,52 +296,54 @@ is_either(const char *s, const char *a,
296%type <y_sym> identifier_sym 296%type <y_sym> identifier_sym
297%type <y_name> identifier 297%type <y_name> identifier
298%type <y_string> string 298%type <y_string> string
299%type <y_tnode> primary_expression 299%type <y_tnode> primary_expression
300%type <y_designation> member_designator 300%type <y_designation> member_designator
301%type <y_tnode> generic_selection 301%type <y_tnode> generic_selection
302%type <y_generic> generic_assoc_list 302%type <y_generic> generic_assoc_list
303%type <y_generic> generic_association 303%type <y_generic> generic_association
304%type <y_tnode> postfix_expression 304%type <y_tnode> postfix_expression
305%type <y_tnode> gcc_statement_expr_list 305%type <y_tnode> gcc_statement_expr_list
306%type <y_tnode> gcc_statement_expr_item 306%type <y_tnode> gcc_statement_expr_item
307%type <y_op> point_or_arrow 307%type <y_op> point_or_arrow
308%type <y_arguments> argument_expression_list 308%type <y_arguments> argument_expression_list
 309%type <y_scl> storage_class_specifiers
309%type <y_tnode> unary_expression 310%type <y_tnode> unary_expression
310%type <y_tnode> cast_expression 311%type <y_tnode> cast_expression
311%type <y_tnode> expression_opt 312%type <y_tnode> expression_opt
312%type <y_tnode> conditional_expression 313%type <y_tnode> conditional_expression
313%type <y_tnode> assignment_expression 314%type <y_tnode> assignment_expression
314%type <y_tnode> expression 315%type <y_tnode> expression
315%type <y_tnode> constant_expression 316%type <y_tnode> constant_expression
316/* No type for declaration_or_error. */ 317/* No type for declaration_or_error. */
317/* No type for declaration. */ 318/* No type for declaration. */
318/* No type for begin_type_declaration_specifiers. */ 319/* No type for begin_type_declaration_specifiers. */
319/* No type for begin_type_declmods. */ 320/* No type for begin_type_declmods. */
320/* No type for begin_type_specifier_qualifier_list. */ 321/* No type for begin_type_specifier_qualifier_list. */
321/* No type for begin_type_specifier_qualifier_list_postfix. */ 322/* No type for begin_type_specifier_qualifier_list_postfix. */
322%type <y_type> begin_type_typespec 323%type <y_type> begin_type_typespec
323/* No type for begin_type_qualifier_list. */ 324/* No type for begin_type_qualifier_list. */
324/* No type for declmod. */ 325/* No type for declmod. */
325/* No type for type_attribute_list_opt. */ 326/* No type for type_attribute_list_opt. */
326/* No type for type_attribute_list. */ 327/* No type for type_attribute_list. */
327/* No type for type_attribute_opt. */ 328/* No type for type_attribute_opt. */
328/* No type for type_attribute. */ 329/* No type for type_attribute. */
329/* No type for begin_type. */ 330/* No type for begin_type. */
330/* No type for end_type. */ 331/* No type for end_type. */
331/* No type for notype_init_declarator_list. */ 332/* No type for notype_init_declarator_list. */
332/* No type for type_init_declarator_list. */ 333/* No type for type_init_declarator_list. */
333/* No type for notype_init_declarator. */ 334/* No type for notype_init_declarator. */
334/* No type for type_init_declarator. */ 335/* No type for type_init_declarator. */
 336%type <y_scl> storage_class_specifier
335%type <y_type> type_specifier 337%type <y_type> type_specifier
336%type <y_type> notype_type_specifier 338%type <y_type> notype_type_specifier
337%type <y_type> struct_or_union_specifier 339%type <y_type> struct_or_union_specifier
338%type <y_tspec> struct_or_union 340%type <y_tspec> struct_or_union
339%type <y_sym> braced_member_declaration_list 341%type <y_sym> braced_member_declaration_list
340%type <y_sym> member_declaration_list_with_rbrace 342%type <y_sym> member_declaration_list_with_rbrace
341%type <y_sym> member_declaration_list 343%type <y_sym> member_declaration_list
342%type <y_sym> member_declaration 344%type <y_sym> member_declaration
343%type <y_sym> notype_member_declarator_list 345%type <y_sym> notype_member_declarator_list
344%type <y_sym> type_member_declarator_list 346%type <y_sym> type_member_declarator_list
345%type <y_sym> notype_member_declarator 347%type <y_sym> notype_member_declarator
346%type <y_sym> type_member_declarator 348%type <y_sym> type_member_declarator
347%type <y_type> enum_specifier 349%type <y_type> enum_specifier
@@ -596,26 +598,39 @@ postfix_expression: @@ -596,26 +598,39 @@ postfix_expression:
596 } 598 }
597 /* Rule 'compound_literal' from C99 6.5.2.5. */ 599 /* Rule 'compound_literal' from C99 6.5.2.5. */
598| T_LPAREN type_name T_RPAREN { 600| T_LPAREN type_name T_RPAREN {
599 sym_t *tmp = mktempsym($2); 601 sym_t *tmp = mktempsym($2);
600 begin_initialization(tmp); 602 begin_initialization(tmp);
601 cgram_declare(tmp, true, NULL); 603 cgram_declare(tmp, true, NULL);
602 } braced_initializer { 604 } braced_initializer {
603 if (!allow_c99) 605 if (!allow_c99)
604 /* compound literals are a C99/GCC extension */ 606 /* compound literals are a C99/GCC extension */
605 gnuism(319); 607 gnuism(319);
606 $$ = build_name(current_initsym(), false); 608 $$ = build_name(current_initsym(), false);
607 end_initialization(); 609 end_initialization();
608 } 610 }
 611 /* Rule 'compound_literal' with storage classes from C23 6.5.3.6. */
 612| T_LPAREN storage_class_specifiers type_name T_RPAREN {
 613 sym_t *tmp = mktempsym($3);
 614 tmp->s_scl = $2;
 615 begin_initialization(tmp);
 616 cgram_declare(tmp, true, NULL);
 617 } braced_initializer {
 618 if (!allow_c99)
 619 /* compound literals are a C99/GCC extension */
 620 gnuism(319);
 621 $$ = build_name(current_initsym(), false);
 622 end_initialization();
 623 }
609| T_LPAREN compound_statement_lbrace { 624| T_LPAREN compound_statement_lbrace {
610 begin_statement_expr(); 625 begin_statement_expr();
611 } gcc_statement_expr_list { 626 } gcc_statement_expr_list {
612 do_statement_expr($4); 627 do_statement_expr($4);
613 } compound_statement_rbrace T_RPAREN { 628 } compound_statement_rbrace T_RPAREN {
614 $$ = end_statement_expr(); 629 $$ = end_statement_expr();
615 } 630 }
616; 631;
617 632
618/* 633/*
619 * The inner part of a GCC statement-expression of the form ({ ... }). 634 * The inner part of a GCC statement-expression of the form ({ ... }).
620 * 635 *
621 * https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html 636 * https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
@@ -672,27 +687,34 @@ argument_expression_list: @@ -672,27 +687,34 @@ argument_expression_list:
672 $$ = expr_zero_alloc(sizeof(*$$), "function_call"); 687 $$ = expr_zero_alloc(sizeof(*$$), "function_call");
673 add_function_argument($$, $1); 688 add_function_argument($$, $1);
674 } 689 }
675| argument_expression_list T_COMMA assignment_expression { 690| argument_expression_list T_COMMA assignment_expression {
676 $$ = $1; 691 $$ = $1;
677 add_function_argument($1, $3); 692 add_function_argument($1, $3);
678 } 693 }
679; 694;
680 695
681 696
682/* C23 6.5.3.6 */ 697/* C23 6.5.3.6 */
683/* The rule 'compound_literal' is inlined into 'postfix_expression'. */ 698/* The rule 'compound_literal' is inlined into 'postfix_expression'. */
684 699
685/* TODO: Implement 'storage_class_specifiers' from C23 6.5.3.6. */ 700/* C23 6.5.3.6 */
 701storage_class_specifiers:
 702 storage_class_specifier
 703| storage_class_specifiers storage_class_specifier {
 704 // TODO C23: maybe merge multiple storage class specifiers
 705 $$ = $1;
 706 }
 707;
686 708
687/* K&R 7.2, C90 ???, C99 6.5.3, C11 6.5.3, C23 6.5.4 */ 709/* K&R 7.2, C90 ???, C99 6.5.3, C11 6.5.3, C23 6.5.4 */
688unary_expression: 710unary_expression:
689 postfix_expression 711 postfix_expression
690| T_INCDEC sys unary_expression { 712| T_INCDEC sys unary_expression {
691 $$ = build_unary($1 ? INCBEF : DECBEF, $2, $3); 713 $$ = build_unary($1 ? INCBEF : DECBEF, $2, $3);
692 } 714 }
693| T_AMPER sys cast_expression { 715| T_AMPER sys cast_expression {
694 $$ = build_unary(ADDR, $2, $3); 716 $$ = build_unary(ADDR, $2, $3);
695 } 717 }
696| T_ASTERISK sys cast_expression { 718| T_ASTERISK sys cast_expression {
697 $$ = build_unary(INDIR, $2, $3); 719 $$ = build_unary(INDIR, $2, $3);
698 } 720 }
@@ -1038,27 +1060,30 @@ type_init_declarator: @@ -1038,27 +1060,30 @@ type_init_declarator:
1038 } 1060 }
1039| type_declarator asm_or_symbolrename_opt { 1061| type_declarator asm_or_symbolrename_opt {
1040 begin_initialization($1); 1062 begin_initialization($1);
1041 cgram_declare($1, true, $2); 1063 cgram_declare($1, true, $2);
1042 } T_ASSIGN initializer { 1064 } T_ASSIGN initializer {
1043 check_size($1); 1065 check_size($1);
1044 end_initialization(); 1066 end_initialization();
1045 } 1067 }
1046; 1068;
1047 1069
1048 1070
1049/* TODO: Implement 'attribute_declaration' from C23 6.7.1. */ 1071/* TODO: Implement 'attribute_declaration' from C23 6.7.1. */
1050 1072
1051/* TODO: Implement 'storage_class_specifier' from C23 6.7.2. */ 1073/* K&R ???, C90 ???, C99 ???, C11 ???, C23 6.7.2 */
 1074storage_class_specifier:
 1075 T_SCLASS
 1076;
1052 1077
1053/* C99 6.7.2, C23 6.7.3.1 */ 1078/* C99 6.7.2, C23 6.7.3.1 */
1054type_specifier: 1079type_specifier:
1055 notype_type_specifier 1080 notype_type_specifier
1056| T_TYPENAME { 1081| T_TYPENAME {
1057 $$ = getsym($1)->s_type; 1082 $$ = getsym($1)->s_type;
1058 } 1083 }
1059; 1084;
1060 1085
1061notype_type_specifier: /* see C99 6.7.2 */ 1086notype_type_specifier: /* see C99 6.7.2 */
1062 T_TYPE { 1087 T_TYPE {
1063 $$ = gettyp($1); 1088 $$ = gettyp($1);
1064 } 1089 }