Module Name: src
Committed By: rillig
Date: Sun May 12 12:28:35 UTC 2024
Modified Files:
src/tests/usr.bin/xlint/lint1: d_c99_bool_strict.c
d_c99_bool_strict_syshdr.c
src/usr.bin/xlint/lint1: ckbool.c externs1.h func.c
Log Message:
lint: in strict bool mode, allow do-while-0
Even though 0 is not a boolean constant, allow this common idiom, to
help in those cases where the C preprocessor used by lint does not mark
tokens as coming from system headers (Clang).
To generate a diff of this commit:
cvs rdiff -u -r1.49 -r1.50 src/tests/usr.bin/xlint/lint1/d_c99_bool_strict.c
cvs rdiff -u -r1.23 -r1.24 \
src/tests/usr.bin/xlint/lint1/d_c99_bool_strict_syshdr.c
cvs rdiff -u -r1.30 -r1.31 src/usr.bin/xlint/lint1/ckbool.c
cvs rdiff -u -r1.227 -r1.228 src/usr.bin/xlint/lint1/externs1.h
cvs rdiff -u -r1.186 -r1.187 src/usr.bin/xlint/lint1/func.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/tests/usr.bin/xlint/lint1/d_c99_bool_strict.c
diff -u src/tests/usr.bin/xlint/lint1/d_c99_bool_strict.c:1.49 src/tests/usr.bin/xlint/lint1/d_c99_bool_strict.c:1.50
--- src/tests/usr.bin/xlint/lint1/d_c99_bool_strict.c:1.49 Sun May 12 11:46:14 2024
+++ src/tests/usr.bin/xlint/lint1/d_c99_bool_strict.c Sun May 12 12:28:35 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: d_c99_bool_strict.c,v 1.49 2024/05/12 11:46:14 rillig Exp $ */
+/* $NetBSD: d_c99_bool_strict.c,v 1.50 2024/05/12 12:28:35 rillig Exp $ */
# 3 "d_c99_bool_strict.c"
/*
@@ -476,7 +476,6 @@ strict_bool_controlling_expression(bool
// or nowhere.
/* expect+1: warning: loop not entered at top [207] */
do {
- /* expect+1: error: controlling expression must be bool, not 'int' [333] */
} while (0);
}
Index: src/tests/usr.bin/xlint/lint1/d_c99_bool_strict_syshdr.c
diff -u src/tests/usr.bin/xlint/lint1/d_c99_bool_strict_syshdr.c:1.23 src/tests/usr.bin/xlint/lint1/d_c99_bool_strict_syshdr.c:1.24
--- src/tests/usr.bin/xlint/lint1/d_c99_bool_strict_syshdr.c:1.23 Sun May 12 11:46:14 2024
+++ src/tests/usr.bin/xlint/lint1/d_c99_bool_strict_syshdr.c Sun May 12 12:28:35 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: d_c99_bool_strict_syshdr.c,v 1.23 2024/05/12 11:46:14 rillig Exp $ */
+/* $NetBSD: d_c99_bool_strict_syshdr.c,v 1.24 2024/05/12 12:28:35 rillig Exp $ */
# 3 "d_c99_bool_strict_syshdr.c"
/*
@@ -17,33 +17,33 @@ extern const unsigned short *ctype_table
extern void println(const char *);
+
+
+
/*
- * On NetBSD 8, <sys/select.h> defines FD_ISSET by enclosing the statements
- * in the well-known 'do { ... } while (CONSTCOND 0)' loop. The 0 in the
- * controlling expression has type INT but should be allowed nevertheless
- * since that header does not have a way to distinguish between bool and int.
- * It just follows the C99 standard, unlike the lint-provided stdbool.h,
- * which redefines 'false' to '__lint_false'.
+ * No matter whether the code is from a system header or not, the idiom
+ * 'do { ... } while (0)' is well known, and using the integer constant 0
+ * instead of the boolean constant 'false' neither creates any type confusion
+ * nor does its value take place in any conversions, as its scope is limited
+ * to the controlling expression of the loop.
*/
void
-strict_bool_system_header_statement_macro(void)
+statement_macro(void)
{
do {
println("nothing");
} while (/*CONSTCOND*/0);
- /* expect-1: error: controlling expression must be bool, not 'int' [333] */
-# 38 "d_c99_bool_strict_syshdr.c" 3 4
+# 39 "d_c99_bool_strict_syshdr.c" 3 4
do {
println("nothing");
- } while (/*CONSTCOND*/0); /* ok */
+ } while (/*CONSTCOND*/0);
-# 43 "d_c99_bool_strict_syshdr.c"
+# 44 "d_c99_bool_strict_syshdr.c"
do {
println("nothing");
} while (/*CONSTCOND*/0);
- /* expect-1: error: controlling expression must be bool, not 'int' [333] */
}
Index: src/usr.bin/xlint/lint1/ckbool.c
diff -u src/usr.bin/xlint/lint1/ckbool.c:1.30 src/usr.bin/xlint/lint1/ckbool.c:1.31
--- src/usr.bin/xlint/lint1/ckbool.c:1.30 Sat Mar 9 13:54:47 2024
+++ src/usr.bin/xlint/lint1/ckbool.c Sun May 12 12:28:34 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: ckbool.c,v 1.30 2024/03/09 13:54:47 rillig Exp $ */
+/* $NetBSD: ckbool.c,v 1.31 2024/05/12 12:28:34 rillig Exp $ */
/*-
* Copyright (c) 2021 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
#include <sys/cdefs.h>
#if defined(__RCSID)
-__RCSID("$NetBSD: ckbool.c,v 1.30 2024/03/09 13:54:47 rillig Exp $");
+__RCSID("$NetBSD: ckbool.c,v 1.31 2024/05/12 12:28:34 rillig Exp $");
#endif
#include <string.h>
@@ -149,7 +149,7 @@ typeok_scalar_strict_bool(op_t op, const
if (mp->m_compares_with_zero) {
bool binary = mp->m_binary;
- bool lbool = is_typeok_bool_compares_with_zero(ln);
+ bool lbool = is_typeok_bool_compares_with_zero(ln, false);
bool ok = true;
if (!binary && !lbool) {
@@ -163,7 +163,7 @@ typeok_scalar_strict_bool(op_t op, const
ok = false;
}
if (binary && op != QUEST &&
- !is_typeok_bool_compares_with_zero(rn)) {
+ !is_typeok_bool_compares_with_zero(rn, false)) {
/* right operand of '%s' must be bool, not '%s' */
error(332, op_name(op), tspec_name(rt));
ok = false;
@@ -198,7 +198,7 @@ typeok_scalar_strict_bool(op_t op, const
}
bool
-is_typeok_bool_compares_with_zero(const tnode_t *tn)
+is_typeok_bool_compares_with_zero(const tnode_t *tn, bool is_do_while)
{
while (tn->tn_op == COMMA)
tn = tn->u.ops.right;
@@ -206,6 +206,7 @@ is_typeok_bool_compares_with_zero(const
return tn->tn_type->t_tspec == BOOL
|| tn->tn_op == BITAND
+ || (is_do_while && is_int_constant_zero(tn, tn->tn_type->t_tspec))
|| (tn->tn_sys && is_scalar(tn->tn_type->t_tspec));
}
Index: src/usr.bin/xlint/lint1/externs1.h
diff -u src/usr.bin/xlint/lint1/externs1.h:1.227 src/usr.bin/xlint/lint1/externs1.h:1.228
--- src/usr.bin/xlint/lint1/externs1.h:1.227 Sun May 12 08:48:36 2024
+++ src/usr.bin/xlint/lint1/externs1.h Sun May 12 12:28:34 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: externs1.h,v 1.227 2024/05/12 08:48:36 rillig Exp $ */
+/* $NetBSD: externs1.h,v 1.228 2024/05/12 12:28:34 rillig Exp $ */
/*
* Copyright (c) 1994, 1995 Jochen Pohl
@@ -288,7 +288,7 @@ tnode_t *build_binary(tnode_t *, op_t, b
tnode_t *build_unary(op_t, bool, tnode_t *);
tnode_t *build_member_access(tnode_t *, op_t, bool, sbuf_t *);
tnode_t *cconv(tnode_t *);
-bool is_typeok_bool_compares_with_zero(const tnode_t *);
+bool is_typeok_bool_compares_with_zero(const tnode_t *, bool);
bool typeok(op_t, int, const tnode_t *, const tnode_t *);
tnode_t *promote(op_t, bool, tnode_t *);
tnode_t *convert(op_t, int, type_t *, tnode_t *);
Index: src/usr.bin/xlint/lint1/func.c
diff -u src/usr.bin/xlint/lint1/func.c:1.186 src/usr.bin/xlint/lint1/func.c:1.187
--- src/usr.bin/xlint/lint1/func.c:1.186 Fri Mar 29 08:35:32 2024
+++ src/usr.bin/xlint/lint1/func.c Sun May 12 12:28:34 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: func.c,v 1.186 2024/03/29 08:35:32 rillig Exp $ */
+/* $NetBSD: func.c,v 1.187 2024/05/12 12:28:34 rillig Exp $ */
/*
* Copyright (c) 1994, 1995 Jochen Pohl
@@ -37,7 +37,7 @@
#include <sys/cdefs.h>
#if defined(__RCSID)
-__RCSID("$NetBSD: func.c,v 1.186 2024/03/29 08:35:32 rillig Exp $");
+__RCSID("$NetBSD: func.c,v 1.187 2024/05/12 12:28:34 rillig Exp $");
#endif
#include <stdlib.h>
@@ -548,7 +548,7 @@ default_label(void)
}
static tnode_t *
-check_controlling_expression(tnode_t *tn)
+check_controlling_expression(tnode_t *tn, bool is_do_while)
{
tn = cconv(tn);
if (tn != NULL)
@@ -563,7 +563,8 @@ check_controlling_expression(tnode_t *tn
return NULL;
}
- if (tn != NULL && Tflag && !is_typeok_bool_compares_with_zero(tn)) {
+ if (tn != NULL && Tflag
+ && !is_typeok_bool_compares_with_zero(tn, is_do_while)) {
/* controlling expression must be bool, not '%s' */
error(333, tn->tn_type->t_is_enum ? type_name(tn->tn_type)
: tspec_name(tn->tn_type->t_tspec));
@@ -576,7 +577,7 @@ void
stmt_if_expr(tnode_t *tn)
{
if (tn != NULL)
- tn = check_controlling_expression(tn);
+ tn = check_controlling_expression(tn, false);
if (tn != NULL)
expr(tn, false, true, false, false);
begin_control_statement(CS_IF);
@@ -721,7 +722,7 @@ stmt_while_expr(tnode_t *tn)
}
if (tn != NULL)
- tn = check_controlling_expression(tn);
+ tn = check_controlling_expression(tn, false);
begin_control_statement(CS_WHILE);
cstmt->c_loop = true;
@@ -762,7 +763,7 @@ stmt_do_while_expr(tnode_t *tn)
set_reached(true);
if (tn != NULL)
- tn = check_controlling_expression(tn);
+ tn = check_controlling_expression(tn, true);
if (tn != NULL && tn->tn_op == CON) {
cstmt->c_maybe_endless = constant_is_nonzero(tn);
@@ -811,7 +812,7 @@ stmt_for_exprs(tnode_t *tn1, tnode_t *tn
expr(tn1, false, false, true, false);
if (tn2 != NULL)
- tn2 = check_controlling_expression(tn2);
+ tn2 = check_controlling_expression(tn2, false);
if (tn2 != NULL)
expr(tn2, false, true, true, false);