lint: merge duplicate code for checking array index
This commit is contained in:
parent
6e7bb15f48
commit
4ed4a1b76a
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: tree.c,v 1.612 2024/03/09 13:54:47 rillig Exp $ */
|
/* $NetBSD: tree.c,v 1.613 2024/03/09 14:54:14 rillig Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1994, 1995 Jochen Pohl
|
* Copyright (c) 1994, 1995 Jochen Pohl
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
#if defined(__RCSID)
|
#if defined(__RCSID)
|
||||||
__RCSID("$NetBSD: tree.c,v 1.612 2024/03/09 13:54:47 rillig Exp $");
|
__RCSID("$NetBSD: tree.c,v 1.613 2024/03/09 14:54:14 rillig Exp $");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
@ -4327,52 +4327,37 @@ expr(tnode_t *tn, bool vctx, bool cond, bool dofreeblk, bool is_do_while)
|
||||||
expr_free_all();
|
expr_free_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* If the expression has the form '*(arr + idx)', check the array index. */
|
||||||
* Checks the range of array indices, if possible.
|
|
||||||
* amper is set if only the address of the element is used. This
|
|
||||||
* means that the index is allowed to refer to the first element
|
|
||||||
* after the array.
|
|
||||||
*/
|
|
||||||
static void
|
static void
|
||||||
check_array_index(tnode_t *tn, bool amper)
|
check_array_index(const tnode_t *indir, bool taking_address)
|
||||||
{
|
{
|
||||||
lint_assert(has_operands(tn));
|
const tnode_t *plus, *arr, *idx;
|
||||||
const tnode_t *ln = tn->u.ops.left;
|
|
||||||
const tnode_t *rn = tn->u.ops.right;
|
|
||||||
|
|
||||||
/* We can only check constant indices. */
|
if (indir->tn_op == INDIR
|
||||||
if (rn->tn_op != CON)
|
&& (plus = indir->u.ops.left, plus->tn_op == PLUS)
|
||||||
return;
|
&& plus->u.ops.left->tn_op == ADDR
|
||||||
|
&& (arr = plus->u.ops.left->u.ops.left, true)
|
||||||
|
&& (arr->tn_op == STRING || arr->tn_op == NAME)
|
||||||
|
&& arr->tn_type->t_tspec == ARRAY
|
||||||
|
&& (idx = plus->u.ops.right, idx->tn_op == CON)
|
||||||
|
&& (!is_incomplete(arr->tn_type) || idx->u.value.u.integer < 0))
|
||||||
|
goto proceed;
|
||||||
|
return;
|
||||||
|
|
||||||
/* Return if the left node does not stem from an array. */
|
proceed:;
|
||||||
if (ln->tn_op != ADDR)
|
int elsz = length_in_bits(arr->tn_type->t_subt, NULL);
|
||||||
return;
|
|
||||||
if (ln->u.ops.left->tn_op != STRING && ln->u.ops.left->tn_op != NAME)
|
|
||||||
return;
|
|
||||||
if (ln->u.ops.left->tn_type->t_tspec != ARRAY)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For incomplete array types, we can print a warning only if the index
|
|
||||||
* is negative.
|
|
||||||
*/
|
|
||||||
if (is_incomplete(ln->u.ops.left->tn_type)
|
|
||||||
&& rn->u.value.u.integer >= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int elsz = length_in_bits(ln->tn_type->t_subt, NULL);
|
|
||||||
if (elsz == 0)
|
if (elsz == 0)
|
||||||
return;
|
return;
|
||||||
elsz /= CHAR_SIZE;
|
elsz /= CHAR_SIZE;
|
||||||
|
|
||||||
/* Change the unit of the index from bytes to element size. */
|
/* Change the unit of the index from bytes to element size. */
|
||||||
int64_t con = is_uinteger(rn->tn_type->t_tspec)
|
int64_t con = is_uinteger(idx->tn_type->t_tspec)
|
||||||
? (int64_t)((uint64_t)rn->u.value.u.integer / elsz)
|
? (int64_t)((uint64_t)idx->u.value.u.integer / elsz)
|
||||||
: rn->u.value.u.integer / elsz;
|
: idx->u.value.u.integer / elsz;
|
||||||
|
|
||||||
int dim = ln->u.ops.left->tn_type->u.dimension + (amper ? 1 : 0);
|
int dim = arr->tn_type->u.dimension + (taking_address ? 1 : 0);
|
||||||
|
|
||||||
if (!is_uinteger(rn->tn_type->t_tspec) && con < 0)
|
if (!is_uinteger(idx->tn_type->t_tspec) && con < 0)
|
||||||
/* array subscript cannot be negative: %ld */
|
/* array subscript cannot be negative: %ld */
|
||||||
warning(167, (long)con);
|
warning(167, (long)con);
|
||||||
else if (dim > 0 && (uint64_t)con >= (uint64_t)dim)
|
else if (dim > 0 && (uint64_t)con >= (uint64_t)dim)
|
||||||
|
@ -4389,15 +4374,7 @@ check_expr_addr(const tnode_t *ln, bool szof, bool fcall)
|
||||||
mark_as_set(ln->u.sym);
|
mark_as_set(ln->u.sym);
|
||||||
mark_as_used(ln->u.sym, fcall, szof);
|
mark_as_used(ln->u.sym, fcall, szof);
|
||||||
}
|
}
|
||||||
if (ln->tn_op == INDIR && ln->u.ops.left->tn_op == PLUS)
|
check_array_index(ln, true);
|
||||||
check_array_index(ln->u.ops.left, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
check_expr_load(const tnode_t *ln)
|
|
||||||
{
|
|
||||||
if (ln->tn_op == INDIR && ln->u.ops.left->tn_op == PLUS)
|
|
||||||
check_array_index(ln->u.ops.left, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -4439,9 +4416,7 @@ check_expr_assign(const tnode_t *ln, bool szof)
|
||||||
if (ln->u.sym->s_scl == EXTERN)
|
if (ln->u.sym->s_scl == EXTERN)
|
||||||
outusg(ln->u.sym);
|
outusg(ln->u.sym);
|
||||||
}
|
}
|
||||||
if (ln->tn_op == INDIR && ln->u.ops.left->tn_op == PLUS)
|
check_array_index(ln, false);
|
||||||
/* check the range of array indices */
|
|
||||||
check_array_index(ln->u.ops.left, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -4463,7 +4438,7 @@ check_expr_op(op_t op, const tnode_t *ln, bool szof, bool fcall, bool eqwarn)
|
||||||
check_expr_addr(ln, szof, fcall);
|
check_expr_addr(ln, szof, fcall);
|
||||||
break;
|
break;
|
||||||
case LOAD:
|
case LOAD:
|
||||||
check_expr_load(ln);
|
check_array_index(ln, false);
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case INCBEF:
|
case INCBEF:
|
||||||
case DECBEF:
|
case DECBEF:
|
||||||
|
|
Loading…
Reference in New Issue