123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617 |
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
- /* $Id$ */
- /* A R I T H M E T I C C O N V E R S I O N S */
- /* This file contains the routines for the various conversions that
- may befall operands in C. It is structurally a mess, but I haven't
- decided yet whether I can't find the right structure or the
- semantics of C is a mess.
- */
- #include <alloc.h>
- #include "debug.h"
- #include "lint.h"
- #include "nobitfield.h"
- #include "idf.h"
- #include <flt_arith.h>
- #include "arith.h"
- #include "sizes.h"
- #include "type.h"
- #include "proto.h"
- #include "label.h"
- #include "expr.h"
- #include "Lpars.h"
- #include "field.h"
- #include "mes.h"
- #include "assert.h"
- #include "ch3.h"
- #include "ch3bin.h"
- #include "code_c.h"
- #include "conversion.h"
- #include "cstoper.h"
- #include "expr_loc.h"
- #include "error.h"
- #include <symbol2str.h>
- extern char options[];
- void arithbalance(struct expr **e1p, int oper, struct expr **e2p) /* 3.1.2.5 */
- {
- /* The expressions *e1p and *e2p are balanced to be operands
- of the arithmetic operator oper.
- We check here if the EX_PTRDIFF flag should be retained.
- They are set to zero in because one of the opreands might
- have a floating type, in which case the flags shouldn't
- travel upward in the expression tree.
- */
- int t1, t2, u1, u2;
- int shifting = (oper == LEFT || oper == RIGHT
- || oper == LEFTAB || oper == RIGHTAB);
- int ptrdiff = 0;
- t1 = any2arith(e1p, oper);
- t2 = any2arith(e2p, oper);
- if (int_size != pointer_size) {
- if ((ptrdiff = ((*e1p)->ex_flags & EX_PTRDIFF))
- || ((*e2p)->ex_flags & EX_PTRDIFF)) {
- if (!((*e1p)->ex_flags & EX_PTRDIFF) && t1 == LONG)
- ptrdiff = 0;
- if (!((*e2p)->ex_flags & EX_PTRDIFF) && t2 == LONG
- && !shifting)
- ptrdiff = 0;
- }
- /* Now turn off ptrdiff flags */
- (*e1p)->ex_flags &= ~EX_PTRDIFF;
- (*e2p)->ex_flags &= ~EX_PTRDIFF;
- }
- /* Now t1 and t2 are either INT, LONG, FLOAT, DOUBLE, or LNGDBL */
- /* If any operand has the type long double, the other operand
- is converted to long double.
- */
- /* ??? t1 == LNGDBL, t2 == DOUBLE */
- if (t1 == LNGDBL) {
- if (t2 != LNGDBL) {
- if (t2 == DOUBLE || t2 == FLOAT)
- float2float(e2p, lngdbl_type);
- else
- int2float(e2p, lngdbl_type);
- }
- return;
- } else if (t2 == LNGDBL) {
- if (t1 != LNGDBL)
- {
- if (t1 == DOUBLE || t1 == FLOAT)
- {
- float2float(e1p, lngdbl_type);
- }
- else
- {
- int2float(e1p, lngdbl_type);
- }
- }
- return;
- }
- /* If any operand has the type double, the other operand
- is converted to double.
- */
- if (t1 == DOUBLE) {
- if (t2 == FLOAT)
- float2float(e2p, double_type);
- else if (t2 != DOUBLE)
- int2float(e2p, double_type);
- return;
- } else if (t2 == DOUBLE) {
- if (t1 == FLOAT)
- float2float(e1p, double_type);
- else if (t1 != DOUBLE)
- int2float(e1p, double_type);
- return;
- }
- /* If any operand has the type float, the other operand
- is converted to float.
- */
- if (t1 == FLOAT) {
- if (t2 != FLOAT)
- int2float(e2p, float_type);
- return;
- } else if (t2 == FLOAT) {
- if (t1 != FLOAT)
- int2float(e1p, float_type);
- return;
- }
- /* Now they are INT or LONG */
- u1 = (*e1p)->ex_type->tp_unsigned;
- u2 = (*e2p)->ex_type->tp_unsigned;
- /* If either operand has type unsigned long int, the other
- operand is converted to unsigned long int.
- */
- if (t1 == LONG && u1 && (t2 != LONG || !u2))
- t2 = int2int(e2p, ulong_type);
- else if (t2 == LONG && u2 && (t1 != LONG || !u1)
- && !shifting) /* ??? */
- t1 = int2int(e1p, ulong_type);
- /* If one operand has type long int and the other has type unsigned
- int, if a long int can represent all values of an unsigned int,
- the operand of type unsigned int is converted to long int; if
- a long int cannot represent all values of an unsigned int,
- both operands are converted to unsigned long int.
- */
- if (t1 == LONG && t2 == INT && u2)
- t2 = int2int(e2p, (int_size<long_size)? long_type : ulong_type);
- else if (t2 == LONG && t1 == INT && u1 && !shifting) /* ??? */
- t1 = int2int(e1p, (int_size<long_size)? long_type : ulong_type);
- /* If either operand has type long int, the other operand is con-
- verted to long int.
- */
- if (t1 == LONG && t2 != LONG)
- t2 = int2int(e2p, long_type);
- else
- if (t2 == LONG && t1 != LONG && !shifting) /* ??? */
- t1 = int2int(e1p, long_type);
- u1 = (*e1p)->ex_type->tp_unsigned;
- u2 = (*e2p)->ex_type->tp_unsigned;
- /* If either operand has type unsigned int, the other operand
- is converted to unsigned int.
- Otherwise, both operands have type int.
- */
- if (u1 && !u2 && !shifting)
- t2 = int2int(e2p, (t1 == LONG) ? ulong_type : uint_type);
- else
- if (!u1 && u2 && !shifting)
- t1 = int2int(e1p, (t2 == LONG) ? ulong_type : uint_type);
- if (int_size != pointer_size) {
- if (ptrdiff) {
- (*e1p)->ex_flags |= EX_PTRDIFF;
- (*e2p)->ex_flags |= EX_PTRDIFF;
- }
- }
- }
- void relbalance(struct expr **e1p, int oper, struct expr **e2p)
- {
- /* The expressions *e1p and *e2p are balanced to be operands
- of the relational operator oper, or the ':'.
- Care is taken to switch the operands in case of a
- null-pointer constant. This is done so that ch3cast()
- allows assignments of a null-pointer to a function
- pointer.
- */
- struct expr *e1 = *e1p, *e2 = *e2p;
- struct expr *tmpexpr;
- if (e1->ex_type->tp_fund == POINTER
- && is_cp_cst(e1)
- && e1->VL_VALUE == 0) {
- tmpexpr = e1;
- e1 = e2;
- e2 = tmpexpr;
- }
- if (e1->ex_type->tp_fund == POINTER)
- ch3pointer(e2p, oper, e1->ex_type);
- else if (e2->ex_type->tp_fund == POINTER)
- ch3pointer(e1p, oper, e2->ex_type);
- else if (e1->ex_type == e2->ex_type
- && e1->ex_type->tp_fund == ENUM) {}
- else if (oper == ':'
- && e1->ex_type->tp_fund == VOID
- && e2->ex_type->tp_fund == VOID) {}
- else
- arithbalance(e1p, oper, e2p);
- }
- void ch3pointer(struct expr **expp, int oper, struct type *tp)
- {
- /* Checks whether *expp may be compared to tp using oper,
- as described in chapter 3.3.8 and 3.3.9.
- tp is known to be a pointer.
- */
- struct expr *exp = *expp;
- if (exp->ex_type->tp_fund == POINTER) {
- if (exp->ex_type != tp)
- ch3cast(expp, oper, tp);
- }
- else
- if (is_integral_type(exp->ex_type)) {
- if ((oper != EQUAL && oper != NOTEQUAL && oper != ':')
- || !(is_cp_cst(exp) && exp->VL_VALUE == 0)) {
- expr_error(exp,"%s on %s and pointer",
- symbol2str(oper),
- symbol2str(exp->ex_type->tp_fund));
- }
- ch3cast(expp, CAST, tp);
- }
- else {
- expr_error(exp, "%s on %s and pointer",
- symbol2str(oper),
- symbol2str(exp->ex_type->tp_fund)
- );
- ch3cast(expp, oper, tp);
- }
- }
- int any2arith(struct expr **expp, int oper)
- {
- /* Turns any expression into int_type, long_type,
- float_type, double_type or lngdbl_type.
- */
- int fund;
- switch (fund = (*expp)->ex_type->tp_fund) {
- case CHAR:
- case SHORT:
- ASSERT((*expp)->ex_type->tp_size <= int_type->tp_size);
- if ((*expp)->ex_type->tp_unsigned
- && (*expp)->ex_type->tp_size == int_type->tp_size) {
- int2int(expp, uint_type);
- } else {
- int2int(expp, int_type);
- }
- break;
- case INT:
- case LONG:
- break;
- case ENUM:
- #ifndef LINT
- /* we do not want this conversion for lint, since we
- want to keep enums and ints separate
- */
- int2int(expp, int_type);
- #endif /* LINT */
- break;
- case FLOAT:
- /* only when it is a parameter and the default promotion should
- occur. Hence this code is moved to any2parameter().
- float2float(expp, double_type);
- break;
- */
- case DOUBLE:
- case LNGDBL:
- break;
- #ifndef NOBITFIELD
- case FIELD:
- field2arith(expp);
- break;
- #endif /* NOBITFIELD */
- default:
- expr_error(*expp, "operator %s on non-numerical operand (%s)",
- symbol2str(oper), symbol2str(fund));
- case ERRONEOUS:
- erroneous2int(expp);
- break;
- }
- return (*expp)->ex_type->tp_fund;
- }
- void erroneous2int(struct expr **expp)
- {
- /* the (erroneous) expression *expp is replaced by an
- int expression
- */
- register struct expr *exp = *expp;
- int flags = exp->ex_flags;
-
- free_expression(exp);
- exp = intexpr((arith)0, INT);
- exp->ex_flags = (flags | EX_ERROR);
- *expp = exp;
- }
- struct expr *arith2arith(struct type *tp, int oper, struct expr *expr)
- {
- /* arith2arith constructs a new expression containing a
- run-time conversion between some arithmetic types.
- */
- struct expr *new = new_expr();
-
- new->ex_file = expr->ex_file;
- new->ex_line = expr->ex_line;
- new->ex_type = tp;
- new->ex_class = Type;
- return new_oper(tp, new, oper, expr);
- }
- int int2int(struct expr **expp, struct type *tp)
- {
- /* The expression *expp, which is of some integral type, is
- converted to the integral type tp.
- */
- struct expr *exp = *expp;
-
- if (is_cp_cst(exp)) {
- struct type *tp1 = exp->ex_type;
- exp->ex_type = tp;
- if (! tp1->tp_unsigned && tp->tp_unsigned) {
- /* Avoid "unreal" overflow warnings, such as
- caused by f.i.:
- unsigned int x = ~0;
- unsigned int y = -1;
- */
- extern long full_mask[];
- long remainder = exp->VL_VALUE &
- ~full_mask[(int)(tp->tp_size)];
- if (remainder == 0 ||
- remainder == ~full_mask[(int)(tp->tp_size)]) {
- exp->VL_VALUE &= ~remainder;
- }
- }
- cut_size(exp);
- }
- else {
- exp = arith2arith(tp, INT2INT, exp);
- }
- *expp = exp;
- return exp->ex_type->tp_fund;
- }
- /* With compile-time constants, we don't set fp_used, since this is done
- * only when necessary in eval.c.
- */
- void int2float(struct expr **expp, struct type *tp)
- {
- /* The expression *expp, which is of some integral type, is
- converted to the floating type tp.
- */
- struct expr *exp = *expp;
- int uns = exp->ex_type->tp_unsigned;
-
- if (is_cp_cst(exp)) {
- exp->ex_type = tp;
- exp->ex_class = Float;
- flt_arith2flt(exp->VL_VALUE, &(exp->FL_ARITH), uns);
- }
- else {
- fp_used = 1;
- *expp = arith2arith(tp, INT2FLOAT, *expp);
- }
- }
- void float2int(struct expr **expp, struct type *tp)
- {
- /* The expression *expp, which is of some floating type, is
- converted to the integral type tp.
- */
- struct expr *ex = *expp;
-
- if (is_fp_cst(ex)) {
- arith ar = flt_flt2arith(&ex->FL_ARITH, tp->tp_unsigned);
- if (flt_status == FLT_OVFL)
- expr_warning(ex,"overflow in float to int conversion");
- else if (flt_status == FLT_UNFL)
- expr_warning(ex,"underflow in float to unsigned conversion");
- ex->ex_type = tp;
- /* The following lines are copied from fill_int_expr */
- ex->ex_class = Value;
- ex->VL_CLASS = Const;
- ex->VL_VALUE = ar;
- cut_size(ex);
- } else {
- fp_used = 1;
- *expp = arith2arith(tp, FLOAT2INT, ex);
- }
- }
- void float2float(struct expr**expp, struct type *tp)
- {
- /* The expression *expp, which is of some floating type, is
- converted to the floating type tp.
- There is no need for an explicit conversion operator
- if the expression is a constant.
- */
-
- if (is_fp_cst(*expp))
- (*expp)->ex_type = tp;
- else {
- fp_used = 1;
- *expp = arith2arith(tp, FLOAT2FLOAT, *expp);
- }
- }
- void array2pointer(struct expr *exp)
- {
- /* The expression, which must be an array, is converted
- to a pointer.
- */
- exp->ex_type = construct_type(POINTER, exp->ex_type->tp_up
- , /* exp->ex_type->tp_typequal */ 0
- , (arith)0, NO_PROTO);
- }
- void function2pointer(struct expr *exp)
- {
- /* The expression, which must be a function, is converted
- to a pointer to the function.
- */
- exp->ex_type = construct_type(POINTER, exp->ex_type, 0,
- (arith)0, NO_PROTO);
- }
- void string2pointer(struct expr *ex)
- {
- /* The expression, which must be a string constant, is converted
- to a pointer to the string-containing area.
- */
- label lbl;
- lbl = code_string(ex->SG_VALUE, ex->SG_LEN);
- ex->ex_class = Value;
- ex->VL_CLASS = Label;
- ex->VL_LBL = lbl;
- ex->VL_VALUE = (arith)0;
- }
- void opnd2integral(struct expr **expp, int oper)
- {
- int fund = (*expp)->ex_type->tp_fund;
- if (fund != INT && fund != LONG) {
- expr_error(*expp, "%s operand to %s",
- symbol2str(fund), symbol2str(oper));
- erroneous2int(expp);
- /* fund = INT; */
- }
- }
- void opnd2logical(struct expr **expp, int oper)
- {
- int fund = (*expp)->ex_type->tp_fund;
- if (fund == FUNCTION || fund == ARRAY) {
- expr_warning(*expp, "%s operand to %s",
- symbol2str(fund),
- symbol2str(oper));
- if (fund == FUNCTION) function2pointer(*expp);
- else array2pointer(*expp);
- }
- #ifndef NOBITFIELD
- else
- if (fund == FIELD)
- field2arith(expp);
- #endif /* NOBITFIELD */
- switch (fund = (*expp)->ex_type->tp_fund) {
- case CHAR:
- case SHORT:
- case INT:
- case LONG:
- case ENUM:
- case POINTER:
- case FLOAT:
- case DOUBLE:
- case LNGDBL:
- break;
- default:
- expr_error(*expp, "%s operand to %s",
- symbol2str(fund), symbol2str(oper));
- case ERRONEOUS:
- erroneous2int(expp);
- break;
- }
- }
- void opnd2test(struct expr **expp, int oper)
- {
- opnd2logical(expp, oper);
- if ((*expp)->ex_class == Oper) {
- switch((*expp)->OP_OPER) {
- case '<':
- case '>':
- case LESSEQ:
- case GREATEREQ:
- case EQUAL:
- case NOTEQUAL:
- case '!':
- case AND:
- case OR: /* && and || also impose a test */
- /* It is already a test */
- return;
- case ',':
- opnd2test(&((*expp)->OP_RIGHT), oper);
- return;
- }
- }
- ch3bin(expp, NOTEQUAL, intexpr((arith)0, INT));
- }
- void any2opnd(struct expr **expp, int oper)
- {
- if (!*expp)
- return;
- if (oper == SIZEOF || oper == ADDRESSOF) return;
- switch ((*expp)->ex_type->tp_fund) {
- case CHAR:
- case SHORT:
- case ENUM:
- #if 0
- case FLOAT: /* not necessary anymore */
- #endif
- any2arith(expp, oper);
- break;
- case ARRAY:
- array2pointer(*expp);
- break;
- case POINTER:
- if ((*expp)->ex_class == String)
- string2pointer(*expp);
- break;
- case FUNCTION:
- function2pointer(*expp);
- break;
- #ifndef NOBITFIELD
- case FIELD:
- field2arith(expp);
- break;
- #endif /* NOBITFIELD */
- }
- }
- void any2parameter(struct expr **expp)
- {
- /* To handle default argument promotions
- */
- any2opnd(expp, '(');
- if (int_size != pointer_size)
- if ((*expp)->ex_flags & EX_PTRDIFF)
- expr_warning(*expp, "pointer difference caused long expression");
- if ((*expp)->ex_type->tp_fund == FLOAT)
- float2float(expp, double_type);
- }
- #ifndef NOBITFIELD
- void field2arith(struct expr **expp)
- {
- /* The expression to extract the bitfield value from the
- memory word is put in the tree.
- */
- struct type *tp = (*expp)->ex_type->tp_up;
- struct field *fd = (*expp)->ex_type->tp_field;
- (*expp)->ex_type = word_type;
- if (tp->tp_unsigned) { /* don't worry about the sign bit */
- if (fd->fd_width >= 8 * (int)word_size)
- (*expp)->ex_type = uword_type;
- ch3bin(expp, RIGHT, intexpr((arith)fd->fd_shift, INT));
- ch3bin(expp, '&', intexpr(fd->fd_mask, INT));
- }
- else { /* take care of the sign bit: sign extend if needed */
- arith other_bits = (int)word_size * 8 - fd->fd_width;
- ch3bin(expp, LEFT,
- intexpr(other_bits - fd->fd_shift,
- INT)
- );
- ch3bin(expp, RIGHT, intexpr(other_bits, INT));
- }
- }
- #endif /* NOBITFIELD */
- /* switch_sign_fp() negates the given floating constant expression,
- * and frees the string representing the old value.
- */
- void switch_sign_fp(struct expr *expr)
- {
- flt_umin(&(expr->FL_ARITH));
- }
|