emit.c revision 1.6 1 /* $NetBSD: emit.c,v 1.6 2021/09/04 15:13:00 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. */
11 /* lint1-extra-flags: -X 231 */
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 static int static_int; /* expect: unused */
108
109 /*
110 * Type qualifiers.
111 */
112
113 extern const int extern_const_int;
114 extern volatile int extern_volatile_int;
115 extern const volatile int extern_const_volatile_int;
116
117 /*
118 * Functions.
119 */
120
121 extern void return_void_unknown_parameters();
122 extern /* implicit int */ return_implicit_int_unknown_parameters();
123
124 /* For function declarations, the keyword 'extern' is optional. */
125 extern void extern_return_void_no_parameters(void);
126 /* implicit extern */ void return_void_no_parameters(void);
127 static void static_return_void_no_parameters(void); /* expect: declared */
128
129 void taking_int(int);
130 /* The 'const' parameter does not make a difference. */
131 void taking_const_int(const int);
132 void taking_int_double_bool(int, double, _Bool);
133 void taking_struct_union_enum_tags(struct struct_tag, union union_tag,
134 enum enum_tag);
135 void taking_struct_union_enum_typedefs(struct_typedef, union_typedef,
136 enum_typedef);
137
138 void taking_varargs(const char *, ...);
139
140 /*
141 * This function does not affect anything outside this translation unit.
142 * Naively there is no need to record this function in the .ln file, but it
143 * is nevertheless recorded. There's probably a good reason for recording
144 * it.
145 */
146 static int static_function(void); /* expect: declared */
147
148 void my_printf(const char *, ...);
149 void my_scanf(const char *, ...);
150
151 /*
152 * String literals that occur in function calls are written to the .ln file,
153 * just in case they are related to a printf-like or scanf-like function.
154 *
155 * In this example, the various strings are not format strings, they just
156 * serve to cover the code that escapes character literals (outqchar in
157 * lint1) and reads them back into characters (inpqstrg in lint2).
158 */
159 void
160 cover_outqchar(void)
161 {
162 my_printf("%s", "%");
163 my_printf("%s", "%s");
164 my_printf("%s", "%%");
165 my_printf("%s", "%\\ %\" %' %\a %\b %\f %\n %\r %\t %\v %\177");
166 }
167
168 void
169 cover_outfstrg(void)
170 {
171 my_printf("%s", "%-3d %+3d % d %#x %03d %*.*s %6.2f %hd %ld %Ld %qd");
172 my_scanf("%s", "%[0-9]s %[^A-Za-z]s %[][A-Za-z0-9]s %[+-]s");
173 }
174
175 /*
176 * Calls to GCC builtin functions should not be emitted since GCC already
177 * guarantees a consistent definition of these function and checks the
178 * arguments, so there is nothing left to do for lint.
179 */
180 void
181 call_gcc_builtins(int x, long *ptr)
182 {
183 long value;
184
185 __builtin_expect(x > 0, 1);
186 __builtin_bswap32(0x12345678);
187
188 __atomic_load(ptr, &value, 0);
189 }
190
191 /*
192 * XXX: It's strange that a function can be annotated with VARARGS even
193 * though it does not take varargs at all.
194 *
195 * This feature is not useful for modern code anyway, it focused on pre-C90
196 * code that did not have function prototypes.
197 */
198
199 /* VARARGS */
200 void
201 varargs_comment(const char *fmt)
202 {
203 }
204
205 /* VARARGS 0 */
206 void
207 varargs_0_comment(const char *fmt)
208 {
209 }
210
211 /* VARARGS 3 */
212 void
213 varargs_3_comment(int a, int b, int c, const char *fmt)
214 {
215 }
216
217 /* PRINTFLIKE */
218 void
219 printflike_comment(const char *fmt)
220 {
221 }
222
223 /* PRINTFLIKE 0 */
224 void
225 printflike_0_comment(const char *fmt)
226 {
227 }
228
229 /* PRINTFLIKE 3 */
230 void
231 printflike_3_comment(int a, int b, const char *fmt)
232 {
233 }
234
235 /* PRINTFLIKE 10 */
236 void
237 printflike_10_comment(int a1, int a2, int a3, int a4, int a5,
238 int a6, int a7, int a8, int a9,
239 const char *fmt)
240 {
241 }
242
243 /* SCANFLIKE */
244 void
245 scanflike_comment(const char *fmt)
246 {
247 }
248
249 /* SCANFLIKE 0 */
250 void
251 scanflike_0_comment(const char *fmt)
252 {
253 }
254
255 /* SCANFLIKE 3 */
256 void
257 scanflike_3_comment(int a, int b, const char *fmt)
258 {
259 }
260
261 int
262 used_function(void)
263 {
264 return 4;
265 }
266
267 inline int
268 inline_function(void)
269 {
270 used_function();
271 (void)used_function();
272 return used_function();
273 }
274
275 extern int declared_used_var;
276 int defined_used_var;
277
278 /*
279 * When a function is used, that usage is output as a 'c' record.
280 * When a variable is used, that usage is output as a 'u' record.
281 */
282 void
283 use_vars(void)
284 {
285 declared_used_var++;
286 defined_used_var++;
287 }
288