Mon Jan 4 17:06:21 2021 UTC ()
lint: in debug mode, print node tree for precedence

>From the code alone, it is too difficult to see how the various internal
operators are combined and what properties they have.  A simple tree
visualization helps to see all the details.

This is used to track down the typo in check_precedence_confusion, to
see whether it could have possibly had any influence at all.


(rillig)
diff -r1.123 -r1.124 src/usr.bin/xlint/lint1/tree.c

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

--- src/usr.bin/xlint/lint1/tree.c 2021/01/04 15:52:51 1.123
+++ src/usr.bin/xlint/lint1/tree.c 2021/01/04 17:06:20 1.124
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: tree.c,v 1.123 2021/01/04 15:52:51 rillig Exp $ */ 1/* $NetBSD: tree.c,v 1.124 2021/01/04 17:06:20 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.123 2021/01/04 15:52:51 rillig Exp $"); 40__RCSID("$NetBSD: tree.c,v 1.124 2021/01/04 17:06:20 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);
@@ -3962,26 +3962,68 @@ cat_strings(strg_t *strg1, strg_t *strg2 @@ -3962,26 +3962,68 @@ cat_strings(strg_t *strg1, strg_t *strg2
3962 } while (/*CONSTCOND*/0) 3962 } while (/*CONSTCOND*/0)
3963 3963
3964 if (strg1->st_tspec == CHAR) 3964 if (strg1->st_tspec == CHAR)
3965 COPY(st_cp); 3965 COPY(st_cp);
3966 else 3966 else
3967 COPY(st_wcp); 3967 COPY(st_wcp);
3968 3968
3969 strg1->st_len = len - 1; /* - NUL */ 3969 strg1->st_len = len - 1; /* - NUL */
3970 free(strg2); 3970 free(strg2);
3971 3971
3972 return strg1; 3972 return strg1;
3973} 3973}
3974 3974
 3975#ifdef DEBUG
 3976static void
 3977dprint_node(const tnode_t *tn)
 3978{
 3979 static int indent = 0;
 3980
 3981 op_t op = tn->tn_op;
 3982
 3983 if (tn == NULL) {
 3984 printf("%*s" "null\n", indent, "");
 3985 return;
 3986 }
 3987
 3988 printf("%*s%s: %s%s%s",
 3989 indent, "",
 3990 op == CVT && !tn->tn_cast ? "convert" :
 3991 op == NAME ? "name" : getopname(op),
 3992 type_name(tn->tn_type), tn->tn_lvalue ? " lvalue" : "",
 3993 tn->tn_parenthesized ? " ()" : "");
 3994 indent += 2;
 3995 if (op == NAME)
 3996 printf(" %s\n", tn->tn_sym->s_name);
 3997 else if (op == CON)
 3998 printf(" value=?\n");
 3999 else if (op == STRING)
 4000 printf(" length=%zu\n", tn->tn_string->st_len);
 4001 else {
 4002 printf("\n");
 4003 dprint_node(tn->tn_left);
 4004 if (modtab[op].m_binary)
 4005 dprint_node(tn->tn_right);
 4006 }
 4007 indent -= 2;
 4008}
 4009#else
 4010/*ARGSUSED*/
 4011static void
 4012dprint_node(const tnode_t *tn)
 4013{
 4014}
 4015#endif
 4016
3975/* 4017/*
3976 * Print a warning if the given node has operands which should be 4018 * Print a warning if the given node has operands which should be
3977 * parenthesized. 4019 * parenthesized.
3978 * 4020 *
3979 * XXX Does not work if an operand is a constant expression. Constant 4021 * XXX Does not work if an operand is a constant expression. Constant
3980 * expressions are already folded. 4022 * expressions are already folded.
3981 */ 4023 */
3982static void 4024static void
3983check_precedence_confusion(tnode_t *tn) 4025check_precedence_confusion(tnode_t *tn)
3984{ 4026{
3985 tnode_t *ln, *rn; 4027 tnode_t *ln, *rn;
3986 op_t lop, rop = NOOP; 4028 op_t lop, rop = NOOP;
3987 int lparn, rparn = 0; 4029 int lparn, rparn = 0;
@@ -3989,26 +4031,28 @@ check_precedence_confusion(tnode_t *tn) @@ -3989,26 +4031,28 @@ check_precedence_confusion(tnode_t *tn)
3989 int dowarn; 4031 int dowarn;
3990 4032
3991 if (!hflag) 4033 if (!hflag)
3992 return; 4034 return;
3993 4035
3994 mp = &modtab[tn->tn_op]; 4036 mp = &modtab[tn->tn_op];
3995 4037
3996 lparn = 0; 4038 lparn = 0;
3997 for (ln = tn->tn_left; ln->tn_op == CVT; ln = ln->tn_left) 4039 for (ln = tn->tn_left; ln->tn_op == CVT; ln = ln->tn_left)
3998 lparn |= ln->tn_parenthesized; 4040 lparn |= ln->tn_parenthesized;
3999 lparn |= ln->tn_parenthesized; 4041 lparn |= ln->tn_parenthesized;
4000 lop = ln->tn_op; 4042 lop = ln->tn_op;
4001 4043
 4044 dprint_node(tn);
 4045
4002 if (mp->m_binary) { 4046 if (mp->m_binary) {
4003 rparn = 0; 4047 rparn = 0;
4004 /* 4048 /*
4005 * FIXME: There is a typo "tn->tn_op == CVT", which should 4049 * FIXME: There is a typo "tn->tn_op == CVT", which should
4006 * rather be "rn->tn_op". Since tn must be a binary operator, 4050 * rather be "rn->tn_op". Since tn must be a binary operator,
4007 * it can never be CVT. 4051 * it can never be CVT.
4008 * 4052 *
4009 * Before fixing this though, there should be a unit test 4053 * Before fixing this though, there should be a unit test
4010 * that demonstrates an actual change in behavior when this 4054 * that demonstrates an actual change in behavior when this
4011 * bug gets fixed. 4055 * bug gets fixed.
4012 */ 4056 */
4013 for (rn = tn->tn_right; tn->tn_op == CVT; rn = rn->tn_left) 4057 for (rn = tn->tn_right; tn->tn_op == CVT; rn = rn->tn_left)
4014 rparn |= rn->tn_parenthesized; 4058 rparn |= rn->tn_parenthesized;