Source-Changes-HG archive

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

[src/trunk]: src lint: add test for treating _Bool as non-scalar type



details:   https://anonhg.NetBSD.org/src/rev/42978c4d7b37
branches:  trunk
changeset: 1017821:42978c4d7b37
user:      rillig <rillig%NetBSD.org@localhost>
date:      Sun Jan 10 17:43:46 2021 +0000

description:
lint: add test for treating _Bool as non-scalar type

This strict mode is not yet implemented.  The plan is to use it for
usr.bin/make, to get rid of the many possible variants of defining the
Boolean type in make.h.  These variants did find some bugs, but not
reliably so.  Using static analysis seems more promising for this.

In an early stage of developing this test, lint1 crashed in the enum
definition in line 213, where the node for the '?:' had been NULL.  This
can happen in other situations as well, such as with syntax errors, but
these should be rare, as lint is usually only run if the compiler has
accepted the source code.  Still, there should not be any assertion
failures while running lint1.

diffstat:

 distrib/sets/lists/tests/mi                     |    4 +-
 tests/usr.bin/xlint/lint1/Makefile              |    4 +-
 tests/usr.bin/xlint/lint1/d_c99_bool_strict.c   |  252 ++++++++++++++++++++++++
 tests/usr.bin/xlint/lint1/d_c99_bool_strict.exp |    2 +
 tests/usr.bin/xlint/lint1/t_integration.sh      |    3 +-
 5 files changed, 262 insertions(+), 3 deletions(-)

diffs (truncated from 315 to 300 lines):

diff -r f45090dd740f -r 42978c4d7b37 distrib/sets/lists/tests/mi
--- a/distrib/sets/lists/tests/mi       Sun Jan 10 15:50:16 2021 +0000
+++ b/distrib/sets/lists/tests/mi       Sun Jan 10 17:43:46 2021 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1008 2021/01/10 11:24:42 rillig Exp $
+# $NetBSD: mi,v 1.1009 2021/01/10 17:43:46 rillig Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -5747,6 +5747,8 @@
 ./usr/tests/usr.bin/xlint/lint1/d_c99_anon_union.c             tests-usr.bin-tests     compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/d_c99_bool.c                   tests-usr.bin-tests     compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/d_c99_bool.exp                 tests-usr.bin-tests     compattestfile,atf
+./usr/tests/usr.bin/xlint/lint1/d_c99_bool_strict.c            tests-usr.bin-tests     compattestfile,atf
+./usr/tests/usr.bin/xlint/lint1/d_c99_bool_strict.exp          tests-usr.bin-tests     compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/d_c99_complex_num.c            tests-usr.bin-tests     compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/d_c99_complex_split.c          tests-usr.bin-tests     compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/d_c99_compound_literal_comma.c tests-usr.bin-tests     compattestfile,atf
diff -r f45090dd740f -r 42978c4d7b37 tests/usr.bin/xlint/lint1/Makefile
--- a/tests/usr.bin/xlint/lint1/Makefile        Sun Jan 10 15:50:16 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/Makefile        Sun Jan 10 17:43:46 2021 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.26 2021/01/10 11:24:42 rillig Exp $
+# $NetBSD: Makefile,v 1.27 2021/01/10 17:43:46 rillig Exp $
 
 NOMAN=         # defined
 
@@ -13,6 +13,8 @@
 FILES+=                d_bltinoffsetof.c
 FILES+=                d_c99_bool.c
 FILES+=                d_c99_bool.exp
+FILES+=                d_c99_bool_strict.c
+FILES+=                d_c99_bool_strict.exp
 FILES+=                d_c99_anon_struct.c
 FILES+=                d_c99_anon_union.c
 FILES+=                d_c99_complex_num.c
diff -r f45090dd740f -r 42978c4d7b37 tests/usr.bin/xlint/lint1/d_c99_bool_strict.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/usr.bin/xlint/lint1/d_c99_bool_strict.c     Sun Jan 10 17:43:46 2021 +0000
@@ -0,0 +1,252 @@
+/*     $NetBSD: d_c99_bool_strict.c,v 1.1 2021/01/10 17:43:46 rillig Exp $     */
+# 3 "d_c99_bool_strict.c"
+
+/*
+ * Experimental feature:  allow to treat _Bool as incompatible with all
+ * scalar types.  This means:
+ *
+ * SB001: Controlling expressions in 'if', 'while', 'for', '?:' must be of
+ * type _Bool instead of scalar.
+ *
+ * SB002: The operators '!', '==', '!=', '<', '<=', '>=', '>', '&&', '||'
+ * return _Bool instead of int.
+ *
+ * SB003: The operators '!', '&&', '||' take _Bool instead of scalar.
+ *
+ * SB004: The only operators that take _Bool are '!', '==', '!=',
+ * '&', '^', '|', '&&', '||', '?', ':', '=', '&=', '^=', '|='.
+ *
+ * SB005: There is no implicit conversion from _Bool to any other type.
+ *
+ * SB006: A constant integer expression is compatible with type _Bool if
+ * it is an integer constant with value 0 or 1, or if the result type of
+ * its main operator is _Bool.
+ */
+
+// Not yet implemented: /* lint1-extra-flags: -B */
+
+/*
+ * The header <stdbool.h> defines the macros bool = _Bool, false = 0 and
+ * true = 1.  Therefore, constant expressions of integer type have to be
+ * regarded as possible boolean constants if their value is either 0 or 1.
+ * At this point of the translation, the preprocessor has already removed
+ * the words "false" and "true" from the source code.
+ */
+
+/*
+ * Using a typedef for bool does not hurt the checks, they all use the
+ * underlying basic type (see tspec_t), which is BOOL.
+ */
+typedef _Bool bool;
+
+void
+SB001_controlling_expression(bool b, int i, double d, const void *p)
+{
+
+       /* Fine due to SB006. */
+       if (/*CONSTCOND*/0)
+               return;
+
+       /* Fine due to SB006. */
+       if (/*CONSTCOND*/1)
+               return;
+
+       /* Not allowed: 2 is not a boolean expression. */
+       if (/*CONSTCOND*/2)
+               return;
+
+       /* Not allowed: There is no implicit conversion from scalar to bool. */
+       if (i)
+               return;
+       if (i != 0)
+               return;
+
+       /* Not allowed: There is no implicit conversion from scalar to bool. */
+       if (d)
+               return;
+       if (d != 0.0)
+               return;
+
+       /* Not allowed: There is no implicit conversion from scalar to bool. */
+       if (p)
+               return;
+       if (p != (void *)0)
+               return;
+
+       /* Using a bool expression is allowed. */
+       if (b)
+               return;
+}
+
+void
+SB002_operator_result(bool b)
+{
+       b = b;
+       char c = b;
+       int i = b;
+       double d = b;
+       void *p = b;
+
+       /* These assignments are all ok. */
+       b = !b;
+       b = i == i;
+       b = i != i;
+       b = i < i;
+       b = i <= i;
+       b = i >= i;
+       b = i > i;
+       b = b && b;
+       b = b || b;
+
+       /*
+        * These assignments are not ok, they implicitly convert from bool
+        * to int.
+        */
+       i = !b;
+       i = i == i;
+       i = i != i;
+       i = i < i;
+       i = i <= i;
+       i = i >= i;
+       i = i > i;
+       i = b && b;
+       i = b || b;
+}
+
+void
+SB003_operands(bool b, int i)
+{
+
+       /* These assignments are ok. */
+       b = !b;
+       b = b && b;
+       b = b || b;
+
+       /* These assignments implicitly convert from scalar to bool. */
+       b = !i;
+       b = i && i;
+       b = i || i;
+}
+
+void
+SB004_non_bool_operands(bool b, unsigned u)
+{
+       b = !b;                 /* ok */
+       b = ~b;                 /* not ok */
+       ++b;                    /* not ok */
+       --b;                    /* not ok */
+       b++;                    /* not ok */
+       b--;                    /* not ok */
+       b = +b;                 /* not ok */
+       b = -b;                 /* not ok */
+
+       b = b * b;              /* not ok */
+       b = b / b;              /* not ok */
+       b = b % b;              /* not ok */
+       b = b + b;              /* not ok */
+       b = b - b;              /* not ok */
+       b = b << b;             /* not ok */
+       b = b >> b;             /* not ok */
+
+       b = b < b;              /* not ok */
+       b = b <= b;             /* not ok */
+       b = b > b;              /* not ok */
+       b = b >= b;             /* not ok */
+       b = b == b;             /* ok */
+       b = b != b;             /* ok */
+
+       b = b & b;              /* ok */
+       b = b ^ b;              /* ok */
+       b = b | b;              /* ok */
+       b = b && b;             /* ok */
+       b = b || b;             /* ok */
+       b = b ? b : b;          /* ok */
+
+       b = b;                  /* ok */
+       b *= b;                 /* not ok */
+       b /= b;                 /* not ok */
+       b %= b;                 /* not ok */
+       b += b;                 /* not ok */
+       b -= b;                 /* not ok */
+       b <<= b;                /* not ok */
+       b >>= b;                /* not ok */
+       b &= b;                 /* ok */
+       b ^= b;                 /* ok */
+       b |= b;                 /* ok */
+
+       /* Operations with mixed types. */
+       u = b * u;              /* not ok */
+       u = u * b;              /* not ok */
+       u = b / u;              /* not ok */
+       u = u / b;              /* not ok */
+       u = b % u;              /* not ok */
+       u = u % b;              /* not ok */
+       u = b + u;              /* not ok */
+       u = u + b;              /* not ok */
+       u = b - u;              /* not ok */
+       u = u - b;              /* not ok */
+       u = b << u;             /* not ok */
+       u = u << b;             /* not ok */
+       u = b >> u;             /* not ok */
+       u = u >> b;             /* not ok */
+       u = b ? u : u;          /* ok */
+       u = b ? b : u;          /* not ok */
+       u = b ? u : b;          /* not ok */
+}
+
+void
+SB005_convert_from_bool_to_scalar(bool b)
+{
+       int i;
+       unsigned u;
+       double d;
+       void *p;
+
+       i = b;                  /* not ok */
+       u = b;                  /* not ok */
+       d = b;                  /* not ok */
+       p = b;                  /* not ok */
+}
+
+enum SB006_bool_constant_expression {
+       /* Ok: 0 is a boolean constant expression. */
+       INT0 = 0 ? 100 : 101,
+
+       /* Ok: 1 is a boolean constant expression. */
+       INT1 = 1 ? 100 : 101,
+
+       /* Not ok: 2 is not a boolean constant (neither 0 nor 1). */
+       INT2 = 2 ? 100 : 101,
+
+       /*
+        * Not ok: the intermediate expression "2 - 2" has return type
+        * scalar, not bool.  It is irrelevant that the final result
+        * is 0, which would be a boolean constant.
+        */
+       ARITH = (2 - 2) ? 100 : 101,
+
+       /*
+        * Ok: The 13 and 12 are not boolean expressions, but they
+        * are not in the calculation path that leads to the final
+        * result.  The important point is that the operator '>' has
+        * return type bool.
+        */
+       Q1 = (13 > 12) ? 100 : 101,
+
+       /*
+        * Not ok: The 7 is irrelevant for the final result of the
+        * expression, yet it turns the result type of the operator
+        * '?:' to be int, not bool.
+        */
+       Q2 = (13 > 12 ? 1 : 7) ? 100 : 101,
+
+       BINAND = 0 & 1,         /* ok */
+
+       BINXOR = 0 ^ 1,         /* ok */
+
+       BINOR = 0 | 1,          /* ok */
+
+       LOGOR = 0 || 1,         /* ok */
+
+       LOGAND = 0 && 1,        /* ok */
+};
diff -r f45090dd740f -r 42978c4d7b37 tests/usr.bin/xlint/lint1/d_c99_bool_strict.exp
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/usr.bin/xlint/lint1/d_c99_bool_strict.exp   Sun Jan 10 17:43:46 2021 +0000
@@ -0,0 +1,2 @@
+d_c99_bool_strict.c(88): warning: illegal combination of pointer (pointer to void) and integer (_Bool), op = [123]
+d_c99_bool_strict.c(208): warning: illegal combination of pointer (pointer to void) and integer (_Bool), op = [123]
diff -r f45090dd740f -r 42978c4d7b37 tests/usr.bin/xlint/lint1/t_integration.sh
--- a/tests/usr.bin/xlint/lint1/t_integration.sh        Sun Jan 10 15:50:16 2021 +0000



Home | Main Index | Thread Index | Old Index