Thu Jul 15 17:20:58 2021 UTC ()
lint: in the grammar, replace %prec with explicit rules

This way, in the arguments of __attribute__, where only constant
expressions are expected, a '=' leads to a syntax error.  Previously,
this was not detected.

No noticeable change in practice since these cases are already handled
by the compilers.


(rillig)
diff -r1.1 -r1.2 src/tests/usr.bin/xlint/lint1/expr_precedence.c
diff -r1.1 -r1.2 src/tests/usr.bin/xlint/lint1/expr_precedence.exp
diff -r1.324 -r1.325 src/usr.bin/xlint/lint1/cgram.y

cvs diff -r1.1 -r1.2 src/tests/usr.bin/xlint/lint1/expr_precedence.c (expand / switch to unified diff)

--- src/tests/usr.bin/xlint/lint1/expr_precedence.c 2021/07/15 17:09:08 1.1
+++ src/tests/usr.bin/xlint/lint1/expr_precedence.c 2021/07/15 17:20:58 1.2
@@ -1,31 +1,30 @@ @@ -1,31 +1,30 @@
1/* $NetBSD: expr_precedence.c,v 1.1 2021/07/15 17:09:08 rillig Exp $ */ 1/* $NetBSD: expr_precedence.c,v 1.2 2021/07/15 17:20:58 rillig Exp $ */
2# 3 "expr_precedence.c" 2# 3 "expr_precedence.c"
3 3
4/* 4/*
5 * Tests for the precedence among operators. 5 * Tests for the precedence among operators.
6 */ 6 */
7 7
8int var; 8int var;
9 9
10/* 10/*
11 * An initializer needs an assignment-expression; the comma must be 11 * An initializer needs an assignment-expression; the comma must be
12 * interpreted as a separator, not an operator. 12 * interpreted as a separator, not an operator.
13 */ 13 */
14/* expect+1: error: syntax error '4' [249] */ 14/* expect+1: error: syntax error '4' [249] */
15int init_error = 3, 4; 15int init_error = 3, 4;
16 16
17/* expect+1: error: non-constant initializer [177] */ 17/* expect+1: error: non-constant initializer [177] */
18int init_syntactically_ok = var = 1 ? 2 : 3; 18int init_syntactically_ok = var = 1 ? 2 : 3;
19 19
20/* 20/*
21 * The arguments of __attribute__ must be constant-expression, as assignments 21 * The arguments of __attribute__ must be constant-expression, as assignments
22 * don't make sense at that point. 22 * don't make sense at that point.
23 */ 23 */
24void __attribute__((format(printf, 24void __attribute__((format(printf,
25 /* expect+2: error: 'var' undefined [99] */ /* XXX: why? */ 25 /* expect+2: error: 'var' undefined [99] */ /* XXX: why? */
26 /* XXX: allow only constant-expression, not assignment-expression */ 26 /* expect+1: syntax error '=' [249] */
27 var = 1, 27 var = 1,
28 /* Syntactically ok, must be a constant expression though. */ 28 /* Syntactically ok, must be a constant expression though. */
29 /* expect+1: error: 'var' undefined [99] */ 
30 var > 0 ? 2 : 1))) 29 var > 0 ? 2 : 1)))
31my_printf(const char *, ...); 30my_printf(const char *, ...);

cvs diff -r1.1 -r1.2 src/tests/usr.bin/xlint/lint1/Attic/expr_precedence.exp (expand / switch to unified diff)

--- src/tests/usr.bin/xlint/lint1/Attic/expr_precedence.exp 2021/07/15 17:09:08 1.1
+++ src/tests/usr.bin/xlint/lint1/Attic/expr_precedence.exp 2021/07/15 17:20:58 1.2
@@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
1expr_precedence.c(15): error: syntax error '4' [249] 1expr_precedence.c(15): error: syntax error '4' [249]
2expr_precedence.c(18): error: non-constant initializer [177] 2expr_precedence.c(18): error: non-constant initializer [177]
3expr_precedence.c(27): error: 'var' undefined [99] 3expr_precedence.c(27): error: 'var' undefined [99]
4expr_precedence.c(30): error: 'var' undefined [99] 4expr_precedence.c(27): error: syntax error '=' [249]

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

--- src/usr.bin/xlint/lint1/cgram.y 2021/07/14 17:19:37 1.324
+++ src/usr.bin/xlint/lint1/cgram.y 2021/07/15 17:20:57 1.325
@@ -1,15 +1,15 @@ @@ -1,15 +1,15 @@
1%{ 1%{
2/* $NetBSD: cgram.y,v 1.324 2021/07/14 17:19:37 rillig Exp $ */ 2/* $NetBSD: cgram.y,v 1.325 2021/07/15 17:20:57 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) && !defined(lint) 37#if defined(__RCSID) && !defined(lint)
38__RCSID("$NetBSD: cgram.y,v 1.324 2021/07/14 17:19:37 rillig Exp $"); 38__RCSID("$NetBSD: cgram.y,v 1.325 2021/07/15 17:20:57 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.
@@ -285,29 +285,30 @@ anonymize(sym_t *s) @@ -285,29 +285,30 @@ anonymize(sym_t *s)
285%type <y_string> string2 285%type <y_string> string2
286 286
287%type <y_tnode> primary_expression 287%type <y_tnode> primary_expression
288%type <y_tnode> generic_selection 288%type <y_tnode> generic_selection
289%type <y_generic> generic_assoc_list 289%type <y_generic> generic_assoc_list
290%type <y_generic> generic_association 290%type <y_generic> generic_association
291%type <y_tnode> postfix_expression 291%type <y_tnode> postfix_expression
292%type <y_tnode> gcc_statement_expr_list 292%type <y_tnode> gcc_statement_expr_list
293%type <y_tnode> gcc_statement_expr_item 293%type <y_tnode> gcc_statement_expr_item
294%type <y_op> point_or_arrow 294%type <y_op> point_or_arrow
295%type <y_tnode> argument_expression_list 295%type <y_tnode> argument_expression_list
296%type <y_tnode> unary_expression 296%type <y_tnode> unary_expression
297%type <y_tnode> cast_expression 297%type <y_tnode> cast_expression
 298%type <y_tnode> conditional_expression
 299%type <y_tnode> assignment_expression
298%type <y_tnode> expression_opt 300%type <y_tnode> expression_opt
299%type <y_tnode> expression 301%type <y_tnode> expression
300%type <y_tnode> assignment_expression 
301%type <y_tnode> constant_expr 302%type <y_tnode> constant_expr
302 303
303%type <y_type> begin_type_typespec 304%type <y_type> begin_type_typespec
304%type <y_type> type_specifier 305%type <y_type> type_specifier
305%type <y_type> notype_type_specifier 306%type <y_type> notype_type_specifier
306%type <y_type> struct_or_union_specifier 307%type <y_type> struct_or_union_specifier
307%type <y_tspec> struct_or_union 308%type <y_tspec> struct_or_union
308%type <y_sym> braced_struct_declaration_list 309%type <y_sym> braced_struct_declaration_list
309%type <y_sym> struct_declaration_list_with_rbrace 310%type <y_sym> struct_declaration_list_with_rbrace
310%type <y_sym> struct_declaration_list 311%type <y_sym> struct_declaration_list
311%type <y_sym> struct_declaration 312%type <y_sym> struct_declaration
312%type <y_sym> notype_struct_declarators 313%type <y_sym> notype_struct_declarators
313%type <y_sym> type_struct_declarators 314%type <y_sym> type_struct_declarators
@@ -552,30 +553,30 @@ gcc_statement_expr_item: @@ -552,30 +553,30 @@ gcc_statement_expr_item:
552point_or_arrow: /* helper for 'postfix_expression' */ 553point_or_arrow: /* helper for 'postfix_expression' */
553 T_POINT { 554 T_POINT {
554 symtyp = FMEMBER; 555 symtyp = FMEMBER;
555 $$ = POINT; 556 $$ = POINT;
556 } 557 }
557 | T_ARROW { 558 | T_ARROW {
558 symtyp = FMEMBER; 559 symtyp = FMEMBER;
559 $$ = ARROW; 560 $$ = ARROW;
560 } 561 }
561 ; 562 ;
562 563
563/* K&R 7.1, C90 ???, C99 6.5.2, C11 6.5.2 */ 564/* K&R 7.1, C90 ???, C99 6.5.2, C11 6.5.2 */
564argument_expression_list: 565argument_expression_list:
565 expression %prec T_COMMA { 566 assignment_expression {
566 $$ = new_function_argument_node(NULL, $1); 567 $$ = new_function_argument_node(NULL, $1);
567 } 568 }
568 | argument_expression_list T_COMMA expression { 569 | argument_expression_list T_COMMA assignment_expression {
569 $$ = new_function_argument_node($1, $3); 570 $$ = new_function_argument_node($1, $3);
570 } 571 }
571 ; 572 ;
572 573
573/* K&R 7.2, C90 ???, C99 6.5.3, C11 6.5.3 */ 574/* K&R 7.2, C90 ???, C99 6.5.3, C11 6.5.3 */
574unary_expression: 575unary_expression:
575 postfix_expression 576 postfix_expression
576 | T_INCDEC unary_expression { 577 | T_INCDEC unary_expression {
577 $$ = build($1 == INC ? INCBEF : DECBEF, $2, NULL); 578 $$ = build($1 == INC ? INCBEF : DECBEF, $2, NULL);
578 } 579 }
579 | T_AMPER cast_expression { 580 | T_AMPER cast_expression {
580 $$ = build(ADDR, $2, NULL); 581 $$ = build(ADDR, $2, NULL);
581 } 582 }
@@ -625,105 +626,108 @@ cast_expression: @@ -625,105 +626,108 @@ cast_expression:
625 unary_expression 626 unary_expression
626 | T_LPAREN type_name T_RPAREN cast_expression { 627 | T_LPAREN type_name T_RPAREN cast_expression {
627 $$ = cast($4, $2); 628 $$ = cast($4, $2);
628 } 629 }
629 ; 630 ;
630 631
631expression_opt: 632expression_opt:
632 /* empty */ { 633 /* empty */ {
633 $$ = NULL; 634 $$ = NULL;
634 } 635 }
635 | expression 636 | expression
636 ; 637 ;
637 638
638/* 'expression' also implements 'multiplicative_expression'. */ 639/* 'conditional_expression' also implements 'multiplicative_expression'. */
639/* 'expression' also implements 'additive_expression'. */ 640/* 'conditional_expression' also implements 'additive_expression'. */
640/* 'expression' also implements 'shift_expression'. */ 641/* 'conditional_expression' also implements 'shift_expression'. */
641/* 'expression' also implements 'relational_expression'. */ 642/* 'conditional_expression' also implements 'relational_expression'. */
642/* 'expression' also implements 'equality_expression'. */ 643/* 'conditional_expression' also implements 'equality_expression'. */
643/* 'expression' also implements 'AND_expression'. */ 644/* 'conditional_expression' also implements 'AND_expression'. */
644/* 'expression' also implements 'exclusive_OR_expression'. */ 645/* 'conditional_expression' also implements 'exclusive_OR_expression'. */
645/* 'expression' also implements 'inclusive_OR_expression'. */ 646/* 'conditional_expression' also implements 'inclusive_OR_expression'. */
646/* 'expression' also implements 'logical_AND_expression'. */ 647/* 'conditional_expression' also implements 'logical_AND_expression'. */
647/* 'expression' also implements 'logical_OR_expression'. */ 648/* 'conditional_expression' also implements 'logical_OR_expression'. */
648/* 'expression' also implements 'conditional_expression'. */ 649/* K&R ???, C90 ???, C99 6.5.5 to 6.5.15, C11 6.5.5 to 6.5.15 */
649/* 'expression' also implements 'assignment_expression'. */ 650conditional_expression:
650/* K&R ???, C90 ???, C99 6.5.5 to 6.5.17, C11 ??? */ 651 conditional_expression T_ASTERISK conditional_expression {
651expression: 
652 expression T_ASTERISK expression { 
653 $$ = build(MULT, $1, $3); 652 $$ = build(MULT, $1, $3);
654 } 653 }
655 | expression T_MULTIPLICATIVE expression { 654 | conditional_expression T_MULTIPLICATIVE conditional_expression {
656 $$ = build($2, $1, $3); 655 $$ = build($2, $1, $3);
657 } 656 }
658 | expression T_ADDITIVE expression { 657 | conditional_expression T_ADDITIVE conditional_expression {
659 $$ = build($2, $1, $3); 658 $$ = build($2, $1, $3);
660 } 659 }
661 | expression T_SHIFT expression { 660 | conditional_expression T_SHIFT conditional_expression {
662 $$ = build($2, $1, $3); 661 $$ = build($2, $1, $3);
663 } 662 }
664 | expression T_RELATIONAL expression { 663 | conditional_expression T_RELATIONAL conditional_expression {
665 $$ = build($2, $1, $3); 664 $$ = build($2, $1, $3);
666 } 665 }
667 | expression T_EQUALITY expression { 666 | conditional_expression T_EQUALITY conditional_expression {
668 $$ = build($2, $1, $3); 667 $$ = build($2, $1, $3);
669 } 668 }
670 | expression T_AMPER expression { 669 | conditional_expression T_AMPER conditional_expression {
671 $$ = build(BITAND, $1, $3); 670 $$ = build(BITAND, $1, $3);
672 } 671 }
673 | expression T_BITXOR expression { 672 | conditional_expression T_BITXOR conditional_expression {
674 $$ = build(BITXOR, $1, $3); 673 $$ = build(BITXOR, $1, $3);
675 } 674 }
676 | expression T_BITOR expression { 675 | conditional_expression T_BITOR conditional_expression {
677 $$ = build(BITOR, $1, $3); 676 $$ = build(BITOR, $1, $3);
678 } 677 }
679 | expression T_LOGAND expression { 678 | conditional_expression T_LOGAND conditional_expression {
680 $$ = build(LOGAND, $1, $3); 679 $$ = build(LOGAND, $1, $3);
681 } 680 }
682 | expression T_LOGOR expression { 681 | conditional_expression T_LOGOR conditional_expression {
683 $$ = build(LOGOR, $1, $3); 682 $$ = build(LOGOR, $1, $3);
684 } 683 }
685 | expression T_QUEST expression T_COLON expression { 684 | conditional_expression T_QUEST conditional_expression
 685 T_COLON conditional_expression {
686 $$ = build(QUEST, $1, build(COLON, $3, $5)); 686 $$ = build(QUEST, $1, build(COLON, $3, $5));
687 } 687 }
688 | expression T_ASSIGN expression { 688 | cast_expression;
 689
 690/* K&R ???, C90 ???, C99 6.5.16, C11 6.5.16 */
 691assignment_expression:
 692 conditional_expression
 693 | assignment_expression T_ASSIGN conditional_expression {
689 $$ = build(ASSIGN, $1, $3); 694 $$ = build(ASSIGN, $1, $3);
690 } 695 }
691 | expression T_OPASSIGN expression { 696 | assignment_expression T_OPASSIGN conditional_expression {
692 $$ = build($2, $1, $3); 697 $$ = build($2, $1, $3);
693 } 698 }
694 | expression T_COMMA expression { 
695 $$ = build(COMMA, $1, $3); 
696 } 
697 | cast_expression 
698 ; 699 ;
699 700
700/* K&R ???, C90 ???, C99 6.5.16, C11 ??? */ 701/* K&R ???, C90 ???, C99 6.5.17, C11 6.5.17 */
701assignment_expression: 702expression:
702 expression %prec T_ASSIGN 703 assignment_expression
 704 | expression T_COMMA assignment_expression {
 705 $$ = build(COMMA, $1, $3);
 706 }
703 ; 707 ;
704 708
705constant_expr_list_opt: /* helper for gcc_attribute */ 709constant_expr_list_opt: /* helper for gcc_attribute */
706 /* empty */ 710 /* empty */
707 | constant_expr_list 711 | constant_expr_list
708 ; 712 ;
709 713
710constant_expr_list: /* helper for gcc_attribute */ 714constant_expr_list: /* helper for gcc_attribute */
711 constant_expr 715 constant_expr
712 | constant_expr_list T_COMMA constant_expr 716 | constant_expr_list T_COMMA constant_expr
713 ; 717 ;
714 718
715constant_expr: /* C99 6.6 */ 719constant_expr: /* C99 6.6 */
716 expression %prec T_ASSIGN 720 conditional_expression
717 ; 721 ;
718 722
719declaration: /* C99 6.7 */ 723declaration: /* C99 6.7 */
720 begin_type_declmods end_type T_SEMI { 724 begin_type_declmods end_type T_SEMI {
721 if (dcs->d_scl == TYPEDEF) { 725 if (dcs->d_scl == TYPEDEF) {
722 /* typedef declares no type name */ 726 /* typedef declares no type name */
723 warning(72); 727 warning(72);
724 } else { 728 } else {
725 /* empty declaration */ 729 /* empty declaration */
726 warning(2); 730 warning(2);
727 } 731 }
728 } 732 }
729 | begin_type_declmods end_type notype_init_declarators T_SEMI 733 | begin_type_declmods end_type notype_init_declarators T_SEMI
@@ -1496,27 +1500,27 @@ parameter_declaration: @@ -1496,27 +1500,27 @@ parameter_declaration:
1496 */ 1500 */
1497 | begin_type_declaration_specifiers end_type type_param_declarator { 1501 | begin_type_declaration_specifiers end_type type_param_declarator {
1498 $$ = declare_argument($3, false); 1502 $$ = declare_argument($3, false);
1499 } 1503 }
1500 | begin_type_declmods end_type abstract_declarator { 1504 | begin_type_declmods end_type abstract_declarator {
1501 $$ = declare_argument($3, false); 1505 $$ = declare_argument($3, false);
1502 } 1506 }
1503 | begin_type_declaration_specifiers end_type abstract_declarator { 1507 | begin_type_declaration_specifiers end_type abstract_declarator {
1504 $$ = declare_argument($3, false); 1508 $$ = declare_argument($3, false);
1505 } 1509 }
1506 ; 1510 ;
1507 1511
1508initializer: /* C99 6.7.8 "Initialization" */ 1512initializer: /* C99 6.7.8 "Initialization" */
1509 expression %prec T_COMMA { 1513 assignment_expression {
1510 init_expr($1); 1514 init_expr($1);
1511 } 1515 }
1512 | init_lbrace init_rbrace { 1516 | init_lbrace init_rbrace {
1513 /* XXX: Empty braces are not covered by C99 6.7.8. */ 1517 /* XXX: Empty braces are not covered by C99 6.7.8. */
1514 } 1518 }
1515 | init_lbrace initializer_list comma_opt init_rbrace 1519 | init_lbrace initializer_list comma_opt init_rbrace
1516 | error 1520 | error
1517 ; 1521 ;
1518 1522
1519initializer_list: /* C99 6.7.8 "Initialization" */ 1523initializer_list: /* C99 6.7.8 "Initialization" */
1520 initializer_list_item 1524 initializer_list_item
1521 | initializer_list T_COMMA initializer_list_item 1525 | initializer_list T_COMMA initializer_list_item
1522 ; 1526 ;