/* * T_FOR T_LPARN opt_expr T_SEMI opt_expr T_SEMI opt_expr T_RPARN */ void for1(tnode_t *tn1, tnode_t *tn2, tnode_t *tn3) { /* * If there is no initialisation expression it is possible that * it is intended not to enter the loop at top. */ if (tn1 != NULL && !reached) { /* loop not entered at top */ warning(207); reached = 1; } pushctrl(T_FOR); cstk->c_loop = 1; /* * Store the tree memory for the reinitialisation expression. * Also remember this expression itself. We must check it at * the end of the loop to get "used but not set" warnings correct. */ cstk->c_fexprm = tsave(); cstk->c_f3expr = tn3; STRUCT_ASSIGN(cstk->c_fpos, curr_pos); STRUCT_ASSIGN(cstk->c_cfpos, csrc_pos); if (tn1 != NULL) expr(tn1, 0, 0); if (tn2 != NULL) tn2 = cconv(tn2); if (tn2 != NULL) tn2 = promote(NOOP, 0, tn2); if (tn2 != NULL && !issclt(tn2->tn_type->t_tspec)) { /* controlling expressions must have scalar type */ error(204); tn2 = NULL; } if (tn2 != NULL) expr(tn2, 0, 1); if (tn2 == NULL) { cstk->c_infinite = 1; } else if (tn2->tn_op == CON) { if (isityp(tn2->tn_type->t_tspec)) { cstk->c_infinite = tn2->tn_val->v_quad != 0; } else { cstk->c_infinite = tn2->tn_val->v_ldbl != 0.0; } } /* Checking the reinitialisation expression is done in for2() */ reached = 1; }
/* * Read an u-record (emitted by lint1 if a symbol was used). */ static void usedsym(pos_t *posp, const char *cp) { usym_t *usym; hte_t *hte; const char *name; usym = xalloc(sizeof (usym_t)); STRUCT_ASSIGN(usym->u_pos, *posp); /* needed as delimiter between two numbers */ if (*cp++ != 'x') inperr(); name = inpname(cp, &cp); hte = _hsearch(renametab, name, 0); if (hte != NULL) hte = hte->h_hte; else hte = hsearch(name, 1); hte->h_used = 1; *hte->h_lusym = usym; hte->h_lusym = &usym->u_nxt; }
/* * SCANFLIKE comment * * Check all arguments until the (n-1)-th as usual. The n-th argument is * used the check the types of remaining arguments. */ void scanflike(int n) { if (n == -1) n = 0; if (dcs->d_ctx != EXTERN) { /* must be outside function: ** %s ** */ warning(280, "SCANFLIKE"); return; } if (scflstrg != -1) { /* duplicate use of ** %s ** */ warning(281, "SCANFLIKE"); } scflstrg = n; STRUCT_ASSIGN(scflpos, curr_pos); }
/* * VARARGS comment * * Makes that lint2 checks only the first n arguments for compatibility * to the function definition. A missing argument is taken to be 0. */ void varargs(int n) { if (n == -1) n = 0; if (dcs->d_ctx != EXTERN) { /* must be outside function: ** %s ** */ warning(280, "VARARGS"); return; } if (nvararg != -1) { /* duplicate use of ** %s ** */ warning(281, "VARARGS"); } nvararg = n; STRUCT_ASSIGN(vapos, curr_pos); }
/* * ARGSUSED comment * * Only the first n arguments of the following function are checked * for usage. A missing argument is taken to be 0. */ void argsused(int n) { if (n == -1) n = 0; if (dcs->d_ctx != EXTERN) { /* must be outside function: ** %s ** */ warning(280, "ARGSUSED"); return; } if (nargusg != -1) { /* duplicate use of ** %s ** */ warning(281, "ARGSUSED"); } nargusg = n; STRUCT_ASSIGN(aupos, curr_pos); }
/* * Do some cleanup after a global declaration or definition. * Especially remove informations about unused lint comments. */ void glclup(int silent) { pos_t cpos; STRUCT_ASSIGN(cpos, curr_pos); if (nargusg != -1) { if (!silent) { STRUCT_ASSIGN(curr_pos, aupos); /* must precede function definition: %s */ warning(282, "ARGSUSED"); } nargusg = -1; } if (nvararg != -1) { if (!silent) { STRUCT_ASSIGN(curr_pos, vapos); /* must precede function definition: %s */ warning(282, "VARARGS"); } nvararg = -1; } if (prflstrg != -1) { if (!silent) { STRUCT_ASSIGN(curr_pos, prflpos); /* must precede function definition: %s */ warning(282, "PRINTFLIKE"); } prflstrg = -1; } if (scflstrg != -1) { if (!silent) { STRUCT_ASSIGN(curr_pos, scflpos); /* must precede function definition: %s */ warning(282, "SCANFLIKE"); } scflstrg = -1; } STRUCT_ASSIGN(curr_pos, cpos); dcs->d_asm = 0; }
/* * for_exprs stmnt * for_exprs error */ void for2(void) { pos_t cpos, cspos; tnode_t *tn3; if (cstk->c_cont) reached = 1; STRUCT_ASSIGN(cpos, curr_pos); STRUCT_ASSIGN(cspos, csrc_pos); /* Restore the tree memory for the reinitialisation expression */ trestor(cstk->c_fexprm); tn3 = cstk->c_f3expr; STRUCT_ASSIGN(curr_pos, cstk->c_fpos); STRUCT_ASSIGN(csrc_pos, cstk->c_cfpos); /* simply "statement not reached" would be confusing */ if (!reached && !rchflg) { /* end-of-loop code not reached */ warning(223); reached = 1; } if (tn3 != NULL) { expr(tn3, 0, 0); } else { tfreeblk(); } STRUCT_ASSIGN(curr_pos, cpos); STRUCT_ASSIGN(csrc_pos, cspos); /* An endless loop without break will never terminate */ reached = cstk->c_break || !cstk->c_infinite; rchflg = 0; popctrl(T_FOR); }
void inittyp(void) { size_t i; static const struct { tspec_t it_tspec; ttab_t it_ttab; } ittab[NTSPEC] = { { SIGNED, { 0, 0, SIGNED, UNSIGN, 0, 0, 0, 0, 0, 0, "signed" } }, { UNSIGN, { 0, 0, SIGNED, UNSIGN, 0, 0, 0, 0, 0, 0, "unsigned" } }, { BOOL, { CHAR_SIZE, 1, BOOL, BOOL, 1, 1, 0, 1, 1, 0, "_Bool" } }, { CHAR, { CHAR_SIZE, CHAR_BIT, SCHAR, UCHAR, 1, 0, 0, 1, 1, 0, "char" } }, { SCHAR, { CHAR_SIZE, CHAR_BIT, SCHAR, UCHAR, 1, 0, 0, 1, 1, 0, "signed char" } }, { UCHAR, { CHAR_SIZE, CHAR_BIT, SCHAR, UCHAR, 1, 1, 0, 1, 1, 0, "unsigned char" } }, { SHORT, { SHORT_SIZE, 2 * CHAR_BIT, SHORT, USHORT, 1, 0, 0, 1, 1, 0, "short" } }, { USHORT, { SHORT_SIZE, 2 * CHAR_BIT, SHORT, USHORT, 1, 1, 0, 1, 1, 0, "unsigned short" } }, { INT, { INT_SIZE, INT_RSIZE * CHAR_BIT, INT, UINT, 1, 0, 0, 1, 1, 0, "int" } }, { UINT, { INT_SIZE, INT_RSIZE * CHAR_BIT, INT, UINT, 1, 1, 0, 1, 1, 0, "unsigned int" } }, { LONG, { LONG_SIZE, 4 * CHAR_BIT, LONG, ULONG, 1, 0, 0, 1, 1, 0, "long" } }, { ULONG, { LONG_SIZE, 4 * CHAR_BIT, LONG, ULONG, 1, 1, 0, 1, 1, 0, "unsigned long" } }, { QUAD, { QUAD_SIZE, 8 * CHAR_BIT, QUAD, UQUAD, 1, 0, 0, 1, 1, 0, "long long" } }, { UQUAD, { QUAD_SIZE, 8 * CHAR_BIT, QUAD, UQUAD, 1, 1, 0, 1, 1, 0, "unsigned long long" } }, { FLOAT, { FLOAT_SIZE, 4 * CHAR_BIT, FLOAT, FLOAT, 0, 0, 1, 1, 1, 0, "float" } }, { DOUBLE, { DOUBLE_SIZE, 8 * CHAR_BIT, DOUBLE, DOUBLE, 0, 0, 1, 1, 1, 0, "double" } }, { LDOUBLE, { LDOUBLE_SIZE, 10 * CHAR_BIT, LDOUBLE, LDOUBLE, 0, 0, 1, 1, 1, 0, "long double" } }, { FCOMPLEX, { FLOAT_SIZE * 2, 4 * CHAR_BIT * 2, FCOMPLEX, FCOMPLEX, 0, 0, 1, 1, 1, 1, "float _Complex" } }, { DCOMPLEX, { DOUBLE_SIZE * 2, 8 * CHAR_BIT * 2, DCOMPLEX, DCOMPLEX, 0, 0, 1, 1, 1, 1, "double _Complex" } }, { LCOMPLEX, { LDOUBLE_SIZE * 2, 8 * CHAR_BIT * 2, LCOMPLEX, LCOMPLEX, 0, 0, 1, 1, 1, 1, "long double _Complex" } }, { VOID, { -1, -1, VOID, VOID, 0, 0, 0, 0, 0, 0, "void" } }, { STRUCT, { -1, -1, STRUCT, STRUCT, 0, 0, 0, 0, 0, 0, "struct" } }, { UNION, { -1, -1, UNION, UNION, 0, 0, 0, 0, 0, 0, "union" } }, { ENUM, { ENUM_SIZE, 3 * CHAR_BIT, ENUM, ENUM, 1, 0, 0, 1, 1, 0, "enum" } }, { PTR, { PTR_SIZE, 4 * CHAR_BIT, PTR, PTR, 0, 1, 0, 0, 1, 0, "pointer" } }, { ARRAY, { -1, -1, ARRAY, ARRAY, 0, 0, 0, 0, 0, 0, "array" } }, { FUNC, { -1, -1, FUNC, FUNC, 0, 0, 0, 0, 0, 0, "function" } }, }; for (i = 0; i < sizeof (ittab) / sizeof (ittab[0]); i++) STRUCT_ASSIGN(ttab[ittab[i].it_tspec], ittab[i].it_ttab); if (!pflag) { for (i = 0; i < NTSPEC; i++) ttab[i].tt_psz = ttab[i].tt_sz; } }
/* * Process a label. * * typ type of the label (T_NAME, T_DEFAULT or T_CASE). * sym symbol table entry of label if typ == T_NAME * tn expression if typ == T_CASE */ void label(int typ, sym_t *sym, tnode_t *tn) { cstk_t *ci; clst_t *cl; val_t *v; val_t nv; tspec_t t; switch (typ) { case T_NAME: if (sym->s_set) { /* label %s redefined */ error(194, sym->s_name); } else { setsflg(sym); } break; case T_CASE: /* find the stack entry for the innermost switch statement */ for (ci = cstk; ci != NULL && !ci->c_switch; ci = ci->c_nxt) continue; if (ci == NULL) { /* case not in switch */ error(195); tn = NULL; } else if (tn != NULL && tn->tn_op != CON) { /* non-constant case expression */ error(197); tn = NULL; } else if (tn != NULL && !isityp(tn->tn_type->t_tspec)) { /* non-integral case expression */ error(198); tn = NULL; } if (tn != NULL) { if (ci->c_swtype == NULL) lerror("label() 1"); if (reached && !ftflg) { if (hflag) /* fallthrough on case statement */ warning(220); } t = tn->tn_type->t_tspec; if (t == LONG || t == ULONG || t == QUAD || t == UQUAD) { if (tflag) /* case label must be of type ... */ warning(203); } /* * get the value of the expression and convert it * to the type of the switch expression */ v = constant(tn); (void) memset(&nv, 0, sizeof nv); cvtcon(CASE, 0, ci->c_swtype, &nv, v); free(v); /* look if we had this value already */ for (cl = ci->c_clst; cl != NULL; cl = cl->cl_nxt) { if (cl->cl_val.v_quad == nv.v_quad) break; } if (cl != NULL && isutyp(nv.v_tspec)) { /* duplicate case in switch, %lu */ error(200, (u_long)nv.v_quad); } else if (cl != NULL) { /* duplicate case in switch, %ld */ error(199, (long)nv.v_quad); } else { /* * append the value to the list of * case values */ cl = xcalloc(1, sizeof (clst_t)); STRUCT_ASSIGN(cl->cl_val, nv); cl->cl_nxt = ci->c_clst; ci->c_clst = cl; } } tfreeblk(); break; case T_DEFAULT: /* find the stack entry for the innermost switch statement */ for (ci = cstk; ci != NULL && !ci->c_switch; ci = ci->c_nxt) continue; if (ci == NULL) { /* default outside switch */ error(201); } else if (ci->c_default) { /* duplicate default in switch */ error(202); } else { if (reached && !ftflg) { if (hflag) /* fallthrough on default statement */ warning(284); } ci->c_default = 1; } break; }; reached = 1; }
/* * Called after a function declaration which introduces a function definition * and before an (optional) old style argument declaration list. * * Puts all symbols declared in the Prototype or in an old style argument * list back to the symbol table. * * Does the usual checking of storage class, type (return value), * redeclaration etc.. */ void funcdef(sym_t *fsym) { int n, warn; sym_t *arg, *sym, *rdsym; funcsym = fsym; /* * Put all symbols declared in the argument list back to the * symbol table. */ for (sym = dcs->d_fpsyms; sym != NULL; sym = sym->s_dlnxt) { if (sym->s_blklev != -1) { if (sym->s_blklev != 1) lerror("funcdef() 1"); inssym(1, sym); } } /* * In osfunc() we did not know whether it is an old style function * definition or only an old style declaration, if there are no * arguments inside the argument list ("f()"). */ if (!fsym->s_type->t_proto && fsym->s_args == NULL) fsym->s_osdef = 1; chktyp(fsym); /* * chktyp() checks for almost all possible errors, but not for * incomplete return values (these are allowed in declarations) */ if (fsym->s_type->t_subt->t_tspec != VOID && incompl(fsym->s_type->t_subt)) { /* cannot return incomplete type */ error(67); } fsym->s_def = DEF; if (fsym->s_scl == TYPEDEF) { fsym->s_scl = EXTERN; /* illegal storage class */ error(8); } if (dcs->d_inline) fsym->s_inline = 1; /* * Arguments in new style function declarations need a name. * (void is already removed from the list of arguments) */ n = 1; for (arg = fsym->s_type->t_args; arg != NULL; arg = arg->s_nxt) { if (arg->s_scl == ABSTRACT) { if (arg->s_name != unnamed) lerror("funcdef() 2"); /* formal parameter lacks name: param #%d */ error(59, n); } else { if (arg->s_name == unnamed) lerror("funcdef() 3"); } n++; } /* * We must also remember the position. s_dpos is overwritten * if this is an old style definition and we had already a * prototype. */ STRUCT_ASSIGN(dcs->d_fdpos, fsym->s_dpos); if ((rdsym = dcs->d_rdcsym) != NULL) { if (!isredec(fsym, (warn = 0, &warn))) { /* * Print nothing if the newly defined function * is defined in old style. A better warning will * be printed in cluparg(). */ if (warn && !fsym->s_osdef) { /* redeclaration of %s */ (*(sflag ? error : warning))(27, fsym->s_name); prevdecl(-1, rdsym); } /* copy usage information */ cpuinfo(fsym, rdsym); /* * If the old symbol was a prototype and the new * one is none, overtake the position of the * declaration of the prototype. */ if (fsym->s_osdef && rdsym->s_type->t_proto) STRUCT_ASSIGN(fsym->s_dpos, rdsym->s_dpos); /* complete the type */ compltyp(fsym, rdsym); /* once a function is inline it remains inline */ if (rdsym->s_inline) fsym->s_inline = 1; } /* remove the old symbol from the symbol table */ rmsym(rdsym); } if (fsym->s_osdef && !fsym->s_type->t_proto) { if (sflag && hflag && strcmp(fsym->s_name, "main") != 0) /* function definition is not a prototype */ warning(286); } if (dcs->d_notyp) /* return value is implicitly declared to be int */ fsym->s_rimpl = 1; reached = 1; }
/* * Process a declaration or definition (d-record). */ static void decldef(pos_t *posp, const char *cp) { sym_t *symp, sym; char c, *ep, *pos1; int used, renamed; hte_t *hte, *renamehte = NULL; const char *name, *rename; (void)memset(&sym, 0, sizeof (sym)); STRUCT_ASSIGN(sym.s_pos, *posp); sym.s_def = NODECL; used = 0; while (strchr("tdeurosvPS", (c = *cp)) != NULL) { cp++; switch (c) { case 't': if (sym.s_def != NODECL) inperr(); sym.s_def = TDEF; break; case 'd': if (sym.s_def != NODECL) inperr(); sym.s_def = DEF; break; case 'e': if (sym.s_def != NODECL) inperr(); sym.s_def = DECL; break; case 'u': if (used) inperr(); used = 1; break; case 'r': if (sym.s_rval) inperr(); sym.s_rval = 1; break; case 'o': if (sym.s_osdef) inperr(); sym.s_osdef = 1; break; case 's': if (sym.s_static) inperr(); sym.s_static = 1; break; case 'v': if (sym.s_va) inperr(); sym.s_va = 1; sym.s_nva = (short)strtol(cp, &ep, 10); if (cp == ep) inperr(); cp = ep; break; case 'P': if (sym.s_prfl) inperr(); sym.s_prfl = 1; sym.s_nprfl = (short)strtol(cp, &ep, 10); if (cp == ep) inperr(); cp = ep; break; case 'S': if (sym.s_scfl) inperr(); sym.s_scfl = 1; sym.s_nscfl = (short)strtol(cp, &ep, 10); if (cp == ep) inperr(); cp = ep; break; } } /* read symbol name, doing renaming if necessary */ name = inpname(cp, &cp); renamed = 0; if (*cp == 'r') { cp++; name = xstrdup(name); rename = inpname(cp, &cp); /* enter it and see if it's already been renamed */ renamehte = _hsearch(renametab, name, 1); if (renamehte->h_hte == NULL) { hte = hsearch(rename, 1); renamehte->h_hte = hte; renamed = 1; } else if (strcmp((hte = renamehte->h_hte)->h_name, rename)) { pos1 = xstrdup(mkpos(&renamehte->h_syms->s_pos)); /* %s renamed multiple times\t%s :: %s */ msg(18, name, pos1, mkpos(&sym.s_pos)); free(pos1); } free((char *)name); } else { /* it might be a previously-done rename */ hte = _hsearch(renametab, name, 0); if (hte != NULL) hte = hte->h_hte; else hte = hsearch(name, 1); } hte->h_used |= used; if (sym.s_def == DEF || sym.s_def == TDEF) hte->h_def = 1; sym.s_type = inptype(cp, &cp); /* * Allocate memory for this symbol only if it was not already * declared or tentatively defined at the same location with * the same type. Works only for symbols with external linkage, * because static symbols, tentatively defined at the same location * but in different translation units are really different symbols. */ for (symp = hte->h_syms; symp != NULL; symp = symp->s_nxt) { if (symp->s_pos.p_isrc == sym.s_pos.p_isrc && symp->s_pos.p_iline == sym.s_pos.p_iline && symp->s_type == sym.s_type && ((symp->s_def == DECL && sym.s_def == DECL) || (!sflag && symp->s_def == TDEF && sym.s_def == TDEF)) && !symp->s_static && !sym.s_static) { break; } } if (symp == NULL) { /* allocsym reserviert keinen Platz fuer s_nva */ if (sym.s_va || sym.s_prfl || sym.s_scfl) { symp = xalloc(sizeof (sym_t)); STRUCT_ASSIGN(*symp, sym); } else { symp = xalloc(sizeof (symp->s_s)); STRUCT_ASSIGN(symp->s_s, sym.s_s); } *hte->h_lsym = symp; hte->h_lsym = &symp->s_nxt; /* XXX hack so we can remember where a symbol was renamed */ if (renamed) renamehte->h_syms = symp; } if (*cp != '\0') inperr(); }
/* * Process a function call record (c-record). */ static void funccall(pos_t *posp, const char *cp) { arginf_t *ai, **lai; char c, *eptr; int rused, rdisc; hte_t *hte; fcall_t *fcall; const char *name; fcall = xalloc(sizeof (fcall_t)); STRUCT_ASSIGN(fcall->f_pos, *posp); /* read flags */ rused = rdisc = 0; lai = &fcall->f_args; while ((c = *cp) == 'u' || c == 'i' || c == 'd' || c == 'z' || c == 'p' || c == 'n' || c == 's') { cp++; switch (c) { case 'u': if (rused || rdisc) inperr(); rused = 1; break; case 'i': if (rused || rdisc) inperr(); break; case 'd': if (rused || rdisc) inperr(); rdisc = 1; break; case 'z': case 'p': case 'n': case 's': ai = xalloc(sizeof (arginf_t)); ai->a_num = (int)strtol(cp, &eptr, 10); if (cp == eptr) inperr(); cp = eptr; if (c == 'z') { ai->a_pcon = ai->a_zero = 1; } else if (c == 'p') { ai->a_pcon = 1; } else if (c == 'n') { ai->a_ncon = 1; } else { ai->a_fmt = 1; ai->a_fstrg = inpqstrg(cp, &cp); } *lai = ai; lai = &ai->a_nxt; break; } } fcall->f_rused = rused; fcall->f_rdisc = rdisc; /* read name of function */ name = inpname(cp, &cp); /* first look it up in the renaming table, then in the normal table */ hte = _hsearch(renametab, name, 0); if (hte != NULL) hte = hte->h_hte; else hte = hsearch(name, 1); hte->h_used = 1; fcall->f_type = inptype(cp, &cp); *hte->h_lcall = fcall; hte->h_lcall = &fcall->f_nxt; if (*cp != '\0') inperr(); }