1281168Spfg/*	$NetBSD: func.c,v 1.22 2005/09/24 15:30:35 perry Exp $	*/
212099Sjoerg
312099Sjoerg/*
412099Sjoerg * Copyright (c) 1994, 1995 Jochen Pohl
512099Sjoerg * All Rights Reserved.
612099Sjoerg *
712099Sjoerg * Redistribution and use in source and binary forms, with or without
812099Sjoerg * modification, are permitted provided that the following conditions
912099Sjoerg * are met:
1012099Sjoerg * 1. Redistributions of source code must retain the above copyright
1112099Sjoerg *    notice, this list of conditions and the following disclaimer.
1212099Sjoerg * 2. Redistributions in binary form must reproduce the above copyright
1312099Sjoerg *    notice, this list of conditions and the following disclaimer in the
1412099Sjoerg *    documentation and/or other materials provided with the distribution.
1512099Sjoerg * 3. All advertising materials mentioning features or use of this software
1612099Sjoerg *    must display the following acknowledgement:
1712099Sjoerg *      This product includes software developed by Jochen Pohl for
1812099Sjoerg *	The NetBSD Project.
1912099Sjoerg * 4. The name of the author may not be used to endorse or promote products
2012099Sjoerg *    derived from this software without specific prior written permission.
2112099Sjoerg *
2212099Sjoerg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2312099Sjoerg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2412099Sjoerg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2512099Sjoerg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2612099Sjoerg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2712099Sjoerg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2812099Sjoerg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2912099Sjoerg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3012099Sjoerg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3112099Sjoerg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3212099Sjoerg */
3312099Sjoerg
3491592Smarkm#include <sys/cdefs.h>
3591592Smarkm#if defined(__RCSID) && !defined(lint)
3691592Smarkm__RCSID("$NetBSD: func.c,v 1.16 2002/01/03 04:25:15 thorpej Exp $");
3712099Sjoerg#endif
3891592Smarkm__FBSDID("$FreeBSD$");
3912099Sjoerg
4012099Sjoerg#include <stdlib.h>
4112099Sjoerg#include <string.h>
4212099Sjoerg
4312099Sjoerg#include "lint1.h"
4491592Smarkm#include "cgram.h"
4512099Sjoerg
4612099Sjoerg/*
4712099Sjoerg * Contains a pointer to the symbol table entry of the current function
4812099Sjoerg * definition.
4912099Sjoerg */
5012099Sjoergsym_t	*funcsym;
5112099Sjoerg
5212099Sjoerg/* Is set as long as a statement can be reached. Must be set at level 0. */
5312099Sjoergint	reached = 1;
5412099Sjoerg
5512099Sjoerg/*
5612099Sjoerg * Is set as long as NOTREACHED is in effect.
5712099Sjoerg * Is reset everywhere where reached can become 0.
5812099Sjoerg */
5912099Sjoergint	rchflg;
6012099Sjoerg
6112099Sjoerg/*
62228992Suqs * In conjunction with reached controls printing of "fallthrough on ..."
6312099Sjoerg * warnings.
6412099Sjoerg * Reset by each statement and set by FALLTHROUGH, switch (switch1())
6512099Sjoerg * and case (label()).
6612099Sjoerg *
6712099Sjoerg * Control statements if, for, while and switch do not reset ftflg because
68228992Suqs * this must be done by the controlled statement. At least for if this is
6912099Sjoerg * important because ** FALLTHROUGH ** after "if (expr) stmnt" is evaluated
70228992Suqs * before the following token, which causes reduction of above, is read.
7112099Sjoerg * This means that ** FALLTHROUGH ** after "if ..." would always be ignored.
7212099Sjoerg */
7312099Sjoergint	ftflg;
7412099Sjoerg
7512099Sjoerg/* Top element of stack for control statements */
7612099Sjoergcstk_t	*cstk;
7712099Sjoerg
7812099Sjoerg/*
7912099Sjoerg * Number of arguments which will be checked for usage in following
8012099Sjoerg * function definition. -1 stands for all arguments.
8112099Sjoerg *
8212099Sjoerg * The position of the last ARGSUSED comment is stored in aupos.
8312099Sjoerg */
8412099Sjoergint	nargusg = -1;
8512099Sjoergpos_t	aupos;
8612099Sjoerg
8712099Sjoerg/*
8812099Sjoerg * Number of arguments of the following function definition whose types
8912099Sjoerg * shall be checked by lint2. -1 stands for all arguments.
9012099Sjoerg *
9112099Sjoerg * The position of the last VARARGS comment is stored in vapos.
9212099Sjoerg */
9312099Sjoergint	nvararg = -1;
9412099Sjoergpos_t	vapos;
9512099Sjoerg
9612099Sjoerg/*
9712099Sjoerg * Both prflstr and scflstrg contain the number of the argument which
9812099Sjoerg * shall be used to check the types of remaining arguments (for PRINTFLIKE
9912099Sjoerg * and SCANFLIKE).
10012099Sjoerg *
10112099Sjoerg * prflpos and scflpos are the positions of the last PRINTFLIKE or
10212099Sjoerg * SCANFLIKE comment.
10312099Sjoerg */
10412099Sjoergint	prflstrg = -1;
10512099Sjoergint	scflstrg = -1;
10612099Sjoergpos_t	prflpos;
10712099Sjoergpos_t	scflpos;
10812099Sjoerg
10912099Sjoerg/*
110228992Suqs * Are both plibflg and llibflg set, prototypes are written as function
11112099Sjoerg * definitions to the output file.
11212099Sjoerg */
11312099Sjoergint	plibflg;
11412099Sjoerg
11512099Sjoerg/*
116228992Suqs * Nonzero means that no warnings about constants in conditional
11712099Sjoerg * context are printed.
11812099Sjoerg */
11912099Sjoergint	ccflg;
12012099Sjoerg
12112099Sjoerg/*
12212099Sjoerg * llibflg is set if a lint library shall be created. The effect of
12312099Sjoerg * llibflg is that all defined symbols are treated as used.
12412099Sjoerg * (The LINTLIBRARY comment also resets vflag.)
12512099Sjoerg */
12612099Sjoergint	llibflg;
12712099Sjoerg
12812099Sjoerg/*
12912099Sjoerg * Nonzero if warnings are suppressed by a LINTED directive
13012099Sjoerg */
13112099Sjoergint	nowarn;
13212099Sjoerg
13312099Sjoerg/*
13491592Smarkm * Nonzero if bitfield type errors are suppressed by a BITFIELDTYPE
13591592Smarkm * directive.
13691592Smarkm */
13791592Smarkmint	bitfieldtype_ok;
13891592Smarkm
13991592Smarkm/*
14012099Sjoerg * Nonzero if complaints about use of "long long" are suppressed in
14112099Sjoerg * the next statement or declaration.
14212099Sjoerg */
14312099Sjoergint	quadflg;
14412099Sjoerg
14512099Sjoerg/*
14612099Sjoerg * Puts a new element at the top of the stack used for control statements.
14712099Sjoerg */
14812099Sjoergvoid
14991592Smarkmpushctrl(int env)
15012099Sjoerg{
15112099Sjoerg	cstk_t	*ci;
15212099Sjoerg
15380284Sobrien	if ((ci = calloc(1, sizeof (cstk_t))) == NULL)
15480284Sobrien		nomem();
15512099Sjoerg	ci->c_env = env;
15612099Sjoerg	ci->c_nxt = cstk;
15712099Sjoerg	cstk = ci;
15812099Sjoerg}
15912099Sjoerg
16012099Sjoerg/*
16112099Sjoerg * Removes the top element of the stack used for control statements.
16212099Sjoerg */
16312099Sjoergvoid
16491592Smarkmpopctrl(int env)
16512099Sjoerg{
16612099Sjoerg	cstk_t	*ci;
16712099Sjoerg	clst_t	*cl;
16812099Sjoerg
16912099Sjoerg	if (cstk == NULL || cstk->c_env != env)
170281168Spfg		LERROR("popctrl()");
17112099Sjoerg
17212099Sjoerg	cstk = (ci = cstk)->c_nxt;
17312099Sjoerg
17412099Sjoerg	while ((cl = ci->c_clst) != NULL) {
17512099Sjoerg		ci->c_clst = cl->cl_nxt;
17612099Sjoerg		free(cl);
17712099Sjoerg	}
17812099Sjoerg
17912099Sjoerg	if (ci->c_swtype != NULL)
18012099Sjoerg		free(ci->c_swtype);
18112099Sjoerg
18212099Sjoerg	free(ci);
18312099Sjoerg}
18412099Sjoerg
18512099Sjoerg/*
18612099Sjoerg * Prints a warning if a statement cannot be reached.
18712099Sjoerg */
18812099Sjoergvoid
18991592Smarkmchkreach(void)
19012099Sjoerg{
19112099Sjoerg	if (!reached && !rchflg) {
19212099Sjoerg		/* statement not reached */
19312099Sjoerg		warning(193);
19412099Sjoerg		reached = 1;
19512099Sjoerg	}
19612099Sjoerg}
19712099Sjoerg
19812099Sjoerg/*
19912099Sjoerg * Called after a function declaration which introduces a function definition
20012099Sjoerg * and before an (optional) old style argument declaration list.
20112099Sjoerg *
20212099Sjoerg * Puts all symbols declared in the Prototype or in an old style argument
20312099Sjoerg * list back to the symbol table.
20412099Sjoerg *
20512099Sjoerg * Does the usual checking of storage class, type (return value),
20612099Sjoerg * redeclaration etc..
20712099Sjoerg */
20812099Sjoergvoid
20991592Smarkmfuncdef(sym_t *fsym)
21012099Sjoerg{
21112099Sjoerg	int	n, warn;
21212099Sjoerg	sym_t	*arg, *sym, *rdsym;
21312099Sjoerg
21412099Sjoerg	funcsym = fsym;
21512099Sjoerg
21612099Sjoerg	/*
21712099Sjoerg	 * Put all symbols declared in the argument list back to the
21812099Sjoerg	 * symbol table.
21912099Sjoerg	 */
22012099Sjoerg	for (sym = dcs->d_fpsyms; sym != NULL; sym = sym->s_dlnxt) {
22112099Sjoerg		if (sym->s_blklev != -1) {
22212099Sjoerg			if (sym->s_blklev != 1)
223281168Spfg				LERROR("funcdef()");
22412099Sjoerg			inssym(1, sym);
22512099Sjoerg		}
22612099Sjoerg	}
22712099Sjoerg
22812099Sjoerg	/*
22912099Sjoerg	 * In osfunc() we did not know whether it is an old style function
23012099Sjoerg	 * definition or only an old style declaration, if there are no
23112099Sjoerg	 * arguments inside the argument list ("f()").
23212099Sjoerg	 */
23312099Sjoerg	if (!fsym->s_type->t_proto && fsym->s_args == NULL)
23412099Sjoerg		fsym->s_osdef = 1;
23512099Sjoerg
23612099Sjoerg	chktyp(fsym);
23712099Sjoerg
23812099Sjoerg	/*
23912099Sjoerg	 * chktyp() checks for almost all possible errors, but not for
24012099Sjoerg	 * incomplete return values (these are allowed in declarations)
24112099Sjoerg	 */
24212099Sjoerg	if (fsym->s_type->t_subt->t_tspec != VOID &&
24312099Sjoerg	    incompl(fsym->s_type->t_subt)) {
24412099Sjoerg		/* cannot return incomplete type */
24512099Sjoerg		error(67);
24612099Sjoerg	}
24712099Sjoerg
24812099Sjoerg	fsym->s_def = DEF;
24912099Sjoerg
25012099Sjoerg	if (fsym->s_scl == TYPEDEF) {
25112099Sjoerg		fsym->s_scl = EXTERN;
25212099Sjoerg		/* illegal storage class */
25312099Sjoerg		error(8);
25412099Sjoerg	}
25512099Sjoerg
25612099Sjoerg	if (dcs->d_inline)
25712099Sjoerg		fsym->s_inline = 1;
25812099Sjoerg
25912099Sjoerg	/*
26012099Sjoerg	 * Arguments in new style function declarations need a name.
26112099Sjoerg	 * (void is already removed from the list of arguments)
26212099Sjoerg	 */
26312099Sjoerg	n = 1;
26412099Sjoerg	for (arg = fsym->s_type->t_args; arg != NULL; arg = arg->s_nxt) {
26512099Sjoerg		if (arg->s_scl == ABSTRACT) {
26612099Sjoerg			if (arg->s_name != unnamed)
267281168Spfg				LERROR("funcdef()");
26812099Sjoerg			/* formal parameter lacks name: param #%d */
26912099Sjoerg			error(59, n);
27012099Sjoerg		} else {
27112099Sjoerg			if (arg->s_name == unnamed)
272281168Spfg				LERROR("funcdef()");
27312099Sjoerg		}
27412099Sjoerg		n++;
27512099Sjoerg	}
27612099Sjoerg
27712099Sjoerg	/*
27812099Sjoerg	 * We must also remember the position. s_dpos is overwritten
27912099Sjoerg	 * if this is an old style definition and we had already a
28012099Sjoerg	 * prototype.
28112099Sjoerg	 */
28212099Sjoerg	STRUCT_ASSIGN(dcs->d_fdpos, fsym->s_dpos);
28312099Sjoerg
28412099Sjoerg	if ((rdsym = dcs->d_rdcsym) != NULL) {
28512099Sjoerg
28612099Sjoerg		if (!isredec(fsym, (warn = 0, &warn))) {
28712099Sjoerg
28812099Sjoerg			/*
28912099Sjoerg			 * Print nothing if the newly defined function
29012099Sjoerg			 * is defined in old style. A better warning will
29112099Sjoerg			 * be printed in cluparg().
29212099Sjoerg			 */
29312099Sjoerg			if (warn && !fsym->s_osdef) {
29412099Sjoerg				/* redeclaration of %s */
29512099Sjoerg				(*(sflag ? error : warning))(27, fsym->s_name);
29612099Sjoerg				prevdecl(-1, rdsym);
29712099Sjoerg			}
29812099Sjoerg
29912099Sjoerg			/* copy usage information */
30012099Sjoerg			cpuinfo(fsym, rdsym);
30112099Sjoerg
30212099Sjoerg			/*
30312099Sjoerg			 * If the old symbol was a prototype and the new
30412099Sjoerg			 * one is none, overtake the position of the
30512099Sjoerg			 * declaration of the prototype.
30612099Sjoerg			 */
30712099Sjoerg			if (fsym->s_osdef && rdsym->s_type->t_proto)
30812099Sjoerg				STRUCT_ASSIGN(fsym->s_dpos, rdsym->s_dpos);
30912099Sjoerg
31012099Sjoerg			/* complete the type */
31112099Sjoerg			compltyp(fsym, rdsym);
31212099Sjoerg
31312099Sjoerg			/* once a function is inline it remains inline */
31412099Sjoerg			if (rdsym->s_inline)
31512099Sjoerg				fsym->s_inline = 1;
31612099Sjoerg
31712099Sjoerg		}
31812099Sjoerg
31912099Sjoerg		/* remove the old symbol from the symbol table */
32012099Sjoerg		rmsym(rdsym);
32112099Sjoerg
32212099Sjoerg	}
32312099Sjoerg
32412099Sjoerg	if (fsym->s_osdef && !fsym->s_type->t_proto) {
32512099Sjoerg		if (sflag && hflag && strcmp(fsym->s_name, "main") != 0)
326228992Suqs			/* function definition is not a prototype */
32712099Sjoerg			warning(286);
32812099Sjoerg	}
32912099Sjoerg
33012099Sjoerg	if (dcs->d_notyp)
33191592Smarkm		/* return value is implicitly declared to be int */
33212099Sjoerg		fsym->s_rimpl = 1;
33312099Sjoerg
33412099Sjoerg	reached = 1;
33512099Sjoerg}
33612099Sjoerg
33712099Sjoerg/*
33812099Sjoerg * Called at the end of a function definition.
33912099Sjoerg */
34012099Sjoergvoid
34191592Smarkmfuncend(void)
34212099Sjoerg{
34312099Sjoerg	sym_t	*arg;
34412099Sjoerg	int	n;
34512099Sjoerg
34612099Sjoerg	if (reached) {
34712099Sjoerg		cstk->c_noretval = 1;
34812099Sjoerg		if (funcsym->s_type->t_subt->t_tspec != VOID &&
34912099Sjoerg		    !funcsym->s_rimpl) {
35012099Sjoerg			/* func. %s falls off bottom without returning value */
35112099Sjoerg			warning(217, funcsym->s_name);
35212099Sjoerg		}
35312099Sjoerg	}
35412099Sjoerg
35512099Sjoerg	/*
356228992Suqs	 * This warning is printed only if the return value was implicitly
35712099Sjoerg	 * declared to be int. Otherwise the wrong return statement
35812099Sjoerg	 * has already printed a warning.
35912099Sjoerg	 */
36012099Sjoerg	if (cstk->c_noretval && cstk->c_retval && funcsym->s_rimpl)
36112099Sjoerg		/* function %s has return (e); and return; */
36212099Sjoerg		warning(216, funcsym->s_name);
36312099Sjoerg
36412099Sjoerg	/* Print warnings for unused arguments */
36512099Sjoerg	arg = dcs->d_fargs;
36612099Sjoerg	n = 0;
36712099Sjoerg	while (arg != NULL && (nargusg == -1 || n < nargusg)) {
36812099Sjoerg		chkusg1(dcs->d_asm, arg);
36912099Sjoerg		arg = arg->s_nxt;
37012099Sjoerg		n++;
37112099Sjoerg	}
37212099Sjoerg	nargusg = -1;
37312099Sjoerg
37412099Sjoerg	/*
37512099Sjoerg	 * write the information about the function definition to the
37612099Sjoerg	 * output file
37791592Smarkm	 * inline functions explicitly declared extern are written as
37812099Sjoerg	 * declarations only.
37912099Sjoerg	 */
38012099Sjoerg	if (dcs->d_scl == EXTERN && funcsym->s_inline) {
38112099Sjoerg		outsym(funcsym, funcsym->s_scl, DECL);
38212099Sjoerg	} else {
38312099Sjoerg		outfdef(funcsym, &dcs->d_fdpos, cstk->c_retval,
38412099Sjoerg			funcsym->s_osdef, dcs->d_fargs);
38512099Sjoerg	}
38612099Sjoerg
38712099Sjoerg	/*
38812099Sjoerg	 * remove all symbols declared during argument declaration from
38912099Sjoerg	 * the symbol table
39012099Sjoerg	 */
39112099Sjoerg	if (dcs->d_nxt != NULL || dcs->d_ctx != EXTERN)
392281168Spfg		LERROR("funcend()");
39312099Sjoerg	rmsyms(dcs->d_fpsyms);
39412099Sjoerg
39512099Sjoerg	/* must be set on level 0 */
39612099Sjoerg	reached = 1;
39712099Sjoerg}
39812099Sjoerg
39912099Sjoerg/*
40012099Sjoerg * Process a label.
40112099Sjoerg *
40212099Sjoerg * typ		type of the label (T_NAME, T_DEFAULT or T_CASE).
40312099Sjoerg * sym		symbol table entry of label if typ == T_NAME
40412099Sjoerg * tn		expression if typ == T_CASE
40512099Sjoerg */
40612099Sjoergvoid
40791592Smarkmlabel(int typ, sym_t *sym, tnode_t *tn)
40812099Sjoerg{
40912099Sjoerg	cstk_t	*ci;
41012099Sjoerg	clst_t	*cl;
41191592Smarkm	val_t	*v;
41291592Smarkm	val_t	nv;
41312099Sjoerg	tspec_t	t;
41412099Sjoerg
41512099Sjoerg	switch (typ) {
41612099Sjoerg
41712099Sjoerg	case T_NAME:
41812099Sjoerg		if (sym->s_set) {
41912099Sjoerg			/* label %s redefined */
42012099Sjoerg			error(194, sym->s_name);
42112099Sjoerg		} else {
42212099Sjoerg			setsflg(sym);
42312099Sjoerg		}
42412099Sjoerg		break;
42512099Sjoerg
42612099Sjoerg	case T_CASE:
42712099Sjoerg
42812099Sjoerg		/* find the stack entry for the innermost switch statement */
42991592Smarkm		for (ci = cstk; ci != NULL && !ci->c_switch; ci = ci->c_nxt)
43091592Smarkm			continue;
43112099Sjoerg
43212099Sjoerg		if (ci == NULL) {
43312099Sjoerg			/* case not in switch */
43412099Sjoerg			error(195);
43512099Sjoerg			tn = NULL;
43612099Sjoerg		} else if (tn != NULL && tn->tn_op != CON) {
43712099Sjoerg			/* non-constant case expression */
43812099Sjoerg			error(197);
43912099Sjoerg			tn = NULL;
44012099Sjoerg		} else if (tn != NULL && !isityp(tn->tn_type->t_tspec)) {
44112099Sjoerg			/* non-integral case expression */
44212099Sjoerg			error(198);
44312099Sjoerg			tn = NULL;
44412099Sjoerg		}
44512099Sjoerg
44612099Sjoerg		if (tn != NULL) {
44712099Sjoerg
44812099Sjoerg			if (ci->c_swtype == NULL)
449281168Spfg				LERROR("label()");
45012099Sjoerg
45112099Sjoerg			if (reached && !ftflg) {
45212099Sjoerg				if (hflag)
45312099Sjoerg					/* fallthrough on case statement */
45412099Sjoerg					warning(220);
45512099Sjoerg			}
45612099Sjoerg
45712099Sjoerg			t = tn->tn_type->t_tspec;
45812099Sjoerg			if (t == LONG || t == ULONG ||
45912099Sjoerg			    t == QUAD || t == UQUAD) {
46012099Sjoerg				if (tflag)
46112099Sjoerg					/* case label must be of type ... */
46212099Sjoerg					warning(203);
46312099Sjoerg			}
46412099Sjoerg
46512099Sjoerg			/*
46612099Sjoerg			 * get the value of the expression and convert it
46712099Sjoerg			 * to the type of the switch expression
46812099Sjoerg			 */
469281168Spfg			v = constant(tn, 1);
47091592Smarkm			(void) memset(&nv, 0, sizeof nv);
47191592Smarkm			cvtcon(CASE, 0, ci->c_swtype, &nv, v);
47212099Sjoerg			free(v);
47312099Sjoerg
47412099Sjoerg			/* look if we had this value already */
47512099Sjoerg			for (cl = ci->c_clst; cl != NULL; cl = cl->cl_nxt) {
47691592Smarkm				if (cl->cl_val.v_quad == nv.v_quad)
47712099Sjoerg					break;
47812099Sjoerg			}
47991592Smarkm			if (cl != NULL && isutyp(nv.v_tspec)) {
48012099Sjoerg				/* duplicate case in switch, %lu */
48191592Smarkm				error(200, (u_long)nv.v_quad);
48212099Sjoerg			} else if (cl != NULL) {
48312099Sjoerg				/* duplicate case in switch, %ld */
48491592Smarkm				error(199, (long)nv.v_quad);
48512099Sjoerg			} else {
48612099Sjoerg				/*
48712099Sjoerg				 * append the value to the list of
48812099Sjoerg				 * case values
48912099Sjoerg				 */
49091592Smarkm				cl = xcalloc(1, sizeof (clst_t));
49191592Smarkm				STRUCT_ASSIGN(cl->cl_val, nv);
49212099Sjoerg				cl->cl_nxt = ci->c_clst;
49312099Sjoerg				ci->c_clst = cl;
49412099Sjoerg			}
49512099Sjoerg		}
49612099Sjoerg		tfreeblk();
49712099Sjoerg		break;
49812099Sjoerg
49912099Sjoerg	case T_DEFAULT:
50012099Sjoerg
50112099Sjoerg		/* find the stack entry for the innermost switch statement */
50291592Smarkm		for (ci = cstk; ci != NULL && !ci->c_switch; ci = ci->c_nxt)
50391592Smarkm			continue;
50412099Sjoerg
50512099Sjoerg		if (ci == NULL) {
50612099Sjoerg			/* default outside switch */
50712099Sjoerg			error(201);
50812099Sjoerg		} else if (ci->c_default) {
50912099Sjoerg			/* duplicate default in switch */
51012099Sjoerg			error(202);
51112099Sjoerg		} else {
51212099Sjoerg			if (reached && !ftflg) {
51312099Sjoerg				if (hflag)
51412099Sjoerg					/* fallthrough on default statement */
51512099Sjoerg					warning(284);
51612099Sjoerg			}
51712099Sjoerg			ci->c_default = 1;
51812099Sjoerg		}
51912099Sjoerg		break;
52012099Sjoerg	};
52112099Sjoerg	reached = 1;
52212099Sjoerg}
52312099Sjoerg
52412099Sjoerg/*
52512099Sjoerg * T_IF T_LPARN expr T_RPARN
52612099Sjoerg */
52712099Sjoergvoid
52891592Smarkmif1(tnode_t *tn)
52912099Sjoerg{
53091592Smarkm
53112099Sjoerg	if (tn != NULL)
53212099Sjoerg		tn = cconv(tn);
53312099Sjoerg	if (tn != NULL)
53412099Sjoerg		tn = promote(NOOP, 0, tn);
535281168Spfg	expr(tn, 0, 1, 1);
53612099Sjoerg	pushctrl(T_IF);
53712099Sjoerg}
53812099Sjoerg
53912099Sjoerg/*
54012099Sjoerg * if_without_else
54112099Sjoerg * if_without_else T_ELSE
54212099Sjoerg */
54312099Sjoergvoid
54491592Smarkmif2(void)
54512099Sjoerg{
54691592Smarkm
54712099Sjoerg	cstk->c_rchif = reached ? 1 : 0;
54812099Sjoerg	reached = 1;
54912099Sjoerg}
55012099Sjoerg
55112099Sjoerg/*
55212099Sjoerg * if_without_else
55312099Sjoerg * if_without_else T_ELSE stmnt
55412099Sjoerg */
55512099Sjoergvoid
55691592Smarkmif3(int els)
55712099Sjoerg{
55891592Smarkm
55912099Sjoerg	if (els) {
56012099Sjoerg		reached |= cstk->c_rchif;
56112099Sjoerg	} else {
56212099Sjoerg		reached = 1;
56312099Sjoerg	}
56412099Sjoerg	popctrl(T_IF);
56512099Sjoerg}
56612099Sjoerg
56712099Sjoerg/*
56812099Sjoerg * T_SWITCH T_LPARN expr T_RPARN
56912099Sjoerg */
57012099Sjoergvoid
57191592Smarkmswitch1(tnode_t *tn)
57212099Sjoerg{
57312099Sjoerg	tspec_t	t;
57412099Sjoerg	type_t	*tp;
57512099Sjoerg
57612099Sjoerg	if (tn != NULL)
57712099Sjoerg		tn = cconv(tn);
57812099Sjoerg	if (tn != NULL)
57912099Sjoerg		tn = promote(NOOP, 0, tn);
58012099Sjoerg	if (tn != NULL && !isityp(tn->tn_type->t_tspec)) {
58112099Sjoerg		/* switch expression must have integral type */
58212099Sjoerg		error(205);
58312099Sjoerg		tn = NULL;
58412099Sjoerg	}
58512099Sjoerg	if (tn != NULL && tflag) {
58612099Sjoerg		t = tn->tn_type->t_tspec;
58712099Sjoerg		if (t == LONG || t == ULONG || t == QUAD || t == UQUAD) {
58812099Sjoerg			/* switch expr. must be of type `int' in trad. C */
58912099Sjoerg			warning(271);
59012099Sjoerg		}
59112099Sjoerg	}
59212099Sjoerg
59312099Sjoerg	/*
59412099Sjoerg	 * Remember the type of the expression. Because its possible
59512099Sjoerg	 * that (*tp) is allocated on tree memory the type must be
59612099Sjoerg	 * duplicated. This is not too complicated because it is
59712099Sjoerg	 * only an integer type.
59812099Sjoerg	 */
59980284Sobrien	if ((tp = calloc(1, sizeof (type_t))) == NULL)
60080284Sobrien		nomem();
60112099Sjoerg	if (tn != NULL) {
60212099Sjoerg		tp->t_tspec = tn->tn_type->t_tspec;
60312099Sjoerg		if ((tp->t_isenum = tn->tn_type->t_isenum) != 0)
60412099Sjoerg			tp->t_enum = tn->tn_type->t_enum;
60512099Sjoerg	} else {
60612099Sjoerg		tp->t_tspec = INT;
60712099Sjoerg	}
60812099Sjoerg
609281168Spfg	expr(tn, 1, 0, 1);
61012099Sjoerg
61112099Sjoerg	pushctrl(T_SWITCH);
61212099Sjoerg	cstk->c_switch = 1;
61312099Sjoerg	cstk->c_swtype = tp;
61412099Sjoerg
61512099Sjoerg	reached = rchflg = 0;
61612099Sjoerg	ftflg = 1;
61712099Sjoerg}
61812099Sjoerg
61912099Sjoerg/*
62012099Sjoerg * switch_expr stmnt
62112099Sjoerg */
62212099Sjoergvoid
62391592Smarkmswitch2(void)
62412099Sjoerg{
62591592Smarkm	int	nenum = 0, nclab = 0;
62612099Sjoerg	sym_t	*esym;
62712099Sjoerg	clst_t	*cl;
62812099Sjoerg
62912099Sjoerg	if (cstk->c_swtype == NULL)
630281168Spfg		LERROR("switch2()");
63112099Sjoerg
63212099Sjoerg	/*
63312099Sjoerg	 * If the switch expression was of type enumeration, count the case
63412099Sjoerg	 * labels and the number of enumerators. If both counts are not
63512099Sjoerg	 * equal print a warning.
63612099Sjoerg	 */
63712099Sjoerg	if (cstk->c_swtype->t_isenum) {
63812099Sjoerg		nenum = nclab = 0;
63912099Sjoerg		if (cstk->c_swtype->t_enum == NULL)
640281168Spfg			LERROR("switch2()");
64112099Sjoerg		for (esym = cstk->c_swtype->t_enum->elem;
64212099Sjoerg		     esym != NULL; esym = esym->s_nxt) {
64312099Sjoerg			nenum++;
64412099Sjoerg		}
64512099Sjoerg		for (cl = cstk->c_clst; cl != NULL; cl = cl->cl_nxt)
64612099Sjoerg			nclab++;
64712099Sjoerg		if (hflag && eflag && nenum != nclab && !cstk->c_default) {
64812099Sjoerg			/* enumeration value(s) not handled in switch */
64912099Sjoerg			warning(206);
65012099Sjoerg		}
65112099Sjoerg	}
65212099Sjoerg
65312099Sjoerg	if (cstk->c_break) {
65412099Sjoerg		/*
65512099Sjoerg		 * end of switch alway reached (c_break is only set if the
65612099Sjoerg		 * break statement can be reached).
65712099Sjoerg		 */
65812099Sjoerg		reached = 1;
65912099Sjoerg	} else if (!cstk->c_default &&
66012099Sjoerg		   (!hflag || !cstk->c_swtype->t_isenum || nenum != nclab)) {
66112099Sjoerg		/*
66212099Sjoerg		 * there are possible values which are not handled in
66312099Sjoerg		 * switch
66412099Sjoerg		 */
66512099Sjoerg		reached = 1;
66612099Sjoerg	}	/*
66712099Sjoerg		 * otherwise the end of the switch expression is reached
66812099Sjoerg		 * if the end of the last statement inside it is reached.
66912099Sjoerg		 */
67012099Sjoerg
67112099Sjoerg	popctrl(T_SWITCH);
67212099Sjoerg}
67312099Sjoerg
67412099Sjoerg/*
67512099Sjoerg * T_WHILE T_LPARN expr T_RPARN
67612099Sjoerg */
67712099Sjoergvoid
67891592Smarkmwhile1(tnode_t *tn)
67912099Sjoerg{
68091592Smarkm
68112099Sjoerg	if (!reached) {
68212099Sjoerg		/* loop not entered at top */
68312099Sjoerg		warning(207);
68412099Sjoerg		reached = 1;
68512099Sjoerg	}
68612099Sjoerg
68712099Sjoerg	if (tn != NULL)
68812099Sjoerg		tn = cconv(tn);
68912099Sjoerg	if (tn != NULL)
69012099Sjoerg		tn = promote(NOOP, 0, tn);
69112099Sjoerg	if (tn != NULL && !issclt(tn->tn_type->t_tspec)) {
69212099Sjoerg		/* controlling expressions must have scalar type */
69312099Sjoerg		error(204);
69412099Sjoerg		tn = NULL;
69512099Sjoerg	}
69612099Sjoerg
69712099Sjoerg	pushctrl(T_WHILE);
69812099Sjoerg	cstk->c_loop = 1;
69912099Sjoerg	if (tn != NULL && tn->tn_op == CON) {
70012099Sjoerg		if (isityp(tn->tn_type->t_tspec)) {
70112099Sjoerg			cstk->c_infinite = tn->tn_val->v_quad != 0;
70212099Sjoerg		} else {
70312099Sjoerg			cstk->c_infinite = tn->tn_val->v_ldbl != 0.0;
70412099Sjoerg		}
70512099Sjoerg	}
70612099Sjoerg
707281168Spfg	expr(tn, 0, 1, 1);
70812099Sjoerg}
70912099Sjoerg
71012099Sjoerg/*
71112099Sjoerg * while_expr stmnt
71212099Sjoerg * while_expr error
71312099Sjoerg */
71412099Sjoergvoid
71591592Smarkmwhile2(void)
71612099Sjoerg{
71791592Smarkm
71812099Sjoerg	/*
71912099Sjoerg	 * The end of the loop can be reached if it is no endless loop
72012099Sjoerg	 * or there was a break statement which was reached.
72112099Sjoerg	 */
72212099Sjoerg	reached = !cstk->c_infinite || cstk->c_break;
72312099Sjoerg	rchflg = 0;
72412099Sjoerg
72512099Sjoerg	popctrl(T_WHILE);
72612099Sjoerg}
72712099Sjoerg
72812099Sjoerg/*
72912099Sjoerg * T_DO
73012099Sjoerg */
73112099Sjoergvoid
73291592Smarkmdo1(void)
73312099Sjoerg{
73491592Smarkm
73512099Sjoerg	if (!reached) {
73612099Sjoerg		/* loop not entered at top */
73712099Sjoerg		warning(207);
73812099Sjoerg		reached = 1;
73912099Sjoerg	}
74012099Sjoerg
74112099Sjoerg	pushctrl(T_DO);
74212099Sjoerg	cstk->c_loop = 1;
74312099Sjoerg}
74412099Sjoerg
74512099Sjoerg/*
74612099Sjoerg * do stmnt do_while_expr
74712099Sjoerg * do error
74812099Sjoerg */
74912099Sjoergvoid
75091592Smarkmdo2(tnode_t *tn)
75112099Sjoerg{
75291592Smarkm
75312099Sjoerg	/*
75412099Sjoerg	 * If there was a continue statement the expression controlling the
75512099Sjoerg	 * loop is reached.
75612099Sjoerg	 */
75712099Sjoerg	if (cstk->c_cont)
75812099Sjoerg		reached = 1;
75912099Sjoerg
76012099Sjoerg	if (tn != NULL)
76112099Sjoerg		tn = cconv(tn);
76212099Sjoerg	if (tn != NULL)
76312099Sjoerg		tn = promote(NOOP, 0, tn);
76412099Sjoerg	if (tn != NULL && !issclt(tn->tn_type->t_tspec)) {
76512099Sjoerg		/* controlling expressions must have scalar type */
76612099Sjoerg		error(204);
76712099Sjoerg		tn = NULL;
76812099Sjoerg	}
76912099Sjoerg
77012099Sjoerg	if (tn != NULL && tn->tn_op == CON) {
77112099Sjoerg		if (isityp(tn->tn_type->t_tspec)) {
77212099Sjoerg			cstk->c_infinite = tn->tn_val->v_quad != 0;
77312099Sjoerg		} else {
77412099Sjoerg			cstk->c_infinite = tn->tn_val->v_ldbl != 0.0;
77512099Sjoerg		}
77612099Sjoerg	}
77712099Sjoerg
778281168Spfg	expr(tn, 0, 1, 1);
77912099Sjoerg
78012099Sjoerg	/*
78112099Sjoerg	 * The end of the loop is only reached if it is no endless loop
78212099Sjoerg	 * or there was a break statement which could be reached.
78312099Sjoerg	 */
78412099Sjoerg	reached = !cstk->c_infinite || cstk->c_break;
78512099Sjoerg	rchflg = 0;
78612099Sjoerg
78712099Sjoerg	popctrl(T_DO);
78812099Sjoerg}
78912099Sjoerg
79012099Sjoerg/*
79112099Sjoerg * T_FOR T_LPARN opt_expr T_SEMI opt_expr T_SEMI opt_expr T_RPARN
79212099Sjoerg */
79312099Sjoergvoid
79491592Smarkmfor1(tnode_t *tn1, tnode_t *tn2, tnode_t *tn3)
79512099Sjoerg{
79691592Smarkm
79712099Sjoerg	/*
79812099Sjoerg	 * If there is no initialisation expression it is possible that
79912099Sjoerg	 * it is intended not to enter the loop at top.
80012099Sjoerg	 */
80112099Sjoerg	if (tn1 != NULL && !reached) {
80212099Sjoerg		/* loop not entered at top */
80312099Sjoerg		warning(207);
80412099Sjoerg		reached = 1;
80512099Sjoerg	}
80612099Sjoerg
80712099Sjoerg	pushctrl(T_FOR);
80812099Sjoerg	cstk->c_loop = 1;
80912099Sjoerg
81012099Sjoerg	/*
81112099Sjoerg	 * Store the tree memory for the reinitialisation expression.
81212099Sjoerg	 * Also remember this expression itself. We must check it at
81312099Sjoerg	 * the end of the loop to get "used but not set" warnings correct.
81412099Sjoerg	 */
81512099Sjoerg	cstk->c_fexprm = tsave();
81612099Sjoerg	cstk->c_f3expr = tn3;
81712099Sjoerg	STRUCT_ASSIGN(cstk->c_fpos, curr_pos);
81812099Sjoerg	STRUCT_ASSIGN(cstk->c_cfpos, csrc_pos);
81912099Sjoerg
82012099Sjoerg	if (tn1 != NULL)
821281168Spfg		expr(tn1, 0, 0, 1);
82212099Sjoerg
82312099Sjoerg	if (tn2 != NULL)
82412099Sjoerg		tn2 = cconv(tn2);
82512099Sjoerg	if (tn2 != NULL)
82612099Sjoerg		tn2 = promote(NOOP, 0, tn2);
82712099Sjoerg	if (tn2 != NULL && !issclt(tn2->tn_type->t_tspec)) {
82812099Sjoerg		/* controlling expressions must have scalar type */
82912099Sjoerg		error(204);
83012099Sjoerg		tn2 = NULL;
83112099Sjoerg	}
83212099Sjoerg	if (tn2 != NULL)
833281168Spfg		expr(tn2, 0, 1, 1);
83412099Sjoerg
83512099Sjoerg	if (tn2 == NULL) {
83612099Sjoerg		cstk->c_infinite = 1;
83712099Sjoerg	} else if (tn2->tn_op == CON) {
83812099Sjoerg		if (isityp(tn2->tn_type->t_tspec)) {
83912099Sjoerg			cstk->c_infinite = tn2->tn_val->v_quad != 0;
84012099Sjoerg		} else {
84112099Sjoerg			cstk->c_infinite = tn2->tn_val->v_ldbl != 0.0;
84212099Sjoerg		}
84312099Sjoerg	}
84412099Sjoerg
84512099Sjoerg	/* Checking the reinitialisation expression is done in for2() */
84612099Sjoerg
84712099Sjoerg	reached = 1;
84812099Sjoerg}
84912099Sjoerg
85012099Sjoerg/*
85112099Sjoerg * for_exprs stmnt
85212099Sjoerg * for_exprs error
85312099Sjoerg */
85412099Sjoergvoid
85591592Smarkmfor2(void)
85612099Sjoerg{
85712099Sjoerg	pos_t	cpos, cspos;
85812099Sjoerg	tnode_t	*tn3;
85912099Sjoerg
86012099Sjoerg	if (cstk->c_cont)
86112099Sjoerg		reached = 1;
86212099Sjoerg
86312099Sjoerg	STRUCT_ASSIGN(cpos, curr_pos);
86412099Sjoerg	STRUCT_ASSIGN(cspos, csrc_pos);
86512099Sjoerg
86612099Sjoerg	/* Restore the tree memory for the reinitialisation expression */
86712099Sjoerg	trestor(cstk->c_fexprm);
86812099Sjoerg	tn3 = cstk->c_f3expr;
86912099Sjoerg	STRUCT_ASSIGN(curr_pos, cstk->c_fpos);
87012099Sjoerg	STRUCT_ASSIGN(csrc_pos, cstk->c_cfpos);
87112099Sjoerg
87212099Sjoerg	/* simply "statement not reached" would be confusing */
87312099Sjoerg	if (!reached && !rchflg) {
87412099Sjoerg		/* end-of-loop code not reached */
87512099Sjoerg		warning(223);
87612099Sjoerg		reached = 1;
87712099Sjoerg	}
87812099Sjoerg
87912099Sjoerg	if (tn3 != NULL) {
880281168Spfg		expr(tn3, 0, 0, 1);
88112099Sjoerg	} else {
88212099Sjoerg		tfreeblk();
88312099Sjoerg	}
88412099Sjoerg
88512099Sjoerg	STRUCT_ASSIGN(curr_pos, cpos);
88612099Sjoerg	STRUCT_ASSIGN(csrc_pos, cspos);
88712099Sjoerg
88812099Sjoerg	/* An endless loop without break will never terminate */
88912099Sjoerg	reached = cstk->c_break || !cstk->c_infinite;
89012099Sjoerg	rchflg = 0;
89112099Sjoerg
89212099Sjoerg	popctrl(T_FOR);
89312099Sjoerg}
89412099Sjoerg
89512099Sjoerg/*
89612099Sjoerg * T_GOTO identifier T_SEMI
89712099Sjoerg * T_GOTO error T_SEMI
89812099Sjoerg */
89912099Sjoergvoid
90091592Smarkmdogoto(sym_t *lab)
90112099Sjoerg{
90291592Smarkm
90312099Sjoerg	setuflg(lab, 0, 0);
90412099Sjoerg
90512099Sjoerg	chkreach();
90612099Sjoerg
90712099Sjoerg	reached = rchflg = 0;
90812099Sjoerg}
90912099Sjoerg
91012099Sjoerg/*
91112099Sjoerg * T_BREAK T_SEMI
91212099Sjoerg */
91312099Sjoergvoid
91491592Smarkmdobreak(void)
91512099Sjoerg{
91612099Sjoerg	cstk_t	*ci;
91712099Sjoerg
91812099Sjoerg	ci = cstk;
91912099Sjoerg	while (ci != NULL && !ci->c_loop && !ci->c_switch)
92012099Sjoerg		ci = ci->c_nxt;
92112099Sjoerg
92212099Sjoerg	if (ci == NULL) {
92312099Sjoerg		/* break outside loop or switch */
92412099Sjoerg		error(208);
92512099Sjoerg	} else {
92612099Sjoerg		if (reached)
92712099Sjoerg			ci->c_break = 1;
92812099Sjoerg	}
92912099Sjoerg
93012099Sjoerg	if (bflag)
93112099Sjoerg		chkreach();
93212099Sjoerg
93312099Sjoerg	reached = rchflg = 0;
93412099Sjoerg}
93512099Sjoerg
93612099Sjoerg/*
93712099Sjoerg * T_CONTINUE T_SEMI
93812099Sjoerg */
93912099Sjoergvoid
94091592Smarkmdocont(void)
94112099Sjoerg{
94212099Sjoerg	cstk_t	*ci;
94312099Sjoerg
94491592Smarkm	for (ci = cstk; ci != NULL && !ci->c_loop; ci = ci->c_nxt)
94591592Smarkm		continue;
94612099Sjoerg
94712099Sjoerg	if (ci == NULL) {
94812099Sjoerg		/* continue outside loop */
94912099Sjoerg		error(209);
95012099Sjoerg	} else {
95112099Sjoerg		ci->c_cont = 1;
95212099Sjoerg	}
95312099Sjoerg
95412099Sjoerg	chkreach();
95512099Sjoerg
95612099Sjoerg	reached = rchflg = 0;
95712099Sjoerg}
95812099Sjoerg
95912099Sjoerg/*
96012099Sjoerg * T_RETURN T_SEMI
96112099Sjoerg * T_RETURN expr T_SEMI
96212099Sjoerg */
96312099Sjoergvoid
96491592Smarkmdoreturn(tnode_t *tn)
96512099Sjoerg{
96612099Sjoerg	tnode_t	*ln, *rn;
96712099Sjoerg	cstk_t	*ci;
96812099Sjoerg	op_t	op;
96912099Sjoerg
97091592Smarkm	for (ci = cstk; ci->c_nxt != NULL; ci = ci->c_nxt)
97191592Smarkm		continue;
97212099Sjoerg
97312099Sjoerg	if (tn != NULL) {
97412099Sjoerg		ci->c_retval = 1;
97512099Sjoerg	} else {
97612099Sjoerg		ci->c_noretval = 1;
97712099Sjoerg	}
97812099Sjoerg
97912099Sjoerg	if (tn != NULL && funcsym->s_type->t_subt->t_tspec == VOID) {
98012099Sjoerg		/* void function %s cannot return value */
98112099Sjoerg		error(213, funcsym->s_name);
98212099Sjoerg		tfreeblk();
98312099Sjoerg		tn = NULL;
98412099Sjoerg	} else if (tn == NULL && funcsym->s_type->t_subt->t_tspec != VOID) {
98512099Sjoerg		/*
98612099Sjoerg		 * Assume that the function has a return value only if it
98712099Sjoerg		 * is explicitly declared.
98812099Sjoerg		 */
98912099Sjoerg		if (!funcsym->s_rimpl)
99012099Sjoerg			/* function %s expects to return value */
99112099Sjoerg			warning(214, funcsym->s_name);
99212099Sjoerg	}
99312099Sjoerg
99412099Sjoerg	if (tn != NULL) {
99512099Sjoerg
99612099Sjoerg		/* Create a temporary node for the left side */
99712099Sjoerg		ln = tgetblk(sizeof (tnode_t));
99812099Sjoerg		ln->tn_op = NAME;
99912099Sjoerg		ln->tn_type = tduptyp(funcsym->s_type->t_subt);
100012099Sjoerg		ln->tn_type->t_const = 0;
100112099Sjoerg		ln->tn_lvalue = 1;
100212099Sjoerg		ln->tn_sym = funcsym;		/* better than nothing */
100312099Sjoerg
100412099Sjoerg		tn = build(RETURN, ln, tn);
100512099Sjoerg
100612099Sjoerg		if (tn != NULL) {
100712099Sjoerg			rn = tn->tn_right;
100812099Sjoerg			while ((op = rn->tn_op) == CVT || op == PLUS)
100912099Sjoerg				rn = rn->tn_left;
101012099Sjoerg			if (rn->tn_op == AMPER && rn->tn_left->tn_op == NAME &&
101112099Sjoerg			    rn->tn_left->tn_sym->s_scl == AUTO) {
101212099Sjoerg				/* %s returns pointer to automatic object */
101312099Sjoerg				warning(302, funcsym->s_name);
101412099Sjoerg			}
101512099Sjoerg		}
101612099Sjoerg
1017281168Spfg		expr(tn, 1, 0, 1);
101812099Sjoerg
101912099Sjoerg	} else {
102012099Sjoerg
102112099Sjoerg		chkreach();
102212099Sjoerg
102312099Sjoerg	}
102412099Sjoerg
102512099Sjoerg	reached = rchflg = 0;
102612099Sjoerg}
102712099Sjoerg
102812099Sjoerg/*
102912099Sjoerg * Do some cleanup after a global declaration or definition.
103012099Sjoerg * Especially remove informations about unused lint comments.
103112099Sjoerg */
103212099Sjoergvoid
103391592Smarkmglclup(int silent)
103412099Sjoerg{
103512099Sjoerg	pos_t	cpos;
103612099Sjoerg
103712099Sjoerg	STRUCT_ASSIGN(cpos, curr_pos);
103812099Sjoerg
103912099Sjoerg	if (nargusg != -1) {
104012099Sjoerg		if (!silent) {
104112099Sjoerg			STRUCT_ASSIGN(curr_pos, aupos);
104212099Sjoerg			/* must precede function definition: %s */
104312099Sjoerg			warning(282, "ARGSUSED");
104412099Sjoerg		}
104512099Sjoerg		nargusg = -1;
104612099Sjoerg	}
104712099Sjoerg	if (nvararg != -1) {
104812099Sjoerg		if (!silent) {
104912099Sjoerg			STRUCT_ASSIGN(curr_pos, vapos);
105012099Sjoerg			/* must precede function definition: %s */
105112099Sjoerg			warning(282, "VARARGS");
105212099Sjoerg		}
105312099Sjoerg		nvararg = -1;
105412099Sjoerg	}
105512099Sjoerg	if (prflstrg != -1) {
105612099Sjoerg		if (!silent) {
105712099Sjoerg			STRUCT_ASSIGN(curr_pos, prflpos);
105812099Sjoerg			/* must precede function definition: %s */
105912099Sjoerg			warning(282, "PRINTFLIKE");
106012099Sjoerg		}
106112099Sjoerg		prflstrg = -1;
106212099Sjoerg	}
106312099Sjoerg	if (scflstrg != -1) {
106412099Sjoerg		if (!silent) {
106512099Sjoerg			STRUCT_ASSIGN(curr_pos, scflpos);
106612099Sjoerg			/* must precede function definition: %s */
106712099Sjoerg			warning(282, "SCANFLIKE");
106812099Sjoerg		}
106912099Sjoerg		scflstrg = -1;
107012099Sjoerg	}
107112099Sjoerg
107212099Sjoerg	STRUCT_ASSIGN(curr_pos, cpos);
107312099Sjoerg
107412099Sjoerg	dcs->d_asm = 0;
107512099Sjoerg}
107612099Sjoerg
107712099Sjoerg/*
107812099Sjoerg * ARGSUSED comment
107912099Sjoerg *
108012099Sjoerg * Only the first n arguments of the following function are checked
108112099Sjoerg * for usage. A missing argument is taken to be 0.
108212099Sjoerg */
108312099Sjoergvoid
108491592Smarkmargsused(int n)
108512099Sjoerg{
108691592Smarkm
108712099Sjoerg	if (n == -1)
108812099Sjoerg		n = 0;
108912099Sjoerg
109012099Sjoerg	if (dcs->d_ctx != EXTERN) {
109112099Sjoerg		/* must be outside function: ** %s ** */
109212099Sjoerg		warning(280, "ARGSUSED");
109312099Sjoerg		return;
109412099Sjoerg	}
109512099Sjoerg	if (nargusg != -1) {
109612099Sjoerg		/* duplicate use of ** %s ** */
109712099Sjoerg		warning(281, "ARGSUSED");
109812099Sjoerg	}
109912099Sjoerg	nargusg = n;
110012099Sjoerg	STRUCT_ASSIGN(aupos, curr_pos);
110112099Sjoerg}
110212099Sjoerg
110312099Sjoerg/*
110412099Sjoerg * VARARGS comment
110512099Sjoerg *
110612099Sjoerg * Makes that lint2 checks only the first n arguments for compatibility
110712099Sjoerg * to the function definition. A missing argument is taken to be 0.
110812099Sjoerg */
110912099Sjoergvoid
111091592Smarkmvarargs(int n)
111112099Sjoerg{
111291592Smarkm
111312099Sjoerg	if (n == -1)
111412099Sjoerg		n = 0;
111512099Sjoerg
111612099Sjoerg	if (dcs->d_ctx != EXTERN) {
111712099Sjoerg		/* must be outside function: ** %s ** */
111812099Sjoerg		warning(280, "VARARGS");
111912099Sjoerg		return;
112012099Sjoerg	}
112112099Sjoerg	if (nvararg != -1) {
112212099Sjoerg		/* duplicate use of  ** %s ** */
112312099Sjoerg		warning(281, "VARARGS");
112412099Sjoerg	}
112512099Sjoerg	nvararg = n;
112612099Sjoerg	STRUCT_ASSIGN(vapos, curr_pos);
112712099Sjoerg}
112812099Sjoerg
112912099Sjoerg/*
113012099Sjoerg * PRINTFLIKE comment
113112099Sjoerg *
113212099Sjoerg * Check all arguments until the (n-1)-th as usual. The n-th argument is
113312099Sjoerg * used the check the types of remaining arguments.
113412099Sjoerg */
113512099Sjoergvoid
113691592Smarkmprintflike(int n)
113712099Sjoerg{
113891592Smarkm
113912099Sjoerg	if (n == -1)
114012099Sjoerg		n = 0;
114112099Sjoerg
114212099Sjoerg	if (dcs->d_ctx != EXTERN) {
114312099Sjoerg		/* must be outside function: ** %s ** */
114412099Sjoerg		warning(280, "PRINTFLIKE");
114512099Sjoerg		return;
114612099Sjoerg	}
114712099Sjoerg	if (prflstrg != -1) {
114812099Sjoerg		/* duplicate use of ** %s ** */
114912099Sjoerg		warning(281, "PRINTFLIKE");
115012099Sjoerg	}
115112099Sjoerg	prflstrg = n;
115212099Sjoerg	STRUCT_ASSIGN(prflpos, curr_pos);
115312099Sjoerg}
115412099Sjoerg
115512099Sjoerg/*
115612099Sjoerg * SCANFLIKE comment
115712099Sjoerg *
115812099Sjoerg * Check all arguments until the (n-1)-th as usual. The n-th argument is
115912099Sjoerg * used the check the types of remaining arguments.
116012099Sjoerg */
116112099Sjoergvoid
116291592Smarkmscanflike(int n)
116312099Sjoerg{
116491592Smarkm
116512099Sjoerg	if (n == -1)
116612099Sjoerg		n = 0;
116712099Sjoerg
116812099Sjoerg	if (dcs->d_ctx != EXTERN) {
116912099Sjoerg		/* must be outside function: ** %s ** */
117012099Sjoerg		warning(280, "SCANFLIKE");
117112099Sjoerg		return;
117212099Sjoerg	}
117312099Sjoerg	if (scflstrg != -1) {
117412099Sjoerg		/* duplicate use of ** %s ** */
117512099Sjoerg		warning(281, "SCANFLIKE");
117612099Sjoerg	}
117712099Sjoerg	scflstrg = n;
117812099Sjoerg	STRUCT_ASSIGN(scflpos, curr_pos);
117912099Sjoerg}
118012099Sjoerg
118112099Sjoerg/*
118212099Sjoerg * Set the linenumber for a CONSTCOND comment. At this and the following
118312099Sjoerg * line no warnings about constants in conditional contexts are printed.
118412099Sjoerg */
118512099Sjoerg/* ARGSUSED */
118612099Sjoergvoid
118791592Smarkmconstcond(int n)
118812099Sjoerg{
118991592Smarkm
119012099Sjoerg	ccflg = 1;
119112099Sjoerg}
119212099Sjoerg
119312099Sjoerg/*
119412099Sjoerg * Suppress printing of "fallthrough on ..." warnings until next
119512099Sjoerg * statement.
119612099Sjoerg */
119712099Sjoerg/* ARGSUSED */
119812099Sjoergvoid
119991592Smarkmfallthru(int n)
120012099Sjoerg{
120191592Smarkm
120212099Sjoerg	ftflg = 1;
120312099Sjoerg}
120412099Sjoerg
120512099Sjoerg/*
120612099Sjoerg * Stop warnings about statements which cannot be reached. Also tells lint
120712099Sjoerg * that the following statements cannot be reached (e.g. after exit()).
120812099Sjoerg */
120912099Sjoerg/* ARGSUSED */
121012099Sjoergvoid
121191592Smarkmnotreach(int n)
121212099Sjoerg{
121391592Smarkm
121412099Sjoerg	reached = 0;
121512099Sjoerg	rchflg = 1;
121612099Sjoerg}
121712099Sjoerg
121812099Sjoerg/* ARGSUSED */
121912099Sjoergvoid
122091592Smarkmlintlib(int n)
122112099Sjoerg{
122291592Smarkm
122312099Sjoerg	if (dcs->d_ctx != EXTERN) {
122412099Sjoerg		/* must be outside function: ** %s ** */
122512099Sjoerg		warning(280, "LINTLIBRARY");
122612099Sjoerg		return;
122712099Sjoerg	}
122812099Sjoerg	llibflg = 1;
122912099Sjoerg	vflag = 0;
123012099Sjoerg}
123112099Sjoerg
123212099Sjoerg/*
123312099Sjoerg * Suppress most warnings at the current and the following line.
123412099Sjoerg */
123512099Sjoerg/* ARGSUSED */
123612099Sjoergvoid
123791592Smarkmlinted(int n)
123812099Sjoerg{
123991592Smarkm
124091592Smarkm#ifdef DEBUG
124191592Smarkm	printf("%s, %d: nowarn = 1\n", curr_pos.p_file, curr_pos.p_line);
124291592Smarkm#endif
124312099Sjoerg	nowarn = 1;
124412099Sjoerg}
124512099Sjoerg
124612099Sjoerg/*
124791592Smarkm * Suppress bitfield type errors on the current line.
124891592Smarkm */
124991592Smarkm/* ARGSUSED */
125091592Smarkmvoid
125191592Smarkmbitfieldtype(int n)
125291592Smarkm{
125391592Smarkm
125491592Smarkm#ifdef DEBUG
125591592Smarkm	printf("%s, %d: bitfieldtype_ok = 1\n", curr_pos.p_file,
125691592Smarkm	    curr_pos.p_line);
125791592Smarkm#endif
125891592Smarkm	bitfieldtype_ok = 1;
125991592Smarkm}
126091592Smarkm
126191592Smarkm/*
126212099Sjoerg * PROTOTLIB in conjunction with LINTLIBRARY can be used to handle
126312099Sjoerg * prototypes like function definitions. This is done if the argument
126412099Sjoerg * to PROTOLIB is nonzero. Otherwise prototypes are handled normaly.
126512099Sjoerg */
126612099Sjoergvoid
126791592Smarkmprotolib(int n)
126812099Sjoerg{
126991592Smarkm
127012099Sjoerg	if (dcs->d_ctx != EXTERN) {
127112099Sjoerg		/* must be outside function: ** %s ** */
127212099Sjoerg		warning(280, "PROTOLIB");
127312099Sjoerg		return;
127412099Sjoerg	}
127512099Sjoerg	plibflg = n == 0 ? 0 : 1;
127612099Sjoerg}
127712099Sjoerg
127812099Sjoerg/*
127912099Sjoerg * Set quadflg to nonzero which means that the next statement/declaration
128012099Sjoerg * may use "long long" without an error or warning.
128112099Sjoerg */
128212099Sjoerg/* ARGSUSED */
128312099Sjoergvoid
128491592Smarkmlonglong(int n)
128512099Sjoerg{
128691592Smarkm
128712099Sjoerg	quadflg = 1;
128812099Sjoerg}
1289