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);