1 /* $NetBSD: emit.c,v 1.18 2024/06/09 16:49:40 rillig Exp $ */ 2 # 3 "emit.c" 3 4 /* 5 * Test the symbol information that lint1 writes to a .ln file. Using this 6 * symbol information, lint2 later checks that the symbols are used 7 * consistently across different translation units. 8 */ 9 10 /* Do not warn about unused parameters or 'extern' declarations. */ 11 /* lint1-extra-flags: -X 231 -X 351 */ 12 13 /* 14 * Define some derived types. 15 */ 16 17 struct struct_tag { 18 int member; 19 }; 20 21 typedef struct { 22 int member; 23 } struct_typedef; 24 25 union union_tag { 26 int member; 27 }; 28 29 typedef union { 30 int member; 31 } union_typedef; 32 33 enum enum_tag { 34 enum_tag_constant 35 }; 36 37 typedef enum { 38 enum_typedef_constant 39 } enum_typedef; 40 41 /* 42 * Variable declarations using the basic types (C99 6.2.5p14). 43 * 44 * Last synced with function outtype from emit1.c 1.43. 45 */ 46 47 extern _Bool extern__Bool; 48 extern float _Complex extern__Complex_float; 49 extern double _Complex extern__Complex_double; 50 extern long double _Complex extern__Complex_long_double; 51 extern char extern_char; 52 extern signed char extern_signed_char; 53 extern unsigned char extern_unsigned_char; 54 extern short extern_short; 55 extern signed short extern_signed_short; 56 extern unsigned short extern_unsigned_short; 57 extern int extern_int; 58 extern signed int extern_signed_int; 59 extern unsigned int extern_unsigned_int; 60 extern long extern_long; 61 extern signed long extern_signed_long; 62 extern unsigned long extern_unsigned_long; 63 extern long long extern_long_long; 64 extern signed long long extern_signed_long_long; 65 extern unsigned long long extern_unsigned_long_long; 66 extern float extern_float; 67 extern double extern_double; 68 extern long double extern_long_double; 69 70 /* 71 * Variable declarations using derived types (C99 6.2.5p20). 72 */ 73 74 extern void * extern_pointer_to_void; 75 extern int extern_array_5_of_int[5]; 76 77 /* 78 * Type tags are written to the .ln file as 'T kind length name', where 'kind' 79 * is either 1, 2 or 3. This is confusing at first since in 'T110struct_tag', 80 * the apparent number 110 is to be read as 'tag kind 1, length 10'. 81 */ 82 extern struct struct_tag extern_struct_tag; 83 extern struct_typedef extern_struct_typedef; 84 extern union union_tag extern_union_tag; 85 extern union_typedef extern_union_typedef; 86 extern enum enum_tag extern_enum_tag; 87 extern enum_typedef extern_enum_typedef; 88 89 extern struct { 90 int member; 91 } extern_anonymous_struct; 92 extern union { 93 int member; 94 } extern_anonymous_union; 95 extern enum { 96 anonymous_enum_constant 97 } extern_anonymous_enum; 98 99 /* 100 * Variable definitions. 101 * 102 * Static variables are not recorded in the .ln file. 103 */ 104 105 extern int declared_int; 106 int defined_int; 107 /* expect+1: warning: static variable 'static_int' unused [226] */ 108 static int static_int; 109 110 /* 111 * Type qualifiers. 112 */ 113 114 extern const int extern_const_int; 115 extern volatile int extern_volatile_int; 116 extern const volatile int extern_const_volatile_int; 117 118 /* 119 * Functions. 120 */ 121 122 extern void return_void_unknown_parameters(); 123 extern /* implicit int */ return_implicit_int_unknown_parameters(); 124 /* expect-1: error: old-style declaration; add 'int' [1] */ 125 /* For function declarations, the keyword 'extern' is optional. */ 126 extern void extern_return_void_no_parameters(void); 127 /* implicit extern */ void return_void_no_parameters(void); 128 /* expect+1: warning: static function 'static_return_void_no_parameters' declared but not defined [290] */ 129 static void static_return_void_no_parameters(void); 130 131 void taking_int(int); 132 /* The 'const' parameter does not make a difference. */ 133 void taking_const_int(const int); 134 void taking_int_double_bool(int, double, _Bool); 135 void taking_struct_union_enum_tags(struct struct_tag, union union_tag, 136 enum enum_tag); 137 void taking_struct_union_enum_typedefs(struct_typedef, union_typedef, 138 enum_typedef); 139 140 void taking_varargs(const char *, ...); 141 142 /* 143 * This function does not affect anything outside this translation unit. 144 * Naively there is no need to record this function in the .ln file, but it 145 * is nevertheless recorded. There's probably a good reason for recording 146 * it. 147 */ 148 /* expect+1: warning: static function 'static_function' declared but not defined [290] */ 149 static int static_function(void); 150 151 void my_printf(const char *, ...); 152 void my_scanf(const char *, ...); 153 154 /* 155 * String literals that occur in function calls are written to the .ln file, 156 * just in case they are related to a printf-like or scanf-like function. 157 * 158 * In this example, the various strings are not format strings, they just 159 * serve to cover the code that escapes character literals (outqchar in 160 * lint1) and reads them back into characters (inpqstrg in lint2). 161 */ 162 void 163 cover_outqchar(void) 164 { 165 my_printf("%s", "%"); 166 my_printf("%s", "%s"); 167 my_printf("%s", "%%"); 168 my_printf("%s", "%\\ %\" %' %\a %\b %\f %\n %\r %\t %\v %\177"); 169 } 170 171 void 172 cover_outfstrg(void) 173 { 174 my_printf("%s", "%-3d %+3d % d %#x %03d %*.*s %6.2f %hd %ld %Ld %qd"); 175 my_scanf("%s", "%[0-9]s %[^A-Za-z]s %[][A-Za-z0-9]s %[+-]s"); 176 } 177 178 /* 179 * Calls to GCC builtin functions should not be emitted since GCC already 180 * guarantees a consistent definition of these function and checks the 181 * arguments, so there is nothing left to do for lint. 182 */ 183 void 184 call_gcc_builtins(int x, long *ptr) 185 { 186 long value; 187 188 __builtin_expect(x > 0, 1); 189 __builtin_bswap32(0x12345678); 190 191 __atomic_load(ptr, &value, 0); 192 } 193 194 /* 195 * XXX: It's strange that a function can be annotated with VARARGS even 196 * though it does not take varargs at all. 197 * 198 * This feature is not useful for modern code anyway, it focused on pre-C90 199 * code that did not have function prototypes. 200 */ 201 202 /* VARARGS */ 203 void 204 varargs_comment(const char *fmt) 205 { 206 } 207 208 /* VARARGS 0 */ 209 void 210 varargs_0_comment(const char *fmt) 211 { 212 } 213 214 /* VARARGS 3 */ 215 void 216 varargs_3_comment(int a, int b, int c, const char *fmt) 217 { 218 } 219 220 /* PRINTFLIKE */ 221 void 222 printflike_comment(const char *fmt) 223 { 224 } 225 226 /* PRINTFLIKE 0 */ 227 void 228 printflike_0_comment(const char *fmt) 229 { 230 } 231 232 /* PRINTFLIKE 3 */ 233 void 234 printflike_3_comment(int a, int b, const char *fmt) 235 { 236 } 237 238 /* PRINTFLIKE 10 */ 239 void 240 printflike_10_comment(int a1, int a2, int a3, int a4, int a5, 241 int a6, int a7, int a8, int a9, 242 const char *fmt) 243 { 244 } 245 246 /* SCANFLIKE */ 247 void 248 scanflike_comment(const char *fmt) 249 { 250 } 251 252 /* SCANFLIKE 0 */ 253 void 254 scanflike_0_comment(const char *fmt) 255 { 256 } 257 258 /* SCANFLIKE 3 */ 259 void 260 scanflike_3_comment(int a, int b, const char *fmt) 261 { 262 } 263 264 int 265 used_function(void) 266 { 267 return 4; 268 } 269 270 inline int 271 inline_function(void) 272 { 273 used_function(); 274 (void)used_function(); 275 return used_function(); 276 } 277 278 extern int declared_used_var; 279 int defined_used_var; 280 281 /* 282 * When a function is used, that usage is output as a 'c' record. 283 * When a variable is used, that usage is output as a 'u' record. 284 */ 285 void 286 use_vars(void) 287 { 288 declared_used_var++; 289 defined_used_var++; 290 } 291 292 /* 293 * Since C99, an initializer may contain a compound expression. This allows 294 * to create trees of pointer data structures at compile time. 295 * 296 * The objects that are created for these compound literals are unnamed, 297 * therefore there is no point in exporting them to the .ln file. 298 * 299 * Before emit1.c 1.60 from 2021-11-28, lint exported them. 300 */ 301 struct compound_expression_in_initializer { 302 const char * const *info; 303 }; 304 305 struct compound_expression_in_initializer compound = { 306 .info = (const char *[16]){ 307 [0] = "zero", 308 }, 309 }; 310 311 /* 312 * Before decl.c 1.312 and init.c 1.242 from 2023-05-22, the type that ended up 313 * in the .ln file was 'A0cC', which was wrong as it had array size 0 instead 314 * of the correct 8. That type had been taken too early, before looking at the 315 * initializer. 316 */ 317 const char array_of_unknown_size[] = "unknown"; 318 319 int used_and_using(int); 320 int only_used(void); 321 322 int 323 only_using(void) 324 { 325 return used_and_using(only_used()); 326 } 327