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