Annotation of src/usr.bin/xlint/lint1/func.c, Revision 1.51
1.51 ! rillig 1: /* $NetBSD: func.c,v 1.50 2021/01/04 22:26:50 rillig Exp $ */
1.2 cgd 2:
1.1 cgd 3: /*
4: * Copyright (c) 1994, 1995 Jochen Pohl
5: * All Rights Reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Jochen Pohl for
18: * The NetBSD Project.
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: */
33:
1.21 jmc 34: #if HAVE_NBTOOL_CONFIG_H
35: #include "nbtool_config.h"
36: #endif
37:
1.8 christos 38: #include <sys/cdefs.h>
1.17 tv 39: #if defined(__RCSID) && !defined(lint)
1.51 ! rillig 40: __RCSID("$NetBSD: func.c,v 1.50 2021/01/04 22:26:50 rillig Exp $");
1.1 cgd 41: #endif
42:
43: #include <stdlib.h>
44: #include <string.h>
45:
46: #include "lint1.h"
1.10 tv 47: #include "cgram.h"
1.1 cgd 48:
49: /*
50: * Contains a pointer to the symbol table entry of the current function
51: * definition.
52: */
53: sym_t *funcsym;
54:
55: /* Is set as long as a statement can be reached. Must be set at level 0. */
56: int reached = 1;
57:
58: /*
59: * Is set as long as NOTREACHED is in effect.
60: * Is reset everywhere where reached can become 0.
61: */
62: int rchflg;
63:
64: /*
1.50 rillig 65: * In conjunction with reached, controls printing of "fallthrough on ..."
1.1 cgd 66: * warnings.
67: * Reset by each statement and set by FALLTHROUGH, switch (switch1())
68: * and case (label()).
69: *
70: * Control statements if, for, while and switch do not reset ftflg because
1.28 rillig 71: * this must be done by the controlled statement. At least for if this is
1.1 cgd 72: * important because ** FALLTHROUGH ** after "if (expr) stmnt" is evaluated
1.50 rillig 73: * before the following token, which causes reduction of above.
1.1 cgd 74: * This means that ** FALLTHROUGH ** after "if ..." would always be ignored.
75: */
76: int ftflg;
77:
1.48 rillig 78: /* The innermost control statement */
79: cstk_t *cstmt;
1.1 cgd 80:
81: /*
82: * Number of arguments which will be checked for usage in following
83: * function definition. -1 stands for all arguments.
84: *
1.31 rillig 85: * The position of the last ARGSUSED comment is stored in argsused_pos.
1.1 cgd 86: */
87: int nargusg = -1;
1.31 rillig 88: pos_t argsused_pos;
1.1 cgd 89:
90: /*
91: * Number of arguments of the following function definition whose types
92: * shall be checked by lint2. -1 stands for all arguments.
93: *
94: * The position of the last VARARGS comment is stored in vapos.
95: */
96: int nvararg = -1;
97: pos_t vapos;
98:
99: /*
1.49 rillig 100: * Both printflike_argnum and scanflike_argnum contain the 1-based number
101: * of the string argument which shall be used to check the types of remaining
102: * arguments (for PRINTFLIKE and SCANFLIKE).
1.1 cgd 103: *
1.31 rillig 104: * printflike_pos and scanflike_pos are the positions of the last PRINTFLIKE
105: * or SCANFLIKE comment.
1.1 cgd 106: */
1.49 rillig 107: int printflike_argnum = -1;
108: int scanflike_argnum = -1;
1.31 rillig 109: pos_t printflike_pos;
110: pos_t scanflike_pos;
1.1 cgd 111:
112: /*
1.28 rillig 113: * If both plibflg and llibflg are set, prototypes are written as function
1.1 cgd 114: * definitions to the output file.
115: */
116: int plibflg;
117:
118: /*
1.28 rillig 119: * Nonzero means that no warnings about constants in conditional
1.6 jpo 120: * context are printed.
1.1 cgd 121: */
1.31 rillig 122: int constcond_flag;
1.1 cgd 123:
124: /*
125: * llibflg is set if a lint library shall be created. The effect of
126: * llibflg is that all defined symbols are treated as used.
127: * (The LINTLIBRARY comment also resets vflag.)
128: */
129: int llibflg;
130:
131: /*
1.6 jpo 132: * Nonzero if warnings are suppressed by a LINTED directive
1.25 christos 133: * LWARN_BAD: error
1.30 rillig 134: * LWARN_ALL: warnings on
1.25 christos 135: * LWARN_NONE: all warnings ignored
136: * 0..n: warning n ignored
1.1 cgd 137: */
1.25 christos 138: int lwarn = LWARN_ALL;
1.6 jpo 139:
140: /*
1.47 rillig 141: * Whether bitfield type errors are suppressed by a BITFIELDTYPE
1.16 thorpej 142: * directive.
143: */
1.47 rillig 144: bool bitfieldtype_ok;
1.16 thorpej 145:
146: /*
1.6 jpo 147: * Nonzero if complaints about use of "long long" are suppressed in
148: * the next statement or declaration.
149: */
150: int quadflg;
1.1 cgd 151:
152: /*
153: * Puts a new element at the top of the stack used for control statements.
154: */
155: void
1.14 lukem 156: pushctrl(int env)
1.1 cgd 157: {
158: cstk_t *ci;
159:
160: ci = xcalloc(1, sizeof (cstk_t));
161: ci->c_env = env;
1.48 rillig 162: ci->c_surrounding = cstmt;
163: cstmt = ci;
1.1 cgd 164: }
165:
166: /*
167: * Removes the top element of the stack used for control statements.
168: */
169: void
1.14 lukem 170: popctrl(int env)
1.1 cgd 171: {
172: cstk_t *ci;
173: clst_t *cl;
174:
1.48 rillig 175: lint_assert(cstmt != NULL);
176: lint_assert(cstmt->c_env == env);
1.1 cgd 177:
1.48 rillig 178: cstmt = (ci = cstmt)->c_surrounding;
1.1 cgd 179:
180: while ((cl = ci->c_clst) != NULL) {
1.33 rillig 181: ci->c_clst = cl->cl_next;
1.1 cgd 182: free(cl);
183: }
184:
185: if (ci->c_swtype != NULL)
186: free(ci->c_swtype);
187:
188: free(ci);
189: }
190:
191: /*
192: * Prints a warning if a statement cannot be reached.
193: */
194: void
1.31 rillig 195: check_statement_reachable(void)
1.1 cgd 196: {
197: if (!reached && !rchflg) {
198: /* statement not reached */
199: warning(193);
200: reached = 1;
201: }
202: }
203:
204: /*
205: * Called after a function declaration which introduces a function definition
206: * and before an (optional) old style argument declaration list.
207: *
1.28 rillig 208: * Puts all symbols declared in the prototype or in an old style argument
1.1 cgd 209: * list back to the symbol table.
210: *
211: * Does the usual checking of storage class, type (return value),
1.28 rillig 212: * redeclaration, etc.
1.1 cgd 213: */
214: void
1.14 lukem 215: funcdef(sym_t *fsym)
1.1 cgd 216: {
1.24 dholland 217: int n, dowarn;
1.1 cgd 218: sym_t *arg, *sym, *rdsym;
219:
220: funcsym = fsym;
221:
222: /*
223: * Put all symbols declared in the argument list back to the
224: * symbol table.
225: */
1.3 jpo 226: for (sym = dcs->d_fpsyms; sym != NULL; sym = sym->s_dlnxt) {
1.1 cgd 227: if (sym->s_blklev != -1) {
1.41 rillig 228: lint_assert(sym->s_blklev == 1);
1.1 cgd 229: inssym(1, sym);
230: }
231: }
232:
233: /*
1.29 rillig 234: * In old_style_function() we did not know whether it is an old
235: * style function definition or only an old style declaration,
236: * if there are no arguments inside the argument list ("f()").
1.1 cgd 237: */
238: if (!fsym->s_type->t_proto && fsym->s_args == NULL)
239: fsym->s_osdef = 1;
240:
1.29 rillig 241: check_type(fsym);
1.1 cgd 242:
243: /*
1.29 rillig 244: * check_type() checks for almost all possible errors, but not for
1.1 cgd 245: * incomplete return values (these are allowed in declarations)
246: */
247: if (fsym->s_type->t_subt->t_tspec != VOID &&
248: incompl(fsym->s_type->t_subt)) {
249: /* cannot return incomplete type */
250: error(67);
251: }
252:
1.4 jpo 253: fsym->s_def = DEF;
1.1 cgd 254:
255: if (fsym->s_scl == TYPEDEF) {
256: fsym->s_scl = EXTERN;
257: /* illegal storage class */
258: error(8);
259: }
260:
1.4 jpo 261: if (dcs->d_inline)
262: fsym->s_inline = 1;
263:
1.1 cgd 264: /*
265: * Arguments in new style function declarations need a name.
266: * (void is already removed from the list of arguments)
267: */
268: n = 1;
1.32 rillig 269: for (arg = fsym->s_type->t_args; arg != NULL; arg = arg->s_next) {
1.1 cgd 270: if (arg->s_scl == ABSTRACT) {
1.41 rillig 271: lint_assert(arg->s_name == unnamed);
1.1 cgd 272: /* formal parameter lacks name: param #%d */
273: error(59, n);
274: } else {
1.41 rillig 275: lint_assert(arg->s_name != unnamed);
1.1 cgd 276: }
277: n++;
278: }
279:
280: /*
1.35 rillig 281: * We must also remember the position. s_def_pos is overwritten
1.1 cgd 282: * if this is an old style definition and we had already a
283: * prototype.
284: */
1.36 rillig 285: dcs->d_fdpos = fsym->s_def_pos;
1.1 cgd 286:
1.3 jpo 287: if ((rdsym = dcs->d_rdcsym) != NULL) {
1.1 cgd 288:
1.29 rillig 289: if (!check_redeclaration(fsym, (dowarn = 0, &dowarn))) {
1.1 cgd 290:
291: /*
1.5 jpo 292: * Print nothing if the newly defined function
1.1 cgd 293: * is defined in old style. A better warning will
1.38 rillig 294: * be printed in check_func_lint_directives().
1.1 cgd 295: */
1.24 dholland 296: if (dowarn && !fsym->s_osdef) {
1.50 rillig 297: if (sflag)
298: /* redeclaration of %s */
299: error(27, fsym->s_name);
300: else
301: /* redeclaration of %s */
302: warning(27, fsym->s_name);
1.29 rillig 303: print_previous_declaration(-1, rdsym);
1.1 cgd 304: }
305:
306: /* copy usage information */
1.29 rillig 307: copy_usage_info(fsym, rdsym);
1.1 cgd 308:
309: /*
310: * If the old symbol was a prototype and the new
311: * one is none, overtake the position of the
312: * declaration of the prototype.
313: */
314: if (fsym->s_osdef && rdsym->s_type->t_proto)
1.36 rillig 315: fsym->s_def_pos = rdsym->s_def_pos;
1.1 cgd 316:
317: /* complete the type */
1.29 rillig 318: complete_type(fsym, rdsym);
1.1 cgd 319:
1.4 jpo 320: /* once a function is inline it remains inline */
321: if (rdsym->s_inline)
322: fsym->s_inline = 1;
323:
1.1 cgd 324: }
325:
326: /* remove the old symbol from the symbol table */
327: rmsym(rdsym);
328:
329: }
330:
331: if (fsym->s_osdef && !fsym->s_type->t_proto) {
332: if (sflag && hflag && strcmp(fsym->s_name, "main") != 0)
1.28 rillig 333: /* function definition is not a prototype */
1.1 cgd 334: warning(286);
335: }
336:
1.3 jpo 337: if (dcs->d_notyp)
1.13 lukem 338: /* return value is implicitly declared to be int */
1.1 cgd 339: fsym->s_rimpl = 1;
340:
341: reached = 1;
342: }
343:
344: /*
345: * Called at the end of a function definition.
346: */
347: void
1.14 lukem 348: funcend(void)
1.1 cgd 349: {
350: sym_t *arg;
351: int n;
352:
353: if (reached) {
1.48 rillig 354: cstmt->c_noretval = 1;
1.1 cgd 355: if (funcsym->s_type->t_subt->t_tspec != VOID &&
356: !funcsym->s_rimpl) {
357: /* func. %s falls off bottom without returning value */
358: warning(217, funcsym->s_name);
359: }
360: }
361:
362: /*
1.22 perry 363: * This warning is printed only if the return value was implicitly
1.1 cgd 364: * declared to be int. Otherwise the wrong return statement
365: * has already printed a warning.
366: */
1.48 rillig 367: if (cstmt->c_noretval && cstmt->c_retval && funcsym->s_rimpl)
1.1 cgd 368: /* function %s has return (e); and return; */
369: warning(216, funcsym->s_name);
370:
371: /* Print warnings for unused arguments */
1.3 jpo 372: arg = dcs->d_fargs;
1.1 cgd 373: n = 0;
374: while (arg != NULL && (nargusg == -1 || n < nargusg)) {
1.29 rillig 375: check_usage_sym(dcs->d_asm, arg);
1.32 rillig 376: arg = arg->s_next;
1.1 cgd 377: n++;
378: }
379: nargusg = -1;
380:
381: /*
1.4 jpo 382: * write the information about the function definition to the
1.1 cgd 383: * output file
1.15 wiz 384: * inline functions explicitly declared extern are written as
1.4 jpo 385: * declarations only.
1.1 cgd 386: */
1.4 jpo 387: if (dcs->d_scl == EXTERN && funcsym->s_inline) {
388: outsym(funcsym, funcsym->s_scl, DECL);
389: } else {
1.48 rillig 390: outfdef(funcsym, &dcs->d_fdpos, cstmt->c_retval,
1.4 jpo 391: funcsym->s_osdef, dcs->d_fargs);
1.1 cgd 392: }
393:
394: /*
395: * remove all symbols declared during argument declaration from
396: * the symbol table
397: */
1.41 rillig 398: lint_assert(dcs->d_next == NULL);
399: lint_assert(dcs->d_ctx == EXTERN);
1.3 jpo 400: rmsyms(dcs->d_fpsyms);
1.1 cgd 401:
402: /* must be set on level 0 */
403: reached = 1;
404: }
405:
406: void
1.42 rillig 407: named_label(sym_t *sym)
408: {
409:
410: if (sym->s_set) {
411: /* label %s redefined */
412: error(194, sym->s_name);
413: } else {
414: mark_as_set(sym);
415: }
416:
417: reached = 1;
418: }
419:
1.43 rillig 420: static void
421: check_case_label(tnode_t *tn, cstk_t *ci)
1.1 cgd 422: {
423: clst_t *cl;
1.11 itohy 424: val_t *v;
425: val_t nv;
1.1 cgd 426: tspec_t t;
427:
1.42 rillig 428: if (ci == NULL) {
429: /* case not in switch */
430: error(195);
1.43 rillig 431: return;
432: }
433:
434: if (tn != NULL && tn->tn_op != CON) {
1.42 rillig 435: /* non-constant case expression */
436: error(197);
1.43 rillig 437: return;
438: }
439:
440: if (tn != NULL && !tspec_is_int(tn->tn_type->t_tspec)) {
1.42 rillig 441: /* non-integral case expression */
442: error(198);
1.43 rillig 443: return;
1.42 rillig 444: }
1.1 cgd 445:
1.43 rillig 446: lint_assert(ci->c_swtype != NULL);
1.1 cgd 447:
1.43 rillig 448: if (reached && !ftflg) {
449: if (hflag)
450: /* fallthrough on case statement */
451: warning(220);
452: }
1.1 cgd 453:
1.43 rillig 454: t = tn->tn_type->t_tspec;
455: if (t == LONG || t == ULONG ||
456: t == QUAD || t == UQUAD) {
457: if (tflag)
1.45 rillig 458: /* case label must be of type `int' in traditional C */
1.43 rillig 459: warning(203);
460: }
1.1 cgd 461:
1.43 rillig 462: /*
463: * get the value of the expression and convert it
464: * to the type of the switch expression
465: */
466: v = constant(tn, 1);
467: (void) memset(&nv, 0, sizeof nv);
468: cvtcon(CASE, 0, ci->c_swtype, &nv, v);
469: free(v);
470:
471: /* look if we had this value already */
472: for (cl = ci->c_clst; cl != NULL; cl = cl->cl_next) {
473: if (cl->cl_val.v_quad == nv.v_quad)
474: break;
475: }
476: if (cl != NULL && tspec_is_uint(nv.v_tspec)) {
477: /* duplicate case in switch: %lu */
478: error(200, (u_long)nv.v_quad);
479: } else if (cl != NULL) {
480: /* duplicate case in switch: %ld */
481: error(199, (long)nv.v_quad);
482: } else {
1.42 rillig 483: /*
1.43 rillig 484: * append the value to the list of
485: * case values
1.42 rillig 486: */
1.43 rillig 487: cl = xcalloc(1, sizeof (clst_t));
488: cl->cl_val = nv;
489: cl->cl_next = ci->c_clst;
490: ci->c_clst = cl;
1.42 rillig 491: }
1.43 rillig 492: }
493:
494: void
495: case_label(tnode_t *tn)
496: {
497: cstk_t *ci;
498:
1.51 ! rillig 499: /* find the innermost switch statement */
1.48 rillig 500: for (ci = cstmt; ci != NULL && !ci->c_switch; ci = ci->c_surrounding)
1.43 rillig 501: continue;
502:
503: check_case_label(tn, ci);
504:
1.42 rillig 505: tfreeblk();
506:
507: reached = 1;
508: }
509:
510: void
511: default_label(void)
512: {
513: cstk_t *ci;
1.1 cgd 514:
1.51 ! rillig 515: /* find the innermost switch statement */
1.48 rillig 516: for (ci = cstmt; ci != NULL && !ci->c_switch; ci = ci->c_surrounding)
1.42 rillig 517: continue;
1.1 cgd 518:
1.42 rillig 519: if (ci == NULL) {
520: /* default outside switch */
521: error(201);
522: } else if (ci->c_default) {
523: /* duplicate default in switch */
524: error(202);
525: } else {
526: if (reached && !ftflg) {
527: if (hflag)
528: /* fallthrough on default statement */
529: warning(284);
1.1 cgd 530: }
1.42 rillig 531: ci->c_default = 1;
532: }
533:
1.1 cgd 534: reached = 1;
535: }
536:
1.39 rillig 537: static tnode_t *
538: check_controlling_expression(tnode_t *tn)
539: {
540: tspec_t t = tn->tn_type->t_tspec;
541:
542: if (tn != NULL)
543: tn = cconv(tn);
544: if (tn != NULL)
545: tn = promote(NOOP, 0, tn);
546:
547: if (tn != NULL && !tspec_is_scalar(t)) {
548: /* C99 6.5.15p4 for the ?: operator; see typeok:QUEST */
549: /* C99 6.8.4.1p1 for if statements */
550: /* C99 6.8.5p2 for while, do and for loops */
551: /* controlling expressions must have scalar type */
552: error(204);
553: return NULL;
554: }
555:
556: return tn;
557: }
558:
1.1 cgd 559: /*
1.44 rillig 560: * T_IF T_LPAREN expr T_RPAREN
1.1 cgd 561: */
562: void
1.14 lukem 563: if1(tnode_t *tn)
1.1 cgd 564: {
1.14 lukem 565:
1.1 cgd 566: if (tn != NULL)
1.39 rillig 567: tn = check_controlling_expression(tn);
1.1 cgd 568: if (tn != NULL)
1.39 rillig 569: expr(tn, 0, 1, 0);
1.1 cgd 570: pushctrl(T_IF);
571: }
572:
573: /*
574: * if_without_else
575: * if_without_else T_ELSE
576: */
577: void
1.14 lukem 578: if2(void)
1.1 cgd 579: {
1.14 lukem 580:
1.48 rillig 581: cstmt->c_rchif = reached ? 1 : 0;
1.1 cgd 582: reached = 1;
583: }
584:
585: /*
586: * if_without_else
587: * if_without_else T_ELSE stmnt
588: */
589: void
1.14 lukem 590: if3(int els)
1.1 cgd 591: {
1.14 lukem 592:
1.1 cgd 593: if (els) {
1.48 rillig 594: reached |= cstmt->c_rchif;
1.1 cgd 595: } else {
596: reached = 1;
597: }
598: popctrl(T_IF);
599: }
600:
601: /*
1.44 rillig 602: * T_SWITCH T_LPAREN expr T_RPAREN
1.1 cgd 603: */
604: void
1.14 lukem 605: switch1(tnode_t *tn)
1.1 cgd 606: {
607: tspec_t t;
608: type_t *tp;
609:
610: if (tn != NULL)
611: tn = cconv(tn);
612: if (tn != NULL)
613: tn = promote(NOOP, 0, tn);
1.27 rillig 614: if (tn != NULL && !tspec_is_int(tn->tn_type->t_tspec)) {
1.1 cgd 615: /* switch expression must have integral type */
616: error(205);
617: tn = NULL;
618: }
619: if (tn != NULL && tflag) {
620: t = tn->tn_type->t_tspec;
621: if (t == LONG || t == ULONG || t == QUAD || t == UQUAD) {
622: /* switch expr. must be of type `int' in trad. C */
623: warning(271);
624: }
625: }
626:
627: /*
1.37 rillig 628: * Remember the type of the expression. Because it's possible
629: * that (*tp) is allocated on tree memory, the type must be
1.1 cgd 630: * duplicated. This is not too complicated because it is
631: * only an integer type.
632: */
633: tp = xcalloc(1, sizeof (type_t));
634: if (tn != NULL) {
635: tp->t_tspec = tn->tn_type->t_tspec;
636: if ((tp->t_isenum = tn->tn_type->t_isenum) != 0)
637: tp->t_enum = tn->tn_type->t_enum;
638: } else {
639: tp->t_tspec = INT;
640: }
641:
1.20 christos 642: expr(tn, 1, 0, 1);
1.1 cgd 643:
644: pushctrl(T_SWITCH);
1.48 rillig 645: cstmt->c_switch = 1;
646: cstmt->c_swtype = tp;
1.1 cgd 647:
648: reached = rchflg = 0;
649: ftflg = 1;
650: }
651:
652: /*
653: * switch_expr stmnt
654: */
655: void
1.14 lukem 656: switch2(void)
1.1 cgd 657: {
1.8 christos 658: int nenum = 0, nclab = 0;
1.1 cgd 659: sym_t *esym;
660: clst_t *cl;
661:
1.48 rillig 662: lint_assert(cstmt->c_swtype != NULL);
1.1 cgd 663:
664: /*
665: * If the switch expression was of type enumeration, count the case
666: * labels and the number of enumerators. If both counts are not
667: * equal print a warning.
668: */
1.48 rillig 669: if (cstmt->c_swtype->t_isenum) {
1.1 cgd 670: nenum = nclab = 0;
1.48 rillig 671: lint_assert(cstmt->c_swtype->t_enum != NULL);
672: for (esym = cstmt->c_swtype->t_enum->elem;
1.32 rillig 673: esym != NULL; esym = esym->s_next) {
1.1 cgd 674: nenum++;
675: }
1.48 rillig 676: for (cl = cstmt->c_clst; cl != NULL; cl = cl->cl_next)
1.1 cgd 677: nclab++;
1.48 rillig 678: if (hflag && eflag && nenum != nclab && !cstmt->c_default) {
1.1 cgd 679: /* enumeration value(s) not handled in switch */
680: warning(206);
681: }
682: }
683:
1.48 rillig 684: if (cstmt->c_break) {
1.1 cgd 685: /*
686: * end of switch alway reached (c_break is only set if the
687: * break statement can be reached).
688: */
689: reached = 1;
1.48 rillig 690: } else if (!cstmt->c_default &&
691: (!hflag || !cstmt->c_swtype->t_isenum || nenum != nclab)) {
1.1 cgd 692: /*
693: * there are possible values which are not handled in
694: * switch
695: */
696: reached = 1;
697: } /*
698: * otherwise the end of the switch expression is reached
699: * if the end of the last statement inside it is reached.
700: */
701:
702: popctrl(T_SWITCH);
703: }
704:
705: /*
1.44 rillig 706: * T_WHILE T_LPAREN expr T_RPAREN
1.1 cgd 707: */
708: void
1.14 lukem 709: while1(tnode_t *tn)
1.1 cgd 710: {
1.14 lukem 711:
1.1 cgd 712: if (!reached) {
713: /* loop not entered at top */
714: warning(207);
715: reached = 1;
716: }
717:
718: if (tn != NULL)
1.39 rillig 719: tn = check_controlling_expression(tn);
1.1 cgd 720:
721: pushctrl(T_WHILE);
1.48 rillig 722: cstmt->c_loop = 1;
1.1 cgd 723: if (tn != NULL && tn->tn_op == CON) {
1.27 rillig 724: if (tspec_is_int(tn->tn_type->t_tspec)) {
1.48 rillig 725: cstmt->c_infinite = tn->tn_val->v_quad != 0;
1.1 cgd 726: } else {
1.48 rillig 727: cstmt->c_infinite = tn->tn_val->v_ldbl != 0.0;
1.1 cgd 728: }
729: }
730:
1.20 christos 731: expr(tn, 0, 1, 1);
1.1 cgd 732: }
733:
734: /*
735: * while_expr stmnt
736: * while_expr error
737: */
738: void
1.14 lukem 739: while2(void)
1.1 cgd 740: {
1.14 lukem 741:
1.1 cgd 742: /*
743: * The end of the loop can be reached if it is no endless loop
744: * or there was a break statement which was reached.
745: */
1.48 rillig 746: reached = !cstmt->c_infinite || cstmt->c_break;
1.1 cgd 747: rchflg = 0;
748:
749: popctrl(T_WHILE);
750: }
751:
752: /*
753: * T_DO
754: */
755: void
1.14 lukem 756: do1(void)
1.1 cgd 757: {
1.14 lukem 758:
1.1 cgd 759: if (!reached) {
760: /* loop not entered at top */
761: warning(207);
762: reached = 1;
763: }
764:
765: pushctrl(T_DO);
1.48 rillig 766: cstmt->c_loop = 1;
1.1 cgd 767: }
768:
769: /*
770: * do stmnt do_while_expr
771: * do error
772: */
773: void
1.14 lukem 774: do2(tnode_t *tn)
1.1 cgd 775: {
1.14 lukem 776:
1.1 cgd 777: /*
1.28 rillig 778: * If there was a continue statement, the expression controlling the
1.1 cgd 779: * loop is reached.
780: */
1.48 rillig 781: if (cstmt->c_cont)
1.1 cgd 782: reached = 1;
783:
784: if (tn != NULL)
1.39 rillig 785: tn = check_controlling_expression(tn);
1.1 cgd 786:
787: if (tn != NULL && tn->tn_op == CON) {
1.27 rillig 788: if (tspec_is_int(tn->tn_type->t_tspec)) {
1.48 rillig 789: cstmt->c_infinite = tn->tn_val->v_quad != 0;
1.1 cgd 790: } else {
1.48 rillig 791: cstmt->c_infinite = tn->tn_val->v_ldbl != 0.0;
1.1 cgd 792: }
1.48 rillig 793: if (!cstmt->c_infinite && cstmt->c_cont)
1.46 rillig 794: /* continue in 'do ... while (0)' loop */
795: error(323);
1.1 cgd 796: }
797:
1.20 christos 798: expr(tn, 0, 1, 1);
1.1 cgd 799:
800: /*
801: * The end of the loop is only reached if it is no endless loop
802: * or there was a break statement which could be reached.
803: */
1.48 rillig 804: reached = !cstmt->c_infinite || cstmt->c_break;
1.1 cgd 805: rchflg = 0;
806:
807: popctrl(T_DO);
808: }
809:
810: /*
1.44 rillig 811: * T_FOR T_LPAREN opt_expr T_SEMI opt_expr T_SEMI opt_expr T_RPAREN
1.1 cgd 812: */
813: void
1.14 lukem 814: for1(tnode_t *tn1, tnode_t *tn2, tnode_t *tn3)
1.1 cgd 815: {
1.14 lukem 816:
1.1 cgd 817: /*
818: * If there is no initialisation expression it is possible that
819: * it is intended not to enter the loop at top.
820: */
821: if (tn1 != NULL && !reached) {
822: /* loop not entered at top */
823: warning(207);
824: reached = 1;
825: }
826:
827: pushctrl(T_FOR);
1.48 rillig 828: cstmt->c_loop = 1;
1.1 cgd 829:
830: /*
831: * Store the tree memory for the reinitialisation expression.
832: * Also remember this expression itself. We must check it at
833: * the end of the loop to get "used but not set" warnings correct.
834: */
1.48 rillig 835: cstmt->c_fexprm = tsave();
836: cstmt->c_f3expr = tn3;
837: cstmt->c_fpos = curr_pos;
838: cstmt->c_cfpos = csrc_pos;
1.1 cgd 839:
840: if (tn1 != NULL)
1.20 christos 841: expr(tn1, 0, 0, 1);
1.1 cgd 842:
843: if (tn2 != NULL)
1.39 rillig 844: tn2 = check_controlling_expression(tn2);
1.1 cgd 845: if (tn2 != NULL)
1.20 christos 846: expr(tn2, 0, 1, 1);
1.1 cgd 847:
848: if (tn2 == NULL) {
1.48 rillig 849: cstmt->c_infinite = 1;
1.1 cgd 850: } else if (tn2->tn_op == CON) {
1.27 rillig 851: if (tspec_is_int(tn2->tn_type->t_tspec)) {
1.48 rillig 852: cstmt->c_infinite = tn2->tn_val->v_quad != 0;
1.1 cgd 853: } else {
1.48 rillig 854: cstmt->c_infinite = tn2->tn_val->v_ldbl != 0.0;
1.1 cgd 855: }
856: }
857:
858: /* Checking the reinitialisation expression is done in for2() */
859:
860: reached = 1;
861: }
862:
863: /*
864: * for_exprs stmnt
865: * for_exprs error
866: */
867: void
1.14 lukem 868: for2(void)
1.1 cgd 869: {
870: pos_t cpos, cspos;
871: tnode_t *tn3;
872:
1.48 rillig 873: if (cstmt->c_cont)
1.1 cgd 874: reached = 1;
875:
1.36 rillig 876: cpos = curr_pos;
877: cspos = csrc_pos;
1.1 cgd 878:
879: /* Restore the tree memory for the reinitialisation expression */
1.48 rillig 880: trestor(cstmt->c_fexprm);
881: tn3 = cstmt->c_f3expr;
882: curr_pos = cstmt->c_fpos;
883: csrc_pos = cstmt->c_cfpos;
1.1 cgd 884:
885: /* simply "statement not reached" would be confusing */
886: if (!reached && !rchflg) {
887: /* end-of-loop code not reached */
888: warning(223);
889: reached = 1;
890: }
891:
892: if (tn3 != NULL) {
1.20 christos 893: expr(tn3, 0, 0, 1);
1.1 cgd 894: } else {
895: tfreeblk();
896: }
897:
1.36 rillig 898: curr_pos = cpos;
899: csrc_pos = cspos;
1.1 cgd 900:
901: /* An endless loop without break will never terminate */
1.48 rillig 902: reached = cstmt->c_break || !cstmt->c_infinite;
1.1 cgd 903: rchflg = 0;
904:
905: popctrl(T_FOR);
906: }
907:
908: /*
909: * T_GOTO identifier T_SEMI
910: * T_GOTO error T_SEMI
911: */
912: void
1.14 lukem 913: dogoto(sym_t *lab)
1.1 cgd 914: {
1.14 lukem 915:
1.29 rillig 916: mark_as_used(lab, 0, 0);
1.1 cgd 917:
1.31 rillig 918: check_statement_reachable();
1.1 cgd 919:
920: reached = rchflg = 0;
921: }
922:
923: /*
924: * T_BREAK T_SEMI
925: */
926: void
1.14 lukem 927: dobreak(void)
1.1 cgd 928: {
929: cstk_t *ci;
930:
1.48 rillig 931: ci = cstmt;
1.1 cgd 932: while (ci != NULL && !ci->c_loop && !ci->c_switch)
1.48 rillig 933: ci = ci->c_surrounding;
1.1 cgd 934:
935: if (ci == NULL) {
936: /* break outside loop or switch */
937: error(208);
938: } else {
939: if (reached)
940: ci->c_break = 1;
941: }
942:
943: if (bflag)
1.31 rillig 944: check_statement_reachable();
1.1 cgd 945:
946: reached = rchflg = 0;
947: }
948:
949: /*
950: * T_CONTINUE T_SEMI
951: */
952: void
1.14 lukem 953: docont(void)
1.1 cgd 954: {
955: cstk_t *ci;
956:
1.48 rillig 957: for (ci = cstmt; ci != NULL && !ci->c_loop; ci = ci->c_surrounding)
1.14 lukem 958: continue;
1.1 cgd 959:
960: if (ci == NULL) {
961: /* continue outside loop */
962: error(209);
963: } else {
964: ci->c_cont = 1;
965: }
966:
1.31 rillig 967: check_statement_reachable();
1.1 cgd 968:
969: reached = rchflg = 0;
970: }
971:
972: /*
973: * T_RETURN T_SEMI
974: * T_RETURN expr T_SEMI
975: */
976: void
1.14 lukem 977: doreturn(tnode_t *tn)
1.1 cgd 978: {
979: tnode_t *ln, *rn;
980: cstk_t *ci;
981: op_t op;
982:
1.48 rillig 983: for (ci = cstmt; ci->c_surrounding != NULL; ci = ci->c_surrounding)
1.14 lukem 984: continue;
1.1 cgd 985:
986: if (tn != NULL) {
987: ci->c_retval = 1;
988: } else {
989: ci->c_noretval = 1;
990: }
991:
992: if (tn != NULL && funcsym->s_type->t_subt->t_tspec == VOID) {
993: /* void function %s cannot return value */
994: error(213, funcsym->s_name);
995: tfreeblk();
996: tn = NULL;
997: } else if (tn == NULL && funcsym->s_type->t_subt->t_tspec != VOID) {
998: /*
999: * Assume that the function has a return value only if it
1000: * is explicitly declared.
1001: */
1002: if (!funcsym->s_rimpl)
1003: /* function %s expects to return value */
1004: warning(214, funcsym->s_name);
1005: }
1006:
1007: if (tn != NULL) {
1008:
1009: /* Create a temporary node for the left side */
1010: ln = tgetblk(sizeof (tnode_t));
1011: ln->tn_op = NAME;
1012: ln->tn_type = tduptyp(funcsym->s_type->t_subt);
1013: ln->tn_type->t_const = 0;
1014: ln->tn_lvalue = 1;
1015: ln->tn_sym = funcsym; /* better than nothing */
1016:
1017: tn = build(RETURN, ln, tn);
1018:
1019: if (tn != NULL) {
1020: rn = tn->tn_right;
1021: while ((op = rn->tn_op) == CVT || op == PLUS)
1022: rn = rn->tn_left;
1023: if (rn->tn_op == AMPER && rn->tn_left->tn_op == NAME &&
1024: rn->tn_left->tn_sym->s_scl == AUTO) {
1025: /* %s returns pointer to automatic object */
1026: warning(302, funcsym->s_name);
1027: }
1028: }
1029:
1.20 christos 1030: expr(tn, 1, 0, 1);
1.1 cgd 1031:
1032: } else {
1033:
1.31 rillig 1034: check_statement_reachable();
1.1 cgd 1035:
1036: }
1037:
1038: reached = rchflg = 0;
1039: }
1040:
1041: /*
1.7 jpo 1042: * Do some cleanup after a global declaration or definition.
1.28 rillig 1043: * Especially remove information about unused lint comments.
1.1 cgd 1044: */
1045: void
1.31 rillig 1046: global_clean_up_decl(int silent)
1.1 cgd 1047: {
1048: pos_t cpos;
1049:
1.36 rillig 1050: cpos = curr_pos;
1.1 cgd 1051:
1052: if (nargusg != -1) {
1.6 jpo 1053: if (!silent) {
1.36 rillig 1054: curr_pos = argsused_pos;
1.40 rillig 1055: /* must precede function definition: ** %s ** */
1.1 cgd 1056: warning(282, "ARGSUSED");
1057: }
1058: nargusg = -1;
1059: }
1060: if (nvararg != -1) {
1.6 jpo 1061: if (!silent) {
1.36 rillig 1062: curr_pos = vapos;
1.40 rillig 1063: /* must precede function definition: ** %s ** */
1.1 cgd 1064: warning(282, "VARARGS");
1065: }
1066: nvararg = -1;
1067: }
1.49 rillig 1068: if (printflike_argnum != -1) {
1.6 jpo 1069: if (!silent) {
1.36 rillig 1070: curr_pos = printflike_pos;
1.40 rillig 1071: /* must precede function definition: ** %s ** */
1.1 cgd 1072: warning(282, "PRINTFLIKE");
1073: }
1.49 rillig 1074: printflike_argnum = -1;
1.1 cgd 1075: }
1.49 rillig 1076: if (scanflike_argnum != -1) {
1.6 jpo 1077: if (!silent) {
1.36 rillig 1078: curr_pos = scanflike_pos;
1.40 rillig 1079: /* must precede function definition: ** %s ** */
1.1 cgd 1080: warning(282, "SCANFLIKE");
1081: }
1.49 rillig 1082: scanflike_argnum = -1;
1.1 cgd 1083: }
1084:
1.36 rillig 1085: curr_pos = cpos;
1.7 jpo 1086:
1087: dcs->d_asm = 0;
1.1 cgd 1088: }
1089:
1090: /*
1091: * ARGSUSED comment
1092: *
1093: * Only the first n arguments of the following function are checked
1094: * for usage. A missing argument is taken to be 0.
1095: */
1096: void
1.14 lukem 1097: argsused(int n)
1.1 cgd 1098: {
1.14 lukem 1099:
1.1 cgd 1100: if (n == -1)
1101: n = 0;
1102:
1.3 jpo 1103: if (dcs->d_ctx != EXTERN) {
1.1 cgd 1104: /* must be outside function: ** %s ** */
1105: warning(280, "ARGSUSED");
1106: return;
1107: }
1108: if (nargusg != -1) {
1109: /* duplicate use of ** %s ** */
1110: warning(281, "ARGSUSED");
1111: }
1112: nargusg = n;
1.36 rillig 1113: argsused_pos = curr_pos;
1.1 cgd 1114: }
1115:
1116: /*
1117: * VARARGS comment
1118: *
1.28 rillig 1119: * Causes lint2 to check only the first n arguments for compatibility
1120: * with the function definition. A missing argument is taken to be 0.
1.1 cgd 1121: */
1122: void
1.14 lukem 1123: varargs(int n)
1.1 cgd 1124: {
1.14 lukem 1125:
1.1 cgd 1126: if (n == -1)
1127: n = 0;
1128:
1.3 jpo 1129: if (dcs->d_ctx != EXTERN) {
1.1 cgd 1130: /* must be outside function: ** %s ** */
1131: warning(280, "VARARGS");
1132: return;
1133: }
1134: if (nvararg != -1) {
1.40 rillig 1135: /* duplicate use of ** %s ** */
1.1 cgd 1136: warning(281, "VARARGS");
1137: }
1138: nvararg = n;
1.36 rillig 1139: vapos = curr_pos;
1.1 cgd 1140: }
1141:
1142: /*
1143: * PRINTFLIKE comment
1144: *
1145: * Check all arguments until the (n-1)-th as usual. The n-th argument is
1146: * used the check the types of remaining arguments.
1147: */
1148: void
1.14 lukem 1149: printflike(int n)
1.1 cgd 1150: {
1.14 lukem 1151:
1.1 cgd 1152: if (n == -1)
1153: n = 0;
1154:
1.3 jpo 1155: if (dcs->d_ctx != EXTERN) {
1.1 cgd 1156: /* must be outside function: ** %s ** */
1157: warning(280, "PRINTFLIKE");
1158: return;
1159: }
1.49 rillig 1160: if (printflike_argnum != -1) {
1.1 cgd 1161: /* duplicate use of ** %s ** */
1162: warning(281, "PRINTFLIKE");
1163: }
1.49 rillig 1164: printflike_argnum = n;
1.36 rillig 1165: printflike_pos = curr_pos;
1.1 cgd 1166: }
1167:
1168: /*
1169: * SCANFLIKE comment
1170: *
1171: * Check all arguments until the (n-1)-th as usual. The n-th argument is
1172: * used the check the types of remaining arguments.
1173: */
1174: void
1.14 lukem 1175: scanflike(int n)
1.1 cgd 1176: {
1.14 lukem 1177:
1.1 cgd 1178: if (n == -1)
1179: n = 0;
1180:
1.3 jpo 1181: if (dcs->d_ctx != EXTERN) {
1.1 cgd 1182: /* must be outside function: ** %s ** */
1183: warning(280, "SCANFLIKE");
1184: return;
1185: }
1.49 rillig 1186: if (scanflike_argnum != -1) {
1.1 cgd 1187: /* duplicate use of ** %s ** */
1188: warning(281, "SCANFLIKE");
1189: }
1.49 rillig 1190: scanflike_argnum = n;
1.36 rillig 1191: scanflike_pos = curr_pos;
1.1 cgd 1192: }
1193:
1194: /*
1.50 rillig 1195: * Set the line number for a CONSTCOND comment. At this and the following
1.1 cgd 1196: * line no warnings about constants in conditional contexts are printed.
1197: */
1198: /* ARGSUSED */
1199: void
1.14 lukem 1200: constcond(int n)
1.1 cgd 1201: {
1.14 lukem 1202:
1.31 rillig 1203: constcond_flag = 1;
1.1 cgd 1204: }
1205:
1206: /*
1207: * Suppress printing of "fallthrough on ..." warnings until next
1208: * statement.
1209: */
1210: /* ARGSUSED */
1211: void
1.14 lukem 1212: fallthru(int n)
1.1 cgd 1213: {
1.14 lukem 1214:
1.1 cgd 1215: ftflg = 1;
1216: }
1217:
1218: /*
1219: * Stop warnings about statements which cannot be reached. Also tells lint
1220: * that the following statements cannot be reached (e.g. after exit()).
1221: */
1222: /* ARGSUSED */
1223: void
1.14 lukem 1224: notreach(int n)
1.1 cgd 1225: {
1.14 lukem 1226:
1.1 cgd 1227: reached = 0;
1228: rchflg = 1;
1229: }
1230:
1231: /* ARGSUSED */
1232: void
1.14 lukem 1233: lintlib(int n)
1.1 cgd 1234: {
1.14 lukem 1235:
1.3 jpo 1236: if (dcs->d_ctx != EXTERN) {
1.1 cgd 1237: /* must be outside function: ** %s ** */
1238: warning(280, "LINTLIBRARY");
1239: return;
1240: }
1241: llibflg = 1;
1242: vflag = 0;
1243: }
1244:
1245: /*
1246: * Suppress most warnings at the current and the following line.
1247: */
1248: /* ARGSUSED */
1249: void
1.14 lukem 1250: linted(int n)
1.1 cgd 1251: {
1.14 lukem 1252:
1.12 christos 1253: #ifdef DEBUG
1.25 christos 1254: printf("%s, %d: lwarn = %d\n", curr_pos.p_file, curr_pos.p_line, n);
1.12 christos 1255: #endif
1.25 christos 1256: lwarn = n;
1.16 thorpej 1257: }
1258:
1259: /*
1260: * Suppress bitfield type errors on the current line.
1261: */
1262: /* ARGSUSED */
1263: void
1264: bitfieldtype(int n)
1265: {
1266:
1267: #ifdef DEBUG
1.47 rillig 1268: printf("%s, %d: bitfieldtype_ok = true\n", curr_pos.p_file,
1.16 thorpej 1269: curr_pos.p_line);
1270: #endif
1.47 rillig 1271: bitfieldtype_ok = true;
1.1 cgd 1272: }
1273:
1274: /*
1.28 rillig 1275: * PROTOLIB in conjunction with LINTLIBRARY can be used to handle
1.1 cgd 1276: * prototypes like function definitions. This is done if the argument
1.28 rillig 1277: * to PROTOLIB is nonzero. Otherwise prototypes are handled normally.
1.1 cgd 1278: */
1279: void
1.14 lukem 1280: protolib(int n)
1.1 cgd 1281: {
1.14 lukem 1282:
1.3 jpo 1283: if (dcs->d_ctx != EXTERN) {
1.1 cgd 1284: /* must be outside function: ** %s ** */
1285: warning(280, "PROTOLIB");
1286: return;
1287: }
1288: plibflg = n == 0 ? 0 : 1;
1.6 jpo 1289: }
1290:
1291: /*
1292: * Set quadflg to nonzero which means that the next statement/declaration
1293: * may use "long long" without an error or warning.
1294: */
1295: /* ARGSUSED */
1296: void
1.14 lukem 1297: longlong(int n)
1.6 jpo 1298: {
1.14 lukem 1299:
1.6 jpo 1300: quadflg = 1;
1.1 cgd 1301: }
CVSweb <webmaster@jp.NetBSD.org>