xref: /netbsd-src/tests/usr.bin/xlint/lint1/emit.c (revision 21b853fa58db206bd43db7c23250fd3bb4c2a3c0)
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
cover_outqchar(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
cover_outfstrg(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
call_gcc_builtins(int x,long * ptr)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
varargs_comment(const char * fmt)204 varargs_comment(const char *fmt)
205 {
206 }
207 
208 /* VARARGS 0 */
209 void
varargs_0_comment(const char * fmt)210 varargs_0_comment(const char *fmt)
211 {
212 }
213 
214 /* VARARGS 3 */
215 void
varargs_3_comment(int a,int b,int c,const char * fmt)216 varargs_3_comment(int a, int b, int c, const char *fmt)
217 {
218 }
219 
220 /* PRINTFLIKE */
221 void
printflike_comment(const char * fmt)222 printflike_comment(const char *fmt)
223 {
224 }
225 
226 /* PRINTFLIKE 0 */
227 void
printflike_0_comment(const char * fmt)228 printflike_0_comment(const char *fmt)
229 {
230 }
231 
232 /* PRINTFLIKE 3 */
233 void
printflike_3_comment(int a,int b,const char * fmt)234 printflike_3_comment(int a, int b, const char *fmt)
235 {
236 }
237 
238 /* PRINTFLIKE 10 */
239 void
printflike_10_comment(int a1,int a2,int a3,int a4,int a5,int a6,int a7,int a8,int a9,const char * fmt)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
scanflike_comment(const char * fmt)248 scanflike_comment(const char *fmt)
249 {
250 }
251 
252 /* SCANFLIKE 0 */
253 void
scanflike_0_comment(const char * fmt)254 scanflike_0_comment(const char *fmt)
255 {
256 }
257 
258 /* SCANFLIKE 3 */
259 void
scanflike_3_comment(int a,int b,const char * fmt)260 scanflike_3_comment(int a, int b, const char *fmt)
261 {
262 }
263 
264 int
used_function(void)265 used_function(void)
266 {
267 	return 4;
268 }
269 
270 inline int
inline_function(void)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
use_vars(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
only_using(void)323 only_using(void)
324 {
325 	return used_and_using(only_used());
326 }
327