Module Name: src
Committed By: rillig
Date: Thu Jan 2 17:35:02 UTC 2025
Modified Files:
src/tests/usr.bin/xlint/lint1: msg_132.c
src/usr.bin/xlint/lint1: tree.c
Log Message:
lint: fix a few wrong warnings about possible loss of accuracy
To generate a diff of this commit:
cvs rdiff -u -r1.49 -r1.50 src/tests/usr.bin/xlint/lint1/msg_132.c
cvs rdiff -u -r1.666 -r1.667 src/usr.bin/xlint/lint1/tree.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/msg_132.c
diff -u src/tests/usr.bin/xlint/lint1/msg_132.c:1.49 src/tests/usr.bin/xlint/lint1/msg_132.c:1.50
--- src/tests/usr.bin/xlint/lint1/msg_132.c:1.49 Thu Jan 2 03:46:27 2025
+++ src/tests/usr.bin/xlint/lint1/msg_132.c Thu Jan 2 17:35:02 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: msg_132.c,v 1.49 2025/01/02 03:46:27 rillig Exp $ */
+/* $NetBSD: msg_132.c,v 1.50 2025/01/02 17:35:02 rillig Exp $ */
# 3 "msg_132.c"
// Test for message: conversion from '%s' to '%s' may lose accuracy [132]
@@ -250,23 +250,36 @@ test_ic_mult(void)
// from __BITS, __SHIFTIN, __SHIFTOUT
u32 = (u16 & 1023ULL) / 1ULL * 1024ULL | (u16 & 1023ULL) / 1ULL * 1ULL;
+
+ // FIXME
+ /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */
+ s8 = 1 * s8;
+ // FIXME
+ /* expect+1: warning: conversion from 'int' to 'short' may lose accuracy [132] */
+ s16 = 1 * s16;
+ s32 = 1 * s32;
+ s64 = 1 * s64;
}
void
test_ic_div(void)
{
- // FIXME
- /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */
u8 = u8 / u8;
- // FIXME
/* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */
u8 = u16 / u8;
- // FIXME
- /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */
u16 = u8 / u8;
u16 = u32 / 65536;
/* expect+1: warning: conversion from 'unsigned int' to 'unsigned short' may lose accuracy [132] */
u16 = u32 / 65535;
+
+ // FIXME
+ /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */
+ s8 = s8 / 1;
+ // FIXME
+ /* expect+1: warning: conversion from 'int' to 'short' may lose accuracy [132] */
+ s16 = s16 / 1;
+ s32 = s32 / 1;
+ s64 = s64 / 1;
}
void
@@ -327,6 +340,11 @@ test_ic_plus(void)
/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
u8 = 256 + u64 % 1;
+ u8 = s8 + 0x80;
+ u16 = s16 + 0x8000;
+ u32 = s32 + 0x80000000;
+ u64 = s64 + 0x8000000000000000;
+
// XXX: No warnings since portable_rank_cmp is the same for both sides.
bits.u11 = bits.u10 + bits.u10 + 1;
bits.u11 = bits.u10 + bits.u10 + 2;
@@ -377,6 +395,11 @@ test_ic_minus(void)
s8 = ((s64 & 0xff) ^ 0x80) - 0x7f;
/* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
s8 = ((s64 & 0xff) ^ 0x80) - 0x81;
+
+ u8 = s8 - -0x80;
+ u16 = s16 - -0x8000;
+ u32 = s32 - -0x80000000;
+ u64 = s64 - -0x8000000000000000;
}
void
@@ -516,6 +539,12 @@ test_ic_cvt(void)
u16 = (u32_t)(u32 & 0x0000ff00);
u16 = (u16_t)u32;
u16 = (u8_t)(u32 & 0xffff) << 8;
+ u16 = (int)3.0;
+
+ u8 = (u8_t)(u64 & 0x0f);
+ u8 = (u8_t)(u64 & 0x0f) << 4;
+ /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */
+ u8 = (u8_t)(u64 & 0x0f) << 5;
}
unsigned char
Index: src/usr.bin/xlint/lint1/tree.c
diff -u src/usr.bin/xlint/lint1/tree.c:1.666 src/usr.bin/xlint/lint1/tree.c:1.667
--- src/usr.bin/xlint/lint1/tree.c:1.666 Thu Jan 2 03:46:27 2025
+++ src/usr.bin/xlint/lint1/tree.c Thu Jan 2 17:35:01 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: tree.c,v 1.666 2025/01/02 03:46:27 rillig Exp $ */
+/* $NetBSD: tree.c,v 1.667 2025/01/02 17:35:01 rillig Exp $ */
/*
* Copyright (c) 1994, 1995 Jochen Pohl
@@ -37,7 +37,7 @@
#include <sys/cdefs.h>
#if defined(__RCSID)
-__RCSID("$NetBSD: tree.c,v 1.666 2025/01/02 03:46:27 rillig Exp $");
+__RCSID("$NetBSD: tree.c,v 1.667 2025/01/02 17:35:01 rillig Exp $");
#endif
#include <float.h>
@@ -77,6 +77,20 @@ s64_abs(int64_t x)
return x >= 0 ? (uint64_t)x : -(uint64_t)x;
}
+static int64_t
+s64_shr(int64_t x, unsigned amount)
+{
+ return x >= 0
+ ? (int64_t)((uint64_t)x >> amount)
+ : (int64_t)~(~(uint64_t)x >> amount);
+}
+
+static uint64_t
+u64_min(uint64_t a, uint64_t b)
+{
+ return a < b ? a : b;
+}
+
static uint64_t
u64_max(uint64_t a, uint64_t b)
{
@@ -84,9 +98,40 @@ u64_max(uint64_t a, uint64_t b)
}
static uint64_t
+u64_fill_right(uint64_t x)
+{
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+ x |= x >> 32;
+ return x;
+}
+
+static int
+portable_rank_cmp(tspec_t t1, tspec_t t2)
+{
+ const ttab_t *p1 = type_properties(t1), *p2 = type_properties(t2);
+ lint_assert(p1->tt_rank_kind == p2->tt_rank_kind);
+ lint_assert(p1->tt_rank_value > 0);
+ lint_assert(p2->tt_rank_value > 0);
+ return (int)p1->tt_rank_value - (int)p2->tt_rank_value;
+}
+
+static unsigned
+width_in_bits(const type_t *tp)
+{
+ lint_assert(is_integer(tp->t_tspec));
+ return tp->t_bitfield
+ ? tp->t_bit_field_width
+ : size_in_bits(tp->t_tspec);
+}
+
+static uint64_t
ui_max_value(const type_t *tp)
{
- return value_bits(size_in_bits(tp->t_tspec));
+ return value_bits(width_in_bits(tp));
}
static int64_t
@@ -125,52 +170,17 @@ si_minus_sat(const type_t *tp, int64_t a
}
}
-static uint64_t
-u64_fill_right(uint64_t x)
-{
- x |= x >> 1;
- x |= x >> 2;
- x |= x >> 4;
- x |= x >> 8;
- x |= x >> 16;
- x |= x >> 32;
- return x;
-}
-
static bool
-str_ends_with(const char *haystack, const char *needle)
+ic_maybe_signed(const type_t *tp, integer_constraints ic)
{
- size_t hlen = strlen(haystack);
- size_t nlen = strlen(needle);
-
- return nlen <= hlen &&
- memcmp(haystack + hlen - nlen, needle, nlen) == 0;
-}
-
-static unsigned
-width_in_bits(const type_t *tp)
-{
-
- lint_assert(is_integer(tp->t_tspec));
- return tp->t_bitfield
- ? tp->t_bit_field_width
- : size_in_bits(tp->t_tspec);
-}
-
-static int
-portable_rank_cmp(tspec_t t1, tspec_t t2)
-{
- const ttab_t *p1 = type_properties(t1), *p2 = type_properties(t2);
- lint_assert(p1->tt_rank_kind == p2->tt_rank_kind);
- lint_assert(p1->tt_rank_value > 0);
- lint_assert(p2->tt_rank_value > 0);
- return (int)p1->tt_rank_value - (int)p2->tt_rank_value;
+ return !is_uinteger(tp->t_tspec) && ic.bclr >> 63 == 0;
}
static bool
-ic_maybe_signed(const type_t *tp, const integer_constraints *ic)
+ic_maybe_signed_binary(const type_t *tp,
+ integer_constraints a, integer_constraints b)
{
- return !is_uinteger(tp->t_tspec) && ic->bclr >> 63 == 0;
+ return !is_uinteger(tp->t_tspec) && (a.bclr & b.bclr) >> 63 == 0;
}
static integer_constraints
@@ -187,7 +197,7 @@ ic_any(const type_t *tp)
c.umax = vbits;
c.bclr = ~c.umax;
} else {
- c.smin = (int64_t)-1 - (int64_t)(vbits >> 1);
+ c.smin = -1 - (int64_t)(vbits >> 1);
c.smax = (int64_t)(vbits >> 1);
c.umin = 0;
c.umax = UINT64_MAX;
@@ -201,7 +211,7 @@ ic_mult(const type_t *tp, integer_constr
{
integer_constraints c;
- if (ic_maybe_signed(tp, &a) || ic_maybe_signed(tp, &b)
+ if (ic_maybe_signed_binary(tp, a, b)
|| (a.umax > 0 && b.umax > ic_any(tp).umax / a.umax))
return ic_any(tp);
@@ -216,43 +226,36 @@ ic_mult(const type_t *tp, integer_constr
static integer_constraints
ic_div(const type_t *tp, integer_constraints a, integer_constraints b)
{
- integer_constraints c;
-
- if (ic_maybe_signed(tp, &a) || ic_maybe_signed(tp, &b) || b.umin == 0)
+ if (ic_maybe_signed_binary(tp, a, b))
return ic_any(tp);
+ integer_constraints c;
c.smin = INT64_MIN;
c.smax = INT64_MAX;
- c.umin = a.umin / b.umax;
- c.umax = a.umax / b.umin;
+ c.umin = a.umin / u64_max(b.umax, 1);
+ c.umax = a.umax / u64_max(b.umin, 1);
c.bclr = ~u64_fill_right(c.umax);
return c;
}
static integer_constraints
-ic_mod_signed(integer_constraints a, integer_constraints b)
-{
- integer_constraints c;
-
- uint64_t max_abs_b = u64_max(s64_abs(b.smin), s64_abs(b.smax));
- if (max_abs_b >> 63 != 0 || max_abs_b == 0)
- return a;
- c.smin = s64_max(a.smin, -(int64_t)(max_abs_b - 1));
- c.smax = s64_min(a.smax, (int64_t)(max_abs_b - 1));
- c.umin = 0;
- c.umax = UINT64_MAX;
- c.bclr = 0;
- return c;
-}
-
-static integer_constraints
ic_mod(const type_t *tp, integer_constraints a, integer_constraints b)
{
- integer_constraints c;
+ if (ic_maybe_signed_binary(tp, a, b)) {
+ uint64_t max_abs_b = u64_max(s64_abs(b.smin), s64_abs(b.smax));
+ if (max_abs_b >> 63 != 0 || max_abs_b == 0)
+ return a;
- if (ic_maybe_signed(tp, &a) || ic_maybe_signed(tp, &b))
- return ic_mod_signed(a, b);
+ integer_constraints c;
+ c.smin = s64_max(a.smin, -(int64_t)(max_abs_b - 1));
+ c.smax = s64_min(a.smax, (int64_t)(max_abs_b - 1));
+ c.umin = 0;
+ c.umax = UINT64_MAX;
+ c.bclr = 0;
+ return c;
+ }
+ integer_constraints c;
c.smin = INT64_MIN;
c.smax = INT64_MAX;
c.umin = 0;
@@ -264,12 +267,12 @@ ic_mod(const type_t *tp, integer_constra
static integer_constraints
ic_plus(const type_t *tp, integer_constraints a, integer_constraints b)
{
- if (ic_maybe_signed(tp, &a) || ic_maybe_signed(tp, &b)) {
+ if (ic_maybe_signed_binary(tp, a, b)) {
integer_constraints c;
c.smin = si_plus_sat(tp, a.smin, b.smin);
c.smax = si_plus_sat(tp, a.smax, b.smax);
- c.umin = 0;
- c.umax = UINT64_MAX;
+ c.umin = c.smin >= 0 ? (uint64_t)c.smin : 0;
+ c.umax = c.smin >= 0 ? (uint64_t)c.smax : UINT64_MAX;
c.bclr = 0;
return c;
}
@@ -285,6 +288,10 @@ ic_plus(const type_t *tp, integer_constr
c.umin = 0;
c.umax = max;
}
+ if (c.umax >> 63 == 0) {
+ c.smin = 0;
+ c.smax = (int64_t)c.umax;
+ }
c.bclr = ~u64_fill_right(c.umax);
return c;
}
@@ -292,20 +299,14 @@ ic_plus(const type_t *tp, integer_constr
static integer_constraints
ic_minus(const type_t *tp, integer_constraints a, integer_constraints b)
{
- if (ic_maybe_signed(tp, &a) || ic_maybe_signed(tp, &b)) {
- integer_constraints c;
- c.smin = si_minus_sat(tp, a.smin, b.smax);
- c.smax = si_minus_sat(tp, a.smax, b.smin);
- c.umin = 0;
- c.umax = UINT64_MAX;
- c.bclr = 0;
- return c;
- }
-
integer_constraints c;
c.smin = si_minus_sat(tp, a.smin, b.smax);
c.smax = si_minus_sat(tp, a.smax, b.smin);
- if (a.umin >= b.umax) {
+
+ if (ic_maybe_signed_binary(tp, a, b)) {
+ c.umin = c.smin >= 0 ? (uint64_t)c.smin : 0;
+ c.umax = c.smin >= 0 ? (uint64_t)c.smax : UINT64_MAX;
+ } else if (a.umin >= b.umax) {
c.umin = a.umin - b.umax;
c.umax = a.umax - b.umin;
} else {
@@ -320,23 +321,27 @@ ic_minus(const type_t *tp, integer_const
static integer_constraints
ic_shl(const type_t *tp, integer_constraints a, integer_constraints b)
{
- integer_constraints c;
- unsigned int amount;
-
- if (ic_maybe_signed(tp, &a))
+ if (ic_maybe_signed(tp, a))
return ic_any(tp);
+ unsigned amount;
if (b.smin == b.smax && b.smin >= 0 && b.smin < 64)
- amount = (unsigned int)b.smin;
+ amount = (unsigned)b.smin;
else if (b.umin == b.umax && b.umin < 64)
- amount = (unsigned int)b.umin;
+ amount = (unsigned)b.umin;
else
return ic_any(tp);
- c.smin = INT64_MIN;
- c.smax = INT64_MAX;
- c.umin = 0;
- c.umax = UINT64_MAX;
+ integer_constraints c;
+ c.umin = a.umin << amount;
+ c.umax = a.umax << amount;
+ if (c.umax >> (width_in_bits(tp) - 1) == 0) {
+ c.smin = (int64_t)c.umin;
+ c.smax = (int64_t)c.umax;
+ } else {
+ c.smin = INT64_MIN;
+ c.smax = INT64_MAX;
+ }
c.bclr = a.bclr << amount | (((uint64_t)1 << amount) - 1);
return c;
}
@@ -344,23 +349,22 @@ ic_shl(const type_t *tp, integer_constra
static integer_constraints
ic_shr(const type_t *tp, integer_constraints a, integer_constraints b)
{
- integer_constraints c;
- unsigned int amount;
-
- if (ic_maybe_signed(tp, &a))
+ if (ic_maybe_signed(tp, a))
return ic_any(tp);
+ unsigned amount;
if (b.smin == b.smax && b.smin >= 0 && b.smin < 64)
- amount = (unsigned int)b.smin;
+ amount = (unsigned)b.smin;
else if (b.umin == b.umax && b.umin < 64)
- amount = (unsigned int)b.umin;
+ amount = (unsigned)b.umin;
else
return ic_any(tp);
- c.smin = INT64_MIN;
- c.smax = INT64_MAX;
- c.umin = 0;
- c.umax = UINT64_MAX;
+ integer_constraints c;
+ c.smin = s64_shr(a.smin, amount);
+ c.smax = s64_shr(a.smax, amount);
+ c.umin = a.umin >> amount;
+ c.umax = a.umax >> amount;
c.bclr = a.bclr >> amount | ~(~(uint64_t)0 >> amount);
return c;
}
@@ -369,15 +373,10 @@ static integer_constraints
ic_bitand(integer_constraints a, integer_constraints b)
{
integer_constraints c;
-
- c.smin = INT64_MIN;
- c.smax = INT64_MAX;
- c.umin = 0;
- c.umax = ~(a.bclr | b.bclr);
- if (c.umax >> 63 == 0) {
- c.smin = 0;
- c.smax = (int64_t)c.umax;
- }
+ c.smin = a.smin & b.smin;
+ c.smax = a.smax & b.smax;
+ c.umin = a.umin & b.umin;
+ c.umax = a.umax & b.umax;
c.bclr = a.bclr | b.bclr;
return c;
}
@@ -385,14 +384,14 @@ ic_bitand(integer_constraints a, integer
static integer_constraints
ic_bitxor(const type_t *tp, integer_constraints a, integer_constraints b)
{
- integer_constraints c = ic_any(tp);
- if (ic_maybe_signed(tp, &a) || ic_maybe_signed(tp, &b))
- return c;
+ if (ic_maybe_signed_binary(tp, a, b))
+ return ic_any(tp);
+
+ integer_constraints c;
+ c.smin = a.smin & b.smin;
+ c.smax = a.smax | b.smax;
+ c.umin = a.umin & b.umin;
c.umax = a.umax | b.umax;
- if (c.umax >> 63 == 0) {
- c.smin = 0;
- c.smax = (int64_t)c.umax;
- }
c.bclr = a.bclr & b.bclr;
return c;
}
@@ -401,11 +400,10 @@ static integer_constraints
ic_bitor(integer_constraints a, integer_constraints b)
{
integer_constraints c;
-
- c.smin = INT64_MIN;
- c.smax = INT64_MAX;
- c.umin = 0;
- c.umax = ~(a.bclr & b.bclr);
+ c.smin = a.smin | b.smin;
+ c.smax = a.smax | b.smax;
+ c.umin = a.umin | b.umin;
+ c.umax = a.umax | b.umax;
c.bclr = a.bclr & b.bclr;
return c;
}
@@ -414,11 +412,10 @@ static integer_constraints
ic_quest_colon(integer_constraints a, integer_constraints b)
{
integer_constraints c;
-
- c.smin = a.smin < b.smin ? a.smin : b.smin;
- c.smax = a.smax > b.smax ? a.smax : b.smax;
- c.umin = a.umin < b.umin ? a.umin : b.umin;
- c.umax = a.umax > b.umax ? a.umax : b.umax;
+ c.smin = s64_min(a.smin, b.smin);
+ c.smax = s64_max(a.smax, b.smax);
+ c.umin = u64_min(a.umin, b.umin);
+ c.umax = u64_max(a.umax, b.umax);
c.bclr = a.bclr & b.bclr;
return c;
}
@@ -426,11 +423,11 @@ ic_quest_colon(integer_constraints a, in
static integer_constraints
ic_con(const type_t *tp, const val_t *v)
{
- integer_constraints c;
-
lint_assert(is_integer(tp->t_tspec));
int64_t si = v->u.integer;
uint64_t ui = (uint64_t)si;
+
+ integer_constraints c;
c.smin = si;
c.smax = si;
c.umin = ui;
@@ -451,6 +448,8 @@ ic_cvt(const type_t *ntp, const type_t *
return a;
if (nw > ow && ou)
return a;
+ if (nu && (~value_bits(nw) & ~a.bclr) == 0)
+ return a;
return ic_any(ntp);
}
@@ -663,6 +662,16 @@ is_compiler_builtin(const char *name)
return false;
}
+static bool
+str_ends_with(const char *haystack, const char *needle)
+{
+ size_t hlen = strlen(haystack);
+ size_t nlen = strlen(needle);
+
+ return nlen <= hlen &&
+ memcmp(haystack + hlen - nlen, needle, nlen) == 0;
+}
+
/* https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html */
static bool
is_gcc_bool_builtin(const char *name)
@@ -1148,9 +1157,7 @@ fold_signed_integer(op_t op, int64_t l,
return l << (r & 63);
case SHR:
/* TODO: warn about out-of-bounds 'r'. */
- if (l < 0)
- return (int64_t)~(~(uint64_t)l >> (r & 63));
- return (int64_t)((uint64_t)l >> (r & 63));
+ return s64_shr(l, r & 63);
case LT:
return l < r ? 1 : 0;
case LE:
@@ -2515,7 +2522,7 @@ typeok_shr(op_t op,
/* operands have integer types (checked in typeok) */
if (pflag && !is_uinteger(olt)) {
integer_constraints lc = ic_expr(ln);
- if (!ic_maybe_signed(ln->tn_type, &lc))
+ if (lc.bclr >> 63 != 0)
return;
if (ln->tn_op != CON)
@@ -4215,7 +4222,7 @@ build_offsetof(const type_t *tp, designa
if (tp->t_tspec != ARRAY)
goto proceed; /* silent error */
tp = tp->t_subt;
- offset_in_bits += (unsigned) dr->dr_subscript
+ offset_in_bits += (unsigned)dr->dr_subscript
* type_size_in_bits(tp);
} else {
if (!is_struct_or_union(tp->t_tspec))