Home | History | Annotate | Line # | Download | only in lint1
msg_132.c revision 1.19
      1 /*	$NetBSD: msg_132.c,v 1.19 2022/06/19 12:14:34 rillig Exp $	*/
      2 # 3 "msg_132.c"
      3 
      4 // Test for message: conversion from '%s' to '%s' may lose accuracy [132]
      5 
      6 /*
      7  * NetBSD's default lint flags only include a single -a, which only flags
      8  * narrowing conversions from long.  To get warnings for all narrowing
      9  * conversions, -a needs to be given more than once.
     10  *
     11  * https://gnats.netbsd.org/14531
     12  */
     13 
     14 /* lint1-extra-flags: -aa */
     15 
     16 unsigned char u8;
     17 unsigned short u16;
     18 unsigned int u32;
     19 unsigned long long u64;
     20 
     21 signed char s8;
     22 signed short s16;
     23 signed int s32;
     24 signed long long s64;
     25 
     26 void
     27 unsigned_to_unsigned(void)
     28 {
     29 	/* expect+1: warning: conversion from 'unsigned short' to 'unsigned char' may lose accuracy [132] */
     30 	u8 = u16;
     31 	/* expect+1: warning: conversion from 'unsigned int' to 'unsigned char' may lose accuracy [132] */
     32 	u8 = u32;
     33 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
     34 	u8 = u64;
     35 
     36 	u16 = u8;
     37 	/* expect+1: warning: conversion from 'unsigned int' to 'unsigned short' may lose accuracy [132] */
     38 	u16 = u32;
     39 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned short' may lose accuracy [132] */
     40 	u16 = u64;
     41 
     42 	u32 = u8;
     43 	u32 = u16;
     44 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
     45 	u32 = u64;
     46 
     47 	u64 = u8;
     48 	u64 = u16;
     49 	u64 = u32;
     50 }
     51 
     52 void
     53 unsigned_to_signed(void)
     54 {
     55 	/* expect+1: warning: conversion from 'unsigned short' to 'signed char' may lose accuracy [132] */
     56 	s8 = u16;
     57 	/* expect+1: warning: conversion from 'unsigned int' to 'signed char' may lose accuracy [132] */
     58 	s8 = u32;
     59 	/* expect+1: warning: conversion from 'unsigned long long' to 'signed char' may lose accuracy [132] */
     60 	s8 = u64;
     61 
     62 	s16 = u8;
     63 	/* expect+1: warning: conversion from 'unsigned int' to 'short' may lose accuracy [132] */
     64 	s16 = u32;
     65 	/* expect+1: warning: conversion from 'unsigned long long' to 'short' may lose accuracy [132] */
     66 	s16 = u64;
     67 
     68 	s32 = u8;
     69 	s32 = u16;
     70 	/* expect+1: warning: conversion from 'unsigned long long' to 'int' may lose accuracy [132] */
     71 	s32 = u64;
     72 
     73 	s64 = u8;
     74 	s64 = u16;
     75 	s64 = u32;
     76 }
     77 
     78 void
     79 signed_to_unsigned(void)
     80 {
     81 	/* expect+1: warning: conversion from 'short' to 'unsigned char' may lose accuracy [132] */
     82 	u8 = s16;
     83 	/* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */
     84 	u8 = s32;
     85 	/* expect+1: warning: conversion from 'long long' to 'unsigned char' may lose accuracy [132] */
     86 	u8 = s64;
     87 
     88 	u16 = s8;
     89 	/* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */
     90 	u16 = s32;
     91 	/* expect+1: warning: conversion from 'long long' to 'unsigned short' may lose accuracy [132] */
     92 	u16 = s64;
     93 
     94 	u32 = s8;
     95 	u32 = s16;
     96 	/* expect+1: warning: conversion from 'long long' to 'unsigned int' may lose accuracy [132] */
     97 	u32 = s64;
     98 
     99 	u64 = s8;
    100 	u64 = s16;
    101 	u64 = s32;
    102 }
    103 
    104 void
    105 signed_to_signed(void)
    106 {
    107 	/* expect+1: warning: conversion from 'short' to 'signed char' may lose accuracy [132] */
    108 	s8 = s16;
    109 	/* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */
    110 	s8 = s32;
    111 	/* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
    112 	s8 = s64;
    113 
    114 	s16 = s8;
    115 	/* expect+1: warning: conversion from 'int' to 'short' may lose accuracy [132] */
    116 	s16 = s32;
    117 	/* expect+1: warning: conversion from 'long long' to 'short' may lose accuracy [132] */
    118 	s16 = s64;
    119 
    120 	s32 = s8;
    121 	s32 = s16;
    122 	/* expect+1: warning: conversion from 'long long' to 'int' may lose accuracy [132] */
    123 	s32 = s64;
    124 
    125 	s64 = s8;
    126 	s64 = s16;
    127 	s64 = s32;
    128 }
    129 
    130 /*
    131  * Before tree.c 1.268 from 2021-04-06, lint wrongly warned that conversion
    132  * to _Bool might lose accuracy.  C99 6.3.1.2 defines a special conversion
    133  * rule from scalar to _Bool though by comparing the value to 0.
    134  */
    135 _Bool
    136 to_bool(long a, long b)
    137 {
    138 	/* seen in fp_lib.h, function wideRightShiftWithSticky */
    139 	return a | b;
    140 }
    141 
    142 /* ARGSUSED */
    143 const char *
    144 cover_build_plus_minus(const char *arr, double idx)
    145 {
    146 	/* expect+3: error: operands of '+' have incompatible types 'pointer' and 'double' [107] */
    147 	/* expect+2: warning: function 'cover_build_plus_minus' expects to return value [214] */
    148 	if (idx > 0.0)
    149 		return arr + idx;
    150 	return arr + (unsigned int)idx;
    151 }
    152 
    153 int
    154 non_constant_expression(void)
    155 {
    156 	/*
    157 	 * Even though this variable definition looks like a constant, it
    158 	 * does not fall within C's definition of an integer constant
    159 	 * expression.  Due to that, lint does not perform constant folding
    160 	 * on the expression built from this variable and thus doesn't know
    161 	 * that the conversion will always succeed.
    162 	 */
    163 	const int not_a_constant = 8;
    164 	/* expect+1: warning: conversion from 'unsigned long long' to 'int' may lose accuracy [132] */
    165 	return not_a_constant * 8ULL;
    166 }
    167 
    168 typedef unsigned char u8_t;
    169 typedef unsigned short u16_t;
    170 typedef unsigned int u32_t;
    171 typedef unsigned long long u64_t;
    172 
    173 /*
    174  * PR 36668 notices that lint wrongly complains about the possible loss.
    175  *
    176  * The expression 'u8_t << 8' is guaranteed to fit into an 'u16_t', and its
    177  * lower 8 bits are guaranteed to be clear.  'u16_t | u8_t' is guaranteed to
    178  * fit into 'u16_t'.
    179  *
    180  * Since tree.c 1.444 from 2022-05-26, lint tracks simple bitwise and
    181  * arithmetic constraints across a single expression.
    182  */
    183 static inline u16_t
    184 be16dec(const void *buf)
    185 {
    186 	const u8_t *p = buf;
    187 
    188 	/*
    189 	 * Before tree.c 1.444 from 2022-05-26, lint complained that the
    190 	 * conversion from 'int' to 'unsigned short' may lose accuracy.
    191 	 */
    192 	return ((u16_t)p[0]) << 8 | p[1];
    193 }
    194 
    195 /*
    196  * Since tree.c 1.434 from 2022-04-19, lint infers the possible values of
    197  * expressions of the form 'integer & constant', see can_represent.
    198  */
    199 static inline void
    200 be32enc(void *buf, u32_t u)
    201 {
    202 	u8_t *p = buf;
    203 
    204 	p[0] = u >> 24 & 0xff;
    205 	p[1] = u >> 16 & 0xff;
    206 	p[2] = u >> 8 & 0xff;
    207 	p[3] = u & 0xff;
    208 }
    209 
    210 u32_t
    211 test_ic_shr(u64_t x)
    212 {
    213 	if (x > 3)
    214 		return x >> 32;
    215 	if (x > 2)
    216 		/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
    217 		return x >> 31;
    218 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
    219 	return x;
    220 }
    221 
    222 
    223 struct bit_fields {
    224 	unsigned bits_32: 32;
    225 	unsigned bits_5: 5;
    226 	unsigned bits_3: 3;
    227 };
    228 
    229 unsigned char
    230 test_bit_fields(struct bit_fields s, unsigned long long m)
    231 {
    232 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
    233 	s.bits_3 = s.bits_32 & m;
    234 
    235 	s.bits_5 = s.bits_3 & m;
    236 	s.bits_32 = s.bits_5 & m;
    237 
    238 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
    239 	return s.bits_32 & m;
    240 }
    241