123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
- /* $Id$ */
- /* Lint miscellaneous routines */
- #include "lint.h"
- #ifdef LINT
- #include <alloc.h> /* for st_free */
- #include "interface.h"
- #ifdef ANSI
- #include <flt_arith.h>
- #endif /* ANSI */
- #include "arith.h" /* definition arith */
- #include "label.h" /* definition label */
- #include "expr.h"
- #include "idf.h"
- #include "def.h"
- #include "code.h" /* RVAL etc */
- #include "LLlex.h"
- #include "Lpars.h"
- #include "stack.h"
- #include "type.h"
- #include "level.h"
- #include "l_state.h"
- extern char *symbol2str();
- extern struct type *func_type;
- PRIVATE lint_enum_arith();
- PRIVATE lint_conversion();
- PRIVATE int numsize();
- check_hiding(idf, lvl, sc)
- struct idf *idf;
- int lvl;
- int sc;
- {
- /* Checks if there is already a definition for this non-extern
- name on a more global level.
- */
- struct def *def = idf->id_def;
-
- if ( def && def->df_level < lvl
- && ! ( lvl == L_FORMAL2
- || def->df_level == L_UNIVERSAL
- || sc == GLOBAL
- || sc == EXTERN
- )
- ) {
- warning("%s is already defined as a %s",
- idf->id_text,
- def->df_level == L_GLOBAL ? "global" :
- def->df_level == L_FORMAL2 ? "formal" :
- "more global local"
- );
- }
- }
- lint_new_oper(expr)
- struct expr *expr;
- {
- /* Does additional checking on a newly constructed expr node
- of class Oper.
- Some code in this routine could be contracted, but since
- I am not sure we have covered the entire ground, we'll
- leave the contracting for some rainy day.
- */
- register struct expr *left = expr->OP_LEFT;
- register struct expr *right = expr->OP_RIGHT;
- register int oper = expr->OP_OPER;
- register int l_fund =
- left == 0 ? 0 : /* for monadics */
- left->ex_type->tp_fund;
- register int r_fund =
- right == 0 ? 0 : /* for ( without parameters */
- right->ex_type->tp_fund;
- /* In ch7.c, in ch7asgn(), a combined operator/assignment
- is hammered into correctness by repeated application of
- ch7bin(), which calls new_oper(), which calls lint_new_oper().
- These spurious calls understandably cause spurious error
- messages, which we don't like. So we try to suppress these
- wierd calls here. This refers to the code marked
- this is really $#@&*%$# !
- in ch7asgn().
- */
- switch (oper) {
- case PLUSAB:
- case MINAB:
- case TIMESAB:
- case DIVAB:
- case MODAB:
- case LEFTAB:
- case RIGHTAB:
- case ANDAB:
- case XORAB:
- case ORAB:
- /* is the left operand wierd? */
- if ( left->ex_class == Value
- && left->VL_CLASS == Const
- && left->VL_VALUE == 0
- ) {
- return;
- }
- }
- switch (oper) {
- case '=':
- lint_conversion(right, l_fund);
- break;
- case PLUSAB:
- lint_conversion(right, l_fund);
- case '+':
- lint_enum_arith(l_fund, oper, r_fund);
- break;
- case MINAB:
- lint_conversion(right, l_fund);
- case '-':
- if (left == 0) {
- /* unary */
- if (r_fund == ENUM)
- warning("negating an enum");
- }
- else {
- /* binary */
- if (l_fund == ENUM && r_fund == ENUM) {
- if (left->ex_type != right->ex_type)
- warning("subtracting enums of different type");
- /* update the type, cem does not do it */
- expr->ex_type = int_type;
- }
- lint_enum_arith(l_fund, oper, r_fund);
- }
- break;
- case TIMESAB:
- lint_conversion(right, l_fund);
- case '*':
- if (left == 0) {
- /* unary */
- }
- else {
- /* binary */
- if (l_fund == ENUM || r_fund == ENUM)
- warning("multiplying enum");
- }
- break;
- case DIVAB:
- lint_conversion(right, l_fund);
- case '/':
- if (l_fund == ENUM || r_fund == ENUM)
- warning("division on enum");
- break;
- case MODAB:
- lint_conversion(right, l_fund);
- case '%':
- if (l_fund == ENUM || r_fund == ENUM)
- warning("modulo on enum");
- break;
- case '~':
- if (r_fund == ENUM || r_fund == FLOAT || r_fund == DOUBLE)
- warning("~ on %s", symbol2str(r_fund));
- break;
- case '!':
- if (r_fund == ENUM)
- warning("! on enum");
- break;
- case INT2INT:
- case INT2FLOAT:
- case FLOAT2INT:
- case FLOAT2FLOAT:
- lint_conversion(right, l_fund);
- break;
- case '<':
- case '>':
- case LESSEQ:
- case GREATEREQ:
- case EQUAL:
- case NOTEQUAL:
- if ( (l_fund == ENUM || r_fund == ENUM)
- && left->ex_type != right->ex_type
- ) {
- warning("comparing enum with non-enum");
- }
- lint_relop(left, right, oper);
- lint_relop(right, left,
- oper == '<' ? '>' :
- oper == '>' ? '<' :
- oper == LESSEQ ? GREATEREQ :
- oper == GREATEREQ ? LESSEQ :
- oper
- );
- break;
- case LEFTAB:
- case RIGHTAB:
- lint_conversion(right, l_fund);
- case LEFT:
- case RIGHT:
- if (l_fund == ENUM || r_fund == ENUM)
- warning("shift on enum");
- break;
- case ANDAB:
- case ORAB:
- case XORAB:
- lint_conversion(right, l_fund);
- case '&':
- case '|':
- case '^':
- if (l_fund == ENUM || r_fund == ENUM)
- warning("bit operations on enum");
- break;
- case ',':
- case '?':
- case ':':
- case AND:
- case OR:
- case POSTINCR:
- case POSTDECR:
- case PLUSPLUS:
- case MINMIN:
- case '(':
- case '.':
- case ARROW:
- default:
- /* OK with lint */
- break;
- }
- }
- PRIVATE
- lint_enum_arith(l_fund, oper, r_fund)
- int l_fund, oper, r_fund;
- {
- if ( l_fund == ENUM
- && r_fund != CHAR
- && r_fund != SHORT
- && r_fund != INT
- ) {
- warning("%s on enum and %s",
- symbol2str(oper), symbol2str(r_fund));
- }
- else
- if ( r_fund == ENUM
- && l_fund != CHAR
- && l_fund != SHORT
- && l_fund != INT
- ) {
- warning("%s on %s and enum",
- symbol2str(oper), symbol2str(l_fund));
- }
- }
- PRIVATE
- lint_conversion(from_expr, to_fund)
- struct expr *from_expr;
- int to_fund;
- {
- register int from_fund = from_expr->ex_type->tp_fund;
- /* was there an attempt to reduce the type of the from_expr
- of the form
- expr & 0377
- or something like this?
- */
- if (from_expr->ex_class == Oper && from_expr->OP_OPER == INT2INT) {
- from_expr = from_expr->OP_LEFT;
- }
- if (from_expr->ex_class == Oper && from_expr->OP_OPER == '&') {
- struct expr *bits =
- is_cp_cst(from_expr->OP_LEFT) ? from_expr->OP_LEFT :
- is_cp_cst(from_expr->OP_RIGHT) ? from_expr->OP_RIGHT :
- 0;
- if (bits) {
- arith val = bits->VL_VALUE;
- if (val < 256)
- from_fund = CHAR;
- else if (val < 256)
- from_fund = SHORT;
- }
- }
- if (numsize(from_fund) > numsize(to_fund)) {
- awarning("conversion from %s to %s may lose accuracy",
- symbol2str(from_fund), symbol2str(to_fund));
- }
- }
- PRIVATE int
- numsize(fund)
- {
- switch (fund) {
- case CHAR: return 1;
- case SHORT: return 2;
- case INT: return 3;
- case ENUM: return 3;
- case LONG: return 4;
- case FLOAT: return 5;
- case DOUBLE: return 6;
- default: return 0;
- }
- }
- lint_ret_conv(from_expr)
- struct expr *from_expr;
- {
- lint_conversion(from_expr, func_type->tp_fund);
- }
- lint_ptr_conv(from, to)
- short from, to;
- {
- /* X -> X ok -- this includes struct -> struct, of any size
- * X -> CHAR ok
- * DOUBLE -> X ok
- * FLOAT -> LONG -> INT -> SHORT ok
- */
- if (from == to)
- return;
- if (to == CHAR)
- return;
- if (from == DOUBLE)
- return;
- switch (from) {
- case FLOAT:
- switch (to) {
- case LONG:
- case INT:
- case SHORT:
- return;
- }
- break;
- case LONG:
- switch (to) {
- case INT:
- case SHORT:
- return;
- }
- break;
- case INT:
- switch (to) {
- case SHORT:
- return;
- }
- break;
- }
- if (from == VOID) {
- /* OK any which way */
- }
- else
- if (from == CHAR) {
- hwarning("pointer to char may not align correctly for a %s",
- symbol2str(to));
- }
- else {
- warning("pointer to %s may not align correctly for a %s",
- symbol2str(from), symbol2str(to));
- }
- }
- lint_relop(left, right, oper)
- struct expr *left, *right;
- int oper; /* '<', '>', LESSEQ, GREATEREQ, EQUAL, NOTEQUAL */
- {
- /* left operand may be converted */
- if ( left->ex_class == Oper
- && left->OP_OPER == INT2INT
- ) {
- left = left->OP_RIGHT;
- }
- /* <unsigned> <relop> <neg-const|0> is doubtful */
- if ( left->ex_type->tp_unsigned
- && right->ex_class == Value
- && right->VL_CLASS == Const
- ) {
- if (!right->ex_type->tp_unsigned && right->VL_VALUE < 0) {
- warning("unsigned compared to negative constant");
- }
- if (right->VL_VALUE == 0) {
- switch (oper) {
- case '<':
- warning("unsigned < 0 will always fail");
- break;
- case LESSEQ:
- warning("unsigned <= 0 is probably wrong");
- break;
- case GREATEREQ:
- warning("unsigned >= 0 will always succeed");
- break;
- }
- }
- }
- /* <char> <relop> <neg-const> is undefined */
- if ( left->ex_type->tp_fund == CHAR
- && right->ex_class == Value
- && right->VL_CLASS == Const
- && (right->VL_VALUE < 0 || right->VL_VALUE > 127)
- ) {
- warning("character compared to negative constant");
- }
- }
- #endif /* LINT */
|