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/ed7453739773
branches:  trunk
changeset: 949358:ed7453739773
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 2da563c0fee6 -r ed7453739773 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 2da563c0fee6 -r ed7453739773 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 2da563c0fee6 -r ed7453739773 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 2da563c0fee6 -r ed7453739773 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 2da563c0fee6 -r ed7453739773 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