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