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).
This commit is contained in:
parent
805a7e0567
commit
681c37d9da
|
@ -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 b, int i, double d, const void *p)
|
|||
// 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
do {
|
||||
println("nothing");
|
||||
} while (/*CONSTCOND*/0); /* ok */
|
||||
|
||||
# 43 "d_c99_bool_strict_syshdr.c"
|
||||
# 39 "d_c99_bool_strict_syshdr.c" 3 4
|
||||
do {
|
||||
println("nothing");
|
||||
} while (/*CONSTCOND*/0);
|
||||
|
||||
# 44 "d_c99_bool_strict_syshdr.c"
|
||||
do {
|
||||
println("nothing");
|
||||
} while (/*CONSTCOND*/0);
|
||||
/* expect-1: error: controlling expression must be bool, not 'int' [333] */
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 mod_t *mp, int arg,
|
|||
|
||||
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 mod_t *mp, int arg,
|
|||
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 mod_t *mp, int arg,
|
|||
}
|
||||
|
||||
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 tnode_t *tn)
|
|||
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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, bool, tnode_t *);
|
|||
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 *);
|
||||
|
|
|
@ -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 *tn2, tnode_t *tn3)
|
|||
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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue