1 /* $NetBSD: queries.c,v 1.6 2022/09/24 19:55:44 rillig Exp $ */ 2 # 3 "queries.c" 3 4 /* 5 * Demonstrate the case-by-case queries. Unlike warnings, queries do not 6 * point to questionable code but rather to code that may be interesting to 7 * inspect manually on a case-by-case basis. 8 * 9 * Possible use cases are: 10 * 11 * Understanding how C works internally, by making the usual arithmetic 12 * conversions visible. 13 * 14 * Finding code that intentionally suppresses a regular lint warning, 15 * such as casts between arithmetic types. 16 */ 17 18 /* lint1-extra-flags: -q 1,2,3,4,5,6,7 */ 19 20 typedef unsigned char u8_t; 21 typedef unsigned short u16_t; 22 typedef unsigned int u32_t; 23 typedef unsigned long long u64_t; 24 typedef signed char s8_t; 25 typedef signed short s16_t; 26 typedef signed int s32_t; 27 typedef signed long long s64_t; 28 29 typedef float f32_t; 30 typedef double f64_t; 31 typedef float _Complex c32_t; 32 typedef double _Complex c64_t; 33 34 typedef char *str_t; 35 typedef const char *cstr_t; 36 typedef volatile char *vstr_t; 37 38 _Bool cond; 39 40 u8_t u8; 41 u16_t u16; 42 u32_t u32; 43 u64_t u64; 44 45 s8_t s8; 46 s16_t s16; 47 s32_t s32; 48 s64_t s64; 49 50 struct { 51 unsigned u8:8; 52 unsigned u9:9; 53 unsigned u10:10; 54 unsigned u32:32; 55 int s8:8; 56 int s9:9; 57 int s10:10; 58 int s32:32; 59 } bits; 60 61 f32_t f32; 62 f64_t f64; 63 64 c32_t c32; 65 c64_t c64; 66 67 char *str; 68 const char *cstr; 69 volatile char *vstr; 70 71 int 72 Q1(double dbl) 73 { 74 /* expect+1: implicit conversion from floating point 'double' to integer 'int' [Q1] */ 75 return dbl; 76 } 77 78 int 79 Q2(double dbl) 80 { 81 /* expect+1: cast from floating point 'double' to integer 'int' [Q2] */ 82 return (int)dbl; 83 } 84 85 void 86 Q3(int i, unsigned u) 87 { 88 /* expect+1: implicit conversion changes sign from 'int' to 'unsigned int' [Q3] */ 89 u = i; 90 91 /* expect+1: implicit conversion changes sign from 'unsigned int' to 'int' [Q3] */ 92 i = u; 93 } 94 95 unsigned long long 96 Q4(signed char *ptr, int i, unsigned long long ull) 97 { 98 /* 99 * The conversion from 'signed char' to 'int' is done by the integer 100 * promotions (C11 6.3.1.1p2), not by the usual arithmetic 101 * conversions (C11 6.3.1.8p1). 102 */ 103 /* expect+2: usual arithmetic conversion for '+' from 'int' to 'unsigned long long' [Q4] */ 104 /* expect+1: implicit conversion changes sign from 'int' to 'unsigned long long' [Q3] */ 105 return ptr[0] + ptr[1] + i + ull; 106 } 107 108 void 109 Q5(signed char *ptr, int i) 110 { 111 if (ptr + i > ptr) 112 return; 113 114 /* expect+1: pointer addition has integer on the left-hand side [Q5] */ 115 if (i + ptr > ptr) 116 return; 117 118 if (ptr[i] != '\0') 119 return; 120 121 /* expect+1: pointer addition has integer on the left-hand side [Q5] */ 122 if (i[ptr] != '\0') 123 return; 124 } 125 126 void 127 Q6(int i) 128 { 129 /* expect+1: no-op cast from 'int' to 'int' [Q6] */ 130 i = (int)4; 131 132 /* expect+1: no-op cast from 'int' to 'int' [Q6] */ 133 i = (int)i + 1; 134 } 135 136 extern void *allocate(void); 137 138 void 139 Q7(void) 140 { 141 142 /* expect+2: no-op cast from '_Bool' to '_Bool' [Q6] */ 143 /* expect+1: redundant cast from '_Bool' to '_Bool' before assignment [Q7] */ 144 cond = (_Bool)cond; 145 cond = (_Bool)u8; 146 u8 = (u8_t)cond; 147 148 /* expect+2: no-op cast from 'unsigned char' to 'unsigned char' [Q6] */ 149 /* expect+1: redundant cast from 'unsigned char' to 'unsigned char' before assignment [Q7] */ 150 u8 = (u8_t)u8; 151 u8 = (u8_t)u16; 152 u8 = (u16_t)u8; 153 /* expect+1: no-op cast from 'unsigned short' to 'unsigned short' [Q6] */ 154 u8 = (u16_t)u16; 155 /* expect+1: no-op cast from 'unsigned char' to 'unsigned char' [Q6] */ 156 u16 = (u8_t)u8; 157 u16 = (u8_t)u16; 158 /* expect+1: redundant cast from 'unsigned char' to 'unsigned short' before assignment [Q7] */ 159 u16 = (u16_t)u8; 160 /* expect+2: no-op cast from 'unsigned short' to 'unsigned short' [Q6] */ 161 /* expect+1: redundant cast from 'unsigned short' to 'unsigned short' before assignment [Q7] */ 162 u16 = (u16_t)u16; 163 164 /* Mixing signed and unsigned types. */ 165 u8 = (u8_t)s8; 166 s8 = (s8_t)u8; 167 /* expect+1: redundant cast from 'unsigned char' to 'short' before assignment [Q7] */ 168 s16 = (s16_t)u8; 169 /* expect+1: redundant cast from 'signed char' to 'short' before assignment [Q7] */ 170 s16 = (s16_t)s8; 171 172 173 /* 174 * Neither GCC nor Clang accept typeof(bit-field), as that would add 175 * unnecessary complexity. Lint accepts it but silently discards the 176 * bit-field portion from the type; see dcs_add_type. 177 */ 178 /* expect+1: redundant cast from 'unsigned char' to 'unsigned int' before assignment [Q7] */ 179 bits.u9 = (typeof(bits.u9))u8; 180 181 182 /* expect+2: no-op cast from 'float' to 'float' [Q6] */ 183 /* expect+1: redundant cast from 'float' to 'float' before assignment [Q7] */ 184 f32 = (f32_t)f32; 185 f32 = (f32_t)f64; 186 f32 = (f64_t)f32; 187 /* expect+1: no-op cast from 'double' to 'double' [Q6] */ 188 f32 = (f64_t)f64; 189 /* expect+1: no-op cast from 'float' to 'float' [Q6] */ 190 f64 = (f32_t)f32; 191 f64 = (f32_t)f64; 192 /* expect+1: redundant cast from 'float' to 'double' before assignment [Q7] */ 193 f64 = (f64_t)f32; 194 /* expect+2: no-op cast from 'double' to 'double' [Q6] */ 195 /* expect+1: redundant cast from 'double' to 'double' before assignment [Q7] */ 196 f64 = (f64_t)f64; 197 198 199 /* expect+2: no-op cast from 'float _Complex' to 'float _Complex' [Q6] */ 200 /* expect+1: redundant cast from 'float _Complex' to 'float _Complex' before assignment [Q7] */ 201 c32 = (c32_t)c32; 202 c32 = (c32_t)c64; 203 c32 = (c64_t)c32; 204 /* expect+1: no-op cast from 'double _Complex' to 'double _Complex' [Q6] */ 205 c32 = (c64_t)c64; 206 /* expect+1: no-op cast from 'float _Complex' to 'float _Complex' [Q6] */ 207 c64 = (c32_t)c32; 208 c64 = (c32_t)c64; 209 /* expect+1: redundant cast from 'float _Complex' to 'double _Complex' before assignment [Q7] */ 210 c64 = (c64_t)c32; 211 /* expect+2: no-op cast from 'double _Complex' to 'double _Complex' [Q6] */ 212 /* expect+1: redundant cast from 'double _Complex' to 'double _Complex' before assignment [Q7] */ 213 c64 = (c64_t)c64; 214 215 216 /* Mixing real and complex floating point types. */ 217 /* expect+1: no-op cast from 'float' to 'float' [Q6] */ 218 c32 = (f32_t)f32; 219 c32 = (c32_t)f32; 220 /* expect+1: no-op cast from 'float' to 'float' [Q6] */ 221 c64 = (f32_t)f32; 222 c64 = (f64_t)f32; 223 c64 = (c32_t)f32; 224 c64 = (c64_t)f32; 225 226 227 /* expect+1: redundant cast from 'pointer to void' to 'pointer to char' before assignment [Q7] */ 228 str = (char *)allocate(); 229 /* expect+1: redundant cast from 'pointer to void' to 'pointer to const char' before assignment [Q7] */ 230 cstr = (const char *)allocate(); 231 cstr = (char *)allocate(); 232 233 /* expect+2: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */ 234 /* expect+1: redundant cast from 'pointer to char' to 'pointer to char' before assignment [Q7] */ 235 str = (str_t)str; 236 str = (str_t)cstr; 237 /* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'const char' [128] */ 238 str = (cstr_t)str; 239 /* expect+2: no-op cast from 'pointer to const char' to 'pointer to const char' [Q6] */ 240 /* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'const char' [128] */ 241 str = (cstr_t)cstr; 242 /* expect+1: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */ 243 cstr = (str_t)str; 244 cstr = (str_t)cstr; 245 cstr = (cstr_t)str; 246 /* expect+2: no-op cast from 'pointer to const char' to 'pointer to const char' [Q6] */ 247 /* expect+1: redundant cast from 'pointer to const char' to 'pointer to const char' before assignment [Q7] */ 248 cstr = (cstr_t)cstr; 249 250 /* expect+2: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */ 251 /* expect+1: redundant cast from 'pointer to char' to 'pointer to char' before assignment [Q7] */ 252 str = (str_t)str; 253 str = (str_t)vstr; 254 /* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'volatile char' [128] */ 255 str = (vstr_t)str; 256 /* expect+2: no-op cast from 'pointer to volatile char' to 'pointer to volatile char' [Q6] */ 257 /* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'volatile char' [128] */ 258 str = (vstr_t)vstr; 259 /* expect+1: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */ 260 vstr = (str_t)str; 261 vstr = (str_t)vstr; 262 vstr = (vstr_t)str; 263 /* expect+2: no-op cast from 'pointer to volatile char' to 'pointer to volatile char' [Q6] */ 264 /* expect+1: redundant cast from 'pointer to volatile char' to 'pointer to volatile char' before assignment [Q7] */ 265 vstr = (vstr_t)vstr; 266 } 267 268 269 /* 270 * Since queries do not affect the exit status, force a warning to make this 271 * test conform to the general expectation that a test that produces output 272 * exits non-successfully. 273 */ 274 /* expect+1: warning: static variable 'unused' unused [226] */ 275 static int unused; 276