Module Name: src Committed By: rillig Date: Wed Jan 1 14:09:28 UTC 2025
Modified Files: src/tests/usr.bin/xlint/lint1: msg_132.c src/usr.bin/xlint/lint1: tree.c Log Message: lint: fix wrong warning about possible loss of accuracy The expression "'0' + random() % 10" always fits in a signed or unsigned char. To generate a diff of this commit: cvs rdiff -u -r1.47 -r1.48 src/tests/usr.bin/xlint/lint1/msg_132.c cvs rdiff -u -r1.664 -r1.665 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.47 src/tests/usr.bin/xlint/lint1/msg_132.c:1.48 --- src/tests/usr.bin/xlint/lint1/msg_132.c:1.47 Wed Jan 1 14:03:42 2025 +++ src/tests/usr.bin/xlint/lint1/msg_132.c Wed Jan 1 14:09:28 2025 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_132.c,v 1.47 2025/01/01 14:03:42 rillig Exp $ */ +/* $NetBSD: msg_132.c,v 1.48 2025/01/01 14:09:28 rillig Exp $ */ # 3 "msg_132.c" // Test for message: conversion from '%s' to '%s' may lose accuracy [132] @@ -307,9 +307,7 @@ test_ic_plus(void) { /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */ s8 = -129 + s64 % 1; - /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */ s8 = -128 + s64 % 1; - /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */ s8 = 127 + s64 % 1; /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */ s8 = 128 + s64 % 1; @@ -320,19 +318,15 @@ test_ic_plus(void) /* expect+2: warning: conversion of negative constant -128 to unsigned type 'unsigned long long' [222] */ /* expect+1: warning: conversion from 'unsigned long long' to 'signed char' may lose accuracy [132] */ s8 = -128 + u64 % 1; - /* expect+1: warning: conversion from 'unsigned long long' to 'signed char' may lose accuracy [132] */ s8 = 127 + u64 % 1; /* expect+1: warning: conversion from 'unsigned long long' to 'signed char' may lose accuracy [132] */ s8 = 128 + u64 % 1; - /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ u8 = 0 + u64 % 1; - /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ u8 = 255 + u64 % 1; /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ u8 = 256 + u64 % 1; - /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */ s8 = '0' + s64 % 10; } Index: src/usr.bin/xlint/lint1/tree.c diff -u src/usr.bin/xlint/lint1/tree.c:1.664 src/usr.bin/xlint/lint1/tree.c:1.665 --- src/usr.bin/xlint/lint1/tree.c:1.664 Sun Dec 15 06:04:17 2024 +++ src/usr.bin/xlint/lint1/tree.c Wed Jan 1 14:09:28 2025 @@ -1,4 +1,4 @@ -/* $NetBSD: tree.c,v 1.664 2024/12/15 06:04:17 rillig Exp $ */ +/* $NetBSD: tree.c,v 1.665 2025/01/01 14:09:28 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.664 2024/12/15 06:04:17 rillig Exp $"); +__RCSID("$NetBSD: tree.c,v 1.665 2025/01/01 14:09:28 rillig Exp $"); #endif #include <float.h> @@ -83,6 +83,45 @@ u64_max(uint64_t a, uint64_t b) return a > b ? a : b; } +static int64_t +si_min_value(const type_t *tp) +{ + uint64_t mask = value_bits(size_in_bits(tp->t_tspec)); + return -(int64_t)(mask >> 1) - 1; +} + +static int64_t +si_max_value(const type_t *tp) +{ + uint64_t mask = value_bits(size_in_bits(tp->t_tspec)); + return (int64_t)(mask >> 1); +} + +static uint64_t +ui_max_value(const type_t *tp) +{ + return value_bits(size_in_bits(tp->t_tspec)); +} + +static int64_t +si_plus_sat(const type_t *tp, int64_t a, int64_t b) +{ + if (a >= 0) { + int64_t max = si_max_value(tp); + return b <= max - a ? a + b : max; + } else { + int64_t min = si_min_value(tp); + return b >= min - a ? a + b : min; + } +} + +static uint64_t +ui_plus_sat(const type_t *tp, uint64_t a, uint64_t b) +{ + uint64_t max = ui_max_value(tp); + return b <= max - a ? a + b : max; +} + static uint64_t u64_fill_right(uint64_t x) { @@ -219,6 +258,20 @@ ic_mod(const type_t *tp, integer_constra } static integer_constraints +ic_plus(const type_t *tp, integer_constraints a, integer_constraints b) +{ + bool maybe_signed = ic_maybe_signed(tp, &a) || ic_maybe_signed(tp, &b); + + integer_constraints c; + c.smin = maybe_signed ? si_plus_sat(tp, a.smin, b.smin) : INT64_MIN; + c.smax = maybe_signed ? si_plus_sat(tp, a.smax, b.smax) : INT64_MAX; + c.umin = maybe_signed ? 0 : ui_plus_sat(tp, a.umin, b.umin); + c.umax = maybe_signed ? UINT64_MAX : ui_plus_sat(tp, a.umax, b.umax); + c.bclr = ~u64_fill_right(c.umax); + return c; +} + +static integer_constraints ic_shl(const type_t *tp, integer_constraints a, integer_constraints b) { integer_constraints c; @@ -360,6 +413,10 @@ ic_expr(const tnode_t *tn) lc = ic_expr(before_conversion(tn->u.ops.left)); rc = ic_expr(before_conversion(tn->u.ops.right)); return ic_mod(tn->tn_type, lc, rc); + case PLUS: + lc = ic_expr(before_conversion(tn->u.ops.left)); + rc = ic_expr(before_conversion(tn->u.ops.right)); + return ic_plus(tn->tn_type, lc, rc); case SHL: lc = ic_expr(tn->u.ops.left); rc = ic_expr(tn->u.ops.right);