1281168Spfg/* $NetBSD: tree.c,v 1.45 2008/03/04 02:41:46 christos Exp $ */ 212099Sjoerg 312099Sjoerg/* 412099Sjoerg * Copyright (c) 1994, 1995 Jochen Pohl 512099Sjoerg * All Rights Reserved. 612099Sjoerg * 712099Sjoerg * Redistribution and use in source and binary forms, with or without 812099Sjoerg * modification, are permitted provided that the following conditions 912099Sjoerg * are met: 1012099Sjoerg * 1. Redistributions of source code must retain the above copyright 1112099Sjoerg * notice, this list of conditions and the following disclaimer. 1212099Sjoerg * 2. Redistributions in binary form must reproduce the above copyright 1312099Sjoerg * notice, this list of conditions and the following disclaimer in the 1412099Sjoerg * documentation and/or other materials provided with the distribution. 1512099Sjoerg * 3. All advertising materials mentioning features or use of this software 1612099Sjoerg * must display the following acknowledgement: 1712099Sjoerg * This product includes software developed by Jochen Pohl for 1812099Sjoerg * The NetBSD Project. 1912099Sjoerg * 4. The name of the author may not be used to endorse or promote products 2012099Sjoerg * derived from this software without specific prior written permission. 2112099Sjoerg * 2212099Sjoerg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2312099Sjoerg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2412099Sjoerg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2512099Sjoerg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2612099Sjoerg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2712099Sjoerg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2812099Sjoerg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2912099Sjoerg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3012099Sjoerg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3112099Sjoerg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3212099Sjoerg */ 3312099Sjoerg 3491592Smarkm#include <sys/cdefs.h> 3591592Smarkm#if defined(__RCSID) && !defined(lint) 36281168Spfg__RCSID("$NetBSD: tree.c,v 1.45 2008/03/04 02:41:46 christos Exp $"); 3712099Sjoerg#endif 3891592Smarkm__FBSDID("$FreeBSD$"); 3912099Sjoerg 4012099Sjoerg#include <stdlib.h> 4112099Sjoerg#include <string.h> 4212099Sjoerg#include <float.h> 4312099Sjoerg#include <limits.h> 4417142Sjkh#include <math.h> 4512099Sjoerg 4612099Sjoerg#include "lint1.h" 4791592Smarkm#include "cgram.h" 4812099Sjoerg 4912099Sjoerg/* Various flags for each operator. */ 5012099Sjoergstatic mod_t modtab[NOPS]; 5112099Sjoerg 5291592Smarkmstatic tnode_t *getinode(tspec_t, int64_t); 5391592Smarkmstatic void ptrcmpok(op_t, tnode_t *, tnode_t *); 5491592Smarkmstatic int asgntypok(op_t, int, tnode_t *, tnode_t *); 5591592Smarkmstatic void chkbeop(op_t, tnode_t *, tnode_t *); 5691592Smarkmstatic void chkeop2(op_t, int, tnode_t *, tnode_t *); 5791592Smarkmstatic void chkeop1(op_t, int, tnode_t *, tnode_t *); 5891592Smarkmstatic tnode_t *mktnode(op_t, type_t *, tnode_t *, tnode_t *); 5991592Smarkmstatic void balance(op_t, tnode_t **, tnode_t **); 6091592Smarkmstatic void incompat(op_t, tspec_t, tspec_t); 6191592Smarkmstatic void illptrc(mod_t *, type_t *, type_t *); 6291592Smarkmstatic void mrgqual(type_t **, type_t *, type_t *); 6391592Smarkmstatic int conmemb(type_t *); 6491592Smarkmstatic void ptconv(int, tspec_t, tspec_t, type_t *, tnode_t *); 6591592Smarkmstatic void iiconv(op_t, int, tspec_t, tspec_t, type_t *, tnode_t *); 6691592Smarkmstatic void piconv(op_t, tspec_t, type_t *, tnode_t *); 6791592Smarkmstatic void ppconv(op_t, tnode_t *, type_t *); 6891592Smarkmstatic tnode_t *bldstr(op_t, tnode_t *, tnode_t *); 6991592Smarkmstatic tnode_t *bldincdec(op_t, tnode_t *); 7091592Smarkmstatic tnode_t *bldamper(tnode_t *, int); 7191592Smarkmstatic tnode_t *bldplmi(op_t, tnode_t *, tnode_t *); 7291592Smarkmstatic tnode_t *bldshft(op_t, tnode_t *, tnode_t *); 7391592Smarkmstatic tnode_t *bldcol(tnode_t *, tnode_t *); 7491592Smarkmstatic tnode_t *bldasgn(op_t, tnode_t *, tnode_t *); 7591592Smarkmstatic tnode_t *plength(type_t *); 7691592Smarkmstatic tnode_t *fold(tnode_t *); 7791592Smarkmstatic tnode_t *foldtst(tnode_t *); 7891592Smarkmstatic tnode_t *foldflt(tnode_t *); 7991592Smarkmstatic tnode_t *chkfarg(type_t *, tnode_t *); 8091592Smarkmstatic tnode_t *parg(int, type_t *, tnode_t *); 8191592Smarkmstatic void nulleff(tnode_t *); 8291592Smarkmstatic void displexpr(tnode_t *, int); 8391592Smarkmstatic void chkaidx(tnode_t *, int); 8491592Smarkmstatic void chkcomp(op_t, tnode_t *, tnode_t *); 8591592Smarkmstatic void precconf(tnode_t *); 8612099Sjoerg 8712099Sjoerg/* 8812099Sjoerg * Initialize mods of operators. 8912099Sjoerg */ 9012099Sjoergvoid 9191592Smarkminitmtab(void) 9212099Sjoerg{ 9312099Sjoerg static struct { 9412099Sjoerg op_t op; 9512099Sjoerg mod_t m; 9612099Sjoerg } imods[] = { 9712099Sjoerg { ARROW, { 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, 9812099Sjoerg "->" } }, 9912099Sjoerg { POINT, { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 10012099Sjoerg "." } }, 10112099Sjoerg { NOT, { 0,1,0,1,0,1,0,1,0,0,0,0,0,0,0,1,0, 10212099Sjoerg "!" } }, 10312099Sjoerg { COMPL, { 0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,1,1, 10412099Sjoerg "~" } }, 10512099Sjoerg { INCBEF, { 0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0, 10612099Sjoerg "prefix++" } }, 10712099Sjoerg { DECBEF, { 0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0, 10812099Sjoerg "prefix--" } }, 10912099Sjoerg { INCAFT, { 0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0, 11012099Sjoerg "postfix++" } }, 11112099Sjoerg { DECAFT, { 0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0, 11212099Sjoerg "postfix--" } }, 11312099Sjoerg { UPLUS, { 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1, 11412099Sjoerg "unary +" } }, 11512099Sjoerg { UMINUS, { 0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,1,1, 11612099Sjoerg "unary -" } }, 11712099Sjoerg { STAR, { 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, 11812099Sjoerg "unary *" } }, 11912099Sjoerg { AMPER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 12012099Sjoerg "unary &" } }, 12112099Sjoerg { MULT, { 1,0,0,0,1,1,1,0,1,0,0,1,0,0,0,1,1, 12212099Sjoerg "*" } }, 12312099Sjoerg { DIV, { 1,0,0,0,1,1,1,0,1,0,1,1,0,0,0,1,1, 12412099Sjoerg "/" } }, 12512099Sjoerg { MOD, { 1,0,1,0,0,1,1,0,1,0,1,1,0,0,0,1,1, 12612099Sjoerg "%" } }, 12712099Sjoerg { PLUS, { 1,0,0,1,0,1,1,0,1,0,0,0,0,0,0,1,0, 12812099Sjoerg "+" } }, 12912099Sjoerg { MINUS, { 1,0,0,1,0,1,1,0,1,0,0,0,0,0,0,1,0, 13012099Sjoerg "-" } }, 13112099Sjoerg { SHL, { 1,0,1,0,0,1,1,0,0,0,0,0,1,0,0,1,1, 13212099Sjoerg "<<" } }, 13312099Sjoerg { SHR, { 1,0,1,0,0,1,1,0,0,0,1,0,1,0,0,1,1, 13412099Sjoerg ">>" } }, 13512099Sjoerg { LT, { 1,1,0,1,0,1,1,0,1,0,1,1,0,1,1,0,1, 13612099Sjoerg "<" } }, 13712099Sjoerg { LE, { 1,1,0,1,0,1,1,0,1,0,1,1,0,1,1,0,1, 13812099Sjoerg "<=" } }, 13912099Sjoerg { GT, { 1,1,0,1,0,1,1,0,1,0,1,1,0,1,1,0,1, 14012099Sjoerg ">" } }, 14112099Sjoerg { GE, { 1,1,0,1,0,1,1,0,1,0,1,1,0,1,1,0,1, 14212099Sjoerg ">=" } }, 14312099Sjoerg { EQ, { 1,1,0,1,0,1,1,0,1,0,0,0,0,1,1,0,1, 14412099Sjoerg "==" } }, 14512099Sjoerg { NE, { 1,1,0,1,0,1,1,0,1,0,0,0,0,1,1,0,1, 14612099Sjoerg "!=" } }, 14712099Sjoerg { AND, { 1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0, 14812099Sjoerg "&" } }, 14912099Sjoerg { XOR, { 1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0, 15012099Sjoerg "^" } }, 15112099Sjoerg { OR, { 1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0, 15212099Sjoerg "|" } }, 15312099Sjoerg { LOGAND, { 1,1,0,1,0,1,0,1,0,0,0,0,0,0,0,1,0, 15412099Sjoerg "&&" } }, 15512099Sjoerg { LOGOR, { 1,1,0,1,0,1,0,1,0,0,0,0,1,0,0,1,0, 15612099Sjoerg "||" } }, 15712099Sjoerg { QUEST, { 1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0, 15812099Sjoerg "?" } }, 15912099Sjoerg { COLON, { 1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0, 16012099Sjoerg ":" } }, 16112099Sjoerg { ASSIGN, { 1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, 16212099Sjoerg "=" } }, 16312099Sjoerg { MULASS, { 1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0, 16412099Sjoerg "*=" } }, 16512099Sjoerg { DIVASS, { 1,0,0,0,1,0,0,0,0,1,0,1,0,0,0,1,0, 16612099Sjoerg "/=" } }, 16712099Sjoerg { MODASS, { 1,0,1,0,0,0,0,0,0,1,0,1,0,0,0,1,0, 16812099Sjoerg "%=" } }, 16912099Sjoerg { ADDASS, { 1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0, 17012099Sjoerg "+=" } }, 17112099Sjoerg { SUBASS, { 1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0, 17212099Sjoerg "-=" } }, 17312099Sjoerg { SHLASS, { 1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0, 17412099Sjoerg "<<=" } }, 17512099Sjoerg { SHRASS, { 1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0, 17612099Sjoerg ">>=" } }, 17712099Sjoerg { ANDASS, { 1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0, 17812099Sjoerg "&=" } }, 17912099Sjoerg { XORASS, { 1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0, 18012099Sjoerg "^=" } }, 18112099Sjoerg { ORASS, { 1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0, 18212099Sjoerg "|=" } }, 18312099Sjoerg { NAME, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 18412099Sjoerg "NAME" } }, 18512099Sjoerg { CON, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 18612099Sjoerg "CON" } }, 18712099Sjoerg { STRING, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 18812099Sjoerg "STRING" } }, 18912099Sjoerg { FSEL, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 19012099Sjoerg "FSEL" } }, 19112099Sjoerg { CALL, { 1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 19212099Sjoerg "CALL" } }, 19312099Sjoerg { COMMA, { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 19412099Sjoerg "," } }, 19512099Sjoerg { CVT, { 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, 19612099Sjoerg "CVT" } }, 19712099Sjoerg { ICALL, { 1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 19812099Sjoerg "ICALL" } }, 19912099Sjoerg { LOAD, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 20012099Sjoerg "LOAD" } }, 20112099Sjoerg { PUSH, { 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, 20212099Sjoerg "PUSH" } }, 20312099Sjoerg { RETURN, { 1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, 20412099Sjoerg "RETURN" } }, 20512099Sjoerg { INIT, { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, 20612099Sjoerg "INIT" } }, 20712099Sjoerg { FARG, { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, 20812099Sjoerg "FARG" } }, 20912099Sjoerg { NOOP } 21012099Sjoerg }; 21112099Sjoerg int i; 21212099Sjoerg 21312099Sjoerg for (i = 0; imods[i].op != NOOP; i++) 21412099Sjoerg STRUCT_ASSIGN(modtab[imods[i].op], imods[i].m); 21512099Sjoerg} 21612099Sjoerg 21712099Sjoerg/* 21812099Sjoerg * Increase degree of reference. 21912099Sjoerg * This is most often used to change type "T" in type "pointer to T". 22012099Sjoerg */ 22112099Sjoergtype_t * 22291592Smarkmincref(type_t *tp, tspec_t t) 22312099Sjoerg{ 22412099Sjoerg type_t *tp2; 22512099Sjoerg 22612099Sjoerg tp2 = getblk(sizeof (type_t)); 22712099Sjoerg tp2->t_tspec = t; 22812099Sjoerg tp2->t_subt = tp; 22912099Sjoerg return (tp2); 23012099Sjoerg} 23112099Sjoerg 23212099Sjoerg/* 23312099Sjoerg * same for use in expressions 23412099Sjoerg */ 23512099Sjoergtype_t * 23691592Smarkmtincref(type_t *tp, tspec_t t) 23712099Sjoerg{ 23812099Sjoerg type_t *tp2; 23912099Sjoerg 24012099Sjoerg tp2 = tgetblk(sizeof (type_t)); 24112099Sjoerg tp2->t_tspec = t; 24212099Sjoerg tp2->t_subt = tp; 24312099Sjoerg return (tp2); 24412099Sjoerg} 24512099Sjoerg 24612099Sjoerg/* 24712099Sjoerg * Create a node for a constant. 24812099Sjoerg */ 24912099Sjoergtnode_t * 25091592Smarkmgetcnode(type_t *tp, val_t *v) 25112099Sjoerg{ 25212099Sjoerg tnode_t *n; 25312099Sjoerg 25412099Sjoerg n = getnode(); 25512099Sjoerg n->tn_op = CON; 25612099Sjoerg n->tn_type = tp; 25712099Sjoerg n->tn_val = tgetblk(sizeof (val_t)); 25812099Sjoerg n->tn_val->v_tspec = tp->t_tspec; 25912099Sjoerg n->tn_val->v_ansiu = v->v_ansiu; 26012099Sjoerg n->tn_val->v_u = v->v_u; 26112099Sjoerg free(v); 26212099Sjoerg return (n); 26312099Sjoerg} 26412099Sjoerg 26512099Sjoerg/* 266108532Sschweikh * Create a node for an integer constant. 26712099Sjoerg */ 26812099Sjoergstatic tnode_t * 26991592Smarkmgetinode(tspec_t t, int64_t q) 27012099Sjoerg{ 27112099Sjoerg tnode_t *n; 27212099Sjoerg 27312099Sjoerg n = getnode(); 27412099Sjoerg n->tn_op = CON; 27512099Sjoerg n->tn_type = gettyp(t); 27612099Sjoerg n->tn_val = tgetblk(sizeof (val_t)); 27712099Sjoerg n->tn_val->v_tspec = t; 27812099Sjoerg n->tn_val->v_quad = q; 27912099Sjoerg return (n); 28012099Sjoerg} 28112099Sjoerg 28212099Sjoerg/* 28312099Sjoerg * Create a node for a name (symbol table entry). 28412099Sjoerg * ntok is the token which follows the name. 28512099Sjoerg */ 28612099Sjoergtnode_t * 28791592Smarkmgetnnode(sym_t *sym, int ntok) 28812099Sjoerg{ 28912099Sjoerg tnode_t *n; 29012099Sjoerg 29112099Sjoerg if (sym->s_scl == NOSCL) { 29212099Sjoerg sym->s_scl = EXTERN; 29312099Sjoerg sym->s_def = DECL; 29412099Sjoerg if (ntok == T_LPARN) { 29512099Sjoerg if (sflag) { 29612099Sjoerg /* function implicitly declared to ... */ 29712099Sjoerg warning(215); 29812099Sjoerg } 29912099Sjoerg /* 30012099Sjoerg * XXX if tflag is set the symbol should be 30112099Sjoerg * exported to level 0 30212099Sjoerg */ 30312099Sjoerg sym->s_type = incref(sym->s_type, FUNC); 30412099Sjoerg } else { 305281168Spfg if (!blklev) { 306281168Spfg /* %s undefined */ 307281168Spfg error(99, sym->s_name); 308281168Spfg } else { 309281168Spfg int fixtype; 310281168Spfg if (strcmp(sym->s_name, "__FUNCTION__") == 0) { 311281168Spfg gnuism(316); 312281168Spfg fixtype = 1; 313281168Spfg } else if (strcmp(sym->s_name, "__func__") == 0) { 314281168Spfg if (!Sflag) 315281168Spfg warning(317); 316281168Spfg fixtype = 1; 317281168Spfg } else { 318281168Spfg error(99, sym->s_name); 319281168Spfg fixtype = 0; 320281168Spfg } 321281168Spfg if (fixtype) { 322281168Spfg sym->s_type = incref(gettyp(CHAR), PTR); 323281168Spfg sym->s_type->t_const = 1; 324281168Spfg } 325281168Spfg } 32612099Sjoerg } 32712099Sjoerg } 32812099Sjoerg 32912099Sjoerg if (sym->s_kind != FVFT && sym->s_kind != FMOS) 330281168Spfg LERROR("getnnode()"); 33112099Sjoerg 33212099Sjoerg n = getnode(); 33312099Sjoerg n->tn_type = sym->s_type; 33412099Sjoerg if (sym->s_scl != ENUMCON) { 33512099Sjoerg n->tn_op = NAME; 33612099Sjoerg n->tn_sym = sym; 33712099Sjoerg if (sym->s_kind == FVFT && sym->s_type->t_tspec != FUNC) 33812099Sjoerg n->tn_lvalue = 1; 33912099Sjoerg } else { 34012099Sjoerg n->tn_op = CON; 34112099Sjoerg n->tn_val = tgetblk(sizeof (val_t)); 34212099Sjoerg *n->tn_val = sym->s_value; 34312099Sjoerg } 34412099Sjoerg 34512099Sjoerg return (n); 34612099Sjoerg} 34712099Sjoerg 34812099Sjoerg/* 34912099Sjoerg * Create a node for a string. 35012099Sjoerg */ 35112099Sjoergtnode_t * 35291592Smarkmgetsnode(strg_t *strg) 35312099Sjoerg{ 35412099Sjoerg size_t len; 35512099Sjoerg tnode_t *n; 35612099Sjoerg 35712099Sjoerg len = strg->st_len; 35812099Sjoerg 35912099Sjoerg n = getnode(); 36012099Sjoerg 36112099Sjoerg n->tn_op = STRING; 36212099Sjoerg n->tn_type = tincref(gettyp(strg->st_tspec), ARRAY); 36312099Sjoerg n->tn_type->t_dim = len + 1; 36412099Sjoerg n->tn_lvalue = 1; 36512099Sjoerg 36612099Sjoerg n->tn_strg = tgetblk(sizeof (strg_t)); 36712099Sjoerg n->tn_strg->st_tspec = strg->st_tspec; 36812099Sjoerg n->tn_strg->st_len = len; 36912099Sjoerg 37012099Sjoerg if (strg->st_tspec == CHAR) { 37112099Sjoerg n->tn_strg->st_cp = tgetblk(len + 1); 37212099Sjoerg (void)memcpy(n->tn_strg->st_cp, strg->st_cp, len + 1); 37312099Sjoerg free(strg->st_cp); 37412099Sjoerg } else { 37512099Sjoerg n->tn_strg->st_wcp = tgetblk((len + 1) * sizeof (wchar_t)); 37612099Sjoerg (void)memcpy(n->tn_strg->st_wcp, strg->st_wcp, 37712099Sjoerg (len + 1) * sizeof (wchar_t)); 37812099Sjoerg free(strg->st_wcp); 37912099Sjoerg } 38012099Sjoerg free(strg); 38112099Sjoerg 38212099Sjoerg return (n); 38312099Sjoerg} 38412099Sjoerg 38512099Sjoerg/* 38612099Sjoerg * Returns a symbol which has the same name as the msym argument and is a 38712099Sjoerg * member of the struct or union specified by the tn argument. 38812099Sjoerg */ 38912099Sjoergsym_t * 39091592Smarkmstrmemb(tnode_t *tn, op_t op, sym_t *msym) 39112099Sjoerg{ 39212099Sjoerg str_t *str; 39312099Sjoerg type_t *tp; 39412099Sjoerg sym_t *sym, *csym; 39512099Sjoerg int eq; 39612099Sjoerg tspec_t t; 39712099Sjoerg 39812099Sjoerg /* 39912099Sjoerg * Remove the member if it was unknown until now (Which means 40012099Sjoerg * that no defined struct or union has a member with the same name). 40112099Sjoerg */ 40212099Sjoerg if (msym->s_scl == NOSCL) { 40312099Sjoerg /* undefined struct/union member: %s */ 404281168Spfg fprintf(stderr, "3. %s\n", msym->s_name); 40512099Sjoerg error(101, msym->s_name); 40612099Sjoerg rmsym(msym); 40712099Sjoerg msym->s_kind = FMOS; 40812099Sjoerg msym->s_scl = MOS; 40912099Sjoerg msym->s_styp = tgetblk(sizeof (str_t)); 41012099Sjoerg msym->s_styp->stag = tgetblk(sizeof (sym_t)); 41112099Sjoerg msym->s_styp->stag->s_name = unnamed; 41212099Sjoerg msym->s_value.v_tspec = INT; 41312099Sjoerg return (msym); 41412099Sjoerg } 41512099Sjoerg 41612099Sjoerg /* Set str to the tag of which msym is expected to be a member. */ 41712099Sjoerg str = NULL; 41812099Sjoerg t = (tp = tn->tn_type)->t_tspec; 41912099Sjoerg if (op == POINT) { 42012099Sjoerg if (t == STRUCT || t == UNION) 42112099Sjoerg str = tp->t_str; 42212099Sjoerg } else if (op == ARROW && t == PTR) { 42312099Sjoerg t = (tp = tp->t_subt)->t_tspec; 42412099Sjoerg if (t == STRUCT || t == UNION) 42512099Sjoerg str = tp->t_str; 42612099Sjoerg } 42712099Sjoerg 42812099Sjoerg /* 42912099Sjoerg * If this struct/union has a member with the name of msym, return 43012099Sjoerg * return this it. 43112099Sjoerg */ 43212099Sjoerg if (str != NULL) { 43312099Sjoerg for (sym = msym; sym != NULL; sym = sym->s_link) { 43412099Sjoerg if (sym->s_scl != MOS && sym->s_scl != MOU) 43512099Sjoerg continue; 43612099Sjoerg if (sym->s_styp != str) 43712099Sjoerg continue; 43812099Sjoerg if (strcmp(sym->s_name, msym->s_name) != 0) 43912099Sjoerg continue; 44012099Sjoerg return (sym); 44112099Sjoerg } 44212099Sjoerg } 44312099Sjoerg 44412099Sjoerg /* 44512099Sjoerg * Set eq to 0 if there are struct/union members with the same name 44612099Sjoerg * and different types and/or offsets. 44712099Sjoerg */ 44812099Sjoerg eq = 1; 44912099Sjoerg for (csym = msym; csym != NULL; csym = csym->s_link) { 45012099Sjoerg if (csym->s_scl != MOS && csym->s_scl != MOU) 45112099Sjoerg continue; 45212099Sjoerg if (strcmp(msym->s_name, csym->s_name) != 0) 45312099Sjoerg continue; 45412099Sjoerg for (sym = csym->s_link ; sym != NULL; sym = sym->s_link) { 45512099Sjoerg int w; 45612099Sjoerg 45712099Sjoerg if (sym->s_scl != MOS && sym->s_scl != MOU) 45812099Sjoerg continue; 45912099Sjoerg if (strcmp(csym->s_name, sym->s_name) != 0) 46012099Sjoerg continue; 46112099Sjoerg if (csym->s_value.v_quad != sym->s_value.v_quad) { 46212099Sjoerg eq = 0; 46312099Sjoerg break; 46412099Sjoerg } 46512099Sjoerg w = 0; 46612099Sjoerg eq = eqtype(csym->s_type, sym->s_type, 0, 0, &w) && !w; 46712099Sjoerg if (!eq) 46812099Sjoerg break; 46912099Sjoerg if (csym->s_field != sym->s_field) { 47012099Sjoerg eq = 0; 47112099Sjoerg break; 47212099Sjoerg } 47312099Sjoerg if (csym->s_field) { 47412099Sjoerg type_t *tp1, *tp2; 47512099Sjoerg 47612099Sjoerg tp1 = csym->s_type; 47712099Sjoerg tp2 = sym->s_type; 47812099Sjoerg if (tp1->t_flen != tp2->t_flen) { 47912099Sjoerg eq = 0; 48012099Sjoerg break; 48112099Sjoerg } 48212099Sjoerg if (tp1->t_foffs != tp2->t_foffs) { 48312099Sjoerg eq = 0; 48412099Sjoerg break; 48512099Sjoerg } 48612099Sjoerg } 48712099Sjoerg } 48812099Sjoerg if (!eq) 48912099Sjoerg break; 49012099Sjoerg } 49112099Sjoerg 49212099Sjoerg /* 49312099Sjoerg * Now handle the case in which the left operand refers really 49412099Sjoerg * to a struct/union, but the right operand is not member of it. 49512099Sjoerg */ 49612099Sjoerg if (str != NULL) { 49712099Sjoerg /* illegal member use: %s */ 49812099Sjoerg if (eq && tflag) { 49912099Sjoerg warning(102, msym->s_name); 50012099Sjoerg } else { 50112099Sjoerg error(102, msym->s_name); 50212099Sjoerg } 50312099Sjoerg return (msym); 50412099Sjoerg } 50512099Sjoerg 50612099Sjoerg /* 50712099Sjoerg * Now the left operand of ARROW does not point to a struct/union 50812099Sjoerg * or the left operand of POINT is no struct/union. 50912099Sjoerg */ 51012099Sjoerg if (eq) { 51112099Sjoerg if (op == POINT) { 51212099Sjoerg /* left operand of "." must be struct/union object */ 51312099Sjoerg if (tflag) { 51412099Sjoerg warning(103); 51512099Sjoerg } else { 51612099Sjoerg error(103); 51712099Sjoerg } 51812099Sjoerg } else { 51912099Sjoerg /* left operand of "->" must be pointer to ... */ 52012099Sjoerg if (tflag && tn->tn_type->t_tspec == PTR) { 52112099Sjoerg warning(104); 52212099Sjoerg } else { 52312099Sjoerg error(104); 52412099Sjoerg } 52512099Sjoerg } 52612099Sjoerg } else { 52712099Sjoerg if (tflag) { 52812099Sjoerg /* non-unique member requires struct/union %s */ 52912099Sjoerg error(105, op == POINT ? "object" : "pointer"); 53012099Sjoerg } else { 53112099Sjoerg /* unacceptable operand of %s */ 53212099Sjoerg error(111, modtab[op].m_name); 53312099Sjoerg } 53412099Sjoerg } 53512099Sjoerg 53612099Sjoerg return (msym); 53712099Sjoerg} 53812099Sjoerg 53912099Sjoerg/* 54012099Sjoerg * Create a tree node. Called for most operands except function calls, 54112099Sjoerg * sizeof and casts. 54212099Sjoerg * 54312099Sjoerg * op operator 54412099Sjoerg * ln left operand 54512099Sjoerg * rn if not NULL, right operand 54612099Sjoerg */ 54712099Sjoergtnode_t * 54891592Smarkmbuild(op_t op, tnode_t *ln, tnode_t *rn) 54912099Sjoerg{ 55012099Sjoerg mod_t *mp; 55112099Sjoerg tnode_t *ntn; 55212099Sjoerg type_t *rtp; 55312099Sjoerg 55412099Sjoerg mp = &modtab[op]; 55512099Sjoerg 55612099Sjoerg /* If there was an error in one of the operands, return. */ 55712099Sjoerg if (ln == NULL || (mp->m_binary && rn == NULL)) 55812099Sjoerg return (NULL); 55912099Sjoerg 56012099Sjoerg /* 56112099Sjoerg * Apply class conversions to the left operand, but only if its 56212099Sjoerg * value is needed or it is compaired with null. 56312099Sjoerg */ 56412099Sjoerg if (mp->m_vctx || mp->m_tctx) 56512099Sjoerg ln = cconv(ln); 56612099Sjoerg /* 56712099Sjoerg * The right operand is almost always in a test or value context, 56812099Sjoerg * except if it is a struct or union member. 56912099Sjoerg */ 57012099Sjoerg if (mp->m_binary && op != ARROW && op != POINT) 57112099Sjoerg rn = cconv(rn); 57212099Sjoerg 57312099Sjoerg /* 57475697Sasmodai * Print some warnings for comparisons of unsigned values with 57512099Sjoerg * constants lower than or equal to null. This must be done 57612099Sjoerg * before promote() because otherwise unsigned char and unsigned 57712099Sjoerg * short would be promoted to int. Also types are tested to be 57812099Sjoerg * CHAR, which would also become int. 57912099Sjoerg */ 58012099Sjoerg if (mp->m_comp) 58112099Sjoerg chkcomp(op, ln, rn); 58212099Sjoerg 58312099Sjoerg /* 58412099Sjoerg * Promote the left operand if it is in a test or value context 58512099Sjoerg */ 58612099Sjoerg if (mp->m_vctx || mp->m_tctx) 58712099Sjoerg ln = promote(op, 0, ln); 58812099Sjoerg /* 58912099Sjoerg * Promote the right operand, but only if it is no struct or 59012099Sjoerg * union member, or if it is not to be assigned to the left operand 59112099Sjoerg */ 59212099Sjoerg if (mp->m_binary && op != ARROW && op != POINT && 59312099Sjoerg op != ASSIGN && op != RETURN) { 59412099Sjoerg rn = promote(op, 0, rn); 59512099Sjoerg } 59612099Sjoerg 59712099Sjoerg /* 59812099Sjoerg * If the result of the operation is different for signed or 59912099Sjoerg * unsigned operands and one of the operands is signed only in 60012099Sjoerg * ANSI C, print a warning. 60112099Sjoerg */ 60212099Sjoerg if (mp->m_tlansiu && ln->tn_op == CON && ln->tn_val->v_ansiu) { 60312099Sjoerg /* ANSI C treats constant as unsigned, op %s */ 60412099Sjoerg warning(218, mp->m_name); 60512099Sjoerg ln->tn_val->v_ansiu = 0; 60612099Sjoerg } 60712099Sjoerg if (mp->m_transiu && rn->tn_op == CON && rn->tn_val->v_ansiu) { 60812099Sjoerg /* ANSI C treats constant as unsigned, op %s */ 60912099Sjoerg warning(218, mp->m_name); 61012099Sjoerg rn->tn_val->v_ansiu = 0; 61112099Sjoerg } 61212099Sjoerg 61312099Sjoerg /* Make sure both operands are of the same type */ 61412099Sjoerg if (mp->m_balance || (tflag && (op == SHL || op == SHR))) 61512099Sjoerg balance(op, &ln, &rn); 61612099Sjoerg 61712099Sjoerg /* 61812099Sjoerg * Check types for compatibility with the operation and mutual 61912099Sjoerg * compatibility. Return if there are serios problems. 62012099Sjoerg */ 62112099Sjoerg if (!typeok(op, 0, ln, rn)) 62212099Sjoerg return (NULL); 62312099Sjoerg 62412099Sjoerg /* And now create the node. */ 62512099Sjoerg switch (op) { 62612099Sjoerg case POINT: 62712099Sjoerg case ARROW: 62812099Sjoerg ntn = bldstr(op, ln, rn); 62912099Sjoerg break; 63012099Sjoerg case INCAFT: 63112099Sjoerg case DECAFT: 63212099Sjoerg case INCBEF: 63312099Sjoerg case DECBEF: 63412099Sjoerg ntn = bldincdec(op, ln); 63512099Sjoerg break; 63612099Sjoerg case AMPER: 63712099Sjoerg ntn = bldamper(ln, 0); 63812099Sjoerg break; 63912099Sjoerg case STAR: 64012099Sjoerg ntn = mktnode(STAR, ln->tn_type->t_subt, ln, NULL); 64112099Sjoerg break; 64212099Sjoerg case PLUS: 64312099Sjoerg case MINUS: 64412099Sjoerg ntn = bldplmi(op, ln, rn); 64512099Sjoerg break; 64612099Sjoerg case SHL: 64712099Sjoerg case SHR: 64812099Sjoerg ntn = bldshft(op, ln, rn); 64912099Sjoerg break; 65012099Sjoerg case COLON: 65112099Sjoerg ntn = bldcol(ln, rn); 65212099Sjoerg break; 65312099Sjoerg case ASSIGN: 65412099Sjoerg case MULASS: 65512099Sjoerg case DIVASS: 65612099Sjoerg case MODASS: 65712099Sjoerg case ADDASS: 65812099Sjoerg case SUBASS: 65912099Sjoerg case SHLASS: 66012099Sjoerg case SHRASS: 66112099Sjoerg case ANDASS: 66212099Sjoerg case XORASS: 66312099Sjoerg case ORASS: 66412099Sjoerg case RETURN: 66512099Sjoerg ntn = bldasgn(op, ln, rn); 66612099Sjoerg break; 66712099Sjoerg case COMMA: 66812099Sjoerg case QUEST: 66912099Sjoerg ntn = mktnode(op, rn->tn_type, ln, rn); 67012099Sjoerg break; 67112099Sjoerg default: 67212099Sjoerg rtp = mp->m_logop ? gettyp(INT) : ln->tn_type; 67312099Sjoerg if (!mp->m_binary && rn != NULL) 674281168Spfg LERROR("build()"); 67512099Sjoerg ntn = mktnode(op, rtp, ln, rn); 67612099Sjoerg break; 67712099Sjoerg } 67812099Sjoerg 67991592Smarkm /* Return if an error occurred. */ 68012099Sjoerg if (ntn == NULL) 68112099Sjoerg return (NULL); 68212099Sjoerg 68312099Sjoerg /* Print a warning if precedence confusion is possible */ 68412099Sjoerg if (mp->m_tpconf) 68512099Sjoerg precconf(ntn); 68612099Sjoerg 68712099Sjoerg /* 68812099Sjoerg * Print a warning if one of the operands is in a context where 68912099Sjoerg * it is compared with null and if this operand is a constant. 69012099Sjoerg */ 69112099Sjoerg if (mp->m_tctx) { 69212099Sjoerg if (ln->tn_op == CON || 69312099Sjoerg ((mp->m_binary && op != QUEST) && rn->tn_op == CON)) { 69412099Sjoerg if (hflag && !ccflg) 69512099Sjoerg /* constant in conditional context */ 69612099Sjoerg warning(161); 69712099Sjoerg } 69812099Sjoerg } 69912099Sjoerg 70012099Sjoerg /* Fold if the operator requires it */ 70112099Sjoerg if (mp->m_fold) { 70212099Sjoerg if (ln->tn_op == CON && (!mp->m_binary || rn->tn_op == CON)) { 70312099Sjoerg if (mp->m_tctx) { 70412099Sjoerg ntn = foldtst(ntn); 70512099Sjoerg } else if (isftyp(ntn->tn_type->t_tspec)) { 70612099Sjoerg ntn = foldflt(ntn); 70712099Sjoerg } else { 70812099Sjoerg ntn = fold(ntn); 70912099Sjoerg } 71012099Sjoerg } else if (op == QUEST && ln->tn_op == CON) { 71112099Sjoerg ntn = ln->tn_val->v_quad ? rn->tn_left : rn->tn_right; 71212099Sjoerg } 71312099Sjoerg } 71412099Sjoerg 71512099Sjoerg return (ntn); 71612099Sjoerg} 71712099Sjoerg 71812099Sjoerg/* 71912099Sjoerg * Perform class conversions. 72012099Sjoerg * 72112099Sjoerg * Arrays of type T are converted into pointers to type T. 72212099Sjoerg * Functions are converted to pointers to functions. 72312099Sjoerg * Lvalues are converted to rvalues. 72412099Sjoerg */ 72512099Sjoergtnode_t * 72691592Smarkmcconv(tnode_t *tn) 72712099Sjoerg{ 72812099Sjoerg type_t *tp; 72912099Sjoerg 73012099Sjoerg /* 73112099Sjoerg * Array-lvalue (array of type T) is converted into rvalue 73212099Sjoerg * (pointer to type T) 73312099Sjoerg */ 73412099Sjoerg if (tn->tn_type->t_tspec == ARRAY) { 73512099Sjoerg if (!tn->tn_lvalue) { 73612099Sjoerg /* %soperand of '%s' must be lvalue */ 73712099Sjoerg /* XXX print correct operator */ 73812099Sjoerg (void)gnuism(114, "", modtab[AMPER].m_name); 73912099Sjoerg } 74012099Sjoerg tn = mktnode(AMPER, tincref(tn->tn_type->t_subt, PTR), 74112099Sjoerg tn, NULL); 74212099Sjoerg } 74312099Sjoerg 74412099Sjoerg /* 74512099Sjoerg * Expression of type function (function with return value of type T) 74612099Sjoerg * in rvalue-expression (pointer to function with return value 74712099Sjoerg * of type T) 74812099Sjoerg */ 74912099Sjoerg if (tn->tn_type->t_tspec == FUNC) 75012099Sjoerg tn = bldamper(tn, 1); 75112099Sjoerg 75212099Sjoerg /* lvalue to rvalue */ 75312099Sjoerg if (tn->tn_lvalue) { 75412099Sjoerg tp = tduptyp(tn->tn_type); 75512099Sjoerg tp->t_const = tp->t_volatile = 0; 75612099Sjoerg tn = mktnode(LOAD, tp, tn, NULL); 75712099Sjoerg } 75812099Sjoerg 75912099Sjoerg return (tn); 76012099Sjoerg} 76112099Sjoerg 76212099Sjoerg/* 76312099Sjoerg * Perform most type checks. First the types are checked using 76412099Sjoerg * informations from modtab[]. After that it is done by hand for 76512099Sjoerg * more complicated operators and type combinations. 76612099Sjoerg * 76712099Sjoerg * If the types are ok, typeok() returns 1, otherwise 0. 76812099Sjoerg */ 76912099Sjoergint 77091592Smarkmtypeok(op_t op, int arg, tnode_t *ln, tnode_t *rn) 77112099Sjoerg{ 77212099Sjoerg mod_t *mp; 77391592Smarkm tspec_t lt, rt = NOTSPEC, lst = NOTSPEC, rst = NOTSPEC, olt = NOTSPEC, 77491592Smarkm ort = NOTSPEC; 77591592Smarkm type_t *ltp, *rtp = NULL, *lstp = NULL, *rstp = NULL; 77612099Sjoerg tnode_t *tn; 77712099Sjoerg 77812099Sjoerg mp = &modtab[op]; 77912099Sjoerg 780281168Spfg if ((ltp = ln->tn_type) == NULL) 781281168Spfg LERROR("typeok()"); 782281168Spfg 783281168Spfg if ((lt = ltp->t_tspec) == PTR) 78412099Sjoerg lst = (lstp = ltp->t_subt)->t_tspec; 78512099Sjoerg if (mp->m_binary) { 786281168Spfg if ((rtp = rn->tn_type) == NULL) 787281168Spfg LERROR("typeok()"); 788281168Spfg if ((rt = rtp->t_tspec) == PTR) 78912099Sjoerg rst = (rstp = rtp->t_subt)->t_tspec; 79012099Sjoerg } 79112099Sjoerg 79212099Sjoerg if (mp->m_rqint) { 79312099Sjoerg /* integertypes required */ 79412099Sjoerg if (!isityp(lt) || (mp->m_binary && !isityp(rt))) { 79512099Sjoerg incompat(op, lt, rt); 79612099Sjoerg return (0); 79712099Sjoerg } 79812099Sjoerg } else if (mp->m_rqsclt) { 79912099Sjoerg /* scalar types required */ 80012099Sjoerg if (!issclt(lt) || (mp->m_binary && !issclt(rt))) { 80112099Sjoerg incompat(op, lt, rt); 80212099Sjoerg return (0); 80312099Sjoerg } 80412099Sjoerg } else if (mp->m_rqatyp) { 80512099Sjoerg /* arithmetic types required */ 80612099Sjoerg if (!isatyp(lt) || (mp->m_binary && !isatyp(rt))) { 80712099Sjoerg incompat(op, lt, rt); 80812099Sjoerg return (0); 80912099Sjoerg } 81012099Sjoerg } 81112099Sjoerg 81212099Sjoerg if (op == SHL || op == SHR || op == SHLASS || op == SHRASS) { 81312099Sjoerg /* 81412099Sjoerg * For these operations we need the types before promotion 81512099Sjoerg * and balancing. 81612099Sjoerg */ 81791592Smarkm for (tn=ln; tn->tn_op==CVT && !tn->tn_cast; tn=tn->tn_left) 81891592Smarkm continue; 81912099Sjoerg olt = tn->tn_type->t_tspec; 82091592Smarkm for (tn=rn; tn->tn_op==CVT && !tn->tn_cast; tn=tn->tn_left) 82191592Smarkm continue; 82212099Sjoerg ort = tn->tn_type->t_tspec; 82312099Sjoerg } 82491592Smarkm 82512099Sjoerg switch (op) { 82612099Sjoerg case POINT: 82712099Sjoerg /* 82812099Sjoerg * Most errors required by ANSI C are reported in strmemb(). 82912099Sjoerg * Here we only must check for totaly wrong things. 83012099Sjoerg */ 83112099Sjoerg if (lt == FUNC || lt == VOID || ltp->t_isfield || 83212099Sjoerg ((lt != STRUCT && lt != UNION) && !ln->tn_lvalue)) { 83312099Sjoerg /* Without tflag we got already an error */ 83412099Sjoerg if (tflag) 83512099Sjoerg /* unacceptable operand of %s */ 83612099Sjoerg error(111, mp->m_name); 83712099Sjoerg return (0); 83812099Sjoerg } 83912099Sjoerg /* Now we have an object we can create a pointer to */ 84012099Sjoerg break; 84112099Sjoerg case ARROW: 84212099Sjoerg if (lt != PTR && !(tflag && isityp(lt))) { 84312099Sjoerg /* Without tflag we got already an error */ 84412099Sjoerg if (tflag) 84512099Sjoerg /* unacceptabel operand of %s */ 84612099Sjoerg error(111, mp->m_name); 84712099Sjoerg return (0); 84812099Sjoerg } 84912099Sjoerg break; 85012099Sjoerg case INCAFT: 85112099Sjoerg case DECAFT: 85212099Sjoerg case INCBEF: 85312099Sjoerg case DECBEF: 85412099Sjoerg /* operands have scalar types (checked above) */ 85512099Sjoerg if (!ln->tn_lvalue) { 85612099Sjoerg if (ln->tn_op == CVT && ln->tn_cast && 85712099Sjoerg ln->tn_left->tn_op == LOAD) { 85812099Sjoerg /* a cast does not yield an lvalue */ 85912099Sjoerg error(163); 86012099Sjoerg } 86112099Sjoerg /* %soperand of %s must be lvalue */ 86212099Sjoerg error(114, "", mp->m_name); 86312099Sjoerg return (0); 86412099Sjoerg } else if (ltp->t_const) { 86512099Sjoerg /* %soperand of %s must be modifiable lvalue */ 86612099Sjoerg if (!tflag) 86712099Sjoerg warning(115, "", mp->m_name); 86812099Sjoerg } 86912099Sjoerg break; 87012099Sjoerg case AMPER: 87112099Sjoerg if (lt == ARRAY || lt == FUNC) { 87212099Sjoerg /* ok, a warning comes later (in bldamper()) */ 87312099Sjoerg } else if (!ln->tn_lvalue) { 87412099Sjoerg if (ln->tn_op == CVT && ln->tn_cast && 87512099Sjoerg ln->tn_left->tn_op == LOAD) { 87612099Sjoerg /* a cast does not yield an lvalue */ 87712099Sjoerg error(163); 87812099Sjoerg } 87912099Sjoerg /* %soperand of %s must be lvalue */ 88012099Sjoerg error(114, "", mp->m_name); 88112099Sjoerg return (0); 88212099Sjoerg } else if (issclt(lt)) { 88312099Sjoerg if (ltp->t_isfield) { 88412099Sjoerg /* cannot take address of bit-field */ 88512099Sjoerg error(112); 88612099Sjoerg return (0); 88712099Sjoerg } 88812099Sjoerg } else if (lt != STRUCT && lt != UNION) { 88912099Sjoerg /* unacceptable operand of %s */ 89012099Sjoerg error(111, mp->m_name); 89112099Sjoerg return (0); 89212099Sjoerg } 89312099Sjoerg if (ln->tn_op == NAME && ln->tn_sym->s_reg) { 89412099Sjoerg /* cannot take address of register %s */ 89512099Sjoerg error(113, ln->tn_sym->s_name); 89612099Sjoerg return (0); 89712099Sjoerg } 89812099Sjoerg break; 89912099Sjoerg case STAR: 90012099Sjoerg /* until now there were no type checks for this operator */ 90112099Sjoerg if (lt != PTR) { 90212099Sjoerg /* cannot dereference non-pointer type */ 90312099Sjoerg error(96); 90412099Sjoerg return (0); 90512099Sjoerg } 90612099Sjoerg break; 90712099Sjoerg case PLUS: 90812099Sjoerg /* operands have scalar types (checked above) */ 90912099Sjoerg if ((lt == PTR && !isityp(rt)) || (rt == PTR && !isityp(lt))) { 91012099Sjoerg incompat(op, lt, rt); 91112099Sjoerg return (0); 91212099Sjoerg } 91312099Sjoerg break; 91412099Sjoerg case MINUS: 91512099Sjoerg /* operands have scalar types (checked above) */ 91612099Sjoerg if (lt == PTR && (!isityp(rt) && rt != PTR)) { 91712099Sjoerg incompat(op, lt, rt); 91812099Sjoerg return (0); 91912099Sjoerg } else if (rt == PTR && lt != PTR) { 92012099Sjoerg incompat(op, lt, rt); 92112099Sjoerg return (0); 92212099Sjoerg } 92312099Sjoerg if (lt == PTR && rt == PTR) { 92412099Sjoerg if (!eqtype(lstp, rstp, 1, 0, NULL)) { 92512099Sjoerg /* illegal pointer subtraction */ 92612099Sjoerg error(116); 92712099Sjoerg } 92812099Sjoerg } 92912099Sjoerg break; 93012099Sjoerg case SHR: 93112099Sjoerg /* operands have integer types (checked above) */ 93212099Sjoerg if (pflag && !isutyp(lt)) { 93312099Sjoerg /* 93412099Sjoerg * The left operand is signed. This means that 93512099Sjoerg * the operation is (possibly) nonportable. 93612099Sjoerg */ 93712099Sjoerg /* bitwise operation on signed value nonportable */ 93812099Sjoerg if (ln->tn_op != CON) { 93912099Sjoerg /* possibly nonportable */ 94012099Sjoerg warning(117); 94112099Sjoerg } else if (ln->tn_val->v_quad < 0) { 94212099Sjoerg warning(120); 94312099Sjoerg } 94412099Sjoerg } else if (!tflag && !sflag && !isutyp(olt) && isutyp(ort)) { 94512099Sjoerg /* 94612099Sjoerg * The left operand would become unsigned in 94712099Sjoerg * traditional C. 94812099Sjoerg */ 94912099Sjoerg if (hflag && 95012099Sjoerg (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { 95112099Sjoerg /* semantics of %s change in ANSI C; use ... */ 95212099Sjoerg warning(118, mp->m_name); 95312099Sjoerg } 95412099Sjoerg } else if (!tflag && !sflag && !isutyp(olt) && !isutyp(ort) && 95512099Sjoerg psize(lt) < psize(rt)) { 95612099Sjoerg /* 95712099Sjoerg * In traditional C the left operand would be extended, 95812099Sjoerg * possibly with 1, and then shifted. 95912099Sjoerg */ 96012099Sjoerg if (hflag && 96112099Sjoerg (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { 96212099Sjoerg /* semantics of %s change in ANSI C; use ... */ 96312099Sjoerg warning(118, mp->m_name); 96412099Sjoerg } 96512099Sjoerg } 96612099Sjoerg goto shift; 96712099Sjoerg case SHL: 96812099Sjoerg /* 96912099Sjoerg * ANSI C does not perform balancing for shift operations, 97012099Sjoerg * but traditional C does. If the width of the right operand 97112099Sjoerg * is greather than the width of the left operand, than in 97212099Sjoerg * traditional C the left operand would be extendet to the 97312099Sjoerg * width of the right operand. For SHL this may result in 97412099Sjoerg * different results. 97512099Sjoerg */ 97612099Sjoerg if (psize(lt) < psize(rt)) { 97712099Sjoerg /* 97812099Sjoerg * XXX If both operands are constant make sure 97912099Sjoerg * that there is really a differencs between 98012099Sjoerg * ANSI C and traditional C. 98112099Sjoerg */ 98212099Sjoerg if (hflag) 98312099Sjoerg /* semantics of %s change in ANSI C; use ... */ 98412099Sjoerg warning(118, mp->m_name); 98512099Sjoerg } 98612099Sjoerg shift: 98712099Sjoerg if (rn->tn_op == CON) { 98812099Sjoerg if (!isutyp(rt) && rn->tn_val->v_quad < 0) { 98912099Sjoerg /* negative shift */ 99012099Sjoerg warning(121); 99191592Smarkm } else if ((uint64_t)rn->tn_val->v_quad == size(lt)) { 99212099Sjoerg /* shift equal to size fo object */ 99312099Sjoerg warning(267); 99491592Smarkm } else if ((uint64_t)rn->tn_val->v_quad > size(lt)) { 99512099Sjoerg /* shift greater than size of object */ 99612099Sjoerg warning(122); 99712099Sjoerg } 99812099Sjoerg } 99912099Sjoerg break; 100012099Sjoerg case EQ: 100112099Sjoerg case NE: 100212099Sjoerg /* 100312099Sjoerg * Accept some things which are allowed with EQ and NE, 100475697Sasmodai * but not with ordered comparisons. 100512099Sjoerg */ 100612099Sjoerg if (lt == PTR && ((rt == PTR && rst == VOID) || isityp(rt))) { 100712099Sjoerg if (rn->tn_op == CON && rn->tn_val->v_quad == 0) 100812099Sjoerg break; 100912099Sjoerg } 101012099Sjoerg if (rt == PTR && ((lt == PTR && lst == VOID) || isityp(lt))) { 101112099Sjoerg if (ln->tn_op == CON && ln->tn_val->v_quad == 0) 101212099Sjoerg break; 101312099Sjoerg } 101412099Sjoerg /* FALLTHROUGH */ 101512099Sjoerg case LT: 101612099Sjoerg case GT: 101712099Sjoerg case LE: 101812099Sjoerg case GE: 101912099Sjoerg if ((lt == PTR || rt == PTR) && lt != rt) { 102012099Sjoerg if (isityp(lt) || isityp(rt)) { 102112099Sjoerg /* illegal comb. of pointer and int., op %s */ 102212099Sjoerg warning(123, mp->m_name); 102312099Sjoerg } else { 102412099Sjoerg incompat(op, lt, rt); 102512099Sjoerg return (0); 102612099Sjoerg } 102712099Sjoerg } else if (lt == PTR && rt == PTR) { 102812099Sjoerg ptrcmpok(op, ln, rn); 102912099Sjoerg } 103012099Sjoerg break; 103112099Sjoerg case QUEST: 103212099Sjoerg if (!issclt(lt)) { 103312099Sjoerg /* first operand must have scalar type, op ? : */ 103412099Sjoerg error(170); 103512099Sjoerg return (0); 103612099Sjoerg } 1037281168Spfg while (rn->tn_op == CVT) 1038281168Spfg rn = rn->tn_left; 103912099Sjoerg if (rn->tn_op != COLON) 1040281168Spfg LERROR("typeok()"); 104112099Sjoerg break; 104212099Sjoerg case COLON: 104312099Sjoerg 104412099Sjoerg if (isatyp(lt) && isatyp(rt)) 104512099Sjoerg break; 104612099Sjoerg 104712099Sjoerg if (lt == STRUCT && rt == STRUCT && ltp->t_str == rtp->t_str) 104812099Sjoerg break; 104912099Sjoerg if (lt == UNION && rt == UNION && ltp->t_str == rtp->t_str) 105012099Sjoerg break; 105112099Sjoerg 105212099Sjoerg /* combination of any pointer and 0, 0L or (void *)0 is ok */ 105312099Sjoerg if (lt == PTR && ((rt == PTR && rst == VOID) || isityp(rt))) { 105412099Sjoerg if (rn->tn_op == CON && rn->tn_val->v_quad == 0) 105512099Sjoerg break; 105612099Sjoerg } 105712099Sjoerg if (rt == PTR && ((lt == PTR && lst == VOID) || isityp(lt))) { 105812099Sjoerg if (ln->tn_op == CON && ln->tn_val->v_quad == 0) 105912099Sjoerg break; 106012099Sjoerg } 106112099Sjoerg 106212099Sjoerg if ((lt == PTR && isityp(rt)) || (isityp(lt) && rt == PTR)) { 106312099Sjoerg /* illegal comb. of ptr. and int., op %s */ 106412099Sjoerg warning(123, mp->m_name); 106512099Sjoerg break; 106612099Sjoerg } 106712099Sjoerg 106812099Sjoerg if (lt == VOID || rt == VOID) { 106912099Sjoerg if (lt != VOID || rt != VOID) 107012099Sjoerg /* incompatible types in conditional */ 107112099Sjoerg warning(126); 107212099Sjoerg break; 107312099Sjoerg } 107412099Sjoerg 107512099Sjoerg if (lt == PTR && rt == PTR && ((lst == VOID && rst == FUNC) || 107612099Sjoerg (lst == FUNC && rst == VOID))) { 107712099Sjoerg /* (void *)0 handled above */ 107812099Sjoerg if (sflag) 107912099Sjoerg /* ANSI C forbids conv. of %s to %s, op %s */ 108012099Sjoerg warning(305, "function pointer", "'void *'", 108112099Sjoerg mp->m_name); 108212099Sjoerg break; 108312099Sjoerg } 108412099Sjoerg 108512099Sjoerg if (rt == PTR && lt == PTR) { 108612099Sjoerg if (!eqtype(lstp, rstp, 1, 0, NULL)) 108712099Sjoerg illptrc(mp, ltp, rtp); 108812099Sjoerg break; 108912099Sjoerg } 109012099Sjoerg 109112099Sjoerg /* incompatible types in conditional */ 109212099Sjoerg error(126); 109312099Sjoerg return (0); 109412099Sjoerg 109512099Sjoerg case ASSIGN: 109612099Sjoerg case INIT: 109712099Sjoerg case FARG: 109812099Sjoerg case RETURN: 109912099Sjoerg if (!asgntypok(op, arg, ln, rn)) 110012099Sjoerg return (0); 110112099Sjoerg goto assign; 110212099Sjoerg case MULASS: 110312099Sjoerg case DIVASS: 110412099Sjoerg case MODASS: 110512099Sjoerg goto assign; 110612099Sjoerg case ADDASS: 110712099Sjoerg case SUBASS: 110812099Sjoerg /* operands have scalar types (checked above) */ 110912099Sjoerg if ((lt == PTR && !isityp(rt)) || rt == PTR) { 111012099Sjoerg incompat(op, lt, rt); 111112099Sjoerg return (0); 111212099Sjoerg } 111312099Sjoerg goto assign; 111412099Sjoerg case SHLASS: 111512099Sjoerg goto assign; 111612099Sjoerg case SHRASS: 111712099Sjoerg if (pflag && !isutyp(lt) && !(tflag && isutyp(rt))) { 111812099Sjoerg /* bitwise operation on s.v. possibly nonportabel */ 111912099Sjoerg warning(117); 112012099Sjoerg } 112112099Sjoerg goto assign; 112212099Sjoerg case ANDASS: 112312099Sjoerg case XORASS: 112412099Sjoerg case ORASS: 112512099Sjoerg goto assign; 112612099Sjoerg assign: 112712099Sjoerg if (!ln->tn_lvalue) { 112812099Sjoerg if (ln->tn_op == CVT && ln->tn_cast && 112912099Sjoerg ln->tn_left->tn_op == LOAD) { 113012099Sjoerg /* a cast does not yield an lvalue */ 113112099Sjoerg error(163); 113212099Sjoerg } 113312099Sjoerg /* %soperand of %s must be lvalue */ 113412099Sjoerg error(114, "left ", mp->m_name); 113512099Sjoerg return (0); 113612099Sjoerg } else if (ltp->t_const || ((lt == STRUCT || lt == UNION) && 113712099Sjoerg conmemb(ltp))) { 113812099Sjoerg /* %soperand of %s must be modifiable lvalue */ 113912099Sjoerg if (!tflag) 114012099Sjoerg warning(115, "left ", mp->m_name); 114112099Sjoerg } 114212099Sjoerg break; 114312099Sjoerg case COMMA: 114412099Sjoerg if (!modtab[ln->tn_op].m_sideeff) 114512099Sjoerg nulleff(ln); 114612099Sjoerg break; 114712099Sjoerg /* LINTED (enumeration values not handled in switch) */ 114891592Smarkm case CON: 114991592Smarkm case CASE: 115091592Smarkm case PUSH: 115191592Smarkm case LOAD: 115291592Smarkm case ICALL: 115391592Smarkm case CVT: 115491592Smarkm case CALL: 115591592Smarkm case FSEL: 115691592Smarkm case STRING: 115791592Smarkm case NAME: 115891592Smarkm case LOGOR: 115991592Smarkm case LOGAND: 116091592Smarkm case OR: 116191592Smarkm case XOR: 116291592Smarkm case AND: 116391592Smarkm case MOD: 116491592Smarkm case DIV: 116591592Smarkm case MULT: 116691592Smarkm case UMINUS: 116791592Smarkm case UPLUS: 116891592Smarkm case DEC: 116991592Smarkm case INC: 117091592Smarkm case COMPL: 117191592Smarkm case NOT: 117291592Smarkm case NOOP: 117391592Smarkm break; 117412099Sjoerg } 117512099Sjoerg 117612099Sjoerg if (mp->m_badeop && 117712099Sjoerg (ltp->t_isenum || (mp->m_binary && rtp->t_isenum))) { 117812099Sjoerg chkbeop(op, ln, rn); 1179281168Spfg } else if (mp->m_enumop && (ltp->t_isenum && rtp && rtp->t_isenum)) { 118012099Sjoerg chkeop2(op, arg, ln, rn); 1181281168Spfg } else if (mp->m_enumop && (ltp->t_isenum || (rtp &&rtp->t_isenum))) { 118212099Sjoerg chkeop1(op, arg, ln, rn); 118312099Sjoerg } 118412099Sjoerg 118512099Sjoerg return (1); 118612099Sjoerg} 118712099Sjoerg 118812099Sjoergstatic void 118991592Smarkmptrcmpok(op_t op, tnode_t *ln, tnode_t *rn) 119012099Sjoerg{ 119112099Sjoerg type_t *ltp, *rtp; 119212099Sjoerg tspec_t lt, rt; 119312099Sjoerg const char *lts, *rts; 119412099Sjoerg 119512099Sjoerg lt = (ltp = ln->tn_type)->t_subt->t_tspec; 119612099Sjoerg rt = (rtp = rn->tn_type)->t_subt->t_tspec; 119712099Sjoerg 119812099Sjoerg if (lt == VOID || rt == VOID) { 119912099Sjoerg if (sflag && (lt == FUNC || rt == FUNC)) { 120012099Sjoerg /* (void *)0 already handled in typeok() */ 120112099Sjoerg *(lt == FUNC ? <s : &rts) = "function pointer"; 120212099Sjoerg *(lt == VOID ? <s : &rts) = "'void *'"; 120375697Sasmodai /* ANSI C forbids comparison of %s with %s */ 120412099Sjoerg warning(274, lts, rts); 120512099Sjoerg } 120612099Sjoerg return; 120712099Sjoerg } 120812099Sjoerg 120912099Sjoerg if (!eqtype(ltp->t_subt, rtp->t_subt, 1, 0, NULL)) { 121012099Sjoerg illptrc(&modtab[op], ltp, rtp); 121112099Sjoerg return; 121212099Sjoerg } 121312099Sjoerg 121412099Sjoerg if (lt == FUNC && rt == FUNC) { 121512099Sjoerg if (sflag && op != EQ && op != NE) 121612099Sjoerg /* ANSI C forbids ordered comp. of func ptr */ 121712099Sjoerg warning(125); 121812099Sjoerg } 121912099Sjoerg} 122012099Sjoerg 122112099Sjoerg/* 122212099Sjoerg * Checks type compatibility for ASSIGN, INIT, FARG and RETURN 122312099Sjoerg * and prints warnings/errors if necessary. 122412099Sjoerg * If the types are (almost) compatible, 1 is returned, otherwise 0. 122512099Sjoerg */ 122612099Sjoergstatic int 122791592Smarkmasgntypok(op_t op, int arg, tnode_t *ln, tnode_t *rn) 122812099Sjoerg{ 122991592Smarkm tspec_t lt, rt, lst = NOTSPEC, rst = NOTSPEC; 123091592Smarkm type_t *ltp, *rtp, *lstp = NULL, *rstp = NULL; 123112099Sjoerg mod_t *mp; 123212099Sjoerg const char *lts, *rts; 123312099Sjoerg 123412099Sjoerg if ((lt = (ltp = ln->tn_type)->t_tspec) == PTR) 123512099Sjoerg lst = (lstp = ltp->t_subt)->t_tspec; 123612099Sjoerg if ((rt = (rtp = rn->tn_type)->t_tspec) == PTR) 123712099Sjoerg rst = (rstp = rtp->t_subt)->t_tspec; 123812099Sjoerg mp = &modtab[op]; 123912099Sjoerg 124012099Sjoerg if (isatyp(lt) && isatyp(rt)) 124112099Sjoerg return (1); 124212099Sjoerg 124312099Sjoerg if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION)) 124412099Sjoerg /* both are struct or union */ 124512099Sjoerg return (ltp->t_str == rtp->t_str); 124612099Sjoerg 124712099Sjoerg /* 0, 0L and (void *)0 may be assigned to any pointer */ 124812099Sjoerg if (lt == PTR && ((rt == PTR && rst == VOID) || isityp(rt))) { 124912099Sjoerg if (rn->tn_op == CON && rn->tn_val->v_quad == 0) 125012099Sjoerg return (1); 125112099Sjoerg } 125212099Sjoerg 125312099Sjoerg if (lt == PTR && rt == PTR && (lst == VOID || rst == VOID)) { 125412099Sjoerg /* two pointers, at least one pointer to void */ 125512099Sjoerg if (sflag && (lst == FUNC || rst == FUNC)) { 125612099Sjoerg /* comb. of ptr to func and ptr to void */ 125712099Sjoerg *(lst == FUNC ? <s : &rts) = "function pointer"; 125812099Sjoerg *(lst == VOID ? <s : &rts) = "'void *'"; 125912099Sjoerg switch (op) { 126012099Sjoerg case INIT: 126112099Sjoerg case RETURN: 126212099Sjoerg /* ANSI C forbids conversion of %s to %s */ 126312099Sjoerg warning(303, rts, lts); 126412099Sjoerg break; 126512099Sjoerg case FARG: 126612099Sjoerg /* ANSI C forbids conv. of %s to %s, arg #%d */ 126712099Sjoerg warning(304, rts, lts, arg); 126812099Sjoerg break; 126912099Sjoerg default: 127012099Sjoerg /* ANSI C forbids conv. of %s to %s, op %s */ 127112099Sjoerg warning(305, rts, lts, mp->m_name); 127212099Sjoerg break; 127312099Sjoerg } 127412099Sjoerg } 127512099Sjoerg } 127612099Sjoerg 127712099Sjoerg if (lt == PTR && rt == PTR && (lst == VOID || rst == VOID || 127812099Sjoerg eqtype(lstp, rstp, 1, 0, NULL))) { 127912099Sjoerg /* compatible pointer types (qualifiers ignored) */ 128012099Sjoerg if (!tflag && 128112099Sjoerg ((!lstp->t_const && rstp->t_const) || 128212099Sjoerg (!lstp->t_volatile && rstp->t_volatile))) { 128312099Sjoerg /* left side has not all qualifiers of right */ 128412099Sjoerg switch (op) { 128512099Sjoerg case INIT: 128612099Sjoerg case RETURN: 128712099Sjoerg /* incompatible pointer types */ 128812099Sjoerg warning(182); 128912099Sjoerg break; 129012099Sjoerg case FARG: 129112099Sjoerg /* argument has incompat. ptr. type, arg #%d */ 129212099Sjoerg warning(153, arg); 129312099Sjoerg break; 129412099Sjoerg default: 129512099Sjoerg /* operands have incompat. ptr. types, op %s */ 129612099Sjoerg warning(128, mp->m_name); 129712099Sjoerg break; 129812099Sjoerg } 129912099Sjoerg } 130012099Sjoerg return (1); 130112099Sjoerg } 130212099Sjoerg 130312099Sjoerg if ((lt == PTR && isityp(rt)) || (isityp(lt) && rt == PTR)) { 130412099Sjoerg switch (op) { 130512099Sjoerg case INIT: 130612099Sjoerg case RETURN: 130712099Sjoerg /* illegal combination of pointer and integer */ 130812099Sjoerg warning(183); 130912099Sjoerg break; 131012099Sjoerg case FARG: 131112099Sjoerg /* illegal comb. of ptr. and int., arg #%d */ 131212099Sjoerg warning(154, arg); 131312099Sjoerg break; 131412099Sjoerg default: 131512099Sjoerg /* illegal comb. of ptr. and int., op %s */ 131612099Sjoerg warning(123, mp->m_name); 131712099Sjoerg break; 131812099Sjoerg } 131912099Sjoerg return (1); 132012099Sjoerg } 132112099Sjoerg 132212099Sjoerg if (lt == PTR && rt == PTR) { 132312099Sjoerg switch (op) { 132412099Sjoerg case INIT: 132512099Sjoerg case RETURN: 132612099Sjoerg illptrc(NULL, ltp, rtp); 132712099Sjoerg break; 132812099Sjoerg case FARG: 132912099Sjoerg /* argument has incompatible pointer type, arg #%d */ 133012099Sjoerg warning(153, arg); 133112099Sjoerg break; 133212099Sjoerg default: 133312099Sjoerg illptrc(mp, ltp, rtp); 133412099Sjoerg break; 133512099Sjoerg } 133612099Sjoerg return (1); 133712099Sjoerg } 133812099Sjoerg 133912099Sjoerg switch (op) { 134012099Sjoerg case INIT: 134112099Sjoerg /* initialisation type mismatch */ 134212099Sjoerg error(185); 134312099Sjoerg break; 134412099Sjoerg case RETURN: 134512099Sjoerg /* return value type mismatch */ 134612099Sjoerg error(211); 134712099Sjoerg break; 134812099Sjoerg case FARG: 134912099Sjoerg /* argument is incompatible with prototype, arg #%d */ 135012099Sjoerg warning(155, arg); 135112099Sjoerg break; 135212099Sjoerg default: 135312099Sjoerg incompat(op, lt, rt); 135412099Sjoerg break; 135512099Sjoerg } 135612099Sjoerg 135712099Sjoerg return (0); 135812099Sjoerg} 135912099Sjoerg 136012099Sjoerg/* 136112099Sjoerg * Prints a warning if an operator, which should be senseless for an 136212099Sjoerg * enum type, is applied to an enum type. 136312099Sjoerg */ 136412099Sjoergstatic void 136591592Smarkmchkbeop(op_t op, tnode_t *ln, tnode_t *rn) 136612099Sjoerg{ 136712099Sjoerg mod_t *mp; 136812099Sjoerg 136912099Sjoerg if (!eflag) 137012099Sjoerg return; 137112099Sjoerg 137212099Sjoerg mp = &modtab[op]; 137312099Sjoerg 137412099Sjoerg if (!(ln->tn_type->t_isenum || 137512099Sjoerg (mp->m_binary && rn->tn_type->t_isenum))) { 137612099Sjoerg return; 137712099Sjoerg } 137812099Sjoerg 137912099Sjoerg /* 138012099Sjoerg * Enum as offset to a pointer is an exception (otherwise enums 138112099Sjoerg * could not be used as array indizes). 138212099Sjoerg */ 138312099Sjoerg if (op == PLUS && 138412099Sjoerg ((ln->tn_type->t_isenum && rn->tn_type->t_tspec == PTR) || 138512099Sjoerg (rn->tn_type->t_isenum && ln->tn_type->t_tspec == PTR))) { 138612099Sjoerg return; 138712099Sjoerg } 138812099Sjoerg 138912099Sjoerg /* dubious operation on enum, op %s */ 139012099Sjoerg warning(241, mp->m_name); 139112099Sjoerg 139212099Sjoerg} 139312099Sjoerg 139412099Sjoerg/* 139512099Sjoerg * Prints a warning if an operator is applied to two different enum types. 139612099Sjoerg */ 139712099Sjoergstatic void 139891592Smarkmchkeop2(op_t op, int arg, tnode_t *ln, tnode_t *rn) 139912099Sjoerg{ 140012099Sjoerg mod_t *mp; 140112099Sjoerg 140212099Sjoerg mp = &modtab[op]; 140312099Sjoerg 140412099Sjoerg if (ln->tn_type->t_enum != rn->tn_type->t_enum) { 140512099Sjoerg switch (op) { 140612099Sjoerg case INIT: 140712099Sjoerg /* enum type mismatch in initialisation */ 140812099Sjoerg warning(210); 140912099Sjoerg break; 141012099Sjoerg case FARG: 141112099Sjoerg /* enum type mismatch, arg #%d */ 141212099Sjoerg warning(156, arg); 141312099Sjoerg break; 141412099Sjoerg case RETURN: 141512099Sjoerg /* return value type mismatch */ 141612099Sjoerg warning(211); 141712099Sjoerg break; 141812099Sjoerg default: 141912099Sjoerg /* enum type mismatch, op %s */ 142012099Sjoerg warning(130, mp->m_name); 142112099Sjoerg break; 142212099Sjoerg } 142312099Sjoerg#if 0 142412099Sjoerg } else if (mp->m_comp && op != EQ && op != NE) { 142512099Sjoerg if (eflag) 142675697Sasmodai /* dubious comparisons of enums */ 142712099Sjoerg warning(243, mp->m_name); 142812099Sjoerg#endif 142912099Sjoerg } 143012099Sjoerg} 143112099Sjoerg 143212099Sjoerg/* 143312099Sjoerg * Prints a warning if an operator has both enum end other integer 143412099Sjoerg * types. 143512099Sjoerg */ 143612099Sjoergstatic void 143791592Smarkmchkeop1(op_t op, int arg, tnode_t *ln, tnode_t *rn) 143812099Sjoerg{ 1439281168Spfg char lbuf[64], rbuf[64]; 144091592Smarkm 144112099Sjoerg if (!eflag) 144212099Sjoerg return; 144312099Sjoerg 144412099Sjoerg switch (op) { 144512099Sjoerg case INIT: 144612099Sjoerg /* 144712099Sjoerg * Initializations with 0 should be allowed. Otherwise, 144812099Sjoerg * we should complain about all uninitialized enums, 144912099Sjoerg * consequently. 145012099Sjoerg */ 145112099Sjoerg if (!rn->tn_type->t_isenum && rn->tn_op == CON && 145212099Sjoerg isityp(rn->tn_type->t_tspec) && rn->tn_val->v_quad == 0) { 145312099Sjoerg return; 145412099Sjoerg } 145512099Sjoerg /* initialisation of '%s' with '%s' */ 1456281168Spfg warning(277, tyname(lbuf, sizeof(lbuf), ln->tn_type), 1457281168Spfg tyname(rbuf, sizeof(rbuf), rn->tn_type)); 145812099Sjoerg break; 145912099Sjoerg case FARG: 146012099Sjoerg /* combination of '%s' and '%s', arg #%d */ 1461281168Spfg warning(278, tyname(lbuf, sizeof(lbuf), ln->tn_type), 1462281168Spfg tyname(rbuf, sizeof(rbuf), rn->tn_type), arg); 146312099Sjoerg break; 146412099Sjoerg case RETURN: 146512099Sjoerg /* combination of '%s' and '%s' in return */ 1466281168Spfg warning(279, tyname(lbuf, sizeof(lbuf), ln->tn_type), 1467281168Spfg tyname(rbuf, sizeof(rbuf), rn->tn_type)); 146812099Sjoerg break; 146912099Sjoerg default: 147012099Sjoerg /* combination of '%s' and %s, op %s */ 1471281168Spfg warning(242, tyname(lbuf, sizeof(lbuf), ln->tn_type), 1472281168Spfg tyname(rbuf, sizeof(rbuf), rn->tn_type), 1473281168Spfg modtab[op].m_name); 147412099Sjoerg break; 147512099Sjoerg } 147612099Sjoerg} 147712099Sjoerg 147812099Sjoerg/* 147912099Sjoerg * Build and initialize a new node. 148012099Sjoerg */ 148112099Sjoergstatic tnode_t * 148291592Smarkmmktnode(op_t op, type_t *type, tnode_t *ln, tnode_t *rn) 148312099Sjoerg{ 148412099Sjoerg tnode_t *ntn; 148512099Sjoerg tspec_t t; 148612099Sjoerg 148712099Sjoerg ntn = getnode(); 148812099Sjoerg 148912099Sjoerg ntn->tn_op = op; 149012099Sjoerg ntn->tn_type = type; 149112099Sjoerg ntn->tn_left = ln; 149212099Sjoerg ntn->tn_right = rn; 149312099Sjoerg 149412099Sjoerg if (op == STAR || op == FSEL) { 149512099Sjoerg if (ln->tn_type->t_tspec == PTR) { 149612099Sjoerg t = ln->tn_type->t_subt->t_tspec; 149712099Sjoerg if (t != FUNC && t != VOID) 149812099Sjoerg ntn->tn_lvalue = 1; 149912099Sjoerg } else { 1500281168Spfg LERROR("mktnode()"); 150112099Sjoerg } 150212099Sjoerg } 150312099Sjoerg 150412099Sjoerg return (ntn); 150512099Sjoerg} 150612099Sjoerg 150712099Sjoerg/* 150812099Sjoerg * Performs usual conversion of operands to (unsigned) int. 150912099Sjoerg * 151012099Sjoerg * If tflag is set or the operand is a function argument with no 151112099Sjoerg * type information (no prototype or variable # of args), convert 151212099Sjoerg * float to double. 151312099Sjoerg */ 151412099Sjoergtnode_t * 151591592Smarkmpromote(op_t op, int farg, tnode_t *tn) 151612099Sjoerg{ 151712099Sjoerg tspec_t t; 151812099Sjoerg type_t *ntp; 151912099Sjoerg int len; 152012099Sjoerg 152112099Sjoerg t = tn->tn_type->t_tspec; 152212099Sjoerg 152312099Sjoerg if (!isatyp(t)) 152412099Sjoerg return (tn); 152512099Sjoerg 152612099Sjoerg if (!tflag) { 152712099Sjoerg /* 152812099Sjoerg * ANSI C requires that the result is always of type INT 152912099Sjoerg * if INT can represent all possible values of the previous 153012099Sjoerg * type. 153112099Sjoerg */ 153212099Sjoerg if (tn->tn_type->t_isfield) { 153312099Sjoerg len = tn->tn_type->t_flen; 153412099Sjoerg if (size(INT) > len) { 153512099Sjoerg t = INT; 153612099Sjoerg } else { 153712099Sjoerg if (size(INT) != len) 1538281168Spfg LERROR("promote()"); 153912099Sjoerg if (isutyp(t)) { 154012099Sjoerg t = UINT; 154112099Sjoerg } else { 154212099Sjoerg t = INT; 154312099Sjoerg } 154412099Sjoerg } 154512099Sjoerg } else if (t == CHAR || t == UCHAR || t == SCHAR) { 154612099Sjoerg t = (size(CHAR) < size(INT) || t != UCHAR) ? 154712099Sjoerg INT : UINT; 154812099Sjoerg } else if (t == SHORT || t == USHORT) { 154912099Sjoerg t = (size(SHORT) < size(INT) || t == SHORT) ? 155012099Sjoerg INT : UINT; 155112099Sjoerg } else if (t == ENUM) { 155212099Sjoerg t = INT; 155312099Sjoerg } else if (farg && t == FLOAT) { 155412099Sjoerg t = DOUBLE; 155512099Sjoerg } 155612099Sjoerg } else { 155712099Sjoerg /* 155812099Sjoerg * In traditional C, keep unsigned and promote FLOAT 155912099Sjoerg * to DOUBLE. 156012099Sjoerg */ 156112099Sjoerg if (t == UCHAR || t == USHORT) { 156212099Sjoerg t = UINT; 156312099Sjoerg } else if (t == CHAR || t == SCHAR || t == SHORT) { 156412099Sjoerg t = INT; 156512099Sjoerg } else if (t == FLOAT) { 156612099Sjoerg t = DOUBLE; 156712099Sjoerg } else if (t == ENUM) { 156812099Sjoerg t = INT; 156912099Sjoerg } 157012099Sjoerg } 157112099Sjoerg 157212099Sjoerg if (t != tn->tn_type->t_tspec) { 157312099Sjoerg ntp = tduptyp(tn->tn_type); 157412099Sjoerg ntp->t_tspec = t; 157512099Sjoerg /* 157612099Sjoerg * Keep t_isenum so we are later able to check compatibility 157712099Sjoerg * of enum types. 157812099Sjoerg */ 157912099Sjoerg tn = convert(op, 0, ntp, tn); 158012099Sjoerg } 158112099Sjoerg 158212099Sjoerg return (tn); 158312099Sjoerg} 158412099Sjoerg 158512099Sjoerg/* 158612099Sjoerg * Insert conversions which are necessary to give both operands the same 158712099Sjoerg * type. This is done in different ways for traditional C and ANIS C. 158812099Sjoerg */ 158912099Sjoergstatic void 159091592Smarkmbalance(op_t op, tnode_t **lnp, tnode_t **rnp) 159112099Sjoerg{ 159212099Sjoerg tspec_t lt, rt, t; 159312099Sjoerg int i, u; 159412099Sjoerg type_t *ntp; 159512099Sjoerg static tspec_t tl[] = { 159612099Sjoerg LDOUBLE, DOUBLE, FLOAT, UQUAD, QUAD, ULONG, LONG, UINT, INT, 159712099Sjoerg }; 159812099Sjoerg 159912099Sjoerg lt = (*lnp)->tn_type->t_tspec; 160012099Sjoerg rt = (*rnp)->tn_type->t_tspec; 160112099Sjoerg 160212099Sjoerg if (!isatyp(lt) || !isatyp(rt)) 160312099Sjoerg return; 160412099Sjoerg 160512099Sjoerg if (!tflag) { 160612099Sjoerg if (lt == rt) { 160712099Sjoerg t = lt; 160812099Sjoerg } else if (lt == LDOUBLE || rt == LDOUBLE) { 160912099Sjoerg t = LDOUBLE; 161012099Sjoerg } else if (lt == DOUBLE || rt == DOUBLE) { 161112099Sjoerg t = DOUBLE; 161212099Sjoerg } else if (lt == FLOAT || rt == FLOAT) { 161312099Sjoerg t = FLOAT; 161412099Sjoerg } else { 161512099Sjoerg /* 161612099Sjoerg * If type A has more bits than type B it should 161712099Sjoerg * be able to hold all possible values of type B. 161812099Sjoerg */ 161912099Sjoerg if (size(lt) > size(rt)) { 162012099Sjoerg t = lt; 162112099Sjoerg } else if (size(lt) < size(rt)) { 162212099Sjoerg t = rt; 162312099Sjoerg } else { 162412099Sjoerg for (i = 3; tl[i] != INT; i++) { 162512099Sjoerg if (tl[i] == lt || tl[i] == rt) 162612099Sjoerg break; 162712099Sjoerg } 162812099Sjoerg if ((isutyp(lt) || isutyp(rt)) && 162912099Sjoerg !isutyp(tl[i])) { 163012099Sjoerg i--; 163112099Sjoerg } 163212099Sjoerg t = tl[i]; 163312099Sjoerg } 163412099Sjoerg } 163512099Sjoerg } else { 163612099Sjoerg /* Keep unsigned in traditional C */ 163712099Sjoerg u = isutyp(lt) || isutyp(rt); 163812099Sjoerg for (i = 0; tl[i] != INT; i++) { 163912099Sjoerg if (lt == tl[i] || rt == tl[i]) 164012099Sjoerg break; 164112099Sjoerg } 164212099Sjoerg t = tl[i]; 164312099Sjoerg if (u && isityp(t) && !isutyp(t)) 164412099Sjoerg t = utyp(t); 164512099Sjoerg } 164612099Sjoerg 164712099Sjoerg if (t != lt) { 164812099Sjoerg ntp = tduptyp((*lnp)->tn_type); 164912099Sjoerg ntp->t_tspec = t; 165012099Sjoerg *lnp = convert(op, 0, ntp, *lnp); 165112099Sjoerg } 165212099Sjoerg if (t != rt) { 165312099Sjoerg ntp = tduptyp((*rnp)->tn_type); 165412099Sjoerg ntp->t_tspec = t; 165512099Sjoerg *rnp = convert(op, 0, ntp, *rnp); 165612099Sjoerg } 165712099Sjoerg} 165812099Sjoerg 165912099Sjoerg/* 166012099Sjoerg * Insert a conversion operator, which converts the type of the node 166112099Sjoerg * to another given type. 166212099Sjoerg * If op is FARG, arg is the number of the argument (used for warnings). 166312099Sjoerg */ 166412099Sjoergtnode_t * 166591592Smarkmconvert(op_t op, int arg, type_t *tp, tnode_t *tn) 166612099Sjoerg{ 166712099Sjoerg tnode_t *ntn; 166891592Smarkm tspec_t nt, ot, ost = NOTSPEC; 166912099Sjoerg 167012099Sjoerg if (tn->tn_lvalue) 1671281168Spfg LERROR("convert()"); 167212099Sjoerg 167312099Sjoerg nt = tp->t_tspec; 167412099Sjoerg if ((ot = tn->tn_type->t_tspec) == PTR) 167512099Sjoerg ost = tn->tn_type->t_subt->t_tspec; 167612099Sjoerg 167712099Sjoerg if (!tflag && !sflag && op == FARG) 167812099Sjoerg ptconv(arg, nt, ot, tp, tn); 167912099Sjoerg if (isityp(nt) && isityp(ot)) { 168012099Sjoerg iiconv(op, arg, nt, ot, tp, tn); 168112099Sjoerg } else if (nt == PTR && ((ot == PTR && ost == VOID) || isityp(ot)) && 168212099Sjoerg tn->tn_op == CON && tn->tn_val->v_quad == 0) { 168312099Sjoerg /* 0, 0L and (void *)0 may be assigned to any pointer. */ 168412099Sjoerg } else if (isityp(nt) && ot == PTR) { 168512099Sjoerg piconv(op, nt, tp, tn); 168612099Sjoerg } else if (nt == PTR && ot == PTR) { 168712099Sjoerg ppconv(op, tn, tp); 168812099Sjoerg } 168912099Sjoerg 169012099Sjoerg ntn = getnode(); 169112099Sjoerg ntn->tn_op = CVT; 169212099Sjoerg ntn->tn_type = tp; 169312099Sjoerg ntn->tn_cast = op == CVT; 169412099Sjoerg if (tn->tn_op != CON || nt == VOID) { 169512099Sjoerg ntn->tn_left = tn; 169612099Sjoerg } else { 169712099Sjoerg ntn->tn_op = CON; 169812099Sjoerg ntn->tn_val = tgetblk(sizeof (val_t)); 169912099Sjoerg cvtcon(op, arg, ntn->tn_type, ntn->tn_val, tn->tn_val); 170012099Sjoerg } 170112099Sjoerg 170212099Sjoerg return (ntn); 170312099Sjoerg} 170412099Sjoerg 170512099Sjoerg/* 170612099Sjoerg * Print a warning if a prototype causes a type conversion that is 170712099Sjoerg * different from what would happen to the same argument in the 170812099Sjoerg * absence of a prototype. 170912099Sjoerg * 171012099Sjoerg * Errors/Warnings about illegal type combinations are already printed 171112099Sjoerg * in asgntypok(). 171212099Sjoerg */ 171312099Sjoergstatic void 171491592Smarkmptconv(int arg, tspec_t nt, tspec_t ot, type_t *tp, tnode_t *tn) 171512099Sjoerg{ 171612099Sjoerg tnode_t *ptn; 1717281168Spfg char buf[64]; 171812099Sjoerg 171912099Sjoerg if (!isatyp(nt) || !isatyp(ot)) 172012099Sjoerg return; 172112099Sjoerg 172212099Sjoerg /* 172312099Sjoerg * If the type of the formal parameter is char/short, a warning 172412099Sjoerg * would be useless, because functions declared the old style 172512099Sjoerg * can't expect char/short arguments. 172612099Sjoerg */ 172712099Sjoerg if (nt == CHAR || nt == UCHAR || nt == SHORT || nt == USHORT) 172812099Sjoerg return; 172912099Sjoerg 173012099Sjoerg /* get default promotion */ 173112099Sjoerg ptn = promote(NOOP, 1, tn); 173212099Sjoerg ot = ptn->tn_type->t_tspec; 173312099Sjoerg 173412099Sjoerg /* return if types are the same with and without prototype */ 173512099Sjoerg if (nt == ot || (nt == ENUM && ot == INT)) 173612099Sjoerg return; 173712099Sjoerg 173812099Sjoerg if (isftyp(nt) != isftyp(ot) || psize(nt) != psize(ot)) { 173912099Sjoerg /* representation and/or width change */ 1740281168Spfg if (!isityp(ot) || psize(ot) > psize(INT)) { 174112099Sjoerg /* conversion to '%s' due to prototype, arg #%d */ 1742281168Spfg warning(259, tyname(buf, sizeof(buf), tp), arg); 1743281168Spfg } 174412099Sjoerg } else if (hflag) { 174512099Sjoerg /* 174612099Sjoerg * they differ in sign or base type (char, short, int, 174712099Sjoerg * long, long long, float, double, long double) 174812099Sjoerg * 174912099Sjoerg * if they differ only in sign and the argument is a constant 175012099Sjoerg * and the msb of the argument is not set, print no warning 175112099Sjoerg */ 175212099Sjoerg if (ptn->tn_op == CON && isityp(nt) && styp(nt) == styp(ot) && 175312099Sjoerg msb(ptn->tn_val->v_quad, ot, -1) == 0) { 175412099Sjoerg /* ok */ 175512099Sjoerg } else { 175612099Sjoerg /* conversion to '%s' due to prototype, arg #%d */ 1757281168Spfg warning(259, tyname(buf, sizeof(buf), tp), arg); 175812099Sjoerg } 175912099Sjoerg } 176012099Sjoerg} 176112099Sjoerg 176212099Sjoerg/* 176312099Sjoerg * Print warnings for conversions of integer types which my cause 176412099Sjoerg * problems. 176512099Sjoerg */ 176612099Sjoerg/* ARGSUSED */ 176712099Sjoergstatic void 176891592Smarkmiiconv(op_t op, int arg, tspec_t nt, tspec_t ot, type_t *tp, tnode_t *tn) 176912099Sjoerg{ 1770281168Spfg char lbuf[64], rbuf[64]; 177112099Sjoerg if (tn->tn_op == CON) 177212099Sjoerg return; 177312099Sjoerg 177412099Sjoerg if (op == CVT) 177512099Sjoerg return; 177612099Sjoerg 177712099Sjoerg#if 0 177812099Sjoerg if (psize(nt) > psize(ot) && isutyp(nt) != isutyp(ot)) { 177912099Sjoerg /* conversion to %s may sign-extend incorrectly (, arg #%d) */ 178012099Sjoerg if (aflag && pflag) { 178112099Sjoerg if (op == FARG) { 1782281168Spfg warning(297, tyname(lbuf, sizeof(lbuf), tp), 1783281168Spfg arg); 178412099Sjoerg } else { 1785281168Spfg warning(131, tyname(lbuf, sizeof(lbuf), tp)); 178612099Sjoerg } 178712099Sjoerg } 178812099Sjoerg } 178912099Sjoerg#endif 179012099Sjoerg 179112099Sjoerg if (psize(nt) < psize(ot) && 179212099Sjoerg (ot == LONG || ot == ULONG || ot == QUAD || ot == UQUAD || 179312099Sjoerg aflag > 1)) { 179412099Sjoerg /* conversion from '%s' may lose accuracy */ 179512099Sjoerg if (aflag) { 179612099Sjoerg if (op == FARG) { 1797281168Spfg warning(298, 1798281168Spfg tyname(rbuf, sizeof(rbuf), tn->tn_type), 1799281168Spfg tyname(lbuf, sizeof(lbuf), tp), 1800281168Spfg arg); 180112099Sjoerg } else { 1802281168Spfg warning(132, 1803281168Spfg tyname(rbuf, sizeof(rbuf), tn->tn_type), 1804281168Spfg tyname(lbuf, sizeof(lbuf), tp)); 180512099Sjoerg } 180691592Smarkm } 180712099Sjoerg } 180812099Sjoerg} 180912099Sjoerg 181012099Sjoerg/* 181112099Sjoerg * Print warnings for dubious conversions of pointer to integer. 181212099Sjoerg */ 181312099Sjoergstatic void 181491592Smarkmpiconv(op_t op, tspec_t nt, type_t *tp, tnode_t *tn) 181512099Sjoerg{ 1816281168Spfg char buf[64]; 181791592Smarkm 181812099Sjoerg if (tn->tn_op == CON) 181912099Sjoerg return; 182012099Sjoerg 182112099Sjoerg if (op != CVT) { 182212099Sjoerg /* We got already an error. */ 182312099Sjoerg return; 182412099Sjoerg } 182512099Sjoerg 182612099Sjoerg if (psize(nt) < psize(PTR)) { 182712099Sjoerg if (pflag && size(nt) >= size(PTR)) { 182812099Sjoerg /* conv. of pointer to %s may lose bits */ 1829281168Spfg warning(134, tyname(buf, sizeof(buf), tp)); 183012099Sjoerg } else { 183112099Sjoerg /* conv. of pointer to %s loses bits */ 1832281168Spfg warning(133, tyname(buf, sizeof(buf), tp)); 183312099Sjoerg } 183412099Sjoerg } 183512099Sjoerg} 183612099Sjoerg 183712099Sjoerg/* 183812099Sjoerg * Print warnings for questionable pointer conversions. 183912099Sjoerg */ 184012099Sjoergstatic void 184191592Smarkmppconv(op_t op, tnode_t *tn, type_t *tp) 184212099Sjoerg{ 184312099Sjoerg tspec_t nt, ot; 184412099Sjoerg const char *nts, *ots; 184512099Sjoerg 184612099Sjoerg /* 184712099Sjoerg * We got already an error (pointers of different types 184812099Sjoerg * without a cast) or we will not get a warning. 184912099Sjoerg */ 185012099Sjoerg if (op != CVT) 185112099Sjoerg return; 185212099Sjoerg 185312099Sjoerg nt = tp->t_subt->t_tspec; 185412099Sjoerg ot = tn->tn_type->t_subt->t_tspec; 185512099Sjoerg 185612099Sjoerg if (nt == VOID || ot == VOID) { 185712099Sjoerg if (sflag && (nt == FUNC || ot == FUNC)) { 185812099Sjoerg /* (void *)0 already handled in convert() */ 185912099Sjoerg *(nt == FUNC ? &nts : &ots) = "function pointer"; 186012099Sjoerg *(nt == VOID ? &nts : &ots) = "'void *'"; 186112099Sjoerg /* ANSI C forbids conversion of %s to %s */ 186212099Sjoerg warning(303, ots, nts); 186312099Sjoerg } 186412099Sjoerg return; 186512099Sjoerg } else if (nt == FUNC && ot == FUNC) { 186612099Sjoerg return; 186712099Sjoerg } else if (nt == FUNC || ot == FUNC) { 186812099Sjoerg /* questionable conversion of function pointer */ 186912099Sjoerg warning(229); 187012099Sjoerg return; 187112099Sjoerg } 187291592Smarkm 187312099Sjoerg if (getbound(tp->t_subt) > getbound(tn->tn_type->t_subt)) { 187412099Sjoerg if (hflag) 187512099Sjoerg /* possible pointer alignment problem */ 187612099Sjoerg warning(135); 187712099Sjoerg } 187812099Sjoerg if (((nt == STRUCT || nt == UNION) && 187912099Sjoerg tp->t_subt->t_str != tn->tn_type->t_subt->t_str) || 188012099Sjoerg psize(nt) != psize(ot)) { 188112099Sjoerg if (cflag) { 188212099Sjoerg /* pointer casts may be troublesome */ 188312099Sjoerg warning(247); 188412099Sjoerg } 188512099Sjoerg } 188612099Sjoerg} 188712099Sjoerg 188812099Sjoerg/* 188912099Sjoerg * Converts a typed constant in a constant of another type. 189012099Sjoerg * 189112099Sjoerg * op operator which requires conversion 189212099Sjoerg * arg if op is FARG, # of argument 189312099Sjoerg * tp type in which to convert the constant 189412099Sjoerg * nv new constant 189512099Sjoerg * v old constant 189612099Sjoerg */ 189712099Sjoergvoid 189891592Smarkmcvtcon(op_t op, int arg, type_t *tp, val_t *nv, val_t *v) 189912099Sjoerg{ 1900281168Spfg char lbuf[64], rbuf[64]; 190112099Sjoerg tspec_t ot, nt; 190291592Smarkm ldbl_t max = 0.0, min = 0.0; 190312099Sjoerg int sz, rchk; 190491592Smarkm int64_t xmask, xmsk1; 190512099Sjoerg int osz, nsz; 190612099Sjoerg 190712099Sjoerg ot = v->v_tspec; 190812099Sjoerg nt = nv->v_tspec = tp->t_tspec; 190912099Sjoerg rchk = 0; 191012099Sjoerg 191112099Sjoerg if (ot == FLOAT || ot == DOUBLE || ot == LDOUBLE) { 191212099Sjoerg switch (nt) { 191312099Sjoerg case CHAR: 191412099Sjoerg max = CHAR_MAX; min = CHAR_MIN; break; 191512099Sjoerg case UCHAR: 191612099Sjoerg max = UCHAR_MAX; min = 0; break; 191712099Sjoerg case SCHAR: 191812099Sjoerg max = SCHAR_MAX; min = SCHAR_MIN; break; 191912099Sjoerg case SHORT: 192012099Sjoerg max = SHRT_MAX; min = SHRT_MIN; break; 192112099Sjoerg case USHORT: 192212099Sjoerg max = USHRT_MAX; min = 0; break; 192312099Sjoerg case ENUM: 192412099Sjoerg case INT: 192512099Sjoerg max = INT_MAX; min = INT_MIN; break; 192612099Sjoerg case UINT: 192712099Sjoerg max = (u_int)UINT_MAX; min = 0; break; 192812099Sjoerg case LONG: 192912099Sjoerg max = LONG_MAX; min = LONG_MIN; break; 193012099Sjoerg case ULONG: 193112099Sjoerg max = (u_long)ULONG_MAX; min = 0; break; 193212099Sjoerg case QUAD: 193312099Sjoerg max = QUAD_MAX; min = QUAD_MIN; break; 193412099Sjoerg case UQUAD: 193591592Smarkm max = (uint64_t)UQUAD_MAX; min = 0; break; 193612099Sjoerg case FLOAT: 193712099Sjoerg max = FLT_MAX; min = -FLT_MAX; break; 193812099Sjoerg case DOUBLE: 193912099Sjoerg max = DBL_MAX; min = -DBL_MAX; break; 194012099Sjoerg case PTR: 194112099Sjoerg /* Got already an error because of float --> ptr */ 194212099Sjoerg case LDOUBLE: 194312099Sjoerg max = LDBL_MAX; min = -LDBL_MAX; break; 194412099Sjoerg default: 1945281168Spfg LERROR("cvtcon()"); 194612099Sjoerg } 194712099Sjoerg if (v->v_ldbl > max || v->v_ldbl < min) { 194812099Sjoerg if (nt == LDOUBLE) 1949281168Spfg LERROR("cvtcon()"); 195012099Sjoerg if (op == FARG) { 195112099Sjoerg /* conv. of %s to %s is out of rng., arg #%d */ 1952281168Spfg warning(295, tyname(lbuf, sizeof(lbuf), 1953281168Spfg gettyp(ot)), tyname(rbuf, sizeof(rbuf), tp), 1954281168Spfg arg); 195512099Sjoerg } else { 195612099Sjoerg /* conversion of %s to %s is out of range */ 1957281168Spfg warning(119, tyname(lbuf, sizeof(lbuf), 1958281168Spfg gettyp(ot)), 1959281168Spfg tyname(rbuf, sizeof(rbuf), tp)); 196012099Sjoerg } 196112099Sjoerg v->v_ldbl = v->v_ldbl > 0 ? max : min; 196212099Sjoerg } 196312099Sjoerg if (nt == FLOAT) { 196412099Sjoerg nv->v_ldbl = (float)v->v_ldbl; 196512099Sjoerg } else if (nt == DOUBLE) { 196612099Sjoerg nv->v_ldbl = (double)v->v_ldbl; 196712099Sjoerg } else if (nt == LDOUBLE) { 196812099Sjoerg nv->v_ldbl = v->v_ldbl; 196912099Sjoerg } else { 197012099Sjoerg nv->v_quad = (nt == PTR || isutyp(nt)) ? 197191592Smarkm (uint64_t)v->v_ldbl : (int64_t)v->v_ldbl; 197212099Sjoerg } 197312099Sjoerg } else { 197412099Sjoerg if (nt == FLOAT) { 197512099Sjoerg nv->v_ldbl = (ot == PTR || isutyp(ot)) ? 197691592Smarkm (float)(uint64_t)v->v_quad : (float)v->v_quad; 197712099Sjoerg } else if (nt == DOUBLE) { 197812099Sjoerg nv->v_ldbl = (ot == PTR || isutyp(ot)) ? 197991592Smarkm (double)(uint64_t)v->v_quad : (double)v->v_quad; 198012099Sjoerg } else if (nt == LDOUBLE) { 198112099Sjoerg nv->v_ldbl = (ot == PTR || isutyp(ot)) ? 198291592Smarkm (ldbl_t)(uint64_t)v->v_quad : (ldbl_t)v->v_quad; 198312099Sjoerg } else { 198412099Sjoerg rchk = 1; /* Check for lost precision. */ 198512099Sjoerg nv->v_quad = v->v_quad; 198612099Sjoerg } 198712099Sjoerg } 198812099Sjoerg 198912099Sjoerg if (v->v_ansiu && isftyp(nt)) { 199012099Sjoerg /* ANSI C treats constant as unsigned */ 199112099Sjoerg warning(157); 199212099Sjoerg v->v_ansiu = 0; 199312099Sjoerg } else if (v->v_ansiu && (isityp(nt) && !isutyp(nt) && 199412099Sjoerg psize(nt) > psize(ot))) { 199512099Sjoerg /* ANSI C treats constant as unsigned */ 199612099Sjoerg warning(157); 199712099Sjoerg v->v_ansiu = 0; 199812099Sjoerg } 199912099Sjoerg 200012099Sjoerg if (nt != FLOAT && nt != DOUBLE && nt != LDOUBLE) { 200112099Sjoerg sz = tp->t_isfield ? tp->t_flen : size(nt); 200212099Sjoerg nv->v_quad = xsign(nv->v_quad, nt, sz); 200312099Sjoerg } 200491592Smarkm 200512099Sjoerg if (rchk && op != CVT) { 200612099Sjoerg osz = size(ot); 200712099Sjoerg nsz = tp->t_isfield ? tp->t_flen : size(nt); 200812099Sjoerg xmask = qlmasks[nsz] ^ qlmasks[osz]; 200912099Sjoerg xmsk1 = qlmasks[nsz] ^ qlmasks[osz - 1]; 201012099Sjoerg /* 201112099Sjoerg * For bitwise operations we are not interested in the 201212099Sjoerg * value, but in the bits itself. 201312099Sjoerg */ 201412099Sjoerg if (op == ORASS || op == OR || op == XOR) { 201512099Sjoerg /* 201612099Sjoerg * Print a warning if bits which were set are 201712099Sjoerg * lost due to the conversion. 201812099Sjoerg * This can happen with operator ORASS only. 201912099Sjoerg */ 202012099Sjoerg if (nsz < osz && (v->v_quad & xmask) != 0) { 202112099Sjoerg /* constant truncated by conv., op %s */ 202212099Sjoerg warning(306, modtab[op].m_name); 202312099Sjoerg } 202412099Sjoerg } else if (op == ANDASS || op == AND) { 202512099Sjoerg /* 202612099Sjoerg * Print a warning if additional bits are not all 1 202712099Sjoerg * and the most significant bit of the old value is 1, 202812099Sjoerg * or if at least one (but not all) removed bit was 0. 202912099Sjoerg */ 203012099Sjoerg if (nsz > osz && 203112099Sjoerg (nv->v_quad & qbmasks[osz - 1]) != 0 && 203212099Sjoerg (nv->v_quad & xmask) != xmask) { 203312099Sjoerg /* 203412099Sjoerg * extra bits set to 0 in conversion 203512099Sjoerg * of '%s' to '%s', op %s 203612099Sjoerg */ 2037281168Spfg warning(309, tyname(lbuf, sizeof(lbuf), 2038281168Spfg gettyp(ot)), tyname(rbuf, sizeof(rbuf), tp), 2039281168Spfg modtab[op].m_name); 204012099Sjoerg } else if (nsz < osz && 204112099Sjoerg (v->v_quad & xmask) != xmask && 204212099Sjoerg (v->v_quad & xmask) != 0) { 204312099Sjoerg /* const. truncated by conv., op %s */ 204412099Sjoerg warning(306, modtab[op].m_name); 204512099Sjoerg } 204612099Sjoerg } else if ((nt != PTR && isutyp(nt)) && 204712099Sjoerg (ot != PTR && !isutyp(ot)) && v->v_quad < 0) { 204812099Sjoerg if (op == ASSIGN) { 204912099Sjoerg /* assignment of negative constant to ... */ 205012099Sjoerg warning(164); 205112099Sjoerg } else if (op == INIT) { 205212099Sjoerg /* initialisation of unsigned with neg. ... */ 205312099Sjoerg warning(221); 205412099Sjoerg } else if (op == FARG) { 205512099Sjoerg /* conversion of neg. const. to ..., arg #%d */ 205612099Sjoerg warning(296, arg); 205712099Sjoerg } else if (modtab[op].m_comp) { 205812099Sjoerg /* we get this warning already in chkcomp() */ 205912099Sjoerg } else { 206012099Sjoerg /* conversion of negative constant to ... */ 206112099Sjoerg warning(222); 206212099Sjoerg } 206312099Sjoerg } else if (nv->v_quad != v->v_quad && nsz <= osz && 206412099Sjoerg (v->v_quad & xmask) != 0 && 206512099Sjoerg (isutyp(ot) || (v->v_quad & xmsk1) != xmsk1)) { 206612099Sjoerg /* 206712099Sjoerg * Loss of significant bit(s). All truncated bits 206812099Sjoerg * of unsigned types or all truncated bits plus the 206912099Sjoerg * msb of the target for signed types are considered 207012099Sjoerg * to be significant bits. Loss of significant bits 207112099Sjoerg * means that at least on of the bits was set in an 207212099Sjoerg * unsigned type or that at least one, but not all of 2073108470Sschweikh * the bits was set in a signed type. 207412099Sjoerg * Loss of significant bits means that it is not 207512099Sjoerg * possible, also not with necessary casts, to convert 2076108532Sschweikh * back to the original type. An example for a 207712099Sjoerg * necessary cast is: 207812099Sjoerg * char c; int i; c = 128; 207912099Sjoerg * i = c; ** yields -128 ** 208012099Sjoerg * i = (unsigned char)c; ** yields 128 ** 208112099Sjoerg */ 208212099Sjoerg if (op == ASSIGN && tp->t_isfield) { 208312099Sjoerg /* precision lost in bit-field assignment */ 208412099Sjoerg warning(166); 208512099Sjoerg } else if (op == ASSIGN) { 208612099Sjoerg /* constant truncated by assignment */ 208712099Sjoerg warning(165); 208812099Sjoerg } else if (op == INIT && tp->t_isfield) { 208912099Sjoerg /* bit-field initializer does not fit */ 209012099Sjoerg warning(180); 209112099Sjoerg } else if (op == INIT) { 209212099Sjoerg /* initializer does not fit */ 209312099Sjoerg warning(178); 209412099Sjoerg } else if (op == CASE) { 209512099Sjoerg /* case label affected by conversion */ 209612099Sjoerg warning(196); 209712099Sjoerg } else if (op == FARG) { 209812099Sjoerg /* conv. of %s to %s is out of rng., arg #%d */ 2099281168Spfg warning(295, tyname(lbuf, sizeof(lbuf), 2100281168Spfg gettyp(ot)), tyname(rbuf, sizeof(rbuf), tp), 2101281168Spfg arg); 210212099Sjoerg } else { 210312099Sjoerg /* conversion of %s to %s is out of range */ 2104281168Spfg warning(119, tyname(lbuf, sizeof(lbuf), 2105281168Spfg gettyp(ot)), 2106281168Spfg tyname(rbuf, sizeof(rbuf), tp)); 210712099Sjoerg } 210812099Sjoerg } else if (nv->v_quad != v->v_quad) { 210912099Sjoerg if (op == ASSIGN && tp->t_isfield) { 211012099Sjoerg /* precision lost in bit-field assignment */ 211112099Sjoerg warning(166); 211212099Sjoerg } else if (op == INIT && tp->t_isfield) { 211312099Sjoerg /* bit-field initializer out of range */ 211412099Sjoerg warning(11); 211512099Sjoerg } else if (op == CASE) { 211612099Sjoerg /* case label affected by conversion */ 211712099Sjoerg warning(196); 211812099Sjoerg } else if (op == FARG) { 211912099Sjoerg /* conv. of %s to %s is out of rng., arg #%d */ 2120281168Spfg warning(295, tyname(lbuf, sizeof(lbuf), 2121281168Spfg gettyp(ot)), tyname(rbuf, sizeof(rbuf), tp), 2122281168Spfg arg); 212312099Sjoerg } else { 212412099Sjoerg /* conversion of %s to %s is out of range */ 2125281168Spfg warning(119, tyname(lbuf, sizeof(lbuf), 2126281168Spfg gettyp(ot)), 2127281168Spfg tyname(rbuf, sizeof(rbuf), tp)); 212812099Sjoerg } 212912099Sjoerg } 213012099Sjoerg } 213112099Sjoerg} 213212099Sjoerg 213312099Sjoerg/* 213412099Sjoerg * Called if incompatible types were detected. 2135108532Sschweikh * Prints an appropriate warning. 213612099Sjoerg */ 213712099Sjoergstatic void 213891592Smarkmincompat(op_t op, tspec_t lt, tspec_t rt) 213912099Sjoerg{ 214012099Sjoerg mod_t *mp; 214112099Sjoerg 214212099Sjoerg mp = &modtab[op]; 214312099Sjoerg 214412099Sjoerg if (lt == VOID || (mp->m_binary && rt == VOID)) { 214512099Sjoerg /* void type illegal in expression */ 214612099Sjoerg error(109); 214712099Sjoerg } else if (op == ASSIGN) { 214812099Sjoerg if ((lt == STRUCT || lt == UNION) && 214912099Sjoerg (rt == STRUCT || rt == UNION)) { 215012099Sjoerg /* assignment of different structures */ 215112099Sjoerg error(240); 215212099Sjoerg } else { 215312099Sjoerg /* assignment type mismatch */ 215412099Sjoerg error(171); 215512099Sjoerg } 215612099Sjoerg } else if (mp->m_binary) { 215712099Sjoerg /* operands of %s have incompatible types */ 215812099Sjoerg error(107, mp->m_name); 215912099Sjoerg } else { 216012099Sjoerg /* operand of %s has incompatible type */ 216112099Sjoerg error(108, mp->m_name); 216212099Sjoerg } 216312099Sjoerg} 216412099Sjoerg 216512099Sjoerg/* 216612099Sjoerg * Called if incompatible pointer types are detected. 216712099Sjoerg * Print an appropriate warning. 216812099Sjoerg */ 216912099Sjoergstatic void 217091592Smarkmillptrc(mod_t *mp, type_t *ltp, type_t *rtp) 217112099Sjoerg{ 217212099Sjoerg tspec_t lt, rt; 217312099Sjoerg 217412099Sjoerg if (ltp->t_tspec != PTR || rtp->t_tspec != PTR) 2175281168Spfg LERROR("illptrc()"); 217612099Sjoerg 217712099Sjoerg lt = ltp->t_subt->t_tspec; 217812099Sjoerg rt = rtp->t_subt->t_tspec; 217912099Sjoerg 218012099Sjoerg if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION)) { 218112099Sjoerg if (mp == NULL) { 218212099Sjoerg /* illegal structure pointer combination */ 218312099Sjoerg warning(244); 218412099Sjoerg } else { 218512099Sjoerg /* illegal structure pointer combination, op %s */ 218612099Sjoerg warning(245, mp->m_name); 218712099Sjoerg } 218812099Sjoerg } else { 218912099Sjoerg if (mp == NULL) { 219012099Sjoerg /* illegal pointer combination */ 219112099Sjoerg warning(184); 219212099Sjoerg } else { 219312099Sjoerg /* illegal pointer combination, op %s */ 219412099Sjoerg warning(124, mp->m_name); 219512099Sjoerg } 219612099Sjoerg } 219712099Sjoerg} 219812099Sjoerg 219912099Sjoerg/* 220012099Sjoerg * Make sure type (*tpp)->t_subt has at least the qualifiers 220112099Sjoerg * of tp1->t_subt and tp2->t_subt. 220212099Sjoerg */ 220312099Sjoergstatic void 220491592Smarkmmrgqual(type_t **tpp, type_t *tp1, type_t *tp2) 220512099Sjoerg{ 220691592Smarkm 220712099Sjoerg if ((*tpp)->t_tspec != PTR || 220812099Sjoerg tp1->t_tspec != PTR || tp2->t_tspec != PTR) { 2209281168Spfg LERROR("mrgqual()"); 221012099Sjoerg } 221112099Sjoerg 221212099Sjoerg if ((*tpp)->t_subt->t_const == 221312099Sjoerg (tp1->t_subt->t_const | tp2->t_subt->t_const) && 221412099Sjoerg (*tpp)->t_subt->t_volatile == 221512099Sjoerg (tp1->t_subt->t_volatile | tp2->t_subt->t_volatile)) { 221612099Sjoerg return; 221712099Sjoerg } 221812099Sjoerg 221912099Sjoerg *tpp = tduptyp(*tpp); 222012099Sjoerg (*tpp)->t_subt = tduptyp((*tpp)->t_subt); 222112099Sjoerg (*tpp)->t_subt->t_const = 222212099Sjoerg tp1->t_subt->t_const | tp2->t_subt->t_const; 222312099Sjoerg (*tpp)->t_subt->t_volatile = 222412099Sjoerg tp1->t_subt->t_volatile | tp2->t_subt->t_volatile; 222512099Sjoerg} 222612099Sjoerg 222712099Sjoerg/* 222812099Sjoerg * Returns 1 if the given structure or union has a constant member 222912099Sjoerg * (maybe recursively). 223012099Sjoerg */ 223112099Sjoergstatic int 223291592Smarkmconmemb(type_t *tp) 223312099Sjoerg{ 223412099Sjoerg sym_t *m; 223512099Sjoerg tspec_t t; 223612099Sjoerg 223712099Sjoerg if ((t = tp->t_tspec) != STRUCT && t != UNION) 2238281168Spfg LERROR("conmemb()"); 223912099Sjoerg for (m = tp->t_str->memb; m != NULL; m = m->s_nxt) { 224012099Sjoerg tp = m->s_type; 224112099Sjoerg if (tp->t_const) 224212099Sjoerg return (1); 224312099Sjoerg if ((t = tp->t_tspec) == STRUCT || t == UNION) { 224412099Sjoerg if (conmemb(m->s_type)) 224512099Sjoerg return (1); 224612099Sjoerg } 224712099Sjoerg } 224812099Sjoerg return (0); 224912099Sjoerg} 225012099Sjoerg 225112099Sjoergconst char * 2252281168Spfgbasictyname(tspec_t t) 225312099Sjoerg{ 2254281168Spfg switch (t) { 2255281168Spfg case CHAR: return "char"; 2256281168Spfg case UCHAR: return "unsigned char"; 2257281168Spfg case SCHAR: return "signed char"; 2258281168Spfg case SHORT: return "short"; 2259281168Spfg case USHORT: return "unsigned short"; 2260281168Spfg case INT: return "int"; 2261281168Spfg case UINT: return "unsigned int"; 2262281168Spfg case LONG: return "long"; 2263281168Spfg case ULONG: return "unsigned long"; 2264281168Spfg case QUAD: return "long long"; 2265281168Spfg case UQUAD: return "unsigned long long"; 2266281168Spfg case FLOAT: return "float"; 2267281168Spfg case DOUBLE: return "double"; 2268281168Spfg case LDOUBLE: return "long double"; 2269281168Spfg case PTR: return "pointer"; 2270281168Spfg case ENUM: return "enum"; 2271281168Spfg case STRUCT: return "struct"; 2272281168Spfg case UNION: return "union"; 2273281168Spfg case FUNC: return "function"; 2274281168Spfg case ARRAY: return "array"; 2275281168Spfg default: 2276281168Spfg LERROR("basictyname()"); 2277281168Spfg return NULL; 2278281168Spfg } 2279281168Spfg} 2280281168Spfg 2281281168Spfgconst char * 2282281168Spfgtyname(char *buf, size_t bufsiz, type_t *tp) 2283281168Spfg{ 228412099Sjoerg tspec_t t; 228512099Sjoerg const char *s; 2286281168Spfg char lbuf[64]; 228712099Sjoerg 228812099Sjoerg if ((t = tp->t_tspec) == INT && tp->t_isenum) 228912099Sjoerg t = ENUM; 229012099Sjoerg 2291281168Spfg s = basictyname(t); 2292281168Spfg 2293281168Spfg 229412099Sjoerg switch (t) { 2295281168Spfg case CHAR: 2296281168Spfg case UCHAR: 2297281168Spfg case SCHAR: 2298281168Spfg case SHORT: 2299281168Spfg case USHORT: 2300281168Spfg case INT: 2301281168Spfg case UINT: 2302281168Spfg case LONG: 2303281168Spfg case ULONG: 2304281168Spfg case QUAD: 2305281168Spfg case UQUAD: 2306281168Spfg case FLOAT: 2307281168Spfg case DOUBLE: 2308281168Spfg case LDOUBLE: 2309281168Spfg case FUNC: 2310281168Spfg (void)snprintf(buf, bufsiz, "%s", s); 2311281168Spfg break; 2312281168Spfg case PTR: 2313281168Spfg (void)snprintf(buf, bufsiz, "%s to %s", s, 2314281168Spfg tyname(lbuf, sizeof(lbuf), tp->t_subt)); 2315281168Spfg break; 2316281168Spfg case ENUM: 2317281168Spfg (void)snprintf(buf, bufsiz, "%s %s", s, 2318281168Spfg tp->t_enum->etag->s_name); 2319281168Spfg break; 2320281168Spfg case STRUCT: 2321281168Spfg case UNION: 2322281168Spfg (void)snprintf(buf, bufsiz, "%s %s", s, 2323281168Spfg tp->t_str->stag->s_name); 2324281168Spfg break; 2325281168Spfg case ARRAY: 2326281168Spfg (void)snprintf(buf, bufsiz, "%s of %s[%d]", s, 2327281168Spfg tyname(lbuf, sizeof(lbuf), tp->t_subt), tp->t_dim); 2328281168Spfg break; 232912099Sjoerg default: 2330281168Spfg LERROR("tyname()"); 233112099Sjoerg } 2332281168Spfg return (buf); 233312099Sjoerg} 233412099Sjoerg 233512099Sjoerg/* 233612099Sjoerg * Create a new node for one of the operators POINT and ARROW. 233712099Sjoerg */ 233812099Sjoergstatic tnode_t * 233991592Smarkmbldstr(op_t op, tnode_t *ln, tnode_t *rn) 234012099Sjoerg{ 234112099Sjoerg tnode_t *ntn, *ctn; 234212099Sjoerg int nolval; 234312099Sjoerg 234412099Sjoerg if (rn->tn_op != NAME) 2345281168Spfg LERROR("bldstr()"); 234612099Sjoerg if (rn->tn_sym->s_value.v_tspec != INT) 2347281168Spfg LERROR("bldstr()"); 234812099Sjoerg if (rn->tn_sym->s_scl != MOS && rn->tn_sym->s_scl != MOU) 2349281168Spfg LERROR("bldstr()"); 235012099Sjoerg 235112099Sjoerg /* 235212099Sjoerg * Remember if the left operand is an lvalue (structure members 235312099Sjoerg * are lvalues if and only if the structure itself is an lvalue). 235412099Sjoerg */ 235512099Sjoerg nolval = op == POINT && !ln->tn_lvalue; 235612099Sjoerg 235712099Sjoerg if (op == POINT) { 235812099Sjoerg ln = bldamper(ln, 1); 235912099Sjoerg } else if (ln->tn_type->t_tspec != PTR) { 236012099Sjoerg if (!tflag || !isityp(ln->tn_type->t_tspec)) 2361281168Spfg LERROR("bldstr()"); 236212099Sjoerg ln = convert(NOOP, 0, tincref(gettyp(VOID), PTR), ln); 236312099Sjoerg } 236412099Sjoerg 236512099Sjoerg#if PTRDIFF_IS_LONG 236612099Sjoerg ctn = getinode(LONG, rn->tn_sym->s_value.v_quad / CHAR_BIT); 236712099Sjoerg#else 236812099Sjoerg ctn = getinode(INT, rn->tn_sym->s_value.v_quad / CHAR_BIT); 236912099Sjoerg#endif 237012099Sjoerg 237112099Sjoerg ntn = mktnode(PLUS, tincref(rn->tn_type, PTR), ln, ctn); 237212099Sjoerg if (ln->tn_op == CON) 237312099Sjoerg ntn = fold(ntn); 237412099Sjoerg 237512099Sjoerg if (rn->tn_type->t_isfield) { 237612099Sjoerg ntn = mktnode(FSEL, ntn->tn_type->t_subt, ntn, NULL); 237712099Sjoerg } else { 237812099Sjoerg ntn = mktnode(STAR, ntn->tn_type->t_subt, ntn, NULL); 237912099Sjoerg } 238012099Sjoerg 238112099Sjoerg if (nolval) 238212099Sjoerg ntn->tn_lvalue = 0; 238312099Sjoerg 238412099Sjoerg return (ntn); 238512099Sjoerg} 238612099Sjoerg 238712099Sjoerg/* 238812099Sjoerg * Create a node for INCAFT, INCBEF, DECAFT and DECBEF. 238912099Sjoerg */ 239012099Sjoergstatic tnode_t * 239191592Smarkmbldincdec(op_t op, tnode_t *ln) 239212099Sjoerg{ 239312099Sjoerg tnode_t *cn, *ntn; 239412099Sjoerg 239512099Sjoerg if (ln == NULL) 2396281168Spfg LERROR("bldincdec()"); 239712099Sjoerg 239812099Sjoerg if (ln->tn_type->t_tspec == PTR) { 239912099Sjoerg cn = plength(ln->tn_type); 240012099Sjoerg } else { 240191592Smarkm cn = getinode(INT, (int64_t)1); 240212099Sjoerg } 240312099Sjoerg ntn = mktnode(op, ln->tn_type, ln, cn); 240412099Sjoerg 240512099Sjoerg return (ntn); 240612099Sjoerg} 240712099Sjoerg 240812099Sjoerg/* 240912099Sjoerg * Create a tree node for the & operator 241012099Sjoerg */ 241112099Sjoergstatic tnode_t * 241291592Smarkmbldamper(tnode_t *tn, int noign) 241312099Sjoerg{ 241412099Sjoerg tnode_t *ntn; 241512099Sjoerg tspec_t t; 241691592Smarkm 241712099Sjoerg if (!noign && ((t = tn->tn_type->t_tspec) == ARRAY || t == FUNC)) { 241812099Sjoerg /* & before array or function: ignored */ 241912099Sjoerg if (tflag) 242012099Sjoerg warning(127); 242112099Sjoerg return (tn); 242212099Sjoerg } 242312099Sjoerg 242412099Sjoerg /* eliminate &* */ 242512099Sjoerg if (tn->tn_op == STAR && 242612099Sjoerg tn->tn_left->tn_type->t_tspec == PTR && 242712099Sjoerg tn->tn_left->tn_type->t_subt == tn->tn_type) { 242812099Sjoerg return (tn->tn_left); 242912099Sjoerg } 243091592Smarkm 243112099Sjoerg ntn = mktnode(AMPER, tincref(tn->tn_type, PTR), tn, NULL); 243212099Sjoerg 243312099Sjoerg return (ntn); 243412099Sjoerg} 243512099Sjoerg 243612099Sjoerg/* 243712099Sjoerg * Create a node for operators PLUS and MINUS. 243812099Sjoerg */ 243912099Sjoergstatic tnode_t * 244091592Smarkmbldplmi(op_t op, tnode_t *ln, tnode_t *rn) 244112099Sjoerg{ 244212099Sjoerg tnode_t *ntn, *ctn; 244312099Sjoerg type_t *tp; 244412099Sjoerg 244512099Sjoerg /* If pointer and integer, then pointer to the lhs. */ 244612099Sjoerg if (rn->tn_type->t_tspec == PTR && isityp(ln->tn_type->t_tspec)) { 244712099Sjoerg ntn = ln; 244812099Sjoerg ln = rn; 244912099Sjoerg rn = ntn; 245012099Sjoerg } 245112099Sjoerg 245212099Sjoerg if (ln->tn_type->t_tspec == PTR && rn->tn_type->t_tspec != PTR) { 245312099Sjoerg 245412099Sjoerg if (!isityp(rn->tn_type->t_tspec)) 2455281168Spfg LERROR("bldplmi()"); 245612099Sjoerg 245712099Sjoerg ctn = plength(ln->tn_type); 245812099Sjoerg if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec) 245912099Sjoerg rn = convert(NOOP, 0, ctn->tn_type, rn); 246012099Sjoerg rn = mktnode(MULT, rn->tn_type, rn, ctn); 246112099Sjoerg if (rn->tn_left->tn_op == CON) 246212099Sjoerg rn = fold(rn); 246312099Sjoerg ntn = mktnode(op, ln->tn_type, ln, rn); 246412099Sjoerg 246512099Sjoerg } else if (rn->tn_type->t_tspec == PTR) { 246612099Sjoerg 246712099Sjoerg if (ln->tn_type->t_tspec != PTR || op != MINUS) 2468281168Spfg LERROR("bldplmi()"); 246912099Sjoerg#if PTRDIFF_IS_LONG 247012099Sjoerg tp = gettyp(LONG); 247112099Sjoerg#else 247212099Sjoerg tp = gettyp(INT); 247312099Sjoerg#endif 247412099Sjoerg ntn = mktnode(op, tp, ln, rn); 247512099Sjoerg if (ln->tn_op == CON && rn->tn_op == CON) 247612099Sjoerg ntn = fold(ntn); 247712099Sjoerg ctn = plength(ln->tn_type); 247812099Sjoerg balance(NOOP, &ntn, &ctn); 247912099Sjoerg ntn = mktnode(DIV, tp, ntn, ctn); 248012099Sjoerg 248112099Sjoerg } else { 248212099Sjoerg 248312099Sjoerg ntn = mktnode(op, ln->tn_type, ln, rn); 248412099Sjoerg 248512099Sjoerg } 248612099Sjoerg return (ntn); 248712099Sjoerg} 248812099Sjoerg 248912099Sjoerg/* 249012099Sjoerg * Create a node for operators SHL and SHR. 249112099Sjoerg */ 249212099Sjoergstatic tnode_t * 249391592Smarkmbldshft(op_t op, tnode_t *ln, tnode_t *rn) 249412099Sjoerg{ 249512099Sjoerg tspec_t t; 249612099Sjoerg tnode_t *ntn; 249712099Sjoerg 249812099Sjoerg if ((t = rn->tn_type->t_tspec) != INT && t != UINT) 249912099Sjoerg rn = convert(CVT, 0, gettyp(INT), rn); 250012099Sjoerg ntn = mktnode(op, ln->tn_type, ln, rn); 250112099Sjoerg return (ntn); 250212099Sjoerg} 250312099Sjoerg 250412099Sjoerg/* 250512099Sjoerg * Create a node for COLON. 250612099Sjoerg */ 250712099Sjoergstatic tnode_t * 250891592Smarkmbldcol(tnode_t *ln, tnode_t *rn) 250912099Sjoerg{ 251012099Sjoerg tspec_t lt, rt, pdt; 251112099Sjoerg type_t *rtp; 251212099Sjoerg tnode_t *ntn; 251312099Sjoerg 251412099Sjoerg lt = ln->tn_type->t_tspec; 251512099Sjoerg rt = rn->tn_type->t_tspec; 251612099Sjoerg#if PTRDIFF_IS_LONG 251712099Sjoerg pdt = LONG; 251812099Sjoerg#else 251912099Sjoerg pdt = INT; 252012099Sjoerg#endif 252112099Sjoerg 252212099Sjoerg /* 252312099Sjoerg * Arithmetic types are balanced, all other type combinations 252412099Sjoerg * still need to be handled. 252512099Sjoerg */ 252612099Sjoerg if (isatyp(lt) && isatyp(rt)) { 252712099Sjoerg rtp = ln->tn_type; 252812099Sjoerg } else if (lt == VOID || rt == VOID) { 252912099Sjoerg rtp = gettyp(VOID); 253012099Sjoerg } else if (lt == STRUCT || lt == UNION) { 253112099Sjoerg /* Both types must be identical. */ 253212099Sjoerg if (rt != STRUCT && rt != UNION) 2533281168Spfg LERROR("bldcol()"); 253412099Sjoerg if (ln->tn_type->t_str != rn->tn_type->t_str) 2535281168Spfg LERROR("bldcol()"); 253612099Sjoerg if (incompl(ln->tn_type)) { 253712099Sjoerg /* unknown operand size, op %s */ 253812099Sjoerg error(138, modtab[COLON].m_name); 253912099Sjoerg return (NULL); 254012099Sjoerg } 254112099Sjoerg rtp = ln->tn_type; 254212099Sjoerg } else if (lt == PTR && isityp(rt)) { 254312099Sjoerg if (rt != pdt) { 254412099Sjoerg rn = convert(NOOP, 0, gettyp(pdt), rn); 254512099Sjoerg rt = pdt; 254612099Sjoerg } 254712099Sjoerg rtp = ln->tn_type; 254812099Sjoerg } else if (rt == PTR && isityp(lt)) { 254912099Sjoerg if (lt != pdt) { 255012099Sjoerg ln = convert(NOOP, 0, gettyp(pdt), ln); 255112099Sjoerg lt = pdt; 255212099Sjoerg } 255312099Sjoerg rtp = rn->tn_type; 255412099Sjoerg } else if (lt == PTR && ln->tn_type->t_subt->t_tspec == VOID) { 255512099Sjoerg if (rt != PTR) 2556281168Spfg LERROR("bldcol()"); 255712099Sjoerg rtp = ln->tn_type; 255812099Sjoerg mrgqual(&rtp, ln->tn_type, rn->tn_type); 255912099Sjoerg } else if (rt == PTR && rn->tn_type->t_subt->t_tspec == VOID) { 256012099Sjoerg if (lt != PTR) 2561281168Spfg LERROR("bldcol()"); 256212099Sjoerg rtp = rn->tn_type; 256312099Sjoerg mrgqual(&rtp, ln->tn_type, rn->tn_type); 256412099Sjoerg } else { 256512099Sjoerg if (lt != PTR || rt != PTR) 2566281168Spfg LERROR("bldcol()"); 256712099Sjoerg /* 256812099Sjoerg * XXX For now we simply take the left type. This is 256912099Sjoerg * probably wrong, if one type contains a functionprototype 257012099Sjoerg * and the other one, at the same place, only an old style 257112099Sjoerg * declaration. 257212099Sjoerg */ 257312099Sjoerg rtp = ln->tn_type; 257412099Sjoerg mrgqual(&rtp, ln->tn_type, rn->tn_type); 257512099Sjoerg } 257612099Sjoerg 257712099Sjoerg ntn = mktnode(COLON, rtp, ln, rn); 257812099Sjoerg 257912099Sjoerg return (ntn); 258012099Sjoerg} 258112099Sjoerg 258212099Sjoerg/* 258312099Sjoerg * Create a node for an assignment operator (both = and op= ). 258412099Sjoerg */ 258512099Sjoergstatic tnode_t * 258691592Smarkmbldasgn(op_t op, tnode_t *ln, tnode_t *rn) 258712099Sjoerg{ 258812099Sjoerg tspec_t lt, rt; 258912099Sjoerg tnode_t *ntn, *ctn; 259012099Sjoerg 259112099Sjoerg if (ln == NULL || rn == NULL) 2592281168Spfg LERROR("bldasgn()"); 259312099Sjoerg 259412099Sjoerg lt = ln->tn_type->t_tspec; 259512099Sjoerg rt = rn->tn_type->t_tspec; 259612099Sjoerg 259712099Sjoerg if ((op == ADDASS || op == SUBASS) && lt == PTR) { 259812099Sjoerg if (!isityp(rt)) 2599281168Spfg LERROR("bldasgn()"); 260012099Sjoerg ctn = plength(ln->tn_type); 260112099Sjoerg if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec) 260212099Sjoerg rn = convert(NOOP, 0, ctn->tn_type, rn); 260312099Sjoerg rn = mktnode(MULT, rn->tn_type, rn, ctn); 260412099Sjoerg if (rn->tn_left->tn_op == CON) 260512099Sjoerg rn = fold(rn); 260612099Sjoerg } 260712099Sjoerg 260812099Sjoerg if ((op == ASSIGN || op == RETURN) && (lt == STRUCT || rt == STRUCT)) { 260912099Sjoerg if (rt != lt || ln->tn_type->t_str != rn->tn_type->t_str) 2610281168Spfg LERROR("bldasgn()"); 261112099Sjoerg if (incompl(ln->tn_type)) { 261212099Sjoerg if (op == RETURN) { 261312099Sjoerg /* cannot return incomplete type */ 261412099Sjoerg error(212); 261512099Sjoerg } else { 261612099Sjoerg /* unknown operand size, op %s */ 261712099Sjoerg error(138, modtab[op].m_name); 261812099Sjoerg } 261912099Sjoerg return (NULL); 262012099Sjoerg } 262112099Sjoerg } 262212099Sjoerg 2623281168Spfg if (op == SHLASS) { 2624281168Spfg if (psize(lt) < psize(rt)) { 2625281168Spfg if (hflag) 2626281168Spfg /* semantics of %s change in ANSI C; use ... */ 2627281168Spfg warning(118, "<<="); 262812099Sjoerg } 2629281168Spfg } else if (op != SHRASS) { 263012099Sjoerg if (op == ASSIGN || lt != PTR) { 263112099Sjoerg if (lt != rt || 263212099Sjoerg (ln->tn_type->t_isfield && rn->tn_op == CON)) { 263312099Sjoerg rn = convert(op, 0, ln->tn_type, rn); 263412099Sjoerg rt = lt; 263512099Sjoerg } 263612099Sjoerg } 263712099Sjoerg } 263812099Sjoerg 263912099Sjoerg ntn = mktnode(op, ln->tn_type, ln, rn); 264012099Sjoerg 264112099Sjoerg return (ntn); 264212099Sjoerg} 264312099Sjoerg 264412099Sjoerg/* 264512099Sjoerg * Get length of type tp->t_subt. 264612099Sjoerg */ 264712099Sjoergstatic tnode_t * 264891592Smarkmplength(type_t *tp) 264912099Sjoerg{ 265012099Sjoerg int elem, elsz; 265112099Sjoerg tspec_t st; 265212099Sjoerg 265312099Sjoerg if (tp->t_tspec != PTR) 2654281168Spfg LERROR("plength()"); 265512099Sjoerg tp = tp->t_subt; 265612099Sjoerg 265712099Sjoerg elem = 1; 265812099Sjoerg elsz = 0; 265912099Sjoerg 266012099Sjoerg while (tp->t_tspec == ARRAY) { 266112099Sjoerg elem *= tp->t_dim; 266212099Sjoerg tp = tp->t_subt; 266312099Sjoerg } 266412099Sjoerg 266512099Sjoerg switch (tp->t_tspec) { 266612099Sjoerg case FUNC: 266712099Sjoerg /* pointer to function is not allowed here */ 266812099Sjoerg error(110); 266912099Sjoerg break; 267012099Sjoerg case VOID: 267112099Sjoerg /* cannot do pointer arithmetic on operand of ... */ 267212099Sjoerg (void)gnuism(136); 267312099Sjoerg break; 267412099Sjoerg case STRUCT: 267512099Sjoerg case UNION: 267612099Sjoerg if ((elsz = tp->t_str->size) == 0) 267712099Sjoerg /* cannot do pointer arithmetic on operand of ... */ 267812099Sjoerg error(136); 267912099Sjoerg break; 268012099Sjoerg case ENUM: 268112099Sjoerg if (incompl(tp)) { 268212099Sjoerg /* cannot do pointer arithmetic on operand of ... */ 268312099Sjoerg warning(136); 268412099Sjoerg } 268512099Sjoerg /* FALLTHROUGH */ 268612099Sjoerg default: 268712099Sjoerg if ((elsz = size(tp->t_tspec)) == 0) { 268812099Sjoerg /* cannot do pointer arithmetic on operand of ... */ 268912099Sjoerg error(136); 269012099Sjoerg } else if (elsz == -1) { 2691281168Spfg LERROR("plength()"); 269212099Sjoerg } 269312099Sjoerg break; 269412099Sjoerg } 269512099Sjoerg 269612099Sjoerg if (elem == 0 && elsz != 0) { 269712099Sjoerg /* cannot do pointer arithmetic on operand of ... */ 269812099Sjoerg error(136); 269912099Sjoerg } 270012099Sjoerg 270112099Sjoerg if (elsz == 0) 270212099Sjoerg elsz = CHAR_BIT; 270312099Sjoerg 270412099Sjoerg#if PTRDIFF_IS_LONG 270512099Sjoerg st = LONG; 270612099Sjoerg#else 270712099Sjoerg st = INT; 270812099Sjoerg#endif 270912099Sjoerg 271091592Smarkm return (getinode(st, (int64_t)(elem * elsz / CHAR_BIT))); 271112099Sjoerg} 271212099Sjoerg 271312099Sjoerg/* 271491592Smarkm * XXX 271591592Smarkm * Note: There appear to be a number of bugs in detecting overflow in 271691592Smarkm * this function. An audit and a set of proper regression tests are needed. 271791592Smarkm * --Perry Metzger, Nov. 16, 2001 271891592Smarkm */ 271991592Smarkm/* 272012099Sjoerg * Do only as much as necessary to compute constant expressions. 272112099Sjoerg * Called only if the operator allows folding and (both) operands 272212099Sjoerg * are constants. 272312099Sjoerg */ 272412099Sjoergstatic tnode_t * 272591592Smarkmfold(tnode_t *tn) 272612099Sjoerg{ 272712099Sjoerg val_t *v; 272812099Sjoerg tspec_t t; 272912099Sjoerg int utyp, ovfl; 273091592Smarkm int64_t sl, sr = 0, q = 0, mask; 273191592Smarkm uint64_t ul, ur = 0; 273212099Sjoerg tnode_t *cn; 273312099Sjoerg 273480284Sobrien if ((v = calloc(1, sizeof (val_t))) == NULL) 273580284Sobrien nomem(); 273612099Sjoerg v->v_tspec = t = tn->tn_type->t_tspec; 273712099Sjoerg 273812099Sjoerg utyp = t == PTR || isutyp(t); 273912099Sjoerg ul = sl = tn->tn_left->tn_val->v_quad; 274012099Sjoerg if (modtab[tn->tn_op].m_binary) 274112099Sjoerg ur = sr = tn->tn_right->tn_val->v_quad; 274212099Sjoerg 274391592Smarkm mask = qlmasks[size(t)]; 274412099Sjoerg ovfl = 0; 274512099Sjoerg 274612099Sjoerg switch (tn->tn_op) { 274712099Sjoerg case UPLUS: 274812099Sjoerg q = sl; 274912099Sjoerg break; 275012099Sjoerg case UMINUS: 275112099Sjoerg q = -sl; 275212099Sjoerg if (msb(q, t, -1) == msb(sl, t, -1)) 275312099Sjoerg ovfl = 1; 275412099Sjoerg break; 275512099Sjoerg case COMPL: 275612099Sjoerg q = ~sl; 275712099Sjoerg break; 275812099Sjoerg case MULT: 275991592Smarkm if (utyp) { 276091592Smarkm q = ul * ur; 276191592Smarkm if (q != (q & mask)) 276291592Smarkm ovfl = 1; 276391592Smarkm else if ((ul != 0) && ((q / ul) != ur)) 276491592Smarkm ovfl = 1; 276591592Smarkm } else { 276691592Smarkm q = sl * sr; 276791592Smarkm if (msb(q, t, -1) != (msb(sl, t, -1) ^ msb(sr, t, -1))) 276891592Smarkm ovfl = 1; 276991592Smarkm } 277012099Sjoerg break; 277112099Sjoerg case DIV: 277212099Sjoerg if (sr == 0) { 277312099Sjoerg /* division by 0 */ 277412099Sjoerg error(139); 277512099Sjoerg q = utyp ? UQUAD_MAX : QUAD_MAX; 277612099Sjoerg } else { 277712099Sjoerg q = utyp ? ul / ur : sl / sr; 277812099Sjoerg } 277912099Sjoerg break; 278012099Sjoerg case MOD: 278112099Sjoerg if (sr == 0) { 278212099Sjoerg /* modulus by 0 */ 278312099Sjoerg error(140); 278412099Sjoerg q = 0; 278512099Sjoerg } else { 278612099Sjoerg q = utyp ? ul % ur : sl % sr; 278712099Sjoerg } 278812099Sjoerg break; 278912099Sjoerg case PLUS: 279012099Sjoerg q = utyp ? ul + ur : sl + sr; 279112099Sjoerg if (msb(sl, t, -1) != 0 && msb(sr, t, -1) != 0) { 279212099Sjoerg if (msb(q, t, -1) == 0) 279312099Sjoerg ovfl = 1; 279412099Sjoerg } else if (msb(sl, t, -1) == 0 && msb(sr, t, -1) == 0) { 279512099Sjoerg if (msb(q, t, -1) != 0) 279612099Sjoerg ovfl = 1; 279712099Sjoerg } 279812099Sjoerg break; 279912099Sjoerg case MINUS: 280012099Sjoerg q = utyp ? ul - ur : sl - sr; 280112099Sjoerg if (msb(sl, t, -1) != 0 && msb(sr, t, -1) == 0) { 280212099Sjoerg if (msb(q, t, -1) == 0) 280312099Sjoerg ovfl = 1; 280412099Sjoerg } else if (msb(sl, t, -1) == 0 && msb(sr, t, -1) != 0) { 280512099Sjoerg if (msb(q, t, -1) != 0) 280612099Sjoerg ovfl = 1; 280712099Sjoerg } 280812099Sjoerg break; 280912099Sjoerg case SHL: 281012099Sjoerg q = utyp ? ul << sr : sl << sr; 281112099Sjoerg break; 281212099Sjoerg case SHR: 281312099Sjoerg /* 281491592Smarkm * The sign must be explicitly extended because 281512099Sjoerg * shifts of signed values are implementation dependent. 281612099Sjoerg */ 281712099Sjoerg q = ul >> sr; 281812099Sjoerg q = xsign(q, t, size(t) - (int)sr); 281912099Sjoerg break; 282012099Sjoerg case LT: 282112099Sjoerg q = utyp ? ul < ur : sl < sr; 282212099Sjoerg break; 282312099Sjoerg case LE: 282412099Sjoerg q = utyp ? ul <= ur : sl <= sr; 282512099Sjoerg break; 282612099Sjoerg case GE: 282712099Sjoerg q = utyp ? ul >= ur : sl >= sr; 282812099Sjoerg break; 282912099Sjoerg case GT: 283012099Sjoerg q = utyp ? ul > ur : sl > sr; 283112099Sjoerg break; 283212099Sjoerg case EQ: 283312099Sjoerg q = utyp ? ul == ur : sl == sr; 283412099Sjoerg break; 283512099Sjoerg case NE: 283612099Sjoerg q = utyp ? ul != ur : sl != sr; 283712099Sjoerg break; 283812099Sjoerg case AND: 283912099Sjoerg q = utyp ? ul & ur : sl & sr; 284012099Sjoerg break; 284112099Sjoerg case XOR: 284212099Sjoerg q = utyp ? ul ^ ur : sl ^ sr; 284312099Sjoerg break; 284412099Sjoerg case OR: 284512099Sjoerg q = utyp ? ul | ur : sl | sr; 284612099Sjoerg break; 284712099Sjoerg default: 2848281168Spfg LERROR("fold()"); 284912099Sjoerg } 285012099Sjoerg 285112099Sjoerg /* XXX does not work for quads. */ 285291592Smarkm if (ovfl || ((q | mask) != ~(uint64_t)0 && (q & ~mask) != 0)) { 285312099Sjoerg if (hflag) 285412099Sjoerg /* integer overflow detected, op %s */ 285512099Sjoerg warning(141, modtab[tn->tn_op].m_name); 285612099Sjoerg } 285712099Sjoerg 285812099Sjoerg v->v_quad = xsign(q, t, -1); 285912099Sjoerg 286012099Sjoerg cn = getcnode(tn->tn_type, v); 286112099Sjoerg 286212099Sjoerg return (cn); 286312099Sjoerg} 286412099Sjoerg 286512099Sjoerg/* 286612099Sjoerg * Same for operators whose operands are compared with 0 (test context). 286712099Sjoerg */ 286812099Sjoergstatic tnode_t * 286991592Smarkmfoldtst(tnode_t *tn) 287012099Sjoerg{ 287191592Smarkm int l, r = 0; 287212099Sjoerg val_t *v; 287312099Sjoerg 287480284Sobrien if ((v = calloc(1, sizeof (val_t))) == NULL) 287580284Sobrien nomem(); 287612099Sjoerg v->v_tspec = tn->tn_type->t_tspec; 287712099Sjoerg if (tn->tn_type->t_tspec != INT) 2878281168Spfg LERROR("foldtst()"); 287912099Sjoerg 288012099Sjoerg if (isftyp(tn->tn_left->tn_type->t_tspec)) { 288112099Sjoerg l = tn->tn_left->tn_val->v_ldbl != 0.0; 288212099Sjoerg } else { 288312099Sjoerg l = tn->tn_left->tn_val->v_quad != 0; 288412099Sjoerg } 288512099Sjoerg 288612099Sjoerg if (modtab[tn->tn_op].m_binary) { 288712099Sjoerg if (isftyp(tn->tn_right->tn_type->t_tspec)) { 288812099Sjoerg r = tn->tn_right->tn_val->v_ldbl != 0.0; 288912099Sjoerg } else { 289012099Sjoerg r = tn->tn_right->tn_val->v_quad != 0; 289112099Sjoerg } 289212099Sjoerg } 289312099Sjoerg 289412099Sjoerg switch (tn->tn_op) { 289512099Sjoerg case NOT: 289612099Sjoerg if (hflag) 289712099Sjoerg /* constant argument to NOT */ 289812099Sjoerg warning(239); 289912099Sjoerg v->v_quad = !l; 290012099Sjoerg break; 290112099Sjoerg case LOGAND: 290212099Sjoerg v->v_quad = l && r; 290312099Sjoerg break; 290412099Sjoerg case LOGOR: 290512099Sjoerg v->v_quad = l || r; 290612099Sjoerg break; 290712099Sjoerg default: 2908281168Spfg LERROR("foldtst()"); 290912099Sjoerg } 291012099Sjoerg 291112099Sjoerg return (getcnode(tn->tn_type, v)); 291212099Sjoerg} 291312099Sjoerg 291412099Sjoerg/* 291512099Sjoerg * Same for operands with floating point type. 291612099Sjoerg */ 291712099Sjoergstatic tnode_t * 291891592Smarkmfoldflt(tnode_t *tn) 291912099Sjoerg{ 292012099Sjoerg val_t *v; 292112099Sjoerg tspec_t t; 292291592Smarkm ldbl_t l, r = 0; 292312099Sjoerg 292480284Sobrien if ((v = calloc(1, sizeof (val_t))) == NULL) 292580284Sobrien nomem(); 292612099Sjoerg v->v_tspec = t = tn->tn_type->t_tspec; 292712099Sjoerg 292812099Sjoerg if (!isftyp(t)) 2929281168Spfg LERROR("foldflt()"); 293012099Sjoerg 293112099Sjoerg if (t != tn->tn_left->tn_type->t_tspec) 2932281168Spfg LERROR("foldflt()"); 293312099Sjoerg if (modtab[tn->tn_op].m_binary && t != tn->tn_right->tn_type->t_tspec) 2934281168Spfg LERROR("foldflt()"); 293512099Sjoerg 293612099Sjoerg l = tn->tn_left->tn_val->v_ldbl; 293712099Sjoerg if (modtab[tn->tn_op].m_binary) 293812099Sjoerg r = tn->tn_right->tn_val->v_ldbl; 293912099Sjoerg 294012099Sjoerg switch (tn->tn_op) { 294112099Sjoerg case UPLUS: 294212099Sjoerg v->v_ldbl = l; 294312099Sjoerg break; 294412099Sjoerg case UMINUS: 294512099Sjoerg v->v_ldbl = -l; 294612099Sjoerg break; 294712099Sjoerg case MULT: 294812099Sjoerg v->v_ldbl = l * r; 294912099Sjoerg break; 295012099Sjoerg case DIV: 295112099Sjoerg if (r == 0.0) { 295212099Sjoerg /* division by 0 */ 295312099Sjoerg error(139); 295412099Sjoerg if (t == FLOAT) { 295512099Sjoerg v->v_ldbl = l < 0 ? -FLT_MAX : FLT_MAX; 295612099Sjoerg } else if (t == DOUBLE) { 295712099Sjoerg v->v_ldbl = l < 0 ? -DBL_MAX : DBL_MAX; 295812099Sjoerg } else { 295912099Sjoerg v->v_ldbl = l < 0 ? -LDBL_MAX : LDBL_MAX; 296012099Sjoerg } 296112099Sjoerg } else { 296212099Sjoerg v->v_ldbl = l / r; 296312099Sjoerg } 296412099Sjoerg break; 296512099Sjoerg case PLUS: 296612099Sjoerg v->v_ldbl = l + r; 296712099Sjoerg break; 296812099Sjoerg case MINUS: 296912099Sjoerg v->v_ldbl = l - r; 297012099Sjoerg break; 297112099Sjoerg case LT: 297212099Sjoerg v->v_quad = l < r; 297312099Sjoerg break; 297412099Sjoerg case LE: 297512099Sjoerg v->v_quad = l <= r; 297612099Sjoerg break; 297712099Sjoerg case GE: 297812099Sjoerg v->v_quad = l >= r; 297912099Sjoerg break; 298012099Sjoerg case GT: 298112099Sjoerg v->v_quad = l > r; 298212099Sjoerg break; 298312099Sjoerg case EQ: 298412099Sjoerg v->v_quad = l == r; 298512099Sjoerg break; 298612099Sjoerg case NE: 298712099Sjoerg v->v_quad = l != r; 298812099Sjoerg break; 298912099Sjoerg default: 2990281168Spfg LERROR("foldflt()"); 299112099Sjoerg } 299212099Sjoerg 299312099Sjoerg if (isnan((double)v->v_ldbl)) 2994281168Spfg LERROR("foldflt()"); 299591592Smarkm if (!finite((double)v->v_ldbl) || 299612099Sjoerg (t == FLOAT && 299712099Sjoerg (v->v_ldbl > FLT_MAX || v->v_ldbl < -FLT_MAX)) || 299812099Sjoerg (t == DOUBLE && 299912099Sjoerg (v->v_ldbl > DBL_MAX || v->v_ldbl < -DBL_MAX))) { 300012099Sjoerg /* floating point overflow detected, op %s */ 300112099Sjoerg warning(142, modtab[tn->tn_op].m_name); 300212099Sjoerg if (t == FLOAT) { 300312099Sjoerg v->v_ldbl = v->v_ldbl < 0 ? -FLT_MAX : FLT_MAX; 300412099Sjoerg } else if (t == DOUBLE) { 300512099Sjoerg v->v_ldbl = v->v_ldbl < 0 ? -DBL_MAX : DBL_MAX; 300612099Sjoerg } else { 300712099Sjoerg v->v_ldbl = v->v_ldbl < 0 ? -LDBL_MAX: LDBL_MAX; 300812099Sjoerg } 300912099Sjoerg } 301012099Sjoerg 301112099Sjoerg return (getcnode(tn->tn_type, v)); 301212099Sjoerg} 301312099Sjoerg 301412099Sjoerg/* 301512099Sjoerg * Create a constant node for sizeof. 301612099Sjoerg */ 301712099Sjoergtnode_t * 301891592Smarkmbldszof(type_t *tp) 301912099Sjoerg{ 302012099Sjoerg int elem, elsz; 302112099Sjoerg tspec_t st; 302212099Sjoerg 302312099Sjoerg elem = 1; 302412099Sjoerg while (tp->t_tspec == ARRAY) { 302512099Sjoerg elem *= tp->t_dim; 302612099Sjoerg tp = tp->t_subt; 302712099Sjoerg } 302812099Sjoerg if (elem == 0) { 302912099Sjoerg /* cannot take size of incomplete type */ 303012099Sjoerg error(143); 303112099Sjoerg elem = 1; 303212099Sjoerg } 303312099Sjoerg switch (tp->t_tspec) { 303412099Sjoerg case FUNC: 303512099Sjoerg /* cannot take size of function */ 303612099Sjoerg error(144); 303712099Sjoerg elsz = 1; 303812099Sjoerg break; 303912099Sjoerg case STRUCT: 304012099Sjoerg case UNION: 304112099Sjoerg if (incompl(tp)) { 304212099Sjoerg /* cannot take size of incomplete type */ 304312099Sjoerg error(143); 304412099Sjoerg elsz = 1; 304512099Sjoerg } else { 304612099Sjoerg elsz = tp->t_str->size; 304712099Sjoerg } 304812099Sjoerg break; 304912099Sjoerg case ENUM: 305012099Sjoerg if (incompl(tp)) { 305112099Sjoerg /* cannot take size of incomplete type */ 305212099Sjoerg warning(143); 305312099Sjoerg } 305412099Sjoerg /* FALLTHROUGH */ 305512099Sjoerg default: 305612099Sjoerg if (tp->t_isfield) { 305712099Sjoerg /* cannot take size of bit-field */ 305812099Sjoerg error(145); 305912099Sjoerg } 306012099Sjoerg if (tp->t_tspec == VOID) { 306112099Sjoerg /* cannot take size of void */ 306212099Sjoerg error(146); 306312099Sjoerg elsz = 1; 306412099Sjoerg } else { 306512099Sjoerg elsz = size(tp->t_tspec); 306612099Sjoerg if (elsz <= 0) 3067281168Spfg LERROR("bldszof()"); 306812099Sjoerg } 306912099Sjoerg break; 307012099Sjoerg } 307112099Sjoerg 307212099Sjoerg#if SIZEOF_IS_ULONG 307312099Sjoerg st = ULONG; 307412099Sjoerg#else 307512099Sjoerg st = UINT; 307612099Sjoerg#endif 307712099Sjoerg 307891592Smarkm return (getinode(st, (int64_t)(elem * elsz / CHAR_BIT))); 307912099Sjoerg} 308012099Sjoerg 308112099Sjoerg/* 308212099Sjoerg * Type casts. 308312099Sjoerg */ 308412099Sjoergtnode_t * 308591592Smarkmcast(tnode_t *tn, type_t *tp) 308612099Sjoerg{ 308712099Sjoerg tspec_t nt, ot; 308812099Sjoerg 308912099Sjoerg if (tn == NULL) 309012099Sjoerg return (NULL); 309112099Sjoerg 309212099Sjoerg tn = cconv(tn); 309312099Sjoerg 309412099Sjoerg nt = tp->t_tspec; 309512099Sjoerg ot = tn->tn_type->t_tspec; 309612099Sjoerg 309712099Sjoerg if (nt == VOID) { 309812099Sjoerg /* 309912099Sjoerg * XXX ANSI C requires scalar types or void (Plauger&Brodie). 310012099Sjoerg * But this seams really questionable. 310112099Sjoerg */ 310212099Sjoerg } else if (nt == STRUCT || nt == UNION || nt == ARRAY || nt == FUNC) { 310312099Sjoerg /* invalid cast expression */ 310412099Sjoerg error(147); 310512099Sjoerg return (NULL); 310612099Sjoerg } else if (ot == STRUCT || ot == UNION) { 310712099Sjoerg /* invalid cast expression */ 310812099Sjoerg error(147); 310912099Sjoerg return (NULL); 311012099Sjoerg } else if (ot == VOID) { 311112099Sjoerg /* improper cast of void expression */ 311212099Sjoerg error(148); 311312099Sjoerg return (NULL); 311412099Sjoerg } else if (isityp(nt) && issclt(ot)) { 311512099Sjoerg /* ok */ 311612099Sjoerg } else if (isftyp(nt) && isatyp(ot)) { 311712099Sjoerg /* ok */ 311812099Sjoerg } else if (nt == PTR && isityp(ot)) { 311912099Sjoerg /* ok */ 312012099Sjoerg } else if (nt == PTR && ot == PTR) { 312112099Sjoerg if (!tp->t_subt->t_const && tn->tn_type->t_subt->t_const) { 312212099Sjoerg if (hflag) 312312099Sjoerg /* cast discards 'const' from ... */ 312412099Sjoerg warning(275); 312512099Sjoerg } 312612099Sjoerg } else { 312712099Sjoerg /* invalid cast expression */ 312812099Sjoerg error(147); 312912099Sjoerg return (NULL); 313012099Sjoerg } 313112099Sjoerg 313212099Sjoerg tn = convert(CVT, 0, tp, tn); 313312099Sjoerg tn->tn_cast = 1; 313412099Sjoerg 313512099Sjoerg return (tn); 313612099Sjoerg} 313712099Sjoerg 313812099Sjoerg/* 313912099Sjoerg * Create the node for a function argument. 314012099Sjoerg * All necessary conversions and type checks are done in funccall(), because 314112099Sjoerg * in funcarg() we have no information about expected argument types. 314212099Sjoerg */ 314312099Sjoergtnode_t * 314491592Smarkmfuncarg(tnode_t *args, tnode_t *arg) 314512099Sjoerg{ 314612099Sjoerg tnode_t *ntn; 314712099Sjoerg 314812099Sjoerg /* 314912099Sjoerg * If there was a serious error in the expression for the argument, 315012099Sjoerg * create a dummy argument so the positions of the remaining arguments 315112099Sjoerg * will not change. 315212099Sjoerg */ 315312099Sjoerg if (arg == NULL) 315491592Smarkm arg = getinode(INT, (int64_t)0); 315512099Sjoerg 315612099Sjoerg ntn = mktnode(PUSH, arg->tn_type, arg, args); 315712099Sjoerg 315812099Sjoerg return (ntn); 315912099Sjoerg} 316012099Sjoerg 316112099Sjoerg/* 316212099Sjoerg * Create the node for a function call. Also check types of 316312099Sjoerg * function arguments and insert conversions, if necessary. 316412099Sjoerg */ 316512099Sjoergtnode_t * 316691592Smarkmfunccall(tnode_t *func, tnode_t *args) 316712099Sjoerg{ 316812099Sjoerg tnode_t *ntn; 316912099Sjoerg op_t fcop; 317012099Sjoerg 317112099Sjoerg if (func == NULL) 317212099Sjoerg return (NULL); 317312099Sjoerg 317412099Sjoerg if (func->tn_op == NAME && func->tn_type->t_tspec == FUNC) { 317512099Sjoerg fcop = CALL; 317612099Sjoerg } else { 317712099Sjoerg fcop = ICALL; 317812099Sjoerg } 317912099Sjoerg 318012099Sjoerg /* 318112099Sjoerg * after cconv() func will always be a pointer to a function 318212099Sjoerg * if it is a valid function designator. 318312099Sjoerg */ 318412099Sjoerg func = cconv(func); 318512099Sjoerg 318612099Sjoerg if (func->tn_type->t_tspec != PTR || 318712099Sjoerg func->tn_type->t_subt->t_tspec != FUNC) { 318812099Sjoerg /* illegal function */ 318912099Sjoerg error(149); 319012099Sjoerg return (NULL); 319112099Sjoerg } 319212099Sjoerg 319312099Sjoerg args = chkfarg(func->tn_type->t_subt, args); 319412099Sjoerg 319512099Sjoerg ntn = mktnode(fcop, func->tn_type->t_subt->t_subt, func, args); 319612099Sjoerg 319712099Sjoerg return (ntn); 319812099Sjoerg} 319912099Sjoerg 320012099Sjoerg/* 320112099Sjoerg * Check types of all function arguments and insert conversions, 320212099Sjoerg * if necessary. 320312099Sjoerg */ 320412099Sjoergstatic tnode_t * 320591592Smarkmchkfarg(type_t *ftp, tnode_t *args) 320612099Sjoerg{ 320712099Sjoerg tnode_t *arg; 320812099Sjoerg sym_t *asym; 320912099Sjoerg tspec_t at; 321012099Sjoerg int narg, npar, n, i; 321112099Sjoerg 321212099Sjoerg /* get # of args in the prototype */ 321312099Sjoerg npar = 0; 321412099Sjoerg for (asym = ftp->t_args; asym != NULL; asym = asym->s_nxt) 321512099Sjoerg npar++; 321612099Sjoerg 321712099Sjoerg /* get # of args in function call */ 321812099Sjoerg narg = 0; 321912099Sjoerg for (arg = args; arg != NULL; arg = arg->tn_right) 322012099Sjoerg narg++; 322112099Sjoerg 322212099Sjoerg asym = ftp->t_args; 322312099Sjoerg if (ftp->t_proto && npar != narg && !(ftp->t_vararg && npar < narg)) { 322412099Sjoerg /* argument mismatch: %d arg%s passed, %d expected */ 322512099Sjoerg error(150, narg, narg > 1 ? "s" : "", npar); 322612099Sjoerg asym = NULL; 322712099Sjoerg } 322891592Smarkm 322912099Sjoerg for (n = 1; n <= narg; n++) { 323012099Sjoerg 323112099Sjoerg /* 323212099Sjoerg * The rightmost argument is at the top of the argument 323312099Sjoerg * subtree. 323412099Sjoerg */ 323591592Smarkm for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) 323691592Smarkm continue; 323712099Sjoerg 323812099Sjoerg /* some things which are always not allowd */ 323912099Sjoerg if ((at = arg->tn_left->tn_type->t_tspec) == VOID) { 324012099Sjoerg /* void expressions may not be arguments, arg #%d */ 324112099Sjoerg error(151, n); 324212099Sjoerg return (NULL); 324312099Sjoerg } else if ((at == STRUCT || at == UNION) && 324412099Sjoerg incompl(arg->tn_left->tn_type)) { 324512099Sjoerg /* argument cannot have unknown size, arg #%d */ 324612099Sjoerg error(152, n); 324712099Sjoerg return (NULL); 324812099Sjoerg } else if (isityp(at) && arg->tn_left->tn_type->t_isenum && 324912099Sjoerg incompl(arg->tn_left->tn_type)) { 325012099Sjoerg /* argument cannot have unknown size, arg #%d */ 325112099Sjoerg warning(152, n); 325212099Sjoerg } 325312099Sjoerg 325412099Sjoerg /* class conversions (arg in value context) */ 325512099Sjoerg arg->tn_left = cconv(arg->tn_left); 325612099Sjoerg 325712099Sjoerg if (asym != NULL) { 325812099Sjoerg arg->tn_left = parg(n, asym->s_type, arg->tn_left); 325912099Sjoerg } else { 326012099Sjoerg arg->tn_left = promote(NOOP, 1, arg->tn_left); 326112099Sjoerg } 326212099Sjoerg arg->tn_type = arg->tn_left->tn_type; 326312099Sjoerg 326412099Sjoerg if (asym != NULL) 326512099Sjoerg asym = asym->s_nxt; 326612099Sjoerg } 326712099Sjoerg 326812099Sjoerg return (args); 326912099Sjoerg} 327012099Sjoerg 327112099Sjoerg/* 327212099Sjoerg * Compare the type of an argument with the corresponding type of a 327312099Sjoerg * prototype parameter. If it is a valid combination, but both types 327412099Sjoerg * are not the same, insert a conversion to convert the argument into 327512099Sjoerg * the type of the parameter. 327612099Sjoerg */ 327712099Sjoergstatic tnode_t * 327891592Smarkmparg( int n, /* pos of arg */ 327991592Smarkm type_t *tp, /* expected type (from prototype) */ 328091592Smarkm tnode_t *tn) /* argument */ 328112099Sjoerg{ 328212099Sjoerg tnode_t *ln; 328312099Sjoerg int warn; 328412099Sjoerg 328580284Sobrien if ((ln = calloc(1, sizeof (tnode_t))) == NULL) 328680284Sobrien nomem(); 328712099Sjoerg ln->tn_type = tduptyp(tp); 328812099Sjoerg ln->tn_type->t_const = 0; 328912099Sjoerg ln->tn_lvalue = 1; 329012099Sjoerg if (typeok(FARG, n, ln, tn)) { 329112099Sjoerg if (!eqtype(tp, tn->tn_type, 1, 0, (warn = 0, &warn)) || warn) 329212099Sjoerg tn = convert(FARG, n, tp, tn); 329312099Sjoerg } 329412099Sjoerg free(ln); 329512099Sjoerg return (tn); 329612099Sjoerg} 329712099Sjoerg 329812099Sjoerg/* 329912099Sjoerg * Return the value of an integral constant expression. 330012099Sjoerg * If the expression is not constant or its type is not an integer 330112099Sjoerg * type, an error message is printed. 330212099Sjoerg */ 330312099Sjoergval_t * 3304281168Spfgconstant(tnode_t *tn, int required) 330512099Sjoerg{ 330612099Sjoerg val_t *v; 330712099Sjoerg 330812099Sjoerg if (tn != NULL) 330912099Sjoerg tn = cconv(tn); 331012099Sjoerg if (tn != NULL) 331112099Sjoerg tn = promote(NOOP, 0, tn); 331212099Sjoerg 331380284Sobrien if ((v = calloc(1, sizeof (val_t))) == NULL) 331480284Sobrien nomem(); 331512099Sjoerg 331612099Sjoerg if (tn == NULL) { 331712099Sjoerg if (nerr == 0) 3318281168Spfg LERROR("constant()"); 331912099Sjoerg v->v_tspec = INT; 332012099Sjoerg v->v_quad = 1; 332112099Sjoerg return (v); 332212099Sjoerg } 332312099Sjoerg 332412099Sjoerg v->v_tspec = tn->tn_type->t_tspec; 332512099Sjoerg 332612099Sjoerg if (tn->tn_op == CON) { 332712099Sjoerg if (tn->tn_type->t_tspec != tn->tn_val->v_tspec) 3328281168Spfg LERROR("constant()"); 332912099Sjoerg if (isityp(tn->tn_val->v_tspec)) { 333012099Sjoerg v->v_ansiu = tn->tn_val->v_ansiu; 333112099Sjoerg v->v_quad = tn->tn_val->v_quad; 333212099Sjoerg return (v); 333312099Sjoerg } 333412099Sjoerg v->v_quad = tn->tn_val->v_ldbl; 333512099Sjoerg } else { 333612099Sjoerg v->v_quad = 1; 333712099Sjoerg } 333812099Sjoerg 333912099Sjoerg /* integral constant expression expected */ 3340281168Spfg if (required) 3341281168Spfg error(55); 3342281168Spfg else 3343281168Spfg c99ism(318); 334412099Sjoerg 334512099Sjoerg if (!isityp(v->v_tspec)) 334612099Sjoerg v->v_tspec = INT; 334712099Sjoerg 334812099Sjoerg return (v); 334912099Sjoerg} 335012099Sjoerg 335112099Sjoerg/* 335212099Sjoerg * Perform some tests on expressions which can't be done in build() and 335312099Sjoerg * functions called by build(). These tests must be done here because 335412099Sjoerg * we need some information about the context in which the operations 335512099Sjoerg * are performed. 335612099Sjoerg * After all tests are performed, expr() frees the memory which is used 335712099Sjoerg * for the expression. 335812099Sjoerg */ 335912099Sjoergvoid 3360281168Spfgexpr(tnode_t *tn, int vctx, int tctx, int freeblk) 336112099Sjoerg{ 336291592Smarkm 336312099Sjoerg if (tn == NULL && nerr == 0) 3364281168Spfg LERROR("expr()"); 336512099Sjoerg 336612099Sjoerg if (tn == NULL) { 336712099Sjoerg tfreeblk(); 336812099Sjoerg return; 336912099Sjoerg } 337012099Sjoerg 337112099Sjoerg /* expr() is also called in global initialisations */ 337212099Sjoerg if (dcs->d_ctx != EXTERN) 337312099Sjoerg chkreach(); 337412099Sjoerg 337512099Sjoerg chkmisc(tn, vctx, tctx, !tctx, 0, 0, 0); 337612099Sjoerg if (tn->tn_op == ASSIGN) { 337712099Sjoerg if (hflag && tctx) 337812099Sjoerg /* assignment in conditional context */ 337912099Sjoerg warning(159); 338012099Sjoerg } else if (tn->tn_op == CON) { 338112099Sjoerg if (hflag && tctx && !ccflg) 338212099Sjoerg /* constant in conditional context */ 338312099Sjoerg warning(161); 338412099Sjoerg } 338512099Sjoerg if (!modtab[tn->tn_op].m_sideeff) { 338612099Sjoerg /* 338712099Sjoerg * for left operands of COMMA this warning is already 338812099Sjoerg * printed 338912099Sjoerg */ 339012099Sjoerg if (tn->tn_op != COMMA && !vctx && !tctx) 339112099Sjoerg nulleff(tn); 339212099Sjoerg } 339312099Sjoerg if (dflag) 339412099Sjoerg displexpr(tn, 0); 339512099Sjoerg 339612099Sjoerg /* free the tree memory */ 3397281168Spfg if (freeblk) 3398281168Spfg tfreeblk(); 339912099Sjoerg} 340012099Sjoerg 340112099Sjoergstatic void 340291592Smarkmnulleff(tnode_t *tn) 340312099Sjoerg{ 340491592Smarkm 340512099Sjoerg if (!hflag) 340612099Sjoerg return; 340712099Sjoerg 340812099Sjoerg while (!modtab[tn->tn_op].m_sideeff) { 340912099Sjoerg if (tn->tn_op == CVT && tn->tn_type->t_tspec == VOID) { 341012099Sjoerg tn = tn->tn_left; 341112099Sjoerg } else if (tn->tn_op == LOGAND || tn->tn_op == LOGOR) { 341212099Sjoerg /* 341312099Sjoerg * && and || have a side effect if the right operand 341412099Sjoerg * has a side effect. 341512099Sjoerg */ 341612099Sjoerg tn = tn->tn_right; 341712099Sjoerg } else if (tn->tn_op == QUEST) { 341812099Sjoerg /* 341912099Sjoerg * ? has a side effect if at least one of its right 342012099Sjoerg * operands has a side effect 342112099Sjoerg */ 342212099Sjoerg tn = tn->tn_right; 342391592Smarkm } else if (tn->tn_op == COLON || tn->tn_op == COMMA) { 342412099Sjoerg /* 342512099Sjoerg * : has a side effect if at least one of its operands 342612099Sjoerg * has a side effect 342712099Sjoerg */ 342812099Sjoerg if (modtab[tn->tn_left->tn_op].m_sideeff) { 342912099Sjoerg tn = tn->tn_left; 343012099Sjoerg } else if (modtab[tn->tn_right->tn_op].m_sideeff) { 343112099Sjoerg tn = tn->tn_right; 343212099Sjoerg } else { 343312099Sjoerg break; 343412099Sjoerg } 343512099Sjoerg } else { 343612099Sjoerg break; 343712099Sjoerg } 343812099Sjoerg } 343912099Sjoerg if (!modtab[tn->tn_op].m_sideeff) 344012099Sjoerg /* expression has null effect */ 344112099Sjoerg warning(129); 344212099Sjoerg} 344312099Sjoerg 344412099Sjoerg/* 344512099Sjoerg * Dump an expression to stdout 344612099Sjoerg * only used for debugging 344712099Sjoerg */ 344812099Sjoergstatic void 344991592Smarkmdisplexpr(tnode_t *tn, int offs) 345012099Sjoerg{ 345191592Smarkm uint64_t uq; 345212099Sjoerg 345312099Sjoerg if (tn == NULL) { 345412099Sjoerg (void)printf("%*s%s\n", offs, "", "NULL"); 345512099Sjoerg return; 345612099Sjoerg } 345712099Sjoerg (void)printf("%*sop %s ", offs, "", modtab[tn->tn_op].m_name); 345812099Sjoerg 345912099Sjoerg if (tn->tn_op == NAME) { 346012099Sjoerg (void)printf("%s: %s ", 346112099Sjoerg tn->tn_sym->s_name, scltoa(tn->tn_sym->s_scl)); 346212099Sjoerg } else if (tn->tn_op == CON && isftyp(tn->tn_type->t_tspec)) { 346312099Sjoerg (void)printf("%#g ", (double)tn->tn_val->v_ldbl); 346412099Sjoerg } else if (tn->tn_op == CON && isityp(tn->tn_type->t_tspec)) { 346512099Sjoerg uq = tn->tn_val->v_quad; 346612099Sjoerg (void)printf("0x %08lx %08lx ", (long)(uq >> 32) & 0xffffffffl, 346712099Sjoerg (long)uq & 0xffffffffl); 346812099Sjoerg } else if (tn->tn_op == CON) { 346912099Sjoerg if (tn->tn_type->t_tspec != PTR) 3470281168Spfg LERROR("displexpr()"); 347112099Sjoerg (void)printf("0x%0*lx ", (int)(sizeof (void *) * CHAR_BIT / 4), 347212099Sjoerg (u_long)tn->tn_val->v_quad); 347312099Sjoerg } else if (tn->tn_op == STRING) { 347412099Sjoerg if (tn->tn_strg->st_tspec == CHAR) { 347512099Sjoerg (void)printf("\"%s\"", tn->tn_strg->st_cp); 347612099Sjoerg } else { 347712099Sjoerg char *s; 347812099Sjoerg size_t n; 347912099Sjoerg n = MB_CUR_MAX * (tn->tn_strg->st_len + 1); 348080284Sobrien if ((s = malloc(n)) == NULL) 348180284Sobrien nomem(); 348212099Sjoerg (void)wcstombs(s, tn->tn_strg->st_wcp, n); 348312099Sjoerg (void)printf("L\"%s\"", s); 348412099Sjoerg free(s); 348512099Sjoerg } 348612099Sjoerg (void)printf(" "); 348712099Sjoerg } else if (tn->tn_op == FSEL) { 348812099Sjoerg (void)printf("o=%d, l=%d ", tn->tn_type->t_foffs, 348912099Sjoerg tn->tn_type->t_flen); 349012099Sjoerg } 349112099Sjoerg (void)printf("%s\n", ttos(tn->tn_type)); 349212099Sjoerg if (tn->tn_op == NAME || tn->tn_op == CON || tn->tn_op == STRING) 349312099Sjoerg return; 349412099Sjoerg displexpr(tn->tn_left, offs + 2); 349512099Sjoerg if (modtab[tn->tn_op].m_binary || 349612099Sjoerg (tn->tn_op == PUSH && tn->tn_right != NULL)) { 349712099Sjoerg displexpr(tn->tn_right, offs + 2); 349812099Sjoerg } 349912099Sjoerg} 350012099Sjoerg 350112099Sjoerg/* 350212099Sjoerg * Called by expr() to recursively perform some tests. 350312099Sjoerg */ 350412099Sjoerg/* ARGSUSED */ 350512099Sjoergvoid 350691592Smarkmchkmisc(tnode_t *tn, int vctx, int tctx, int eqwarn, int fcall, int rvdisc, 350791592Smarkm int szof) 350812099Sjoerg{ 350912099Sjoerg tnode_t *ln, *rn; 351012099Sjoerg mod_t *mp; 351112099Sjoerg int nrvdisc, cvctx, ctctx; 351212099Sjoerg op_t op; 351312099Sjoerg scl_t sc; 351412099Sjoerg dinfo_t *di; 351512099Sjoerg 351612099Sjoerg if (tn == NULL) 351712099Sjoerg return; 351812099Sjoerg 351912099Sjoerg ln = tn->tn_left; 352012099Sjoerg rn = tn->tn_right; 352112099Sjoerg mp = &modtab[op = tn->tn_op]; 352212099Sjoerg 352312099Sjoerg switch (op) { 352412099Sjoerg case AMPER: 352512099Sjoerg if (ln->tn_op == NAME && (reached || rchflg)) { 352612099Sjoerg if (!szof) 352712099Sjoerg setsflg(ln->tn_sym); 352812099Sjoerg setuflg(ln->tn_sym, fcall, szof); 352912099Sjoerg } 353012099Sjoerg if (ln->tn_op == STAR && ln->tn_left->tn_op == PLUS) 353112099Sjoerg /* check the range of array indices */ 353212099Sjoerg chkaidx(ln->tn_left, 1); 353312099Sjoerg break; 353412099Sjoerg case LOAD: 353512099Sjoerg if (ln->tn_op == STAR && ln->tn_left->tn_op == PLUS) 353612099Sjoerg /* check the range of array indices */ 353712099Sjoerg chkaidx(ln->tn_left, 0); 353812099Sjoerg /* FALLTHROUGH */ 353912099Sjoerg case PUSH: 354012099Sjoerg case INCBEF: 354112099Sjoerg case DECBEF: 354212099Sjoerg case INCAFT: 354312099Sjoerg case DECAFT: 354412099Sjoerg case ADDASS: 354512099Sjoerg case SUBASS: 354612099Sjoerg case MULASS: 354712099Sjoerg case DIVASS: 354812099Sjoerg case MODASS: 354912099Sjoerg case ANDASS: 355012099Sjoerg case ORASS: 355112099Sjoerg case XORASS: 355212099Sjoerg case SHLASS: 355312099Sjoerg case SHRASS: 355412099Sjoerg if (ln->tn_op == NAME && (reached || rchflg)) { 355512099Sjoerg sc = ln->tn_sym->s_scl; 355612099Sjoerg /* 3557108532Sschweikh * Look if there was an asm statement in one of the 355812099Sjoerg * compound statements we are in. If not, we don't 355912099Sjoerg * print a warning. 356012099Sjoerg */ 356112099Sjoerg for (di = dcs; di != NULL; di = di->d_nxt) { 356212099Sjoerg if (di->d_asm) 356312099Sjoerg break; 356412099Sjoerg } 356512099Sjoerg if (sc != EXTERN && sc != STATIC && 356612099Sjoerg !ln->tn_sym->s_set && !szof && di == NULL) { 356712099Sjoerg /* %s may be used before set */ 356812099Sjoerg warning(158, ln->tn_sym->s_name); 356912099Sjoerg setsflg(ln->tn_sym); 357012099Sjoerg } 357112099Sjoerg setuflg(ln->tn_sym, 0, 0); 357212099Sjoerg } 357312099Sjoerg break; 357412099Sjoerg case ASSIGN: 357512099Sjoerg if (ln->tn_op == NAME && !szof && (reached || rchflg)) { 357612099Sjoerg setsflg(ln->tn_sym); 357712099Sjoerg if (ln->tn_sym->s_scl == EXTERN) 357812099Sjoerg outusg(ln->tn_sym); 357912099Sjoerg } 358012099Sjoerg if (ln->tn_op == STAR && ln->tn_left->tn_op == PLUS) 358112099Sjoerg /* check the range of array indices */ 358212099Sjoerg chkaidx(ln->tn_left, 0); 358312099Sjoerg break; 358412099Sjoerg case CALL: 358512099Sjoerg if (ln->tn_op != AMPER || ln->tn_left->tn_op != NAME) 3586281168Spfg LERROR("chkmisc()"); 358712099Sjoerg if (!szof) 358812099Sjoerg outcall(tn, vctx || tctx, rvdisc); 358912099Sjoerg break; 359012099Sjoerg case EQ: 359112099Sjoerg /* equality operator "==" found where "=" was exp. */ 359212099Sjoerg if (hflag && eqwarn) 359312099Sjoerg warning(160); 359412099Sjoerg break; 359512099Sjoerg case CON: 359612099Sjoerg case NAME: 359712099Sjoerg case STRING: 359812099Sjoerg return; 359912099Sjoerg /* LINTED (enumeration values not handled in switch) */ 360091592Smarkm case OR: 360191592Smarkm case XOR: 360291592Smarkm case NE: 360391592Smarkm case GE: 360491592Smarkm case GT: 360591592Smarkm case LE: 360691592Smarkm case LT: 360791592Smarkm case SHR: 360891592Smarkm case SHL: 360991592Smarkm case MINUS: 361091592Smarkm case PLUS: 361191592Smarkm case MOD: 361291592Smarkm case DIV: 361391592Smarkm case MULT: 361491592Smarkm case STAR: 361591592Smarkm case UMINUS: 361691592Smarkm case UPLUS: 361791592Smarkm case DEC: 361891592Smarkm case INC: 361991592Smarkm case COMPL: 362091592Smarkm case NOT: 362191592Smarkm case POINT: 362291592Smarkm case ARROW: 362391592Smarkm case NOOP: 362491592Smarkm case AND: 362591592Smarkm case FARG: 362691592Smarkm case CASE: 362791592Smarkm case INIT: 362891592Smarkm case RETURN: 362991592Smarkm case ICALL: 363091592Smarkm case CVT: 363191592Smarkm case COMMA: 363291592Smarkm case FSEL: 363391592Smarkm case COLON: 363491592Smarkm case QUEST: 363591592Smarkm case LOGOR: 363691592Smarkm case LOGAND: 363791592Smarkm break; 363812099Sjoerg } 363912099Sjoerg 364012099Sjoerg cvctx = mp->m_vctx; 364112099Sjoerg ctctx = mp->m_tctx; 364212099Sjoerg /* 364312099Sjoerg * values of operands of ':' are not used if the type of at least 364412099Sjoerg * one of the operands (for gcc compatibility) is void 364512099Sjoerg * XXX test/value context of QUEST should probably be used as 364612099Sjoerg * context for both operands of COLON 364712099Sjoerg */ 364812099Sjoerg if (op == COLON && tn->tn_type->t_tspec == VOID) 364912099Sjoerg cvctx = ctctx = 0; 365012099Sjoerg nrvdisc = op == CVT && tn->tn_type->t_tspec == VOID; 365112099Sjoerg chkmisc(ln, cvctx, ctctx, mp->m_eqwarn, op == CALL, nrvdisc, szof); 365212099Sjoerg 365312099Sjoerg switch (op) { 365412099Sjoerg case PUSH: 365512099Sjoerg if (rn != NULL) 365612099Sjoerg chkmisc(rn, 0, 0, mp->m_eqwarn, 0, 0, szof); 365712099Sjoerg break; 365812099Sjoerg case LOGAND: 365912099Sjoerg case LOGOR: 366012099Sjoerg chkmisc(rn, 0, 1, mp->m_eqwarn, 0, 0, szof); 366112099Sjoerg break; 366212099Sjoerg case COLON: 366312099Sjoerg chkmisc(rn, cvctx, ctctx, mp->m_eqwarn, 0, 0, szof); 366412099Sjoerg break; 366591592Smarkm case COMMA: 366691592Smarkm chkmisc(rn, vctx, tctx, mp->m_eqwarn, 0, 0, szof); 366791592Smarkm break; 366812099Sjoerg default: 366912099Sjoerg if (mp->m_binary) 367012099Sjoerg chkmisc(rn, 1, 0, mp->m_eqwarn, 0, 0, szof); 367112099Sjoerg break; 367212099Sjoerg } 367312099Sjoerg 367412099Sjoerg} 367512099Sjoerg 367612099Sjoerg/* 367712099Sjoerg * Checks the range of array indices, if possible. 367812099Sjoerg * amper is set if only the address of the element is used. This 367912099Sjoerg * means that the index is allowd to refere to the first element 368012099Sjoerg * after the array. 368112099Sjoerg */ 368212099Sjoergstatic void 368391592Smarkmchkaidx(tnode_t *tn, int amper) 368412099Sjoerg{ 368512099Sjoerg int dim; 368612099Sjoerg tnode_t *ln, *rn; 368712099Sjoerg int elsz; 368891592Smarkm int64_t con; 368912099Sjoerg 369012099Sjoerg ln = tn->tn_left; 369112099Sjoerg rn = tn->tn_right; 369212099Sjoerg 369312099Sjoerg /* We can only check constant indices. */ 369412099Sjoerg if (rn->tn_op != CON) 369512099Sjoerg return; 369612099Sjoerg 369712099Sjoerg /* Return if the left node does not stem from an array. */ 369812099Sjoerg if (ln->tn_op != AMPER) 369912099Sjoerg return; 370012099Sjoerg if (ln->tn_left->tn_op != STRING && ln->tn_left->tn_op != NAME) 370112099Sjoerg return; 370212099Sjoerg if (ln->tn_left->tn_type->t_tspec != ARRAY) 370312099Sjoerg return; 370491592Smarkm 370512099Sjoerg /* 370612099Sjoerg * For incomplete array types, we can print a warning only if 370712099Sjoerg * the index is negative. 370812099Sjoerg */ 370912099Sjoerg if (incompl(ln->tn_left->tn_type) && rn->tn_val->v_quad >= 0) 371012099Sjoerg return; 371112099Sjoerg 371212099Sjoerg /* Get the size of one array element */ 371312099Sjoerg if ((elsz = length(ln->tn_type->t_subt, NULL)) == 0) 371412099Sjoerg return; 371512099Sjoerg elsz /= CHAR_BIT; 371612099Sjoerg 371712099Sjoerg /* Change the unit of the index from bytes to element size. */ 371812099Sjoerg if (isutyp(rn->tn_type->t_tspec)) { 371991592Smarkm con = (uint64_t)rn->tn_val->v_quad / elsz; 372012099Sjoerg } else { 372112099Sjoerg con = rn->tn_val->v_quad / elsz; 372212099Sjoerg } 372312099Sjoerg 372412099Sjoerg dim = ln->tn_left->tn_type->t_dim + (amper ? 1 : 0); 372512099Sjoerg 372612099Sjoerg if (!isutyp(rn->tn_type->t_tspec) && con < 0) { 372712099Sjoerg /* array subscript cannot be negative: %ld */ 372812099Sjoerg warning(167, (long)con); 372991592Smarkm } else if (dim > 0 && (uint64_t)con >= dim) { 373012099Sjoerg /* array subscript cannot be > %d: %ld */ 373112099Sjoerg warning(168, dim - 1, (long)con); 373212099Sjoerg } 373312099Sjoerg} 373412099Sjoerg 373512099Sjoerg/* 373675697Sasmodai * Check for ordered comparisons of unsigned values with 0. 373712099Sjoerg */ 373812099Sjoergstatic void 373991592Smarkmchkcomp(op_t op, tnode_t *ln, tnode_t *rn) 374012099Sjoerg{ 3741281168Spfg char buf[64]; 374212099Sjoerg tspec_t lt, rt; 374312099Sjoerg mod_t *mp; 374412099Sjoerg 374512099Sjoerg lt = ln->tn_type->t_tspec; 374612099Sjoerg rt = rn->tn_type->t_tspec; 374712099Sjoerg mp = &modtab[op]; 374812099Sjoerg 374912099Sjoerg if (ln->tn_op != CON && rn->tn_op != CON) 375012099Sjoerg return; 375112099Sjoerg 375212099Sjoerg if (!isityp(lt) || !isityp(rt)) 375312099Sjoerg return; 375412099Sjoerg 375512099Sjoerg if ((hflag || pflag) && lt == CHAR && rn->tn_op == CON && 375612099Sjoerg (rn->tn_val->v_quad < 0 || 375712099Sjoerg rn->tn_val->v_quad > ~(~0 << (CHAR_BIT - 1)))) { 375875697Sasmodai /* nonportable character comparison, op %s */ 375912099Sjoerg warning(230, mp->m_name); 376012099Sjoerg return; 376112099Sjoerg } 376212099Sjoerg if ((hflag || pflag) && rt == CHAR && ln->tn_op == CON && 376312099Sjoerg (ln->tn_val->v_quad < 0 || 376412099Sjoerg ln->tn_val->v_quad > ~(~0 << (CHAR_BIT - 1)))) { 376575697Sasmodai /* nonportable character comparison, op %s */ 376612099Sjoerg warning(230, mp->m_name); 376712099Sjoerg return; 376812099Sjoerg } 376912099Sjoerg if (isutyp(lt) && !isutyp(rt) && 377012099Sjoerg rn->tn_op == CON && rn->tn_val->v_quad <= 0) { 377112099Sjoerg if (rn->tn_val->v_quad < 0) { 377275697Sasmodai /* comparison of %s with %s, op %s */ 3773281168Spfg warning(162, tyname(buf, sizeof(buf), ln->tn_type), 3774281168Spfg "negative constant", mp->m_name); 377512099Sjoerg } else if (op == LT || op == GE || (hflag && op == LE)) { 377675697Sasmodai /* comparison of %s with %s, op %s */ 3777281168Spfg warning(162, tyname(buf, sizeof(buf), ln->tn_type), 3778281168Spfg "0", mp->m_name); 377912099Sjoerg } 378012099Sjoerg return; 378112099Sjoerg } 378212099Sjoerg if (isutyp(rt) && !isutyp(lt) && 378312099Sjoerg ln->tn_op == CON && ln->tn_val->v_quad <= 0) { 378412099Sjoerg if (ln->tn_val->v_quad < 0) { 378575697Sasmodai /* comparison of %s with %s, op %s */ 3786281168Spfg warning(162, "negative constant", 3787281168Spfg tyname(buf, sizeof(buf), rn->tn_type), mp->m_name); 378812099Sjoerg } else if (op == GT || op == LE || (hflag && op == GE)) { 378975697Sasmodai /* comparison of %s with %s, op %s */ 3790281168Spfg warning(162, "0", tyname(buf, sizeof(buf), rn->tn_type), 3791281168Spfg mp->m_name); 379212099Sjoerg } 379312099Sjoerg return; 379412099Sjoerg } 379512099Sjoerg} 379612099Sjoerg 379712099Sjoerg/* 379812099Sjoerg * Takes an expression an returns 0 if this expression can be used 379912099Sjoerg * for static initialisation, otherwise -1. 380012099Sjoerg * 3801281168Spfg * Constant initialisation expressions must be constant or an address 380212099Sjoerg * of a static object with an optional offset. In the first case, 380312099Sjoerg * the result is returned in *offsp. In the second case, the static 380412099Sjoerg * object is returned in *symp and the offset in *offsp. 380512099Sjoerg * 380612099Sjoerg * The expression can consist of PLUS, MINUS, AMPER, NAME, STRING and 380712099Sjoerg * CON. Type conversions are allowed if they do not change binary 380812099Sjoerg * representation (including width). 380912099Sjoerg */ 381012099Sjoergint 381191592Smarkmconaddr(tnode_t *tn, sym_t **symp, ptrdiff_t *offsp) 381212099Sjoerg{ 381312099Sjoerg sym_t *sym; 381412099Sjoerg ptrdiff_t offs1, offs2; 381512099Sjoerg tspec_t t, ot; 381612099Sjoerg 381712099Sjoerg switch (tn->tn_op) { 381812099Sjoerg case MINUS: 3819281168Spfg if (tn->tn_right->tn_op == CVT) 3820281168Spfg return conaddr(tn->tn_right, symp, offsp); 3821281168Spfg else if (tn->tn_right->tn_op != CON) 382212099Sjoerg return (-1); 382312099Sjoerg /* FALLTHROUGH */ 382412099Sjoerg case PLUS: 382512099Sjoerg offs1 = offs2 = 0; 382612099Sjoerg if (tn->tn_left->tn_op == CON) { 382712099Sjoerg offs1 = (ptrdiff_t)tn->tn_left->tn_val->v_quad; 382812099Sjoerg if (conaddr(tn->tn_right, &sym, &offs2) == -1) 382912099Sjoerg return (-1); 383012099Sjoerg } else if (tn->tn_right->tn_op == CON) { 383112099Sjoerg offs2 = (ptrdiff_t)tn->tn_right->tn_val->v_quad; 383212099Sjoerg if (tn->tn_op == MINUS) 383312099Sjoerg offs2 = -offs2; 383412099Sjoerg if (conaddr(tn->tn_left, &sym, &offs1) == -1) 383512099Sjoerg return (-1); 383612099Sjoerg } else { 383712099Sjoerg return (-1); 383812099Sjoerg } 383912099Sjoerg *symp = sym; 384012099Sjoerg *offsp = offs1 + offs2; 384112099Sjoerg break; 384212099Sjoerg case AMPER: 384312099Sjoerg if (tn->tn_left->tn_op == NAME) { 384412099Sjoerg *symp = tn->tn_left->tn_sym; 384512099Sjoerg *offsp = 0; 384612099Sjoerg } else if (tn->tn_left->tn_op == STRING) { 384712099Sjoerg /* 384812099Sjoerg * If this would be the front end of a compiler we 384912099Sjoerg * would return a label instead of 0. 385012099Sjoerg */ 385112099Sjoerg *offsp = 0; 385212099Sjoerg } 385312099Sjoerg break; 385412099Sjoerg case CVT: 385512099Sjoerg t = tn->tn_type->t_tspec; 385612099Sjoerg ot = tn->tn_left->tn_type->t_tspec; 3857281168Spfg if ((!isityp(t) && t != PTR) || (!isityp(ot) && ot != PTR)) 385812099Sjoerg return (-1); 3859281168Spfg else if (psize(t) != psize(ot)) { 386012099Sjoerg return (-1); 386112099Sjoerg } 386212099Sjoerg if (conaddr(tn->tn_left, symp, offsp) == -1) 386312099Sjoerg return (-1); 386412099Sjoerg break; 386512099Sjoerg default: 386612099Sjoerg return (-1); 386712099Sjoerg } 386812099Sjoerg return (0); 386912099Sjoerg} 387012099Sjoerg 387112099Sjoerg/* 387212099Sjoerg * Concatenate two string constants. 387312099Sjoerg */ 387412099Sjoergstrg_t * 387591592Smarkmcatstrg(strg_t *strg1, strg_t *strg2) 387612099Sjoerg{ 387712099Sjoerg size_t len1, len2, len; 387812099Sjoerg 387912099Sjoerg if (strg1->st_tspec != strg2->st_tspec) { 388012099Sjoerg /* cannot concatenate wide and regular string literals */ 388112099Sjoerg error(292); 388212099Sjoerg return (strg1); 388312099Sjoerg } 388412099Sjoerg 388512099Sjoerg len = (len1 = strg1->st_len) + (len2 = strg2->st_len); 388612099Sjoerg 388712099Sjoerg if (strg1->st_tspec == CHAR) { 388880284Sobrien if ((strg1->st_cp = realloc(strg1->st_cp, len + 1)) == NULL) 388980284Sobrien nomem(); 389012099Sjoerg (void)memcpy(strg1->st_cp + len1, strg2->st_cp, len2 + 1); 389112099Sjoerg free(strg2->st_cp); 389212099Sjoerg } else { 389380284Sobrien if ((strg1->st_wcp = realloc(strg1->st_wcp, (len + 1) * 389480284Sobrien sizeof (wchar_t))) == NULL) 389580284Sobrien nomem(); 389612099Sjoerg (void)memcpy(strg1->st_wcp + len1, strg2->st_wcp, 389712099Sjoerg (len2 + 1) * sizeof (wchar_t)); 389812099Sjoerg free(strg2->st_wcp); 389912099Sjoerg } 3900224702Skevlo strg1->st_len = len; 390112099Sjoerg free(strg2); 390212099Sjoerg 390312099Sjoerg return (strg1); 390412099Sjoerg} 390512099Sjoerg 390612099Sjoerg/* 390712099Sjoerg * Print a warning if the given node has operands which should be 390812099Sjoerg * parenthesized. 390912099Sjoerg * 391012099Sjoerg * XXX Does not work if an operand is a constant expression. Constant 391112099Sjoerg * expressions are already folded. 391212099Sjoerg */ 391312099Sjoergstatic void 391491592Smarkmprecconf(tnode_t *tn) 391512099Sjoerg{ 391612099Sjoerg tnode_t *ln, *rn; 391791592Smarkm op_t lop, rop = NOOP; 391891592Smarkm int lparn, rparn = 0; 391912099Sjoerg mod_t *mp; 392012099Sjoerg int warn; 392112099Sjoerg 392212099Sjoerg if (!hflag) 392312099Sjoerg return; 392412099Sjoerg 392512099Sjoerg mp = &modtab[tn->tn_op]; 392612099Sjoerg 392712099Sjoerg lparn = 0; 392812099Sjoerg for (ln = tn->tn_left; ln->tn_op == CVT; ln = ln->tn_left) 392912099Sjoerg lparn |= ln->tn_parn; 393012099Sjoerg lparn |= ln->tn_parn; 393112099Sjoerg lop = ln->tn_op; 393212099Sjoerg 393312099Sjoerg if (mp->m_binary) { 393412099Sjoerg rparn = 0; 393512099Sjoerg for (rn = tn->tn_right; tn->tn_op == CVT; rn = rn->tn_left) 393612099Sjoerg rparn |= rn->tn_parn; 393712099Sjoerg rparn |= rn->tn_parn; 393812099Sjoerg rop = rn->tn_op; 393912099Sjoerg } 394012099Sjoerg 394112099Sjoerg warn = 0; 394212099Sjoerg 394312099Sjoerg switch (tn->tn_op) { 394412099Sjoerg case SHL: 394512099Sjoerg case SHR: 394612099Sjoerg if (!lparn && (lop == PLUS || lop == MINUS)) { 394712099Sjoerg warn = 1; 394812099Sjoerg } else if (!rparn && (rop == PLUS || rop == MINUS)) { 394912099Sjoerg warn = 1; 395012099Sjoerg } 395112099Sjoerg break; 395212099Sjoerg case LOGOR: 395312099Sjoerg if (!lparn && lop == LOGAND) { 395412099Sjoerg warn = 1; 395512099Sjoerg } else if (!rparn && rop == LOGAND) { 395612099Sjoerg warn = 1; 395712099Sjoerg } 395812099Sjoerg break; 395912099Sjoerg case AND: 396012099Sjoerg case XOR: 396112099Sjoerg case OR: 396212099Sjoerg if (!lparn && lop != tn->tn_op) { 396312099Sjoerg if (lop == PLUS || lop == MINUS) { 396412099Sjoerg warn = 1; 396512099Sjoerg } else if (lop == AND || lop == XOR) { 396612099Sjoerg warn = 1; 396712099Sjoerg } 396812099Sjoerg } 396912099Sjoerg if (!warn && !rparn && rop != tn->tn_op) { 397012099Sjoerg if (rop == PLUS || rop == MINUS) { 397112099Sjoerg warn = 1; 397212099Sjoerg } else if (rop == AND || rop == XOR) { 397312099Sjoerg warn = 1; 397412099Sjoerg } 397512099Sjoerg } 397612099Sjoerg break; 397712099Sjoerg /* LINTED (enumeration values not handled in switch) */ 397891592Smarkm case DECAFT: 397991592Smarkm case XORASS: 398091592Smarkm case SHLASS: 398191592Smarkm case NOOP: 398291592Smarkm case ARROW: 398391592Smarkm case ORASS: 398491592Smarkm case POINT: 398591592Smarkm case NAME: 398691592Smarkm case NOT: 398791592Smarkm case COMPL: 398891592Smarkm case CON: 398991592Smarkm case INC: 399091592Smarkm case STRING: 399191592Smarkm case DEC: 399291592Smarkm case INCBEF: 399391592Smarkm case DECBEF: 399491592Smarkm case INCAFT: 399591592Smarkm case FSEL: 399691592Smarkm case CALL: 399791592Smarkm case COMMA: 399891592Smarkm case CVT: 399991592Smarkm case ICALL: 400091592Smarkm case LOAD: 400191592Smarkm case PUSH: 400291592Smarkm case RETURN: 400391592Smarkm case INIT: 400491592Smarkm case CASE: 400591592Smarkm case FARG: 400691592Smarkm case SUBASS: 400791592Smarkm case ADDASS: 400891592Smarkm case MODASS: 400991592Smarkm case DIVASS: 401091592Smarkm case MULASS: 401191592Smarkm case ASSIGN: 401291592Smarkm case COLON: 401391592Smarkm case QUEST: 401491592Smarkm case LOGAND: 401591592Smarkm case NE: 401691592Smarkm case EQ: 401791592Smarkm case GE: 401891592Smarkm case GT: 401991592Smarkm case LE: 402091592Smarkm case LT: 402191592Smarkm case MINUS: 402291592Smarkm case PLUS: 402391592Smarkm case MOD: 402491592Smarkm case DIV: 402591592Smarkm case MULT: 402691592Smarkm case AMPER: 402791592Smarkm case STAR: 402891592Smarkm case UMINUS: 402991592Smarkm case SHRASS: 403091592Smarkm case UPLUS: 403191592Smarkm case ANDASS: 403291592Smarkm break; 403312099Sjoerg } 403412099Sjoerg 403512099Sjoerg if (warn) { 403612099Sjoerg /* precedence confusion possible: parenthesize! */ 403712099Sjoerg warning(169); 403812099Sjoerg } 403912099Sjoerg 404012099Sjoerg} 4041