123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409 |
- /* $Header$ */
- /* 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 "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"
- #define is_zero(ex) \
- ((ex)->ex_class == Value && (ex)->VL_VALUE == (arith)0 && \
- (ex)->VL_IDF == 0)
- 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)
- register struct expr **expp;
- struct idf *idf;
- {
- /* The selector idf is applied to *expp; oper may be '.' or
- ARROW.
- */
- register struct type *tp = (*expp)->ex_type;
- register struct sdef *sd;
- if (oper == ARROW) {
- if (tp->tp_fund == POINTER) /* normal case */
- tp = tp->tp_up;
- else { /* constructions like "12->selector" and
- "char c; c->selector"
- */
- switch (tp->tp_fund) {
- case CHAR:
- case SHORT:
- case INT:
- case LONG:
- case ENUM:
- /* Allowed by RM 14.1 */
- ch7cast(expp, CAST, pa_type);
- sd = idf2sdef(idf, tp);
- tp = sd->sd_stype;
- break;
- default:
- error("-> applied to %s",
- symbol2str(tp->tp_fund));
- case ERRONEOUS:
- (*expp)->ex_type = error_type;
- return;
- }
- } /* tp->tp_fund != POINTER */
- } /* oper == ARROW */
- else { /* oper == '.' */
- /* filter out illegal expressions "non_lvalue.sel" */
- if (!(*expp)->ex_lvalue) {
- error("dot requires lvalue");
- (*expp)->ex_type = error_type;
- return;
- }
- }
- switch (tp->tp_fund) {
- case POINTER: /* for int *p; p->next = ... */
- case STRUCT:
- case UNION:
- break;
- case CHAR:
- case SHORT:
- case INT:
- case LONG:
- case ENUM:
- /* warning will be given by idf2sdef() */
- break;
- default:
- if (!is_anon_idf(idf))
- error("selector %s applied to %s",
- idf->id_text, symbol2str(tp->tp_fund));
- case ERRONEOUS:
- (*expp)->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 ((*expp)->ex_class == Value) {
- /* It is an object we know the address of; so
- we can calculate the address of the
- selected member
- */
- (*expp)->VL_VALUE += sd->sd_offset;
- (*expp)->ex_type = sd->sd_type;
- }
- else
- if ((*expp)->ex_class == Oper) {
- struct oper *op = &((*expp)->ex_object.ex_oper);
-
- if (op->op_oper == '.' || op->op_oper == ARROW) {
- op->op_right->VL_VALUE += sd->sd_offset;
- (*expp)->ex_type = sd->sd_type;
- }
- else
- *expp = new_oper(sd->sd_type, *expp, '.',
- intexpr(sd->sd_offset, INT));
- }
- }
- else /* oper == ARROW */
- *expp = new_oper(sd->sd_type,
- *expp, oper, intexpr(sd->sd_offset, INT));
- (*expp)->ex_lvalue = sd->sd_type->tp_fund != ARRAY;
- }
- ch7incr(expp, oper)
- register struct expr **expp;
- {
- /* The monadic prefix/postfix incr/decr operator oper is
- applied to *expp.
- */
- arith addend;
- struct expr *expr;
- register int fund = (*expp)->ex_type->tp_fund;
- if (!(*expp)->ex_lvalue) {
- error("no lvalue with %s", symbol2str(oper));
- return;
- }
- if (fund == ENUM) {
- warning("%s on enum", symbol2str(oper));
- addend = (arith)1;
- }
- else
- if (is_arith_type((*expp)->ex_type))
- addend = (arith)1;
- else
- if (fund == POINTER)
- addend = size_of_type((*expp)->ex_type->tp_up, "object");
- #ifndef NOBITFIELD
- else
- if (fund == FIELD)
- addend = (arith)1;
- #endif NOBITFIELD
- else {
- if ((*expp)->ex_type != error_type)
- error("%s on %s",
- symbol2str(oper),
- symbol2str((*expp)->ex_type->tp_fund)
- );
- return;
- }
- expr = intexpr(addend, INT);
- ch7cast(&expr, CAST, (*expp)->ex_type);
- #ifndef NOBITFIELD
- if (fund == FIELD)
- *expp = new_oper((*expp)->ex_type->tp_up, *expp, oper, expr);
- else
- #endif NOBITFIELD
- *expp = new_oper((*expp)->ex_type, *expp, oper, expr);
- }
- 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);
- oldtp = (*expp)->ex_type;
- if (oldtp == tp)
- {} /* life is easy */
- else
- #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 (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 ( oldtp->tp_fund == ENUM &&
- tp->tp_fund == ENUM &&
- oper != CAST
- )
- warning("%s on enums of different types",
- symbol2str(oper));
- int2int(expp, tp);
- }
- else
- if (oldi && !i) {
- if (oldtp->tp_fund == ENUM && oper != CAST)
- warning("conversion of enum to %s\n",
- symbol2str(tp->tp_fund));
- int2float(expp, tp);
- }
- else
- if (!oldi && i)
- float2int(expp, tp);
- else /* !oldi && !i */
- float2float(expp, tp);
- }
- else
- if (oldtp->tp_fund == POINTER && tp->tp_fund == POINTER) {
- if (oper != CAST)
- warning("incompatible pointers in %s",
- symbol2str(oper));
- (*expp)->ex_type = tp; /* free conversion */
- }
- else
- if (oldtp->tp_fund == POINTER && is_integral_type(tp)) {
- /* from pointer to integral */
- if (oper != CAST)
- warning("illegal conversion of pointer to %s",
- symbol2str(tp->tp_fund));
- if (oldtp->tp_size > tp->tp_size)
- warning("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 RETURN:
- if (is_zero(*expp))
- break;
- default:
- warning("illegal conversion of %s to pointer",
- symbol2str(oldtp->tp_fund));
- break;
- }
- if (oldtp->tp_size > tp->tp_size)
- warning("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_size == tp->tp_size && oper == CAST) {
- warning("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;
- }
- }
- ch7asgn(expp, oper, expr)
- register struct expr **expp;
- struct expr *expr;
- {
- /* The assignment operators.
- */
- int fund = (*expp)->ex_type->tp_fund;
- /* We expect an lvalue */
- if (!(*expp)->ex_lvalue) {
- error("no lvalue in lhs of %s", symbol2str(oper));
- (*expp)->ex_depth = 99; /* no direct store/load at EVAL() */
- /* what is 99 ??? DG */
- }
- switch (oper) {
- case '=':
- ch7cast(&expr, oper, (*expp)->ex_type);
- break;
- case TIMESAB:
- case DIVAB:
- case MODAB:
- if (!is_arith_type((*expp)->ex_type))
- error("%s on %s", symbol2str(oper), symbol2str(fund));
- any2arith(&expr, oper);
- ch7cast(&expr, CAST, (*expp)->ex_type);
- break;
- case PLUSAB:
- case MINAB:
- any2arith(&expr, oper);
- if (fund == POINTER) {
- if (!is_integral_type(expr->ex_type))
- error("%s on non-integral type (%s)",
- symbol2str(oper), symbol2str(fund));
- ch7bin(&expr, '*',
- intexpr(
- size_of_type(
- (*expp)->ex_type->tp_up,
- "object"
- ),
- pa_type->tp_fund
- )
- );
- }
- else
- if (!is_arith_type((*expp)->ex_type))
- error("%s on %s", symbol2str(oper), symbol2str(fund));
- else
- ch7cast(&expr, CAST, (*expp)->ex_type);
- break;
- case LEFTAB:
- case RIGHTAB:
- ch7cast(&expr, oper, int_type);
- if (!is_integral_type((*expp)->ex_type))
- error("%s on %s", symbol2str(oper), symbol2str(fund));
- break;
- case ANDAB:
- case XORAB:
- case ORAB:
- if (!is_integral_type((*expp)->ex_type))
- error("%s on %s", symbol2str(oper), symbol2str(fund));
- ch7cast(&expr, oper, (*expp)->ex_type);
- break;
- }
- #ifndef NOBITFIELD
- if (fund == FIELD)
- *expp = new_oper((*expp)->ex_type->tp_up, *expp, oper, expr);
- else
- #endif NOBITFIELD
- *expp = new_oper((*expp)->ex_type, *expp, oper, expr);
- }
- /* Some interesting (?) questions answered.
- */
- int
- is_integral_type(tp)
- 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)
- struct type *tp;
- {
- switch (tp->tp_fund) {
- case CHAR:
- case SHORT:
- case INT:
- case LONG:
- case ENUM:
- case FLOAT:
- case DOUBLE:
- return 1;
- #ifndef NOBITFIELD
- case FIELD:
- return is_arith_type(tp->tp_up);
- #endif NOBITFIELD
- default:
- return 0;
- }
- }
|