Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/xlint/lint1 lint: fix two wrong error messages in st...



details:   https://anonhg.NetBSD.org/src/rev/3dca98d042b3
branches:  trunk
changeset: 1018127:3dca98d042b3
user:      rillig <rillig%NetBSD.org@localhost>
date:      Sat Jan 23 22:20:17 2021 +0000

description:
lint: fix two wrong error messages in strict bool mode

The strict bool mode gets complicated because for system headers the
rules need to be relaxed since they cannot be changed easily, often not at all.

Still, if lint validates a program in strict bool mode, that program
must run with equal behavior regarding boolean expressions even on a
pre-C99 platform.

diffstat:

 tests/usr.bin/xlint/lint1/d_c99_bool_strict_syshdr.c   |   6 +-
 tests/usr.bin/xlint/lint1/d_c99_bool_strict_syshdr.exp |   2 -
 usr.bin/xlint/lint1/externs1.h                         |   4 +-
 usr.bin/xlint/lint1/func.c                             |   6 +-
 usr.bin/xlint/lint1/lint1.h                            |   3 +-
 usr.bin/xlint/lint1/mem1.c                             |  11 +-
 usr.bin/xlint/lint1/tree.c                             |  92 ++++++++++++-----
 7 files changed, 81 insertions(+), 43 deletions(-)

diffs (truncated from 309 to 300 lines):

diff -r efb3ad87e1b1 -r 3dca98d042b3 tests/usr.bin/xlint/lint1/d_c99_bool_strict_syshdr.c
--- a/tests/usr.bin/xlint/lint1/d_c99_bool_strict_syshdr.c      Sat Jan 23 20:00:19 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/d_c99_bool_strict_syshdr.c      Sat Jan 23 22:20:17 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: d_c99_bool_strict_syshdr.c,v 1.3 2021/01/23 19:03:55 rillig Exp $      */
+/*     $NetBSD: d_c99_bool_strict_syshdr.c,v 1.4 2021/01/23 22:20:18 rillig Exp $      */
 # 3 "d_c99_bool_strict_syshdr.c"
 
 /*
@@ -79,13 +79,13 @@
 # 80 "d_c99_bool_strict_syshdr.c" 3 4
            (int)((ctype_table + 1)[c] & 0x0040) != 0   /* BOOL */
 # 82 "d_c99_bool_strict_syshdr.c"
-       ;                       /* expect: 107 */
+       ;
 
        if (
 # 86 "d_c99_bool_strict_syshdr.c" 3 4
            (int)((ctype_table + 1)[c] & 0x0040)        /* INT */
 # 88 "d_c99_bool_strict_syshdr.c"
-       )                       /*FIXME*//* expect: 333 */
+       )
                println("system macro returning INT");
 
        if (
diff -r efb3ad87e1b1 -r 3dca98d042b3 tests/usr.bin/xlint/lint1/d_c99_bool_strict_syshdr.exp
--- a/tests/usr.bin/xlint/lint1/d_c99_bool_strict_syshdr.exp    Sat Jan 23 20:00:19 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/d_c99_bool_strict_syshdr.exp    Sat Jan 23 22:20:17 2021 +0000
@@ -1,8 +1,6 @@
 d_c99_bool_strict_syshdr.c(32): controlling expression must be bool, not 'int' [333]
 d_c99_bool_strict_syshdr.c(42): controlling expression must be bool, not 'int' [333]
 d_c99_bool_strict_syshdr.c(76): operands of '=' have incompatible types (_Bool != int) [107]
-d_c99_bool_strict_syshdr.c(82): operands of '=' have incompatible types (int != _Bool) [107]
-d_c99_bool_strict_syshdr.c(88): controlling expression must be bool, not 'int' [333]
 d_c99_bool_strict_syshdr.c(121): operands of '!=' have incompatible types (_Bool != int) [107]
 d_c99_bool_strict_syshdr.c(121): warning: function ch_isspace_sys_bool expects to return value [214]
 d_c99_bool_strict_syshdr.c(115): warning: argument c unused in function ch_isspace_sys_bool [231]
diff -r efb3ad87e1b1 -r 3dca98d042b3 usr.bin/xlint/lint1/externs1.h
--- a/usr.bin/xlint/lint1/externs1.h    Sat Jan 23 20:00:19 2021 +0000
+++ b/usr.bin/xlint/lint1/externs1.h    Sat Jan 23 22:20:17 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: externs1.h,v 1.60 2021/01/23 17:58:03 rillig Exp $     */
+/*     $NetBSD: externs1.h,v 1.61 2021/01/23 22:20:17 rillig Exp $     */
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -205,7 +205,7 @@
 extern sym_t   *struct_or_union_member(tnode_t *, op_t, sym_t *);
 extern tnode_t *build(op_t, tnode_t *, tnode_t *);
 extern tnode_t *cconv(tnode_t *);
-extern bool    is_strict_bool(const tnode_t *);
+extern bool    is_typeok_bool_operand(const tnode_t *);
 extern bool    typeok(op_t, int, const tnode_t *, const tnode_t *);
 extern tnode_t *promote(op_t, bool, tnode_t *);
 extern tnode_t *convert(op_t, int, type_t *, tnode_t *);
diff -r efb3ad87e1b1 -r 3dca98d042b3 usr.bin/xlint/lint1/func.c
--- a/usr.bin/xlint/lint1/func.c        Sat Jan 23 20:00:19 2021 +0000
+++ b/usr.bin/xlint/lint1/func.c        Sat Jan 23 22:20:17 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: func.c,v 1.64 2021/01/18 20:02:34 rillig Exp $ */
+/*     $NetBSD: func.c,v 1.65 2021/01/23 22:20:17 rillig Exp $ */
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: func.c,v 1.64 2021/01/18 20:02:34 rillig Exp $");
+__RCSID("$NetBSD: func.c,v 1.65 2021/01/23 22:20:17 rillig Exp $");
 #endif
 
 #include <stdlib.h>
@@ -550,7 +550,7 @@
                return NULL;
        }
 
-       if (tn != NULL && Tflag && !is_strict_bool(tn)) {
+       if (tn != NULL && Tflag && !is_typeok_bool_operand(tn)) {
                /* controlling expression must be bool, not '%s' */
                error(333, tspec_name(tn->tn_type->t_tspec));
                return NULL;
diff -r efb3ad87e1b1 -r 3dca98d042b3 usr.bin/xlint/lint1/lint1.h
--- a/usr.bin/xlint/lint1/lint1.h       Sat Jan 23 20:00:19 2021 +0000
+++ b/usr.bin/xlint/lint1/lint1.h       Sat Jan 23 22:20:17 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lint1.h,v 1.59 2021/01/18 19:24:09 rillig Exp $ */
+/* $NetBSD: lint1.h,v 1.60 2021/01/23 22:20:17 rillig Exp $ */
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou.  All Rights Reserved.
@@ -288,6 +288,7 @@
        bool    tn_lvalue : 1;  /* node is lvalue */
        bool    tn_cast : 1;    /* if tn_op == CVT, it's an explicit cast */
        bool    tn_parenthesized : 1;
+       bool    tn_from_system_header : 1;
        union {
                struct {
                        struct  tnode *_tn_left;        /* (left) operand */
diff -r efb3ad87e1b1 -r 3dca98d042b3 usr.bin/xlint/lint1/mem1.c
--- a/usr.bin/xlint/lint1/mem1.c        Sat Jan 23 20:00:19 2021 +0000
+++ b/usr.bin/xlint/lint1/mem1.c        Sat Jan 23 22:20:17 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mem1.c,v 1.24 2021/01/18 20:02:34 rillig Exp $ */
+/*     $NetBSD: mem1.c,v 1.25 2021/01/23 22:20:17 rillig Exp $ */
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: mem1.c,v 1.24 2021/01/18 20:02:34 rillig Exp $");
+__RCSID("$NetBSD: mem1.c,v 1.25 2021/01/23 22:20:17 rillig Exp $");
 #endif
 
 #include <sys/types.h>
@@ -348,13 +348,14 @@
 }
 
 /*
- * Get memory for a new tree node.
+ * Return a freshly allocated tree node.
  */
 tnode_t *
 getnode(void)
 {
-
-       return tgetblk(sizeof (tnode_t));
+       tnode_t *tn = tgetblk(sizeof *tn);
+       tn->tn_from_system_header = in_system_header;
+       return tn;
 }
 
 /*
diff -r efb3ad87e1b1 -r 3dca98d042b3 usr.bin/xlint/lint1/tree.c
--- a/usr.bin/xlint/lint1/tree.c        Sat Jan 23 20:00:19 2021 +0000
+++ b/usr.bin/xlint/lint1/tree.c        Sat Jan 23 22:20:17 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tree.c,v 1.182 2021/01/18 20:02:34 rillig Exp $        */
+/*     $NetBSD: tree.c,v 1.183 2021/01/23 22:20:17 rillig Exp $        */
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: tree.c,v 1.182 2021/01/18 20:02:34 rillig Exp $");
+__RCSID("$NetBSD: tree.c,v 1.183 2021/01/23 22:20:17 rillig Exp $");
 #endif
 
 #include <float.h>
@@ -722,25 +722,24 @@
        return tn;
 }
 
-static bool
-is_bool_compatible(tspec_t t, const tnode_t *tn)
-{
-       if (t == BOOL)
-               return true;
-       return in_system_header && t == INT && tn->tn_op == CON &&
-              (tn->tn_val->v_quad == 0 || tn->tn_val->v_quad == 1);
-}
-
-/* In strict bool mode, see if the node's type is compatible with bool. */
+/*
+ * See if the node is valid as operand of an operator that compares its
+ * argument with 0.
+ */
 bool
-is_strict_bool(const tnode_t *tn)
+is_typeok_bool_operand(const tnode_t *tn)
 {
        tspec_t t;
 
+       lint_assert(Tflag);
+
        tn = before_conversion(tn);
        t = tn->tn_type->t_tspec;
 
-       if (is_bool_compatible(t, tn))
+       if (t == BOOL)
+               return true;
+
+       if (tn->tn_from_system_header && is_scalar(t))
                return true;
 
        /* For enums that are used as bit sets, allow "flags & FLAG". */
@@ -1101,18 +1100,54 @@
 }
 
 /*
- * Whether the operator can handle (bool, bool) as well as (scalar, scalar),
- * but not mixtures between the two type classes.
+ * See if in strict bool mode, the operator takes either two bool operands
+ * or two arbitrary other operands.
  */
 static bool
-needs_compatible_types(op_t op)
+is_assignment_bool_or_other(op_t op)
+{
+       return op == ASSIGN ||
+              op == ANDASS || op == XORASS || op == ORASS ||
+              op == RETURN || op == FARG;
+}
+
+static bool
+is_symmetric_bool_or_other(op_t op)
 {
        return op == EQ || op == NE ||
               op == BITAND || op == BITXOR || op == BITOR ||
-              op == COLON ||
-              op == ASSIGN || op == ANDASS || op == XORASS || op == ORASS ||
-              op == RETURN ||
-              op == FARG;
+              op == COLON;
+}
+
+static bool
+is_bool_int_constant(const tnode_t *tn, tspec_t t)
+{
+       return t == INT &&
+              tn->tn_from_system_header &&
+              tn->tn_op == CON &&
+              (tn->tn_val->v_quad == 0 || tn->tn_val->v_quad == 1);
+}
+
+static bool
+is_typeok_strict_bool(op_t op,
+                     const tnode_t *ln, tspec_t lt,
+                     const tnode_t *rn, tspec_t rt)
+{
+       if (rn == NULL)
+               return true;    /* TODO: check unary operators as well. */
+
+       if ((lt == BOOL) == (rt == BOOL))
+               return true;
+
+       if (is_bool_int_constant(ln, lt) || is_bool_int_constant(rn, rt))
+               return true;
+
+       if (is_assignment_bool_or_other(op)) {
+               return lt != BOOL &&
+                      (ln->tn_from_system_header || rn->tn_from_system_header);
+       }
+
+       return !is_symmetric_bool_or_other(op);
 }
 
 /*
@@ -1129,9 +1164,7 @@
                              const tnode_t *rn, tspec_t rt)
 {
 
-       if (!needs_compatible_types(op))
-               return true;
-       if (is_bool_compatible(lt, ln) == is_bool_compatible(rt, rn))
+       if (is_typeok_strict_bool(op, ln, lt, rn, rt))
                return true;
 
        if (op == FARG) {
@@ -1175,7 +1208,7 @@
 
        if (mp->m_requires_bool || op == QUEST) {
                bool binary = mp->m_binary;
-               bool lbool = is_strict_bool(ln);
+               bool lbool = is_typeok_bool_operand(ln);
                bool ok = true;
 
                if (!binary && !lbool) {
@@ -1188,7 +1221,7 @@
                        error(331, getopname(op), tspec_name(lt));
                        ok = false;
                }
-               if (binary && op != QUEST && !is_strict_bool(rn)) {
+               if (binary && op != QUEST && !is_typeok_bool_operand(rn)) {
                        /* right operand of '%s' must be bool, not '%s' */
                        error(332, getopname(op), tspec_name(rt));
                        ok = false;
@@ -1521,7 +1554,7 @@
        if (lt == BOOL && is_scalar(rt))        /* C99 6.3.1.2 */
                return true;
 
-       if (is_arithmetic(lt) && is_arithmetic(rt))
+       if (is_arithmetic(lt) && (is_arithmetic(rt) || rt == BOOL))
                return true;
 
        if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION))
@@ -1773,6 +1806,10 @@
 
        ntn->tn_op = op;
        ntn->tn_type = type;
+       if (ln->tn_from_system_header)
+               ntn->tn_from_system_header = true;
+       if (rn != NULL && rn->tn_from_system_header)
+               ntn->tn_from_system_header = true;
        ntn->tn_left = ln;
        ntn->tn_right = rn;



Home | Main Index | Thread Index | Old Index