Tue Jan 5 00:17:21 2021 UTC ()
lint: extract code for determining possible precedence confusion

The function check_precedence_confusion was pretty long, and right in
the middle of that function was the complicated part of determining
which of the operand combinations are confusing and which aren't.

Extract this part into a separate function to document on which
information this decision is based.  This makes it easier to understand
the code since there are fewer local variables around.

As a left-over from a previous commit, rop and rparn don't need to be
initialized twice, now that the assertion for a binary operator is in
place.

Remove the large and useless switch statement over all operator types.
This list was completely unsorted, for no apparent reason.  To see the
list of operators, better look them up in ops.def, there was no need to
have this list duplicated here.


(rillig)
diff -r1.133 -r1.134 src/usr.bin/xlint/lint1/tree.c

cvs diff -r1.133 -r1.134 src/usr.bin/xlint/lint1/tree.c (expand / switch to unified diff)

--- src/usr.bin/xlint/lint1/tree.c 2021/01/04 23:58:19 1.133
+++ src/usr.bin/xlint/lint1/tree.c 2021/01/05 00:17:21 1.134
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: tree.c,v 1.133 2021/01/04 23:58:19 rillig Exp $ */ 1/* $NetBSD: tree.c,v 1.134 2021/01/05 00:17:21 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.
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 33
34#if HAVE_NBTOOL_CONFIG_H 34#if HAVE_NBTOOL_CONFIG_H
35#include "nbtool_config.h" 35#include "nbtool_config.h"
36#endif 36#endif
37 37
38#include <sys/cdefs.h> 38#include <sys/cdefs.h>
39#if defined(__RCSID) && !defined(lint) 39#if defined(__RCSID) && !defined(lint)
40__RCSID("$NetBSD: tree.c,v 1.133 2021/01/04 23:58:19 rillig Exp $"); 40__RCSID("$NetBSD: tree.c,v 1.134 2021/01/05 00:17:21 rillig Exp $");
41#endif 41#endif
42 42
43#include <float.h> 43#include <float.h>
44#include <limits.h> 44#include <limits.h>
45#include <math.h> 45#include <math.h>
46#include <signal.h> 46#include <signal.h>
47#include <stdlib.h> 47#include <stdlib.h>
48#include <string.h> 48#include <string.h>
49 49
50#include "lint1.h" 50#include "lint1.h"
51#include "cgram.h" 51#include "cgram.h"
52 52
53static tnode_t *new_integer_constant_node(tspec_t, int64_t); 53static tnode_t *new_integer_constant_node(tspec_t, int64_t);
@@ -3967,151 +3967,93 @@ cat_strings(strg_t *strg1, strg_t *strg2 @@ -3967,151 +3967,93 @@ cat_strings(strg_t *strg1, strg_t *strg2
3967 } while (/*CONSTCOND*/0) 3967 } while (/*CONSTCOND*/0)
3968 3968
3969 if (strg1->st_tspec == CHAR) 3969 if (strg1->st_tspec == CHAR)
3970 COPY(st_cp); 3970 COPY(st_cp);
3971 else 3971 else
3972 COPY(st_wcp); 3972 COPY(st_wcp);
3973 3973
3974 strg1->st_len = len - 1; /* - NUL */ 3974 strg1->st_len = len - 1; /* - NUL */
3975 free(strg2); 3975 free(strg2);
3976 3976
3977 return strg1; 3977 return strg1;
3978} 3978}
3979 3979
 3980static bool
 3981is_confusing_precedence(op_t op, op_t lop, bool lparen, op_t rop, bool rparen)
 3982{
 3983
 3984 if (op == SHL || op == SHR) {
 3985 if (!lparen && (lop == PLUS || lop == MINUS)) {
 3986 return true;
 3987 } else if (!rparen && (rop == PLUS || rop == MINUS)) {
 3988 return true;
 3989 }
 3990 return false;
 3991 }
 3992
 3993 if (op == LOGOR) {
 3994 if (!lparen && lop == LOGAND) {
 3995 return true;
 3996 } else if (!rparen && rop == LOGAND) {
 3997 return true;
 3998 }
 3999 return false;
 4000 }
 4001
 4002 lint_assert(op == AND || op == XOR || op == OR);
 4003 if (!lparen && lop != op) {
 4004 if (lop == PLUS || lop == MINUS) {
 4005 return true;
 4006 } else if (lop == AND || lop == XOR) {
 4007 return true;
 4008 }
 4009 }
 4010 if (!rparen && rop != op) {
 4011 if (rop == PLUS || rop == MINUS) {
 4012 return true;
 4013 } else if (rop == AND || rop == XOR) {
 4014 return true;
 4015 }
 4016 }
 4017 return false;
 4018}
 4019
3980/* 4020/*
3981 * Print a warning if the given node has operands which should be 4021 * Print a warning if the given node has operands which should be
3982 * parenthesized. 4022 * parenthesized.
3983 * 4023 *
3984 * XXX Does not work if an operand is a constant expression. Constant 4024 * XXX Does not work if an operand is a constant expression. Constant
3985 * expressions are already folded. 4025 * expressions are already folded.
3986 */ 4026 */
3987static void 4027static void
3988check_precedence_confusion(tnode_t *tn) 4028check_precedence_confusion(tnode_t *tn)
3989{ 4029{
3990 tnode_t *ln, *rn; 4030 tnode_t *ln, *rn;
3991 op_t lop, rop = NOOP; 4031 op_t lop, rop;
3992 int lparn, rparn = 0; 4032 bool lparn, rparn;
3993 mod_t *mp; 4033 mod_t *mp;
3994 int dowarn; 
3995 4034
3996 if (!hflag) 4035 if (!hflag)
3997 return; 4036 return;
3998 4037
3999 mp = &modtab[tn->tn_op]; 4038 mp = &modtab[tn->tn_op];
4000 lint_assert(mp->m_binary); 4039 lint_assert(mp->m_binary);
4001 4040
4002 dprint_node(tn); 4041 dprint_node(tn);
4003 4042
4004 lparn = 0; 4043 lparn = false;
4005 for (ln = tn->tn_left; ln->tn_op == CVT; ln = ln->tn_left) 4044 for (ln = tn->tn_left; ln->tn_op == CVT; ln = ln->tn_left)
4006 lparn |= ln->tn_parenthesized; 4045 lparn |= ln->tn_parenthesized;
4007 lparn |= ln->tn_parenthesized; 4046 lparn |= ln->tn_parenthesized;
4008 lop = ln->tn_op; 4047 lop = ln->tn_op;
4009 4048
4010 rparn = 0; 4049 rparn = false;
4011 for (rn = tn->tn_right; rn->tn_op == CVT; rn = rn->tn_left) 4050 for (rn = tn->tn_right; rn->tn_op == CVT; rn = rn->tn_left)
4012 rparn |= rn->tn_parenthesized; 4051 rparn |= rn->tn_parenthesized;
4013 rparn |= rn->tn_parenthesized; 4052 rparn |= rn->tn_parenthesized;
4014 rop = rn->tn_op; 4053 rop = rn->tn_op;
4015 4054
4016 dowarn = 0; 4055 if (is_confusing_precedence(tn->tn_op, lop, lparn, rop, rparn)) {
4017 
4018 switch (tn->tn_op) { 
4019 case SHL: 
4020 case SHR: 
4021 if (!lparn && (lop == PLUS || lop == MINUS)) { 
4022 dowarn = 1; 
4023 } else if (!rparn && (rop == PLUS || rop == MINUS)) { 
4024 dowarn = 1; 
4025 } 
4026 break; 
4027 case LOGOR: 
4028 if (!lparn && lop == LOGAND) { 
4029 dowarn = 1; 
4030 } else if (!rparn && rop == LOGAND) { 
4031 dowarn = 1; 
4032 } 
4033 break; 
4034 case AND: 
4035 case XOR: 
4036 case OR: 
4037 if (!lparn && lop != tn->tn_op) { 
4038 if (lop == PLUS || lop == MINUS) { 
4039 dowarn = 1; 
4040 } else if (lop == AND || lop == XOR) { 
4041 dowarn = 1; 
4042 } 
4043 } 
4044 if (!dowarn && !rparn && rop != tn->tn_op) { 
4045 if (rop == PLUS || rop == MINUS) { 
4046 dowarn = 1; 
4047 } else if (rop == AND || rop == XOR) { 
4048 dowarn = 1; 
4049 } 
4050 } 
4051 break; 
4052 /* LINTED206: (enumeration values not handled in switch) */ 
4053 case DECAFT: 
4054 case XORASS: 
4055 case SHLASS: 
4056 case NOOP: 
4057 case ARROW: 
4058 case ORASS: 
4059 case POINT: 
4060 case NAME: 
4061 case NOT: 
4062 case COMPL: 
4063 case CON: 
4064 case INC: 
4065 case STRING: 
4066 case DEC: 
4067 case INCBEF: 
4068 case DECBEF: 
4069 case INCAFT: 
4070 case FSEL: 
4071 case CALL: 
4072 case COMMA: 
4073 case CVT: 
4074 case ICALL: 
4075 case LOAD: 
4076 case PUSH: 
4077 case RETURN: 
4078 case INIT: 
4079 case CASE: 
4080 case FARG: 
4081 case SUBASS: 
4082 case ADDASS: 
4083 case MODASS: 
4084 case DIVASS: 
4085 case MULASS: 
4086 case ASSIGN: 
4087 case COLON: 
4088 case QUEST: 
4089 case LOGAND: 
4090 case NE: 
4091 case EQ: 
4092 case GE: 
4093 case GT: 
4094 case LE: 
4095 case LT: 
4096 case MINUS: 
4097 case PLUS: 
4098 case MOD: 
4099 case DIV: 
4100 case MULT: 
4101 case AMPER: 
4102 case STAR: 
4103 case UMINUS: 
4104 case SHRASS: 
4105 case UPLUS: 
4106 case ANDASS: 
4107 case REAL: 
4108 case IMAG: 
4109 break; 
4110 } 
4111 
4112 if (dowarn) { 
4113 /* precedence confusion possible: parenthesize! */ 4056 /* precedence confusion possible: parenthesize! */
4114 warning(169); 4057 warning(169);
4115 } 4058 }
4116 
4117} 4059}