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: move check for strict bool mode in...



details:   https://anonhg.NetBSD.org/src/rev/02d2fc80dead
branches:  trunk
changeset: 961021:02d2fc80dead
user:      rillig <rillig%NetBSD.org@localhost>
date:      Tue Apr 06 13:17:04 2021 +0000

description:
lint: move check for strict bool mode into separate file

No functional change.

diffstat:

 usr.bin/xlint/lint1/Makefile   |    7 +-
 usr.bin/xlint/lint1/ckbool.c   |  270 +++++++++++++++++++++++++++++++++++++++++
 usr.bin/xlint/lint1/externs1.h |    9 +-
 usr.bin/xlint/lint1/tree.c     |  211 +-------------------------------
 4 files changed, 286 insertions(+), 211 deletions(-)

diffs (truncated from 562 to 300 lines):

diff -r bc639b157201 -r 02d2fc80dead usr.bin/xlint/lint1/Makefile
--- a/usr.bin/xlint/lint1/Makefile      Tue Apr 06 13:11:22 2021 +0000
+++ b/usr.bin/xlint/lint1/Makefile      Tue Apr 06 13:17:04 2021 +0000
@@ -1,10 +1,11 @@
-#      $NetBSD: Makefile,v 1.65 2021/04/05 02:05:47 rillig Exp $
+#      $NetBSD: Makefile,v 1.66 2021/04/06 13:17:04 rillig Exp $
 
 .include <bsd.own.mk>
 
 PROG=          lint1
-SRCS=          cgram.y ckctype.c ckgetopt.c decl.c emit.c emit1.c err.c \
-               func.c init.c inittyp.c lex.c \
+SRCS=          cgram.y \
+               ckbool.c ckctype.c ckgetopt.c \
+               decl.c emit.c emit1.c err.c func.c init.c inittyp.c lex.c \
                main1.c mem.c mem1.c oper.c print.c scan.l tree.c tyname.c
 
 MAN=           lint.7
diff -r bc639b157201 -r 02d2fc80dead usr.bin/xlint/lint1/ckbool.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.bin/xlint/lint1/ckbool.c      Tue Apr 06 13:17:04 2021 +0000
@@ -0,0 +1,270 @@
+/* $NetBSD: ckbool.c,v 1.1 2021/04/06 13:17:04 rillig Exp $ */
+
+/*-
+ * Copyright (c) 2021 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Roland Illig <rillig%NetBSD.org@localhost>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+
+#if defined(__RCSID) && !defined(lint)
+__RCSID("$NetBSD: ckbool.c,v 1.1 2021/04/06 13:17:04 rillig Exp $");
+#endif
+
+#include <string.h>
+
+#include "lint1.h"
+
+
+/*
+ * The option -T treats _Bool as incompatible with all other scalar types.
+ * See d_c99_bool_strict.c for the exact rules and for examples.
+ */
+
+static const char *
+op_name(op_t op)
+{
+       return modtab[op].m_name;
+}
+
+/*
+ * See if in strict bool mode, the operator takes either two bool operands
+ * or two arbitrary other operands.
+ */
+static bool
+is_assignment_bool_or_other(op_t op)
+{
+       return op == ASSIGN ||
+              op == ANDASS || op == XORASS || op == ORASS ||
+              op == RETURN || op == INIT || 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;
+}
+
+static bool
+is_int_constant_zero(const tnode_t *tn, tspec_t t)
+{
+       return t == INT && tn->tn_op == CON && tn->tn_val->v_quad == 0;
+}
+
+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 ((ln->tn_from_system_header || rn->tn_from_system_header) &&
+           (is_int_constant_zero(ln, lt) || is_int_constant_zero(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);
+}
+
+/*
+ * Some operators require that either both operands are bool or both are
+ * scalar.
+ *
+ * Code that passes this check can be compiled in a pre-C99 environment that
+ * doesn't implement the special rule C99 6.3.1.2, without silent change in
+ * behavior.
+ */
+static bool
+typeok_strict_bool_compatible(op_t op, int arg,
+                             const tnode_t *ln, tspec_t lt,
+                             const tnode_t *rn, tspec_t rt)
+{
+
+       if (is_typeok_strict_bool(op, ln, lt, rn, rt))
+               return true;
+
+       if (op == FARG) {
+               /* argument #%d expects '%s', gets passed '%s' */
+               error(334, arg, tspec_name(lt), tspec_name(rt));
+       } else if (op == RETURN) {
+               /* return value type mismatch (%s) and (%s) */
+               error(211, tspec_name(lt), tspec_name(rt));
+       } else {
+               /* operands of '%s' have incompatible types (%s != %s) */
+               error(107, op_name(op), tspec_name(lt), tspec_name(rt));
+       }
+
+       return false;
+}
+
+/*
+ * In strict bool mode, check whether the types of the operands match the
+ * operator.
+ */
+bool
+typeok_scalar_strict_bool(op_t op, const mod_t *mp, int arg,
+                         const tnode_t *ln,
+                         const tnode_t *rn)
+
+{
+       tspec_t lt, rt;
+
+       ln = before_conversion(ln);
+       lt = ln->tn_type->t_tspec;
+
+       if (rn != NULL) {
+               rn = before_conversion(rn);
+               rt = rn->tn_type->t_tspec;
+       } else {
+               rt = NOTSPEC;
+       }
+
+       if (!typeok_strict_bool_compatible(op, arg, ln, lt, rn, rt))
+               return false;
+
+       if (mp->m_requires_bool || op == QUEST) {
+               bool binary = mp->m_binary;
+               bool lbool = is_typeok_bool_operand(ln);
+               bool ok = true;
+
+               if (!binary && !lbool) {
+                       /* operand of '%s' must be bool, not '%s' */
+                       error(330, op_name(op), tspec_name(lt));
+                       ok = false;
+               }
+               if (binary && !lbool) {
+                       /* left operand of '%s' must be bool, not '%s' */
+                       error(331, op_name(op), tspec_name(lt));
+                       ok = false;
+               }
+               if (binary && op != QUEST && !is_typeok_bool_operand(rn)) {
+                       /* right operand of '%s' must be bool, not '%s' */
+                       error(332, op_name(op), tspec_name(rt));
+                       ok = false;
+               }
+               return ok;
+       }
+
+       if (!mp->m_takes_bool) {
+               bool binary = mp->m_binary;
+               bool lbool = ln->tn_type->t_tspec == BOOL;
+               bool ok = true;
+
+               if (!binary && lbool) {
+                       /* operand of '%s' must not be bool */
+                       error(335, op_name(op));
+                       ok = false;
+               }
+               if (binary && lbool) {
+                       /* left operand of '%s' must not be bool */
+                       error(336, op_name(op));
+                       ok = false;
+               }
+               if (binary && rn->tn_type->t_tspec == BOOL) {
+                       /* right operand of '%s' must not be bool */
+                       error(337, op_name(op));
+                       ok = false;
+               }
+               return ok;
+       }
+
+       return true;
+}
+
+/*
+ * See if the node is valid as operand of an operator that compares its
+ * argument with 0.
+ */
+bool
+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 (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". */
+       if (tn->tn_op == BITAND &&
+           tn->tn_left->tn_op == CVT &&
+           tn->tn_left->tn_type->t_tspec == INT && !tn->tn_left->tn_cast &&
+           tn->tn_left->tn_left->tn_type->t_tspec == ENUM &&
+           /*
+            * XXX: Somehow the type information got lost here.  The type
+            * of the enum constant on the right-hand side should still be
+            * ENUM, but is INT.
+            */
+           tn->tn_right->tn_type->t_tspec == INT)
+               return true;
+
+       return false;
+}
+
+bool
+fallback_symbol_strict_bool(sym_t *sym)
+{
+       if (Tflag && strcmp(sym->s_name, "__lint_false") == 0) {
+               sym->s_scl = CTCONST; /* close enough */
+               sym->s_type = gettyp(BOOL);
+               sym->s_value.v_tspec = BOOL;
+               sym->s_value.v_ansiu = false;
+               sym->s_value.v_quad = 0;
+               return true;
+       }
+
+       if (Tflag && strcmp(sym->s_name, "__lint_true") == 0) {
+               sym->s_scl = CTCONST; /* close enough */
+               sym->s_type = gettyp(BOOL);
+               sym->s_value.v_tspec = BOOL;
+               sym->s_value.v_ansiu = false;
+               sym->s_value.v_quad = 1;
+               return true;
+       }
+
+       return false;
+}
diff -r bc639b157201 -r 02d2fc80dead usr.bin/xlint/lint1/externs1.h
--- a/usr.bin/xlint/lint1/externs1.h    Tue Apr 06 13:11:22 2021 +0000
+++ b/usr.bin/xlint/lint1/externs1.h    Tue Apr 06 13:17:04 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: externs1.h,v 1.100 2021/04/05 02:05:47 rillig Exp $    */
+/*     $NetBSD: externs1.h,v 1.101 2021/04/06 13:17:04 rillig Exp $    */
 
 /*



Home | Main Index | Thread Index | Old Index