chk.c revision 1.72 1 /* $NetBSD: chk.c,v 1.72 2025/05/24 07:38:59 rillig Exp $ */
2
3 /*
4 * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved.
5 * Copyright (c) 1994, 1995 Jochen Pohl
6 * All Rights Reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Jochen Pohl for
19 * The NetBSD Project.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #if HAVE_NBTOOL_CONFIG_H
36 #include "nbtool_config.h"
37 #endif
38
39 #include <sys/cdefs.h>
40 #if defined(__RCSID)
41 __RCSID("$NetBSD: chk.c,v 1.72 2025/05/24 07:38:59 rillig Exp $");
42 #endif
43
44 #include <ctype.h>
45 #include <limits.h>
46 #include <stdlib.h>
47 #include <string.h>
48
49 #include "lint2.h"
50
51 static void check_used_not_defined(const hte_t *);
52 static void check_defined_not_used(const hte_t *);
53 static void check_declared_not_used_or_defined(const hte_t *);
54 static void check_multiple_definitions(const hte_t *);
55 static void chkvtui(const hte_t *, const sym_t *, const sym_t *);
56 static void chkvtdi(const hte_t *, const sym_t *, const sym_t *);
57 static void chkfaui(const hte_t *, const sym_t *, const sym_t *);
58 static void chkau(const hte_t *, int, const sym_t *, const sym_t *,
59 const pos_t *, const fcall_t *, const fcall_t *,
60 const type_t *, const type_t *);
61 static void check_return_values(const hte_t *, const sym_t *);
62 static void check_argument_declarations(const hte_t *,
63 const sym_t *, const sym_t *);
64 static void printflike(const hte_t *, const fcall_t *,
65 int, const char *, const type_t **);
66 static void scanflike(const hte_t *, const fcall_t *,
67 int, const char *, const type_t **);
68 static void bad_format_string(const hte_t *, const fcall_t *);
69 static void inconsistent_arguments(const hte_t *, const fcall_t *, int);
70 static void too_few_arguments(const hte_t *, const fcall_t *);
71 static void too_many_arguments(const hte_t *, const fcall_t *);
72 static bool types_compatible(const type_t *, const type_t *,
73 bool, bool, bool, bool *);
74 static bool prototypes_compatible(const type_t *, const type_t *, bool *);
75 static bool matches_no_arg_function(const type_t *, bool *);
76
77
78 /*
79 * If there is a symbol named "main", mark it as used.
80 */
81 void
82 mark_main_as_used(void)
83 {
84 hte_t *hte;
85
86 if ((hte = htab_search("main", false)) != NULL)
87 hte->h_used = true;
88 }
89
90 /*
91 * Performs all tests for a single name
92 */
93 void
94 check_name(const hte_t *hte)
95 {
96 sym_t *sym, *def, *pdecl, *decl;
97
98 if (!uflag) {
99 check_used_not_defined(hte);
100 check_defined_not_used(hte);
101 if (xflag)
102 check_declared_not_used_or_defined(hte);
103 }
104 check_multiple_definitions(hte);
105
106 /* Get definition, prototype declaration and declaration */
107 def = pdecl = decl = NULL;
108 for (sym = hte->h_syms; sym != NULL; sym = sym->s_next) {
109 if (def == NULL && (sym->s_def == DEF || sym->s_def == TDEF))
110 def = sym;
111 if (pdecl == NULL && sym->s_def == DECL &&
112 TP(sym->s_type)->t_tspec == FUNC &&
113 TP(sym->s_type)->t_proto) {
114 pdecl = sym;
115 }
116 if (decl == NULL && sym->s_def == DECL)
117 decl = sym;
118 }
119
120 /* A prototype is better than an old-style declaration. */
121 if (pdecl != NULL)
122 decl = pdecl;
123
124 chkvtui(hte, def, decl);
125
126 chkvtdi(hte, def, decl);
127
128 chkfaui(hte, def, decl);
129
130 check_return_values(hte, def);
131
132 check_argument_declarations(hte, def, decl);
133 }
134
135 /*
136 * Print a warning if the name has been used, but not defined.
137 */
138 static void
139 check_used_not_defined(const hte_t *hte)
140 {
141 fcall_t *fcall;
142 usym_t *usym;
143
144 if (!hte->h_used || hte->h_def)
145 return;
146
147 if ((fcall = hte->h_calls) != NULL) {
148 /* %s is used in %s but never defined */
149 msg(0, hte->h_name, mkpos(&fcall->f_pos));
150 } else if ((usym = hte->h_usyms) != NULL) {
151 /* %s is used in %s but never defined */
152 msg(0, hte->h_name, mkpos(&usym->u_pos));
153 }
154 }
155
156 /*
157 * Print a warning if the name has been defined, but never used.
158 */
159 static void
160 check_defined_not_used(const hte_t *hte)
161 {
162 sym_t *sym;
163
164 if (!hte->h_def || hte->h_used)
165 return;
166
167 for (sym = hte->h_syms; sym != NULL; sym = sym->s_next) {
168 if (sym->s_def == DEF || sym->s_def == TDEF) {
169 /* %s is defined in %s but never used */
170 msg(1, hte->h_name, mkpos(&sym->s_pos));
171 break;
172 }
173 }
174 }
175
176 /*
177 * Print a warning if the variable has been declared, but is not used
178 * or defined.
179 */
180 static void
181 check_declared_not_used_or_defined(const hte_t *hte)
182 {
183 sym_t *sym;
184
185 if (hte->h_syms == NULL || hte->h_used || hte->h_def)
186 return;
187
188 sym = hte->h_syms;
189 if (TP(sym->s_type)->t_tspec == FUNC)
190 return;
191
192 if (sym->s_def != DECL)
193 errx(1, "internal error: check_declared_not_used_or_defined");
194 /* %s is declared in %s but never used or defined */
195 msg(2, hte->h_name, mkpos(&sym->s_pos));
196 }
197
198 /*
199 * Print a warning if there is more than one definition for
200 * this name.
201 */
202 static void
203 check_multiple_definitions(const hte_t *hte)
204 {
205 sym_t *sym, *def1;
206
207 if (!hte->h_def)
208 return;
209
210 def1 = NULL;
211 for (sym = hte->h_syms; sym != NULL; sym = sym->s_next) {
212 /*
213 * C90 allows tentative definitions of the same name in only
214 * one compilation unit.
215 */
216 if (sym->s_def != DEF && (!sflag || sym->s_def != TDEF))
217 continue;
218 if (sym->s_inline)
219 continue;
220 if (def1 == NULL) {
221 def1 = sym;
222 continue;
223 }
224 /* %s has multiple definitions in %s and %s */
225 msg(3, hte->h_name, mkpos(&def1->s_pos), mkpos(&sym->s_pos));
226 }
227 }
228
229 /*
230 * Print a warning if the return value assumed for a function call
231 * differs from the return value of the function definition or
232 * function declaration.
233 *
234 * If no definition/declaration can be found, the assumed return values
235 * are always int. So there is no need to compare with another function
236 * call as it's done for function arguments.
237 */
238 static void
239 chkvtui(const hte_t *hte, const sym_t *def, const sym_t *decl)
240 {
241 fcall_t *call;
242 type_t *tp1, *tp2;
243 bool dowarn, eq;
244 tspec_t t1;
245
246 if (hte->h_calls == NULL)
247 return;
248
249 if (def == NULL)
250 def = decl;
251 if (def == NULL)
252 return;
253
254 t1 = (tp1 = TP(def->s_type)->t_subt)->t_tspec;
255 for (call = hte->h_calls; call != NULL; call = call->f_next) {
256 tp2 = TP(call->f_type)->t_subt;
257 eq = types_compatible(tp1, tp2,
258 true, false, false, (dowarn = false, &dowarn));
259 if (!call->f_rused) {
260 /* no return value used */
261 if ((t1 == STRUCT || t1 == UNION) && !eq) {
262 /*
263 * If a function returns a struct or union, it
264 * must be declared to return a struct or
265 * union, even if the return value is ignored.
266 * This is necessary because the caller must
267 * allocate stack space for the return value.
268 * If it does not, the return value would
269 * overwrite other data.
270 *
271 * XXX: The following message may be confusing
272 * because it occurs also if the return value
273 * was declared inconsistently. But this
274 * behavior matches pcc-based lint, so it is
275 * accepted for now.
276 */
277 /* %s's return type in %s must be decl... */
278 msg(17, hte->h_name,
279 mkpos(&def->s_pos), mkpos(&call->f_pos));
280 }
281 continue;
282 }
283 if (!eq || (sflag && dowarn)) {
284 /* %s has its return value used inconsistently ... */
285 msg(4, hte->h_name,
286 mkpos(&def->s_pos), mkpos(&call->f_pos));
287 }
288 }
289 }
290
291 /*
292 * Print a warning if a definition/declaration does not match another
293 * definition/declaration of the same name. For functions, only the
294 * types of return values are tested.
295 */
296 static void
297 chkvtdi(const hte_t *hte, const sym_t *def, const sym_t *decl)
298 {
299 if (def == NULL)
300 def = decl;
301 if (def == NULL)
302 return;
303
304 const type_t *tp1 = TP(def->s_type);
305 for (sym_t *sym = hte->h_syms; sym != NULL; sym = sym->s_next) {
306 if (sym == def)
307 continue;
308 const type_t *tp2 = TP(sym->s_type);
309 bool dowarn = false;
310 bool is_func = tp1->t_tspec == FUNC && tp2->t_tspec == FUNC;
311 const type_t *xt1 = is_func ? tp1->t_subt : tp1;
312 const type_t *xt2 = is_func ? tp2->t_subt : tp2;
313 bool eq = types_compatible(xt1, xt2,
314 is_func, false, false, &dowarn);
315 if (!eq || (sflag && dowarn)) {
316 /* %s %s '%s' at %s, versus '%s' at %s */
317 msg(5, hte->h_name,
318 is_func ? "returns" : "has type",
319 type_name(xt1), mkpos(&def->s_pos),
320 type_name(xt2), mkpos(&sym->s_pos));
321 }
322 }
323 }
324
325 static int
326 total_args(int n, const type_t **tpp)
327 {
328 for (; *tpp != NULL; tpp++)
329 n++;
330 return n;
331 }
332
333 /*
334 * Print a warning if a function is called with arguments which does
335 * not match the function definition, declaration or another call
336 * of the same function.
337 */
338 static void
339 chkfaui(const hte_t *hte, const sym_t *def, const sym_t *decl)
340 {
341 const type_t *tp1, *tp2, **ap1, **ap2;
342 const pos_t *pos1p = NULL;
343 fcall_t *calls, *call, *call1;
344 int n, as;
345 arginf_t *ai;
346
347 if ((calls = hte->h_calls) == NULL)
348 return;
349
350 /*
351 * If we find a function definition, we use this for comparison,
352 * otherwise the first prototype we can find. If there is no definition
353 * or prototype declaration, the first function call is used.
354 */
355 tp1 = NULL;
356 call1 = NULL;
357 if (def != NULL) {
358 if ((tp1 = TP(def->s_type))->t_tspec != FUNC)
359 return;
360 pos1p = &def->s_pos;
361 } else if (decl != NULL && TP(decl->s_type)->t_proto) {
362 if ((tp1 = TP(decl->s_type))->t_tspec != FUNC)
363 return;
364 pos1p = &decl->s_pos;
365 }
366 if (tp1 == NULL) {
367 call1 = calls;
368 calls = calls->f_next;
369 if ((tp1 = TP(call1->f_type))->t_tspec != FUNC)
370 return;
371 pos1p = &call1->f_pos;
372 }
373
374 n = 1;
375 for (call = calls; call != NULL; call = call->f_next) {
376 if ((tp2 = TP(call->f_type))->t_tspec != FUNC)
377 continue;
378 ap1 = tp1->t_args;
379 ap2 = tp2->t_args;
380 n = 0;
381 while (*ap1 != NULL && *ap2 != NULL) {
382 if (def != NULL && def->s_check_only_first_args &&
383 n >= def->s_check_num_args)
384 break;
385 n++;
386 chkau(hte, n, def, decl, pos1p, call1, call,
387 *ap1, *ap2);
388 ap1++;
389 ap2++;
390 }
391 if (*ap1 == *ap2) {
392 /* equal # of arguments */
393 } else if (def != NULL && def->s_check_only_first_args &&
394 n >= def->s_check_num_args) {
395 /*
396 * function definition with VARARGS; The # of arguments
397 * of the call must be at least as large as the
398 * parameter of VARARGS.
399 */
400 } else if (*ap2 != NULL && tp1->t_proto && tp1->t_vararg) {
401 /*
402 * prototype with ... and function call with at least
403 * the same # of arguments as declared in the
404 * prototype.
405 */
406 } else {
407 /* %s has %d parameters in %s, versus %d ... */
408 msg(7, hte->h_name, total_args(n, ap1), mkpos(pos1p),
409 total_args(n, ap2), mkpos(&call->f_pos));
410 continue;
411 }
412
413 /* perform SCANFLIKE/PRINTFLIKE tests */
414 if (def == NULL || (!def->s_printflike && !def->s_scanflike))
415 continue;
416 as = def->s_printflike
417 ? def->s_printflike_arg
418 : def->s_scanflike_arg;
419 for (ai = call->f_args; ai != NULL; ai = ai->a_next) {
420 if (ai->a_num == as)
421 break;
422 }
423 if (ai == NULL || !ai->a_fmt)
424 continue;
425 if (def->s_printflike) {
426 printflike(hte, call, n, ai->a_fstrg, ap2);
427 } else {
428 scanflike(hte, call, n, ai->a_fstrg, ap2);
429 }
430 }
431 }
432
433 /*
434 * Check a single argument in a function call.
435 *
436 * hte a pointer to the hash table entry of the function
437 * n the number of the argument (1..)
438 * def the function definition or NULL
439 * decl prototype declaration, old-style declaration or NULL
440 * pos1p position of definition, declaration of first call
441 * call1 first call, if both def and decl are old-style def/decl
442 * call checked call
443 * arg1 currently checked argument of def/decl/call1
444 * arg2 currently checked argument of call
445 */
446 static void
447 chkau(const hte_t *hte,
448 int n, const sym_t *def, const sym_t *decl,
449 const pos_t *pos1p, const fcall_t *call1, const fcall_t *call,
450 const type_t *arg1, const type_t *arg2)
451 {
452 bool promote, asgn, dowarn;
453 tspec_t t1, t2;
454 arginf_t *ai, *ai1;
455
456 /*
457 * If a function definition is available (def != NULL), we compare the
458 * function call (call) with the definition. Otherwise, if a function
459 * definition is available and it is not an old-style definition (decl
460 * != NULL && TP(decl->s_type)->t_proto), we compare the call with this
461 * declaration. Otherwise we compare it with the first call we have
462 * found (call1).
463 */
464
465 /* arg1 must be promoted if it stems from an old-style definition */
466 promote = def != NULL && def->s_old_style_function;
467
468 /*
469 * If we compare with a definition or declaration, we must perform the
470 * same checks for qualifiers in indirected types as in assignments.
471 */
472 asgn = def != NULL || (decl != NULL && TP(decl->s_type)->t_proto);
473
474 dowarn = false;
475 if (types_compatible(arg1, arg2, true, promote, asgn, &dowarn) &&
476 (!sflag || !dowarn))
477 return;
478
479 /*-
480 * Other lint implementations print warnings as soon as the type of an
481 * argument does not match exactly the expected type. The result are
482 * lots of warnings which are really not necessary.
483 * We print a warning only if
484 * (0) at least one type is not an integer type and types differ
485 * (1) hflag is set and types differ
486 * (2) types differ, except in signedness
487 *
488 * If the argument is an integer constant whose msb is not set,
489 * signedness is ignored (e.g. 0 matches both signed and unsigned int).
490 * This is with and without hflag.
491 *
492 * If the argument is an integer constant with value 0 and the expected
493 * argument is of type pointer and the width of the integer constant is
494 * the same as the width of the pointer, no warning is printed.
495 */
496 t1 = arg1->t_tspec;
497 t2 = arg2->t_tspec;
498 if (is_integer(t1) && is_integer(t2) &&
499 !arg1->t_is_enum && !arg2->t_is_enum) {
500 if (promote) {
501 /*
502 * XXX Here is a problem: Although it is possible to
503 * pass an int where a char/short it expected, there
504 * may be loss in significant digits. We should first
505 * check for const arguments if they can be converted
506 * into the original parameter type.
507 */
508 if (t1 == FLOAT) {
509 t1 = DOUBLE;
510 } else if (t1 == CHAR || t1 == SCHAR) {
511 t1 = INT;
512 } else if (t1 == UCHAR) {
513 t1 = tflag ? UINT : INT;
514 } else if (t1 == SHORT) {
515 t1 = INT;
516 } else if (t1 == USHORT) {
517 t1 = INT_MAX < USHRT_MAX || tflag ? UINT : INT;
518 }
519 }
520
521 if (signed_type(t1) == signed_type(t2)) {
522
523 /*
524 * types differ only in signedness; get information
525 * about arguments
526 */
527
528 /*
529 * treat a definition like a call with variable
530 * arguments
531 */
532 ai1 = call1 != NULL ? call1->f_args : NULL;
533
534 /*
535 * if two calls are compared, ai1 is set to the
536 * information for the n-th argument, if this was a
537 * constant, otherwise to NULL
538 */
539 for ( ; ai1 != NULL; ai1 = ai1->a_next) {
540 if (ai1->a_num == n)
541 break;
542 }
543 /*
544 * ai is set to the information of the n-th arg of the
545 * (second) call, if this was a constant, otherwise to
546 * NULL
547 */
548 for (ai = call->f_args; ai != NULL; ai = ai->a_next) {
549 if (ai->a_num == n)
550 break;
551 }
552
553 if (ai1 == NULL && ai == NULL) {
554 /* no constant at all */
555 if (!hflag)
556 return;
557 } else if (ai1 == NULL || ai == NULL) {
558 /* one constant */
559 if (ai == NULL)
560 ai = ai1;
561 if (ai->a_zero || ai->a_pcon)
562 /* same value in signed and unsigned */
563 return;
564 /* value (not representation) differently */
565 } else {
566 /*
567 * two constants, one signed, one unsigned; if
568 * the msb of one of the constants is set, the
569 * argument is used inconsistently.
570 */
571 if (!ai1->a_ncon && !ai->a_ncon)
572 return;
573 }
574 }
575
576 } else if (t1 == PTR && is_integer(t2)) {
577 for (ai = call->f_args; ai != NULL; ai = ai->a_next) {
578 if (ai->a_num == n)
579 break;
580 }
581 /*
582 * Vendor implementations of lint (e.g. HP-UX, Digital UNIX)
583 * don't care about the size of the integer argument, only
584 * whether or not it is zero. We do the same.
585 */
586 if (ai != NULL && ai->a_zero)
587 return;
588 }
589
590 /* %s has argument %d with type '%s' at %s, versus '%s' at %s */
591 msg(6, hte->h_name, n, type_name(arg1), mkpos(pos1p),
592 type_name(arg2), mkpos(&call->f_pos));
593 }
594
595 /*
596 * Compare the types in the NULL-terminated array ap with the format
597 * string fmt.
598 */
599 static void
600 printflike(const hte_t *hte, const fcall_t *call,
601 int n, const char *fmt, const type_t **ap)
602 {
603 const char *fp;
604 char fc;
605 bool fwidth, prec, left, sign, space, alt, zero;
606 tspec_t sz, t1, t2 = NO_TSPEC;
607 const type_t *tp;
608
609 fp = fmt;
610 fc = *fp++;
611
612 for (;;) {
613 if (fc == '\0') {
614 if (*ap != NULL)
615 too_many_arguments(hte, call);
616 break;
617 }
618 if (fc != '%') {
619 bad_format_string(hte, call);
620 break;
621 }
622 fc = *fp++;
623 fwidth = prec = left = sign = space = alt = zero = false;
624 sz = NO_TSPEC;
625
626 /* Flags */
627 for (;;) {
628 if (fc == '-') {
629 if (left)
630 break;
631 left = true;
632 } else if (fc == '+') {
633 if (sign)
634 break;
635 sign = true;
636 } else if (fc == ' ') {
637 if (space)
638 break;
639 space = true;
640 } else if (fc == '#') {
641 if (alt)
642 break;
643 alt = true;
644 } else if (fc == '0') {
645 if (zero)
646 break;
647 zero = true;
648 } else {
649 break;
650 }
651 fc = *fp++;
652 }
653
654 /* field width */
655 if (ch_isdigit(fc)) {
656 fwidth = true;
657 do { fc = *fp++; } while (ch_isdigit(fc));
658 } else if (fc == '*') {
659 fwidth = true;
660 fc = *fp++;
661 if ((tp = *ap++) == NULL) {
662 too_few_arguments(hte, call);
663 break;
664 }
665 n++;
666 if ((t1 = tp->t_tspec) != INT && (hflag || t1 != UINT))
667 inconsistent_arguments(hte, call, n);
668 }
669
670 /* precision */
671 if (fc == '.') {
672 fc = *fp++;
673 prec = true;
674 if (ch_isdigit(fc)) {
675 do {
676 fc = *fp++;
677 } while (ch_isdigit(fc));
678 } else if (fc == '*') {
679 fc = *fp++;
680 if ((tp = *ap++) == NULL) {
681 too_few_arguments(hte, call);
682 break;
683 }
684 n++;
685 if (tp->t_tspec != INT)
686 inconsistent_arguments(hte, call, n);
687 } else {
688 bad_format_string(hte, call);
689 break;
690 }
691 }
692
693 if (fc == 'h') {
694 sz = SHORT;
695 } else if (fc == 'l') {
696 sz = LONG;
697 } else if (fc == 'q') {
698 sz = LLONG;
699 } else if (fc == 'L') {
700 sz = LDOUBLE;
701 }
702 if (sz != NO_TSPEC)
703 fc = *fp++;
704
705 if (fc == '%') {
706 if (sz != NO_TSPEC || left || sign || space ||
707 alt || zero || prec || fwidth) {
708 bad_format_string(hte, call);
709 }
710 fc = *fp++;
711 continue;
712 }
713
714 if (fc == '\0') {
715 bad_format_string(hte, call);
716 break;
717 }
718
719 if ((tp = *ap++) == NULL) {
720 too_few_arguments(hte, call);
721 break;
722 }
723 n++;
724 if ((t1 = tp->t_tspec) == PTR)
725 t2 = tp->t_subt->t_tspec;
726
727 if (fc == 'd' || fc == 'i') {
728 if (alt || sz == LDOUBLE) {
729 bad_format_string(hte, call);
730 break;
731 }
732 int_conv:
733 if (sz == LONG) {
734 if (t1 != LONG && (hflag || t1 != ULONG))
735 inconsistent_arguments(hte, call, n);
736 } else if (sz == LLONG) {
737 if (t1 != LLONG && (hflag || t1 != ULLONG))
738 inconsistent_arguments(hte, call, n);
739 } else {
740 /*
741 * SHORT is always promoted to INT, USHORT to
742 * INT or UINT.
743 */
744 if (t1 != INT && (hflag || t1 != UINT))
745 inconsistent_arguments(hte, call, n);
746 }
747 } else if (fc == 'o' || fc == 'u' || fc == 'x' || fc == 'X') {
748 if ((alt && fc == 'u') || sz == LDOUBLE)
749 bad_format_string(hte, call);
750 uint_conv:
751 if (sz == LONG) {
752 if (t1 != ULONG && (hflag || t1 != LONG))
753 inconsistent_arguments(hte, call, n);
754 } else if (sz == LLONG) {
755 if (t1 != ULLONG && (hflag || t1 != LLONG))
756 inconsistent_arguments(hte, call, n);
757 } else if (sz == SHORT) {
758 /* USHORT was promoted to INT or UINT */
759 if (t1 != UINT && t1 != INT)
760 inconsistent_arguments(hte, call, n);
761 } else {
762 if (t1 != UINT && (hflag || t1 != INT))
763 inconsistent_arguments(hte, call, n);
764 }
765 } else if (fc == 'D' || fc == 'O' || fc == 'U') {
766 if ((alt && fc != 'O') || sz != NO_TSPEC || !tflag)
767 bad_format_string(hte, call);
768 sz = LONG;
769 if (fc == 'D') {
770 goto int_conv;
771 } else {
772 goto uint_conv;
773 }
774 } else if (fc == 'f' || fc == 'e' || fc == 'E' ||
775 fc == 'g' || fc == 'G') {
776 if (sz == NO_TSPEC)
777 sz = DOUBLE;
778 if (sz != DOUBLE && sz != LDOUBLE)
779 bad_format_string(hte, call);
780 if (t1 != sz)
781 inconsistent_arguments(hte, call, n);
782 } else if (fc == 'c') {
783 if (sz != NO_TSPEC || alt || zero)
784 bad_format_string(hte, call);
785 if (t1 != INT)
786 inconsistent_arguments(hte, call, n);
787 } else if (fc == 's') {
788 if (sz != NO_TSPEC || alt || zero)
789 bad_format_string(hte, call);
790 if (t1 != PTR ||
791 (t2 != CHAR && t2 != UCHAR && t2 != SCHAR)) {
792 inconsistent_arguments(hte, call, n);
793 }
794 } else if (fc == 'p') {
795 if (fwidth || prec || sz != NO_TSPEC || alt || zero)
796 bad_format_string(hte, call);
797 if (t1 != PTR || (hflag && t2 != VOID))
798 inconsistent_arguments(hte, call, n);
799 } else if (fc == 'n') {
800 if (fwidth || prec || alt || zero || sz == LDOUBLE)
801 bad_format_string(hte, call);
802 if (t1 != PTR) {
803 inconsistent_arguments(hte, call, n);
804 } else if (sz == LONG) {
805 if (t2 != LONG && t2 != ULONG)
806 inconsistent_arguments(hte, call, n);
807 } else if (sz == SHORT) {
808 if (t2 != SHORT && t2 != USHORT)
809 inconsistent_arguments(hte, call, n);
810 } else {
811 if (t2 != INT && t2 != UINT)
812 inconsistent_arguments(hte, call, n);
813 }
814 } else {
815 bad_format_string(hte, call);
816 break;
817 }
818
819 fc = *fp++;
820 }
821 }
822
823 /*
824 * Compare the types in the NULL-terminated array ap with the format
825 * string fmt.
826 */
827 static void
828 scanflike(const hte_t *hte, const fcall_t *call,
829 int n, const char *fmt, const type_t **ap)
830 {
831 const char *fp;
832 char fc;
833 bool noasgn, fwidth;
834 tspec_t sz, t1 = NO_TSPEC, t2 = NO_TSPEC;
835 const type_t *tp = NULL;
836
837 fp = fmt;
838 fc = *fp++;
839
840 for (;;) {
841 if (fc == '\0') {
842 if (*ap != NULL)
843 too_many_arguments(hte, call);
844 break;
845 }
846 if (fc != '%') {
847 bad_format_string(hte, call);
848 break;
849 }
850 fc = *fp++;
851
852 noasgn = fwidth = false;
853 sz = NO_TSPEC;
854
855 if (fc == '*') {
856 noasgn = true;
857 fc = *fp++;
858 }
859
860 if (ch_isdigit(fc)) {
861 fwidth = true;
862 do { fc = *fp++; } while (ch_isdigit(fc));
863 }
864
865 if (fc == 'h') {
866 sz = SHORT;
867 } else if (fc == 'l') {
868 sz = LONG;
869 } else if (fc == 'q') {
870 sz = LLONG;
871 } else if (fc == 'L') {
872 sz = LDOUBLE;
873 }
874 if (sz != NO_TSPEC)
875 fc = *fp++;
876
877 if (fc == '%') {
878 if (sz != NO_TSPEC || noasgn || fwidth)
879 bad_format_string(hte, call);
880 fc = *fp++;
881 continue;
882 }
883
884 if (!noasgn) {
885 if ((tp = *ap++) == NULL) {
886 too_few_arguments(hte, call);
887 break;
888 }
889 n++;
890 if ((t1 = tp->t_tspec) == PTR)
891 t2 = tp->t_subt->t_tspec;
892 }
893
894 if (fc == 'd' || fc == 'i' || fc == 'n') {
895 if (sz == LDOUBLE)
896 bad_format_string(hte, call);
897 if (sz != SHORT && sz != LONG && sz != LLONG)
898 sz = INT;
899 conv:
900 if (!noasgn) {
901 if (t1 != PTR) {
902 inconsistent_arguments(hte, call, n);
903 } else if (t2 != signed_type(sz)) {
904 inconsistent_arguments(hte, call, n);
905 } else if (hflag && t2 != sz) {
906 inconsistent_arguments(hte, call, n);
907 } else if (tp->t_subt->t_const) {
908 inconsistent_arguments(hte, call, n);
909 }
910 }
911 } else if (fc == 'o' || fc == 'u' || fc == 'x') {
912 if (sz == LDOUBLE)
913 bad_format_string(hte, call);
914 if (sz == SHORT) {
915 sz = USHORT;
916 } else if (sz == LONG) {
917 sz = ULONG;
918 } else if (sz == LLONG) {
919 sz = ULLONG;
920 } else {
921 sz = UINT;
922 }
923 goto conv;
924 } else if (fc == 'D') {
925 if (sz != NO_TSPEC || !tflag)
926 bad_format_string(hte, call);
927 sz = LONG;
928 goto conv;
929 } else if (fc == 'O') {
930 if (sz != NO_TSPEC || !tflag)
931 bad_format_string(hte, call);
932 sz = ULONG;
933 goto conv;
934 } else if (fc == 'X') {
935 /*
936 * XXX valid in C90, but in NetBSD's libc implemented
937 * as "lx". That's why it should be avoided.
938 */
939 if (sz != NO_TSPEC || !tflag)
940 bad_format_string(hte, call);
941 sz = ULONG;
942 goto conv;
943 } else if (fc == 'E') {
944 /*
945 * XXX valid in C90, but in NetBSD's libc implemented
946 * as "lf". That's why it should be avoided.
947 */
948 if (sz != NO_TSPEC || !tflag)
949 bad_format_string(hte, call);
950 sz = DOUBLE;
951 goto conv;
952 } else if (fc == 'F') {
953 /* XXX only for backward compatibility */
954 if (sz != NO_TSPEC || !tflag)
955 bad_format_string(hte, call);
956 sz = DOUBLE;
957 goto conv;
958 } else if (fc == 'G') {
959 /*
960 * XXX valid in C90, but in NetBSD's libc not
961 * implemented
962 */
963 if (sz != NO_TSPEC && sz != LONG && sz != LDOUBLE)
964 bad_format_string(hte, call);
965 goto fconv;
966 } else if (fc == 'e' || fc == 'f' || fc == 'g') {
967 fconv:
968 if (sz == NO_TSPEC) {
969 sz = FLOAT;
970 } else if (sz == LONG) {
971 sz = DOUBLE;
972 } else if (sz != LDOUBLE) {
973 bad_format_string(hte, call);
974 sz = FLOAT;
975 }
976 goto conv;
977 } else if (fc == 's' || fc == '[' || fc == 'c') {
978 if (sz != NO_TSPEC)
979 bad_format_string(hte, call);
980 if (fc == '[') {
981 if ((fc = *fp++) == '-') {
982 bad_format_string(hte, call);
983 fc = *fp++;
984 }
985 if (fc != ']') {
986 bad_format_string(hte, call);
987 if (fc == '\0')
988 break;
989 }
990 }
991 if (!noasgn) {
992 if (t1 != PTR) {
993 inconsistent_arguments(hte, call, n);
994 } else if (t2 != CHAR && t2 != UCHAR &&
995 t2 != SCHAR) {
996 inconsistent_arguments(hte, call, n);
997 }
998 }
999 } else if (fc == 'p') {
1000 if (sz != NO_TSPEC)
1001 bad_format_string(hte, call);
1002 if (!noasgn) {
1003 if (t1 != PTR || t2 != PTR) {
1004 inconsistent_arguments(hte, call, n);
1005 } else if (tp->t_subt->t_subt->t_tspec!=VOID) {
1006 if (hflag)
1007 inconsistent_arguments(hte, call, n);
1008 }
1009 }
1010 } else {
1011 bad_format_string(hte, call);
1012 break;
1013 }
1014
1015 fc = *fp++;
1016 }
1017 }
1018
1019 static void
1020 bad_format_string(const hte_t *hte, const fcall_t *call)
1021 {
1022
1023 /* %s is called with a malformed format string in %s */
1024 msg(13, hte->h_name, mkpos(&call->f_pos));
1025 }
1026
1027 static void
1028 inconsistent_arguments(const hte_t *hte, const fcall_t *call, int n)
1029 {
1030
1031 /* %s is called in %s with argument %d being incompatible with ... */
1032 msg(14, hte->h_name, mkpos(&call->f_pos), n);
1033 }
1034
1035 static void
1036 too_few_arguments(const hte_t *hte, const fcall_t *call)
1037 {
1038
1039 /* %s is called in %s with too few arguments for format string */
1040 msg(15, hte->h_name, mkpos(&call->f_pos));
1041 }
1042
1043 static void
1044 too_many_arguments(const hte_t *hte, const fcall_t *call)
1045 {
1046
1047 /* %s is called in %s with too many arguments for format string */
1048 msg(16, hte->h_name, mkpos(&call->f_pos));
1049 }
1050
1051 /*
1052 * List of functions where we usually don't care about their result.
1053 * NB: Must be sorted.
1054 */
1055 static const char ignorelist[][8] = {
1056 "memcpy",
1057 "memmove",
1058 "memset",
1059 "printf",
1060 "strcat",
1061 "strcpy",
1062 "vprintf",
1063 };
1064
1065 /*
1066 * Print warnings for return values which are used but not returned,
1067 * or return values which are always or sometimes ignored.
1068 */
1069 static void
1070 check_return_values(const hte_t *hte, const sym_t *def)
1071 {
1072 fcall_t *call;
1073 bool used, ignored;
1074
1075 if (def == NULL)
1076 /* don't know whether or not the functions returns a value */
1077 return;
1078
1079 if (hte->h_calls == NULL)
1080 return;
1081
1082 if (def->s_function_has_return_value) {
1083 /*
1084 * XXX as soon as we are able to disable single warnings, the
1085 * following dependencies from hflag should be removed. But for
1086 * now I don't want to be bothered by these warnings which are
1087 * almost always useless.
1088 */
1089 if (!hflag)
1090 return;
1091 if (hflag && bsearch(hte->h_name, ignorelist,
1092 sizeof(ignorelist) / sizeof(ignorelist[0]),
1093 sizeof(ignorelist[0]),
1094 (int (*)(const void *, const void *))strcmp) != NULL)
1095 return;
1096
1097 /* function has return value */
1098 used = ignored = false;
1099 for (call = hte->h_calls; call != NULL; call = call->f_next) {
1100 used |= call->f_rused || call->f_rdisc;
1101 ignored |= !call->f_rused && !call->f_rdisc;
1102 }
1103 if (!used && ignored) {
1104 /* %s returns a value that is always ignored */
1105 msg(8, hte->h_name);
1106 } else if (used && ignored) {
1107 /* %s returns a value that is sometimes ignored */
1108 msg(9, hte->h_name);
1109 }
1110 } else {
1111 /* function has no return value */
1112 for (call = hte->h_calls; call != NULL; call = call->f_next) {
1113 if (call->f_rused)
1114 /* %s has its return value used in %s but doesn't return one */
1115 msg(10, hte->h_name, mkpos(&call->f_pos));
1116 }
1117 }
1118 }
1119
1120 /*
1121 * Print warnings for inconsistent argument declarations.
1122 */
1123 static void
1124 check_argument_declarations(const hte_t *hte,
1125 const sym_t *def, const sym_t *decl)
1126 {
1127 bool osdef, eq, dowarn;
1128 int n;
1129 const sym_t *sym1, *sym;
1130 const type_t **ap1, **ap2, *tp1, *tp2;
1131
1132 osdef = false;
1133 if (def != NULL) {
1134 osdef = def->s_old_style_function;
1135 sym1 = def;
1136 } else if (decl != NULL && TP(decl->s_type)->t_proto) {
1137 sym1 = decl;
1138 } else {
1139 return;
1140 }
1141 if (TP(sym1->s_type)->t_tspec != FUNC)
1142 return;
1143
1144 /*
1145 * XXX Prototypes should also be compared with old-style function
1146 * declarations.
1147 */
1148
1149 for (sym = hte->h_syms; sym != NULL; sym = sym->s_next) {
1150 if (sym == sym1 || !TP(sym->s_type)->t_proto)
1151 continue;
1152 ap1 = TP(sym1->s_type)->t_args;
1153 ap2 = TP(sym->s_type)->t_args;
1154 n = 0;
1155 while (*ap1 != NULL && *ap2 != NULL) {
1156 const type_t *xt1, *xt2;
1157 dowarn = false;
1158 eq = types_compatible(xt1 = *ap1, xt2 = *ap2,
1159 true, osdef, false, &dowarn);
1160 if (!eq || dowarn) {
1161 /* %s has parameter %d declared as '%s' ... */
1162 msg(11, hte->h_name, n + 1,
1163 type_name(xt1), mkpos(&sym1->s_pos),
1164 type_name(xt2), mkpos(&sym->s_pos));
1165 }
1166 n++;
1167 ap1++;
1168 ap2++;
1169 }
1170 if (*ap1 == *ap2) {
1171 tp1 = TP(sym1->s_type);
1172 tp2 = TP(sym->s_type);
1173 if (tp1->t_vararg == tp2->t_vararg)
1174 continue;
1175 if (tp2->t_vararg && sym1->s_check_only_first_args &&
1176 sym1->s_check_num_args == n && !sflag) {
1177 continue;
1178 }
1179 }
1180 /* %s has %d parameters in %s, versus %d in %s */
1181 msg(12, hte->h_name,
1182 total_args(n, ap1), mkpos(&sym1->s_pos),
1183 total_args(n, ap2), mkpos(&sym->s_pos));
1184 }
1185 }
1186
1187
1188 /*
1189 * Check compatibility of two types. Returns whether types are compatible.
1190 *
1191 * ignqual if set, ignore qualifiers of outermost type; used for
1192 * function arguments
1193 * promote if set, promote left type before comparison; used for
1194 * comparisons of arguments with parameters of old-style
1195 * definitions
1196 * asgn left indirected type must have at least the same qualifiers
1197 * like right indirected type (for assignments and function
1198 * arguments)
1199 * *dowarn set to true if an old-style declaration was compared with
1200 * an incompatible prototype declaration
1201 */
1202 static bool
1203 types_compatible(const type_t *tp1, const type_t *tp2,
1204 bool ignqual, bool promot, bool asgn, bool *dowarn)
1205 {
1206 tspec_t t, to;
1207 int indir;
1208
1209 to = NO_TSPEC;
1210 indir = 0;
1211
1212 while (tp1 != NULL && tp2 != NULL) {
1213
1214 t = tp1->t_tspec;
1215 if (promot) {
1216 if (t == FLOAT) {
1217 t = DOUBLE;
1218 } else if (t == CHAR || t == SCHAR) {
1219 t = INT;
1220 } else if (t == UCHAR) {
1221 t = tflag ? UINT : INT;
1222 } else if (t == SHORT) {
1223 t = INT;
1224 } else if (t == USHORT) {
1225 t = INT_MAX < USHRT_MAX || tflag ? UINT : INT;
1226 }
1227 }
1228
1229 if (asgn && to == PTR) {
1230 if (indir == 1 && (t == VOID || tp2->t_tspec == VOID))
1231 return true;
1232 }
1233
1234 if (t != tp2->t_tspec) {
1235 /*
1236 * Give pointer to types which differ only in
1237 * signedness a chance if not sflag and not hflag.
1238 */
1239 if (sflag || hflag || to != PTR)
1240 return false;
1241 if (signed_type(t) != signed_type(tp2->t_tspec))
1242 return false;
1243 }
1244
1245 if (tp1->t_is_enum && tp2->t_is_enum) {
1246 if (tp1->t_istag && tp2->t_istag) {
1247 return tp1->t_tag == tp2->t_tag;
1248 } else if (tp1->t_istynam && tp2->t_istynam) {
1249 return tp1->t_tynam == tp2->t_tynam;
1250 } else if (tp1->t_isuniqpos && tp2->t_isuniqpos) {
1251 return (tp1->t_uniqpos.p_line ==
1252 tp2->t_uniqpos.p_line &&
1253 tp1->t_uniqpos.p_file ==
1254 tp2->t_uniqpos.p_file &&
1255 tp1->t_uniqpos.p_uniq ==
1256 tp2->t_uniqpos.p_uniq);
1257 } else {
1258 return false;
1259 }
1260 }
1261
1262 /*
1263 * XXX Handle combinations of enum and int if eflag is set. But
1264 * note: enum and 0 should be allowed.
1265 */
1266
1267 if (asgn && indir == 1) {
1268 if (!tp1->t_const && tp2->t_const)
1269 return false;
1270 if (!tp1->t_volatile && tp2->t_volatile)
1271 return false;
1272 } else if (!ignqual && !tflag) {
1273 if (tp1->t_const != tp2->t_const)
1274 return false;
1275 if (tp1->t_const != tp2->t_const)
1276 return false;
1277 }
1278
1279 if (t == STRUCT || t == UNION) {
1280 if (tp1->t_istag && tp2->t_istag) {
1281 return tp1->t_tag == tp2->t_tag;
1282 } else if (tp1->t_istynam && tp2->t_istynam) {
1283 return tp1->t_tynam == tp2->t_tynam;
1284 } else if (tp1->t_isuniqpos && tp2->t_isuniqpos) {
1285 return (tp1->t_uniqpos.p_line ==
1286 tp2->t_uniqpos.p_line &&
1287 tp1->t_uniqpos.p_file ==
1288 tp2->t_uniqpos.p_file &&
1289 tp1->t_uniqpos.p_uniq ==
1290 tp2->t_uniqpos.p_uniq);
1291 } else {
1292 return false;
1293 }
1294 }
1295
1296 if (t == ARRAY && tp1->t_dim != tp2->t_dim) {
1297 if (tp1->t_dim != 0 && tp2->t_dim != 0)
1298 return false;
1299 }
1300
1301 if (t == FUNC) {
1302 if (tp1->t_proto && tp2->t_proto) {
1303 if (!prototypes_compatible(tp1, tp2, dowarn))
1304 return false;
1305 } else if (tp1->t_proto) {
1306 if (!matches_no_arg_function(tp1, dowarn))
1307 return false;
1308 } else if (tp2->t_proto) {
1309 if (!matches_no_arg_function(tp2, dowarn))
1310 return false;
1311 }
1312 }
1313
1314 tp1 = tp1->t_subt;
1315 tp2 = tp2->t_subt;
1316 ignqual = promot = false;
1317 to = t;
1318 indir++;
1319 }
1320
1321 return tp1 == tp2;
1322 }
1323
1324 /*
1325 * Compares arguments of two prototypes
1326 */
1327 static bool
1328 prototypes_compatible(const type_t *tp1, const type_t *tp2, bool *dowarn)
1329 {
1330
1331 if (tp1->t_vararg != tp2->t_vararg)
1332 return false;
1333
1334 const type_t **a1 = tp1->t_args;
1335 const type_t **a2 = tp2->t_args;
1336
1337 for (; *a1 != NULL && *a2 != NULL; a1++, a2++)
1338 if (!types_compatible(*a1, *a2, true, false, false, dowarn))
1339 return false;
1340 return *a1 == *a2;
1341 }
1342
1343 /*
1344 * Returns whether all parameters of a prototype are compatible with an
1345 * old-style function declaration.
1346 *
1347 * This is the case if the following conditions are met:
1348 * 1. the prototype must have a fixed number of parameters
1349 * 2. no parameter is of type float
1350 * 3. no parameter is converted to another type if integer promotion
1351 * is applied on it
1352 */
1353 static bool
1354 matches_no_arg_function(const type_t *tp, bool *dowarn)
1355 {
1356 if (tp->t_vararg && dowarn != NULL)
1357 *dowarn = true;
1358 for (const type_t **arg = tp->t_args; *arg != NULL; arg++) {
1359 tspec_t t = (*arg)->t_tspec;
1360 if (t == FLOAT)
1361 return false;
1362 if (t == CHAR || t == SCHAR || t == UCHAR)
1363 return false;
1364 if (t == SHORT || t == USHORT)
1365 return false;
1366 }
1367 return true;
1368 }
1369