123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
- /* $Id$ */
- /* S E M A N T I C A N A L Y S I S -- C H A P T E R 7 RM */
- #include "lint.h"
- #include "nofloat.h"
- #include "debug.h"
- #include "nobitfield.h"
- #include "idf.h"
- #include "arith.h"
- #include "type.h"
- #include "struct.h"
- #include "label.h"
- #include "expr.h"
- #include "def.h"
- #include "Lpars.h"
- #include "assert.h"
- extern char options[];
- extern char *symbol2str();
- /* Most expression-handling routines have a pointer to a
- (struct type *) as first parameter. The object under the pointer
- gets updated in the process.
- */
- ch7sel(expp, oper, idf)
- struct expr **expp;
- struct idf *idf;
- {
- /* The selector idf is applied to *expp; oper may be '.' or
- ARROW.
- */
- register struct expr *exp;
- register struct type *tp;
- register struct sdef *sd;
- any2opnd(expp, oper);
- exp = *expp;
- tp = exp->ex_type;
- if (oper == ARROW) {
- if (tp->tp_fund == POINTER &&
- ( tp->tp_up->tp_fund == STRUCT ||
- tp->tp_up->tp_fund == UNION)) /* normal case */
- tp = tp->tp_up;
- else { /* constructions like "12->selector" and
- "char c; c->selector"
- */
- switch (tp->tp_fund) {
- case INT:
- case LONG:
- /* Allowed by RM 14.1 */
- ch7cast(expp, CAST, pa_type);
- sd = idf2sdef(idf, tp);
- tp = sd->sd_stype;
- break;
- case POINTER:
- break;
- default:
- expr_error(exp, "-> applied to %s",
- symbol2str(tp->tp_fund));
- case ERRONEOUS:
- exp->ex_type = error_type;
- return;
- }
- }
- } /* oper == ARROW */
- else { /* oper == '.' */
- /* filter out illegal expressions "non_lvalue.sel" */
- if (!exp->ex_lvalue) {
- expr_error(exp, "dot requires lvalue");
- return;
- }
- }
- exp = *expp;
- switch (tp->tp_fund) {
- case POINTER: /* for int *p; p->next = ... */
- case STRUCT:
- case UNION:
- break;
- case INT:
- case LONG:
- /* warning will be given by idf2sdef() */
- break;
- default:
- if (!is_anon_idf(idf))
- expr_error(exp, "selector %s applied to %s",
- idf->id_text, symbol2str(tp->tp_fund));
- case ERRONEOUS:
- exp->ex_type = error_type;
- return;
- }
- sd = idf2sdef(idf, tp);
- if (oper == '.') {
- /* there are 3 cases in which the selection can be
- performed compile-time:
- I: n.sel (n either an identifier or a constant)
- II: (e.s1).s2 (transformed into (e.(s1+s2)))
- III: (e->s1).s2 (transformed into (e->(s1+s2)))
- The code performing these conversions is
- extremely obscure.
- */
- if (exp->ex_class == Value) {
- /* It is an object we know the address of; so
- we can calculate the address of the
- selected member
- */
- exp->VL_VALUE += sd->sd_offset;
- exp->ex_type = sd->sd_type;
- if (exp->ex_type == error_type)
- exp->ex_flags |= EX_ERROR;
- }
- else
- if (exp->ex_class == Oper) {
- struct oper *op = &(exp->ex_object.ex_oper);
-
- if (op->op_oper == '.' || op->op_oper == ARROW) {
- ASSERT(is_cp_cst(op->op_right));
- op->op_right->VL_VALUE += sd->sd_offset;
- exp->ex_type = sd->sd_type;
- if (exp->ex_type == error_type)
- exp->ex_flags |= EX_ERROR;
- }
- else
- exp = new_oper(sd->sd_type, exp, '.',
- intexpr(sd->sd_offset, INT));
- }
- }
- else /* oper == ARROW */
- exp = new_oper(sd->sd_type,
- exp, oper, intexpr(sd->sd_offset, INT));
- exp->ex_lvalue = (sd->sd_type->tp_fund != ARRAY);
- *expp = exp;
- }
- ch7incr(expp, oper)
- struct expr **expp;
- {
- /* The monadic prefix/postfix incr/decr operator oper is
- applied to *expp.
- */
- ch7asgn(expp, oper, intexpr((arith)1, INT));
- }
- ch7cast(expp, oper, tp)
- register struct expr **expp;
- register struct type *tp;
- {
- /* The expression *expp is cast to type tp; the cast is
- caused by the operator oper. If the cast has
- to be passed on to run time, its left operand will be an
- expression of class Type.
- */
- register struct type *oldtp;
- if ((*expp)->ex_type->tp_fund == FUNCTION)
- function2pointer(*expp);
- if ((*expp)->ex_type->tp_fund == ARRAY)
- array2pointer(*expp);
- if ((*expp)->ex_class == String)
- string2pointer(*expp);
- oldtp = (*expp)->ex_type;
- #ifndef NOBITFIELD
- if (oldtp->tp_fund == FIELD) {
- field2arith(expp);
- ch7cast(expp, oper, tp);
- }
- else
- if (tp->tp_fund == FIELD) {
- ch7cast(expp, oper, tp->tp_up);
- }
- else
- #endif /* NOBITFIELD */
- if (oldtp == tp) {
- /* life is easy */
- }
- else
- if (tp->tp_fund == VOID) {
- /* Easy again */
- (*expp)->ex_type = void_type;
- }
- else
- if (is_arith_type(oldtp) && is_arith_type(tp)) {
- int oldi = is_integral_type(oldtp);
- int i = is_integral_type(tp);
- if (oldi && i) {
- if ( oper != CAST
- && ( tp->tp_fund == ENUM
- || oldtp->tp_fund == ENUM
- )
- ) {
- expr_warning(*expp,
- "dubious %s on enum",
- symbol2str(oper));
- }
- #ifdef LINT
- if (oper == CAST)
- (*expp)->ex_type = tp;
- else
- int2int(expp, tp);
- #else /* LINT */
- int2int(expp, tp);
- #endif /* LINT */
- }
- #ifndef NOFLOAT
- else
- if (oldi && !i) {
- if (oldtp->tp_fund == ENUM && oper != CAST)
- expr_warning(*expp,
- "conversion of enum to %s\n",
- symbol2str(tp->tp_fund));
- #ifdef LINT
- if (oper == CAST)
- (*expp)->ex_type = tp;
- else
- int2float(expp, tp);
- #else /* LINT */
- int2float(expp, tp);
- #endif /* LINT */
- }
- else
- if (!oldi && i) {
- #ifdef LINT
- if (oper == CAST)
- (*expp)->ex_type = tp;
- else
- float2int(expp, tp);
- #else /* LINT */
- float2int(expp, tp);
- #endif /* LINT */
- }
- else {
- /* !oldi && !i */
- #ifdef LINT
- if (oper == CAST)
- (*expp)->ex_type = tp;
- else
- float2float(expp, tp);
- #else /* LINT */
- float2float(expp, tp);
- #endif /* LINT */
- }
- #else /* NOFLOAT */
- else {
- crash("(ch7cast) floats not implemented\n");
- /*NOTREACHED*/
- }
- #endif /* NOFLOAT */
- }
- else
- if (oldtp->tp_fund == POINTER && tp->tp_fund == POINTER) {
- if (oper != CAST)
- expr_warning(*expp, "incompatible pointers in %s",
- symbol2str(oper));
- #ifdef LINT
- if (oper != CAST)
- lint_ptr_conv(oldtp->tp_up->tp_fund, tp->tp_up->tp_fund);
- #endif /* LINT */
- (*expp)->ex_type = tp; /* free conversion */
- }
- else
- if (oldtp->tp_fund == POINTER && is_integral_type(tp)) {
- /* from pointer to integral */
- if (oper != CAST)
- expr_warning(*expp,
- "illegal conversion of pointer to %s",
- symbol2str(tp->tp_fund));
- if (oldtp->tp_size > tp->tp_size)
- expr_warning(*expp,
- "conversion of pointer to %s loses accuracy",
- symbol2str(tp->tp_fund));
- if (oldtp->tp_size != tp->tp_size)
- int2int(expp, tp);
- else
- (*expp)->ex_type = tp;
- }
- else
- if (tp->tp_fund == POINTER && is_integral_type(oldtp)) {
- /* from integral to pointer */
- switch (oper) {
- case CAST:
- break;
- case EQUAL:
- case NOTEQUAL:
- case ':':
- case '=':
- case RETURN:
- if (is_cp_cst(*expp) && (*expp)->VL_VALUE == (arith)0)
- break;
- default:
- expr_warning(*expp,
- "dubious conversion of %s to pointer",
- symbol2str(oldtp->tp_fund));
- break;
- }
- if (oldtp->tp_size > tp->tp_size)
- expr_warning(*expp,
- "conversion of %s to pointer loses accuracy",
- symbol2str(oldtp->tp_fund));
- if (oldtp->tp_size != tp->tp_size)
- int2int(expp, tp);
- else
- (*expp)->ex_type = tp;
- }
- else
- if (oldtp->tp_fund == ERRONEOUS) {
- /* we just won't look */
- (*expp)->ex_type = tp; /* brute force */
- }
- else
- if (oldtp->tp_size == tp->tp_size && oper == CAST) {
- expr_warning(*expp, "dubious conversion based on equal size");
- (*expp)->ex_type = tp; /* brute force */
- }
- else {
- if (oldtp->tp_fund != ERRONEOUS && tp->tp_fund != ERRONEOUS)
- expr_error(*expp, "cannot convert %s to %s",
- symbol2str(oldtp->tp_fund),
- symbol2str(tp->tp_fund)
- );
- (*expp)->ex_type = tp; /* brute force */
- }
- }
- ch7asgn(expp, oper, expr)
- struct expr **expp;
- struct expr *expr;
- {
- /* The assignment operators.
- "f op= e" should be interpreted as
- "f = (typeof f)((typeof (f op e))f op (typeof (f op e))e)"
- and not as "f = f op (typeof f)e".
- Consider, for example, (i == 10) i *= 0.9; (i == 9), where
- typeof i == int.
- The resulting expression tree becomes:
- op=
- / \
- / \
- f (typeof (f op e))e
- EVAL should however take care of evaluating (typeof (f op e))f
- */
- register struct expr *exp = *expp;
- int fund = exp->ex_type->tp_fund;
- struct type *tp;
- /* We expect an lvalue */
- if (!exp->ex_lvalue) {
- expr_error(exp, "no lvalue in lhs of %s", symbol2str(oper));
- exp->ex_depth = 99; /* no direct store/load at EVAL() */
- /* what is 99 ??? DG */
- }
- if (oper == '=') {
- ch7cast(&expr, oper, exp->ex_type);
- tp = expr->ex_type;
- }
- else { /* turn e into e' where typeof(e') = typeof (f op e) */
- struct expr *extmp = intexpr((arith)0, INT);
- /* this is really $#@&*%$# ! */
- /* if you correct this, please correct lint_new_oper() too */
- extmp->ex_lvalue = 1;
- extmp->ex_type = exp->ex_type;
- ch7bin(&extmp, oper, expr);
- /* Note that ch7bin creates a tree of the expression
- ((typeof (f op e))f op (typeof (f op e))e),
- where f ~ extmp and e ~ expr.
- We want to use (typeof (f op e))e.
- Ch7bin does not create a tree if both operands
- were illegal or constants!
- */
- tp = extmp->ex_type; /* perform the arithmetic in type tp */
- if (extmp->ex_class == Oper) {
- expr = extmp->OP_RIGHT;
- extmp->OP_RIGHT = NILEXPR;
- free_expression(extmp);
- }
- else
- expr = extmp;
- }
- #ifndef NOBITFIELD
- if (fund == FIELD)
- exp = new_oper(exp->ex_type->tp_up, exp, oper, expr);
- else
- exp = new_oper(exp->ex_type, exp, oper, expr);
- #else /* NOBITFIELD */
- exp = new_oper(exp->ex_type, exp, oper, expr);
- #endif /* NOBITFIELD */
- exp->OP_TYPE = tp; /* for EVAL() */
- exp->ex_flags |= EX_SIDEEFFECTS;
- *expp = exp;
- }
- /* Some interesting (?) questions answered.
- */
- int
- is_integral_type(tp)
- register struct type *tp;
- {
- switch (tp->tp_fund) {
- case CHAR:
- case SHORT:
- case INT:
- case LONG:
- case ENUM:
- return 1;
- #ifndef NOBITFIELD
- case FIELD:
- return is_integral_type(tp->tp_up);
- #endif /* NOBITFIELD */
- default:
- return 0;
- }
- }
- int
- is_arith_type(tp)
- register struct type *tp;
- {
- switch (tp->tp_fund) {
- case CHAR:
- case SHORT:
- case INT:
- case LONG:
- case ENUM:
- #ifndef NOFLOAT
- case FLOAT:
- case DOUBLE:
- #endif /* NOFLOAT */
- return 1;
- #ifndef NOBITFIELD
- case FIELD:
- return is_arith_type(tp->tp_up);
- #endif /* NOBITFIELD */
- default:
- return 0;
- }
- }
|