Exemple #1
0
/*
 * T_WHILE T_LPARN expr T_RPARN
 */
void
while1(tnode_t *tn)
{

	if (!reached) {
		/* loop not entered at top */
		warning(207);
		reached = 1;
	}

	if (tn != NULL)
		tn = cconv(tn);
	if (tn != NULL)
		tn = promote(NOOP, 0, tn);
	if (tn != NULL && !issclt(tn->tn_type->t_tspec)) {
		/* controlling expressions must have scalar type */
		error(204);
		tn = NULL;
	}

	pushctrl(T_WHILE);
	cstk->c_loop = 1;
	if (tn != NULL && tn->tn_op == CON) {
		if (isityp(tn->tn_type->t_tspec)) {
			cstk->c_infinite = tn->tn_val->v_quad != 0;
		} else {
			cstk->c_infinite = tn->tn_val->v_ldbl != 0.0;
		}
	}

	expr(tn, 0, 1);
}
Exemple #2
0
/*
 * 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;
}
Exemple #3
0
/*
 * T_SWITCH T_LPARN expr T_RPARN
 */
void
switch1(tnode_t *tn)
{
	tspec_t	t;
	type_t	*tp;

	if (tn != NULL)
		tn = cconv(tn);
	if (tn != NULL)
		tn = promote(NOOP, 0, tn);
	if (tn != NULL && !isityp(tn->tn_type->t_tspec)) {
		/* switch expression must have integral type */
		error(205);
		tn = NULL;
	}
	if (tn != NULL && tflag) {
		t = tn->tn_type->t_tspec;
		if (t == LONG || t == ULONG || t == QUAD || t == UQUAD) {
			/* switch expr. must be of type `int' in trad. C */
			warning(271);
		}
	}

	/*
	 * Remember the type of the expression. Because its possible
	 * that (*tp) is allocated on tree memory the type must be
	 * duplicated. This is not too complicated because it is
	 * only an integer type.
	 */
	if ((tp = calloc(1, sizeof (type_t))) == NULL)
		nomem();
	if (tn != NULL) {
		tp->t_tspec = tn->tn_type->t_tspec;
		if ((tp->t_isenum = tn->tn_type->t_isenum) != 0)
			tp->t_enum = tn->tn_type->t_enum;
	} else {
		tp->t_tspec = INT;
	}

	expr(tn, 1, 0);

	pushctrl(T_SWITCH);
	cstk->c_switch = 1;
	cstk->c_swtype = tp;

	reached = rchflg = 0;
	ftflg = 1;
}
Exemple #4
0
/*
 * do stmnt do_while_expr
 * do error
 */
void
do2(tnode_t *tn)
{

	/*
	 * If there was a continue statement the expression controlling the
	 * loop is reached.
	 */
	if (cstk->c_cont)
		reached = 1;

	if (tn != NULL)
		tn = cconv(tn);
	if (tn != NULL)
		tn = promote(NOOP, 0, tn);
	if (tn != NULL && !issclt(tn->tn_type->t_tspec)) {
		/* controlling expressions must have scalar type */
		error(204);
		tn = NULL;
	}

	if (tn != NULL && tn->tn_op == CON) {
		if (isityp(tn->tn_type->t_tspec)) {
			cstk->c_infinite = tn->tn_val->v_quad != 0;
		} else {
			cstk->c_infinite = tn->tn_val->v_ldbl != 0.0;
		}
		if (!cstk->c_infinite && cstk->c_cont)
		    error(323);
	}

	expr(tn, 0, 1, 1);

	/*
	 * The end of the loop is only reached if it is no endless loop
	 * or there was a break statement which could be reached.
	 */
	reached = !cstk->c_infinite || cstk->c_break;
	rchflg = 0;

	popctrl(T_DO);
}
Exemple #5
0
/*
 * Check a single argument in a function call.
 *
 *  hte		a pointer to the hash table entry of the function
 *  n		the number of the argument (1..)
 *  def		the function definition or NULL
 *  decl	prototype declaration, old style declaration or NULL
 *  pos1p	position of definition, declaration of first call
 *  call1	first call, if both def and decl are old style def/decl
 *  call	checked call
 *  arg1	currently checked argument of def/decl/call1
 *  arg2	currently checked argument of call
 *
 */
static void
chkau(hte_t *hte, int n, sym_t *def, sym_t *decl, pos_t *pos1p,
      fcall_t *call1, fcall_t *call, type_t *arg1, type_t *arg2)
{
    /* LINTED (automatic hides external declaration: warn) */
    int	promote, asgn, warn;
    tspec_t	t1, t2;
    arginf_t *ai, *ai1;
    char	*pos1;

    /*
     * If a function definition is available (def != NULL), we compare the
     * function call (call) with the definition. Otherwise, if a function
     * definition is available and it is not an old style definition
     * (decl != NULL && TP(decl->s_type)->t_proto), we compare the call
     * with this declaration. Otherwise we compare it with the first
     * call we have found (call1).
     */

    /* arg1 must be promoted if it stems from an old style definition */
    promote = def != NULL && def->s_osdef;

    /*
     * If we compair with a definition or declaration, we must perform
     * the same checks for qualifiers in indirected types as in
     * assignments.
     */
    asgn = def != NULL || (decl != NULL && TP(decl->s_type)->t_proto);

    warn = 0;
    if (eqtype(arg1, arg2, 1, promote, asgn, &warn) && (!sflag || !warn))
        return;

    /*
     * Other lint implementations print warnings as soon as the type
     * of an argument does not match exactly the expected type. The
     * result are lots of warnings which are really not necessary.
     * We print a warning only if
     *   (0) at least one type is not an integer type and types differ
     *   (1) hflag is set and types differ
     *   (2) types differ, except in signedness
     * If the argument is an integer constant whose msb is not set,
     * signedness is ignored (e.g. 0 matches both signed and unsigned
     * int). This is with and without hflag.
     * If the argument is an integer constant with value 0 and the
     * expected argument is of type pointer and the width of the
     * integer constant is the same as the width of the pointer,
     * no warning is printed.
     */
    t1 = arg1->t_tspec;
    t2 = arg2->t_tspec;
    if (isityp(t1) && isityp(t2) && !arg1->t_isenum && !arg2->t_isenum) {
        if (promote) {
            /*
             * XXX Here is a problem: Although it is possible to
             * pass an int where a char/short it expected, there
             * may be loss in significant digits. We should first
             * check for const arguments if they can be converted
             * into the original parameter type.
             */
            if (t1 == FLOAT) {
                t1 = DOUBLE;
            } else if (t1 == CHAR || t1 == SCHAR) {
                t1 = INT;
            } else if (t1 == UCHAR) {
                t1 = tflag ? UINT : INT;
            } else if (t1 == SHORT) {
                t1 = INT;
            } else if (t1 == USHORT) {
                /* CONSTCOND */
                t1 = INT_MAX < USHRT_MAX || tflag ? UINT : INT;
            }
        }

        if (styp(t1) == styp(t2)) {

            /*
             * types differ only in signedness; get information
             * about arguments
             */

            /*
             * treat a definition like a call with variable
             * arguments
             */
            ai1 = call1 != NULL ? call1->f_args : NULL;

            /*
             * if two calls are compared, ai1 is set to the
             * information for the n-th argument, if this was
             * a constant, otherwise to NULL
             */
            for ( ; ai1 != NULL; ai1 = ai1->a_nxt) {
                if (ai1->a_num == n)
                    break;
            }
            /*
             * ai is set to the information of the n-th arg
             * of the (second) call, if this was a constant,
             * otherwise to NULL
             */
            for (ai = call->f_args; ai != NULL; ai = ai->a_nxt) {
                if (ai->a_num == n)
                    break;
            }

            if (ai1 == NULL && ai == NULL) {
                /* no constant at all */
                if (!hflag)
                    return;
            } else if (ai1 == NULL || ai == NULL) {
                /* one constant */
                if (ai == NULL)
                    ai = ai1;
                if (ai->a_zero || ai->a_pcon)
                    /* same value in signed and unsigned */
                    return;
                /* value (not representation) differently */
            } else {
                /*
                 * two constants, one signed, one unsigned;
                 * if the msb of one of the constants is set,
                 * the argument is used inconsistently.
                 */
                if (!ai1->a_ncon && !ai->a_ncon)
                    return;
            }
        }

    } else if (t1 == PTR && isityp(t2)) {
        for (ai = call->f_args; ai != NULL; ai = ai->a_nxt) {
            if (ai->a_num == n)
                break;
        }
        /*
         * Vendor implementations of lint (e.g. HP-UX, Digital UNIX)
         * don't care about the size of the integer argument,
         * only whether or not it is zero.  We do the same.
         */
        if (ai != NULL && ai->a_zero)
            return;
    }

    pos1 = xstrdup(mkpos(pos1p));
    /* %s, arg %d used inconsistently\t%s  ::  %s */
    msg(6, hte->h_name, n, pos1, mkpos(&call->f_pos));
    free(pos1);
}
Exemple #6
0
/*
 * write out all information necessary for lint2 to check function
 * calls
 *
 * rvused is set if the return value is used (asigned to a variable)
 * rvdisc is set if the return value is not used and not ignored
 * (casted to void)
 */
void
outcall(tnode_t *tn, int rvused, int rvdisc)
{
	tnode_t	*args, *arg;
	int	narg, n, i;
	int64_t	q;
	tspec_t	t;

	/* reset buffer */
	outclr();

	/*
	 * line number of .c source, 'c' for function call, Id of current
	 * source (.c or .h), and line in current source
	 */
	outint(csrc_pos.p_line);
	outchar('c');
	outint(getfnid(curr_pos.p_file));
	outchar('.');
	outint(curr_pos.p_line);

	/*
	 * flags; 'u' and 'i' must be last to make sure a letter
	 * is between the numeric argument of a flag and the name of
	 * the function
	 */
	narg = 0;
	args = tn->tn_right;
	for (arg = args; arg != NULL; arg = arg->tn_right)
		narg++;
	/* informations about arguments */
	for (n = 1; n <= narg; n++) {
		/* the last argument is the top one in the tree */
		for (i = narg, arg = args; i > n; i--, arg = arg->tn_right)
			continue;
		arg = arg->tn_left;
		if (arg->tn_op == CON) {
			if (isityp(t = arg->tn_type->t_tspec)) {
				/*
				 * XXX it would probably be better to
				 * explicitly test the sign
				 */
				if ((q = arg->tn_val->v_quad) == 0) {
					/* zero constant */
					outchar('z');
				} else if (msb(q, t, 0) == 0) {
					/* positive if casted to signed */
					outchar('p');
				} else {
					/* negative if casted to signed */
					outchar('n');
				}
				outint(n);
			}
		} else if (arg->tn_op == AMPER &&
			   arg->tn_left->tn_op == STRING &&
			   arg->tn_left->tn_strg->st_tspec == CHAR) {
			/* constant string, write all format specifiers */
			outchar('s');
			outint(n);
			outfstrg(arg->tn_left->tn_strg);
		}

	}
	/* return value discarded/used/ignored */
	outchar(rvdisc ? 'd' : (rvused ? 'u' : 'i'));

	/* name of the called function */
	outname(tn->tn_left->tn_left->tn_sym->s_name);

	/* types of arguments */
	outchar('f');
	outint(narg);
	for (n = 1; n <= narg; n++) {
		/* the last argument is the top one in the tree */
		for (i = narg, arg = args; i > n; i--, arg = arg->tn_right)
			continue;
		outtype(arg->tn_left->tn_type);
	}
	/* expected type of return value */
	outtype(tn->tn_type);
}
Exemple #7
0
/*
 * 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;
}
Exemple #8
0
void
mkinit(tnode_t *tn)
{
	ptrdiff_t offs;
	sym_t	*sym;
	tspec_t	lt, rt;
	tnode_t	*ln;
	struct	mbl *tmem;
	scl_t	sc;

	if (initerr || tn == NULL)
		goto end;

	sc = initsym->s_scl;

	/*
	 * Do not test for automatic aggregat initialisation. If the
	 * initializer starts with a brace we have the warning already.
	 * If not, an error will be printed that the initializer must
	 * be enclosed by braces.
	 */

	/*
	 * Local initialisation of non-array-types with only one expression
	 * without braces is done by ASSIGN
	 */
	if ((sc == AUTO || sc == REG) &&
	    initsym->s_type->t_tspec != ARRAY && initstk->i_nxt == NULL) {
		ln = getnnode(initsym, 0);
		ln->tn_type = tduptyp(ln->tn_type);
		ln->tn_type->t_const = 0;
		tn = build(ASSIGN, ln, tn);
		expr(tn, 0, 0);
		goto end;
	}

	/*
	 * Remove all entries which cannot be used for further initializers
	 * and do not require a closing brace.
	 */
	popinit(0);

	/* Initialisations by strings are done in strginit(). */
	if (strginit(tn))
		goto end;

	nextinit(0);
	if (initerr || tn == NULL)
		goto end;

	initstk->i_cnt--;

	/* Create a temporary node for the left side. */
	ln = tgetblk(sizeof (tnode_t));
	ln->tn_op = NAME;
	ln->tn_type = tduptyp(initstk->i_type);
	ln->tn_type->t_const = 0;
	ln->tn_lvalue = 1;
	ln->tn_sym = initsym;		/* better than nothing */

	tn = cconv(tn);

	lt = ln->tn_type->t_tspec;
	rt = tn->tn_type->t_tspec;

	if (!issclt(lt))
		lerror("mkinit() 1");

	if (!typeok(INIT, 0, ln, tn))
		goto end;

	/*
	 * Store the tree memory. This is nessesary because otherwise
	 * expr() would free it.
	 */
	tmem = tsave();
	expr(tn, 1, 0);
	trestor(tmem);

	if (isityp(lt) && ln->tn_type->t_isfield && !isityp(rt)) {
		/*
		 * Bit-fields can be initialized in trad. C only by integer
		 * constants.
		 */
		if (tflag)
			/* bit-field initialisation is illegal in trad. C */
			warning(186);
	}

	if (lt != rt || (initstk->i_type->t_isfield && tn->tn_op == CON))
		tn = convert(INIT, 0, initstk->i_type, tn);

	if (tn != NULL && tn->tn_op != CON) {
		sym = NULL;
		offs = 0;
		if (conaddr(tn, &sym, &offs) == -1) {
			if (sc == AUTO || sc == REG) {
				/* non-constant initializer */
				(void)gnuism(177);
			} else {
				/* non-constant initializer */
				error(177);
			}
		}
	}

 end:
	tfreeblk();
}