191592Smarkm/* $NetBSD: tree.c,v 1.24 2002/01/31 22:30:20 tv 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) 3691592Smarkm__RCSID("$NetBSD: tree.c,v 1.24 2002/01/31 22:30:20 tv 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 { 30512099Sjoerg /* %s undefined */ 30612099Sjoerg error(99, sym->s_name); 30712099Sjoerg } 30812099Sjoerg } 30912099Sjoerg 31012099Sjoerg if (sym->s_kind != FVFT && sym->s_kind != FMOS) 31112099Sjoerg lerror("getnnode() 1"); 31212099Sjoerg 31312099Sjoerg n = getnode(); 31412099Sjoerg n->tn_type = sym->s_type; 31512099Sjoerg if (sym->s_scl != ENUMCON) { 31612099Sjoerg n->tn_op = NAME; 31712099Sjoerg n->tn_sym = sym; 31812099Sjoerg if (sym->s_kind == FVFT && sym->s_type->t_tspec != FUNC) 31912099Sjoerg n->tn_lvalue = 1; 32012099Sjoerg } else { 32112099Sjoerg n->tn_op = CON; 32212099Sjoerg n->tn_val = tgetblk(sizeof (val_t)); 32312099Sjoerg *n->tn_val = sym->s_value; 32412099Sjoerg } 32512099Sjoerg 32612099Sjoerg return (n); 32712099Sjoerg} 32812099Sjoerg 32912099Sjoerg/* 33012099Sjoerg * Create a node for a string. 33112099Sjoerg */ 33212099Sjoergtnode_t * 33391592Smarkmgetsnode(strg_t *strg) 33412099Sjoerg{ 33512099Sjoerg size_t len; 33612099Sjoerg tnode_t *n; 33712099Sjoerg 33812099Sjoerg len = strg->st_len; 33912099Sjoerg 34012099Sjoerg n = getnode(); 34112099Sjoerg 34212099Sjoerg n->tn_op = STRING; 34312099Sjoerg n->tn_type = tincref(gettyp(strg->st_tspec), ARRAY); 34412099Sjoerg n->tn_type->t_dim = len + 1; 34512099Sjoerg n->tn_lvalue = 1; 34612099Sjoerg 34712099Sjoerg n->tn_strg = tgetblk(sizeof (strg_t)); 34812099Sjoerg n->tn_strg->st_tspec = strg->st_tspec; 34912099Sjoerg n->tn_strg->st_len = len; 35012099Sjoerg 35112099Sjoerg if (strg->st_tspec == CHAR) { 35212099Sjoerg n->tn_strg->st_cp = tgetblk(len + 1); 35312099Sjoerg (void)memcpy(n->tn_strg->st_cp, strg->st_cp, len + 1); 35412099Sjoerg free(strg->st_cp); 35512099Sjoerg } else { 35612099Sjoerg n->tn_strg->st_wcp = tgetblk((len + 1) * sizeof (wchar_t)); 35712099Sjoerg (void)memcpy(n->tn_strg->st_wcp, strg->st_wcp, 35812099Sjoerg (len + 1) * sizeof (wchar_t)); 35912099Sjoerg free(strg->st_wcp); 36012099Sjoerg } 36112099Sjoerg free(strg); 36212099Sjoerg 36312099Sjoerg return (n); 36412099Sjoerg} 36512099Sjoerg 36612099Sjoerg/* 36712099Sjoerg * Returns a symbol which has the same name as the msym argument and is a 36812099Sjoerg * member of the struct or union specified by the tn argument. 36912099Sjoerg */ 37012099Sjoergsym_t * 37191592Smarkmstrmemb(tnode_t *tn, op_t op, sym_t *msym) 37212099Sjoerg{ 37312099Sjoerg str_t *str; 37412099Sjoerg type_t *tp; 37512099Sjoerg sym_t *sym, *csym; 37612099Sjoerg int eq; 37712099Sjoerg tspec_t t; 37812099Sjoerg 37912099Sjoerg /* 38012099Sjoerg * Remove the member if it was unknown until now (Which means 38112099Sjoerg * that no defined struct or union has a member with the same name). 38212099Sjoerg */ 38312099Sjoerg if (msym->s_scl == NOSCL) { 38412099Sjoerg /* undefined struct/union member: %s */ 38512099Sjoerg error(101, msym->s_name); 38612099Sjoerg rmsym(msym); 38712099Sjoerg msym->s_kind = FMOS; 38812099Sjoerg msym->s_scl = MOS; 38912099Sjoerg msym->s_styp = tgetblk(sizeof (str_t)); 39012099Sjoerg msym->s_styp->stag = tgetblk(sizeof (sym_t)); 39112099Sjoerg msym->s_styp->stag->s_name = unnamed; 39212099Sjoerg msym->s_value.v_tspec = INT; 39312099Sjoerg return (msym); 39412099Sjoerg } 39512099Sjoerg 39612099Sjoerg /* Set str to the tag of which msym is expected to be a member. */ 39712099Sjoerg str = NULL; 39812099Sjoerg t = (tp = tn->tn_type)->t_tspec; 39912099Sjoerg if (op == POINT) { 40012099Sjoerg if (t == STRUCT || t == UNION) 40112099Sjoerg str = tp->t_str; 40212099Sjoerg } else if (op == ARROW && t == PTR) { 40312099Sjoerg t = (tp = tp->t_subt)->t_tspec; 40412099Sjoerg if (t == STRUCT || t == UNION) 40512099Sjoerg str = tp->t_str; 40612099Sjoerg } 40712099Sjoerg 40812099Sjoerg /* 40912099Sjoerg * If this struct/union has a member with the name of msym, return 41012099Sjoerg * return this it. 41112099Sjoerg */ 41212099Sjoerg if (str != NULL) { 41312099Sjoerg for (sym = msym; sym != NULL; sym = sym->s_link) { 41412099Sjoerg if (sym->s_scl != MOS && sym->s_scl != MOU) 41512099Sjoerg continue; 41612099Sjoerg if (sym->s_styp != str) 41712099Sjoerg continue; 41812099Sjoerg if (strcmp(sym->s_name, msym->s_name) != 0) 41912099Sjoerg continue; 42012099Sjoerg return (sym); 42112099Sjoerg } 42212099Sjoerg } 42312099Sjoerg 42412099Sjoerg /* 42512099Sjoerg * Set eq to 0 if there are struct/union members with the same name 42612099Sjoerg * and different types and/or offsets. 42712099Sjoerg */ 42812099Sjoerg eq = 1; 42912099Sjoerg for (csym = msym; csym != NULL; csym = csym->s_link) { 43012099Sjoerg if (csym->s_scl != MOS && csym->s_scl != MOU) 43112099Sjoerg continue; 43212099Sjoerg if (strcmp(msym->s_name, csym->s_name) != 0) 43312099Sjoerg continue; 43412099Sjoerg for (sym = csym->s_link ; sym != NULL; sym = sym->s_link) { 43512099Sjoerg int w; 43612099Sjoerg 43712099Sjoerg if (sym->s_scl != MOS && sym->s_scl != MOU) 43812099Sjoerg continue; 43912099Sjoerg if (strcmp(csym->s_name, sym->s_name) != 0) 44012099Sjoerg continue; 44112099Sjoerg if (csym->s_value.v_quad != sym->s_value.v_quad) { 44212099Sjoerg eq = 0; 44312099Sjoerg break; 44412099Sjoerg } 44512099Sjoerg w = 0; 44612099Sjoerg eq = eqtype(csym->s_type, sym->s_type, 0, 0, &w) && !w; 44712099Sjoerg if (!eq) 44812099Sjoerg break; 44912099Sjoerg if (csym->s_field != sym->s_field) { 45012099Sjoerg eq = 0; 45112099Sjoerg break; 45212099Sjoerg } 45312099Sjoerg if (csym->s_field) { 45412099Sjoerg type_t *tp1, *tp2; 45512099Sjoerg 45612099Sjoerg tp1 = csym->s_type; 45712099Sjoerg tp2 = sym->s_type; 45812099Sjoerg if (tp1->t_flen != tp2->t_flen) { 45912099Sjoerg eq = 0; 46012099Sjoerg break; 46112099Sjoerg } 46212099Sjoerg if (tp1->t_foffs != tp2->t_foffs) { 46312099Sjoerg eq = 0; 46412099Sjoerg break; 46512099Sjoerg } 46612099Sjoerg } 46712099Sjoerg } 46812099Sjoerg if (!eq) 46912099Sjoerg break; 47012099Sjoerg } 47112099Sjoerg 47212099Sjoerg /* 47312099Sjoerg * Now handle the case in which the left operand refers really 47412099Sjoerg * to a struct/union, but the right operand is not member of it. 47512099Sjoerg */ 47612099Sjoerg if (str != NULL) { 47712099Sjoerg /* illegal member use: %s */ 47812099Sjoerg if (eq && tflag) { 47912099Sjoerg warning(102, msym->s_name); 48012099Sjoerg } else { 48112099Sjoerg error(102, msym->s_name); 48212099Sjoerg } 48312099Sjoerg return (msym); 48412099Sjoerg } 48512099Sjoerg 48612099Sjoerg /* 48712099Sjoerg * Now the left operand of ARROW does not point to a struct/union 48812099Sjoerg * or the left operand of POINT is no struct/union. 48912099Sjoerg */ 49012099Sjoerg if (eq) { 49112099Sjoerg if (op == POINT) { 49212099Sjoerg /* left operand of "." must be struct/union object */ 49312099Sjoerg if (tflag) { 49412099Sjoerg warning(103); 49512099Sjoerg } else { 49612099Sjoerg error(103); 49712099Sjoerg } 49812099Sjoerg } else { 49912099Sjoerg /* left operand of "->" must be pointer to ... */ 50012099Sjoerg if (tflag && tn->tn_type->t_tspec == PTR) { 50112099Sjoerg warning(104); 50212099Sjoerg } else { 50312099Sjoerg error(104); 50412099Sjoerg } 50512099Sjoerg } 50612099Sjoerg } else { 50712099Sjoerg if (tflag) { 50812099Sjoerg /* non-unique member requires struct/union %s */ 50912099Sjoerg error(105, op == POINT ? "object" : "pointer"); 51012099Sjoerg } else { 51112099Sjoerg /* unacceptable operand of %s */ 51212099Sjoerg error(111, modtab[op].m_name); 51312099Sjoerg } 51412099Sjoerg } 51512099Sjoerg 51612099Sjoerg return (msym); 51712099Sjoerg} 51812099Sjoerg 51912099Sjoerg/* 52012099Sjoerg * Create a tree node. Called for most operands except function calls, 52112099Sjoerg * sizeof and casts. 52212099Sjoerg * 52312099Sjoerg * op operator 52412099Sjoerg * ln left operand 52512099Sjoerg * rn if not NULL, right operand 52612099Sjoerg */ 52712099Sjoergtnode_t * 52891592Smarkmbuild(op_t op, tnode_t *ln, tnode_t *rn) 52912099Sjoerg{ 53012099Sjoerg mod_t *mp; 53112099Sjoerg tnode_t *ntn; 53212099Sjoerg type_t *rtp; 53312099Sjoerg 53412099Sjoerg mp = &modtab[op]; 53512099Sjoerg 53612099Sjoerg /* If there was an error in one of the operands, return. */ 53712099Sjoerg if (ln == NULL || (mp->m_binary && rn == NULL)) 53812099Sjoerg return (NULL); 53912099Sjoerg 54012099Sjoerg /* 54112099Sjoerg * Apply class conversions to the left operand, but only if its 54212099Sjoerg * value is needed or it is compaired with null. 54312099Sjoerg */ 54412099Sjoerg if (mp->m_vctx || mp->m_tctx) 54512099Sjoerg ln = cconv(ln); 54612099Sjoerg /* 54712099Sjoerg * The right operand is almost always in a test or value context, 54812099Sjoerg * except if it is a struct or union member. 54912099Sjoerg */ 55012099Sjoerg if (mp->m_binary && op != ARROW && op != POINT) 55112099Sjoerg rn = cconv(rn); 55212099Sjoerg 55312099Sjoerg /* 55475697Sasmodai * Print some warnings for comparisons of unsigned values with 55512099Sjoerg * constants lower than or equal to null. This must be done 55612099Sjoerg * before promote() because otherwise unsigned char and unsigned 55712099Sjoerg * short would be promoted to int. Also types are tested to be 55812099Sjoerg * CHAR, which would also become int. 55912099Sjoerg */ 56012099Sjoerg if (mp->m_comp) 56112099Sjoerg chkcomp(op, ln, rn); 56212099Sjoerg 56312099Sjoerg /* 56412099Sjoerg * Promote the left operand if it is in a test or value context 56512099Sjoerg */ 56612099Sjoerg if (mp->m_vctx || mp->m_tctx) 56712099Sjoerg ln = promote(op, 0, ln); 56812099Sjoerg /* 56912099Sjoerg * Promote the right operand, but only if it is no struct or 57012099Sjoerg * union member, or if it is not to be assigned to the left operand 57112099Sjoerg */ 57212099Sjoerg if (mp->m_binary && op != ARROW && op != POINT && 57312099Sjoerg op != ASSIGN && op != RETURN) { 57412099Sjoerg rn = promote(op, 0, rn); 57512099Sjoerg } 57612099Sjoerg 57712099Sjoerg /* 57812099Sjoerg * If the result of the operation is different for signed or 57912099Sjoerg * unsigned operands and one of the operands is signed only in 58012099Sjoerg * ANSI C, print a warning. 58112099Sjoerg */ 58212099Sjoerg if (mp->m_tlansiu && ln->tn_op == CON && ln->tn_val->v_ansiu) { 58312099Sjoerg /* ANSI C treats constant as unsigned, op %s */ 58412099Sjoerg warning(218, mp->m_name); 58512099Sjoerg ln->tn_val->v_ansiu = 0; 58612099Sjoerg } 58712099Sjoerg if (mp->m_transiu && rn->tn_op == CON && rn->tn_val->v_ansiu) { 58812099Sjoerg /* ANSI C treats constant as unsigned, op %s */ 58912099Sjoerg warning(218, mp->m_name); 59012099Sjoerg rn->tn_val->v_ansiu = 0; 59112099Sjoerg } 59212099Sjoerg 59312099Sjoerg /* Make sure both operands are of the same type */ 59412099Sjoerg if (mp->m_balance || (tflag && (op == SHL || op == SHR))) 59512099Sjoerg balance(op, &ln, &rn); 59612099Sjoerg 59712099Sjoerg /* 59812099Sjoerg * Check types for compatibility with the operation and mutual 59912099Sjoerg * compatibility. Return if there are serios problems. 60012099Sjoerg */ 60112099Sjoerg if (!typeok(op, 0, ln, rn)) 60212099Sjoerg return (NULL); 60312099Sjoerg 60412099Sjoerg /* And now create the node. */ 60512099Sjoerg switch (op) { 60612099Sjoerg case POINT: 60712099Sjoerg case ARROW: 60812099Sjoerg ntn = bldstr(op, ln, rn); 60912099Sjoerg break; 61012099Sjoerg case INCAFT: 61112099Sjoerg case DECAFT: 61212099Sjoerg case INCBEF: 61312099Sjoerg case DECBEF: 61412099Sjoerg ntn = bldincdec(op, ln); 61512099Sjoerg break; 61612099Sjoerg case AMPER: 61712099Sjoerg ntn = bldamper(ln, 0); 61812099Sjoerg break; 61912099Sjoerg case STAR: 62012099Sjoerg ntn = mktnode(STAR, ln->tn_type->t_subt, ln, NULL); 62112099Sjoerg break; 62212099Sjoerg case PLUS: 62312099Sjoerg case MINUS: 62412099Sjoerg ntn = bldplmi(op, ln, rn); 62512099Sjoerg break; 62612099Sjoerg case SHL: 62712099Sjoerg case SHR: 62812099Sjoerg ntn = bldshft(op, ln, rn); 62912099Sjoerg break; 63012099Sjoerg case COLON: 63112099Sjoerg ntn = bldcol(ln, rn); 63212099Sjoerg break; 63312099Sjoerg case ASSIGN: 63412099Sjoerg case MULASS: 63512099Sjoerg case DIVASS: 63612099Sjoerg case MODASS: 63712099Sjoerg case ADDASS: 63812099Sjoerg case SUBASS: 63912099Sjoerg case SHLASS: 64012099Sjoerg case SHRASS: 64112099Sjoerg case ANDASS: 64212099Sjoerg case XORASS: 64312099Sjoerg case ORASS: 64412099Sjoerg case RETURN: 64512099Sjoerg ntn = bldasgn(op, ln, rn); 64612099Sjoerg break; 64712099Sjoerg case COMMA: 64812099Sjoerg case QUEST: 64912099Sjoerg ntn = mktnode(op, rn->tn_type, ln, rn); 65012099Sjoerg break; 65112099Sjoerg default: 65212099Sjoerg rtp = mp->m_logop ? gettyp(INT) : ln->tn_type; 65312099Sjoerg if (!mp->m_binary && rn != NULL) 65412099Sjoerg lerror("build() 1"); 65512099Sjoerg ntn = mktnode(op, rtp, ln, rn); 65612099Sjoerg break; 65712099Sjoerg } 65812099Sjoerg 65991592Smarkm /* Return if an error occurred. */ 66012099Sjoerg if (ntn == NULL) 66112099Sjoerg return (NULL); 66212099Sjoerg 66312099Sjoerg /* Print a warning if precedence confusion is possible */ 66412099Sjoerg if (mp->m_tpconf) 66512099Sjoerg precconf(ntn); 66612099Sjoerg 66712099Sjoerg /* 66812099Sjoerg * Print a warning if one of the operands is in a context where 66912099Sjoerg * it is compared with null and if this operand is a constant. 67012099Sjoerg */ 67112099Sjoerg if (mp->m_tctx) { 67212099Sjoerg if (ln->tn_op == CON || 67312099Sjoerg ((mp->m_binary && op != QUEST) && rn->tn_op == CON)) { 67412099Sjoerg if (hflag && !ccflg) 67512099Sjoerg /* constant in conditional context */ 67612099Sjoerg warning(161); 67712099Sjoerg } 67812099Sjoerg } 67912099Sjoerg 68012099Sjoerg /* Fold if the operator requires it */ 68112099Sjoerg if (mp->m_fold) { 68212099Sjoerg if (ln->tn_op == CON && (!mp->m_binary || rn->tn_op == CON)) { 68312099Sjoerg if (mp->m_tctx) { 68412099Sjoerg ntn = foldtst(ntn); 68512099Sjoerg } else if (isftyp(ntn->tn_type->t_tspec)) { 68612099Sjoerg ntn = foldflt(ntn); 68712099Sjoerg } else { 68812099Sjoerg ntn = fold(ntn); 68912099Sjoerg } 69012099Sjoerg } else if (op == QUEST && ln->tn_op == CON) { 69112099Sjoerg ntn = ln->tn_val->v_quad ? rn->tn_left : rn->tn_right; 69212099Sjoerg } 69312099Sjoerg } 69412099Sjoerg 69512099Sjoerg return (ntn); 69612099Sjoerg} 69712099Sjoerg 69812099Sjoerg/* 69912099Sjoerg * Perform class conversions. 70012099Sjoerg * 70112099Sjoerg * Arrays of type T are converted into pointers to type T. 70212099Sjoerg * Functions are converted to pointers to functions. 70312099Sjoerg * Lvalues are converted to rvalues. 70412099Sjoerg */ 70512099Sjoergtnode_t * 70691592Smarkmcconv(tnode_t *tn) 70712099Sjoerg{ 70812099Sjoerg type_t *tp; 70912099Sjoerg 71012099Sjoerg /* 71112099Sjoerg * Array-lvalue (array of type T) is converted into rvalue 71212099Sjoerg * (pointer to type T) 71312099Sjoerg */ 71412099Sjoerg if (tn->tn_type->t_tspec == ARRAY) { 71512099Sjoerg if (!tn->tn_lvalue) { 71612099Sjoerg /* %soperand of '%s' must be lvalue */ 71712099Sjoerg /* XXX print correct operator */ 71812099Sjoerg (void)gnuism(114, "", modtab[AMPER].m_name); 71912099Sjoerg } 72012099Sjoerg tn = mktnode(AMPER, tincref(tn->tn_type->t_subt, PTR), 72112099Sjoerg tn, NULL); 72212099Sjoerg } 72312099Sjoerg 72412099Sjoerg /* 72512099Sjoerg * Expression of type function (function with return value of type T) 72612099Sjoerg * in rvalue-expression (pointer to function with return value 72712099Sjoerg * of type T) 72812099Sjoerg */ 72912099Sjoerg if (tn->tn_type->t_tspec == FUNC) 73012099Sjoerg tn = bldamper(tn, 1); 73112099Sjoerg 73212099Sjoerg /* lvalue to rvalue */ 73312099Sjoerg if (tn->tn_lvalue) { 73412099Sjoerg tp = tduptyp(tn->tn_type); 73512099Sjoerg tp->t_const = tp->t_volatile = 0; 73612099Sjoerg tn = mktnode(LOAD, tp, tn, NULL); 73712099Sjoerg } 73812099Sjoerg 73912099Sjoerg return (tn); 74012099Sjoerg} 74112099Sjoerg 74212099Sjoerg/* 74312099Sjoerg * Perform most type checks. First the types are checked using 74412099Sjoerg * informations from modtab[]. After that it is done by hand for 74512099Sjoerg * more complicated operators and type combinations. 74612099Sjoerg * 74712099Sjoerg * If the types are ok, typeok() returns 1, otherwise 0. 74812099Sjoerg */ 74912099Sjoergint 75091592Smarkmtypeok(op_t op, int arg, tnode_t *ln, tnode_t *rn) 75112099Sjoerg{ 75212099Sjoerg mod_t *mp; 75391592Smarkm tspec_t lt, rt = NOTSPEC, lst = NOTSPEC, rst = NOTSPEC, olt = NOTSPEC, 75491592Smarkm ort = NOTSPEC; 75591592Smarkm type_t *ltp, *rtp = NULL, *lstp = NULL, *rstp = NULL; 75612099Sjoerg tnode_t *tn; 75712099Sjoerg 75812099Sjoerg mp = &modtab[op]; 75912099Sjoerg 76012099Sjoerg if ((lt = (ltp = ln->tn_type)->t_tspec) == PTR) 76112099Sjoerg lst = (lstp = ltp->t_subt)->t_tspec; 76212099Sjoerg if (mp->m_binary) { 76312099Sjoerg if ((rt = (rtp = rn->tn_type)->t_tspec) == PTR) 76412099Sjoerg rst = (rstp = rtp->t_subt)->t_tspec; 76512099Sjoerg } 76612099Sjoerg 76712099Sjoerg if (mp->m_rqint) { 76812099Sjoerg /* integertypes required */ 76912099Sjoerg if (!isityp(lt) || (mp->m_binary && !isityp(rt))) { 77012099Sjoerg incompat(op, lt, rt); 77112099Sjoerg return (0); 77212099Sjoerg } 77312099Sjoerg } else if (mp->m_rqsclt) { 77412099Sjoerg /* scalar types required */ 77512099Sjoerg if (!issclt(lt) || (mp->m_binary && !issclt(rt))) { 77612099Sjoerg incompat(op, lt, rt); 77712099Sjoerg return (0); 77812099Sjoerg } 77912099Sjoerg } else if (mp->m_rqatyp) { 78012099Sjoerg /* arithmetic types required */ 78112099Sjoerg if (!isatyp(lt) || (mp->m_binary && !isatyp(rt))) { 78212099Sjoerg incompat(op, lt, rt); 78312099Sjoerg return (0); 78412099Sjoerg } 78512099Sjoerg } 78612099Sjoerg 78712099Sjoerg if (op == SHL || op == SHR || op == SHLASS || op == SHRASS) { 78812099Sjoerg /* 78912099Sjoerg * For these operations we need the types before promotion 79012099Sjoerg * and balancing. 79112099Sjoerg */ 79291592Smarkm for (tn=ln; tn->tn_op==CVT && !tn->tn_cast; tn=tn->tn_left) 79391592Smarkm continue; 79412099Sjoerg olt = tn->tn_type->t_tspec; 79591592Smarkm for (tn=rn; tn->tn_op==CVT && !tn->tn_cast; tn=tn->tn_left) 79691592Smarkm continue; 79712099Sjoerg ort = tn->tn_type->t_tspec; 79812099Sjoerg } 79991592Smarkm 80012099Sjoerg switch (op) { 80112099Sjoerg case POINT: 80212099Sjoerg /* 80312099Sjoerg * Most errors required by ANSI C are reported in strmemb(). 80412099Sjoerg * Here we only must check for totaly wrong things. 80512099Sjoerg */ 80612099Sjoerg if (lt == FUNC || lt == VOID || ltp->t_isfield || 80712099Sjoerg ((lt != STRUCT && lt != UNION) && !ln->tn_lvalue)) { 80812099Sjoerg /* Without tflag we got already an error */ 80912099Sjoerg if (tflag) 81012099Sjoerg /* unacceptable operand of %s */ 81112099Sjoerg error(111, mp->m_name); 81212099Sjoerg return (0); 81312099Sjoerg } 81412099Sjoerg /* Now we have an object we can create a pointer to */ 81512099Sjoerg break; 81612099Sjoerg case ARROW: 81712099Sjoerg if (lt != PTR && !(tflag && isityp(lt))) { 81812099Sjoerg /* Without tflag we got already an error */ 81912099Sjoerg if (tflag) 82012099Sjoerg /* unacceptabel operand of %s */ 82112099Sjoerg error(111, mp->m_name); 82212099Sjoerg return (0); 82312099Sjoerg } 82412099Sjoerg break; 82512099Sjoerg case INCAFT: 82612099Sjoerg case DECAFT: 82712099Sjoerg case INCBEF: 82812099Sjoerg case DECBEF: 82912099Sjoerg /* operands have scalar types (checked above) */ 83012099Sjoerg if (!ln->tn_lvalue) { 83112099Sjoerg if (ln->tn_op == CVT && ln->tn_cast && 83212099Sjoerg ln->tn_left->tn_op == LOAD) { 83312099Sjoerg /* a cast does not yield an lvalue */ 83412099Sjoerg error(163); 83512099Sjoerg } 83612099Sjoerg /* %soperand of %s must be lvalue */ 83712099Sjoerg error(114, "", mp->m_name); 83812099Sjoerg return (0); 83912099Sjoerg } else if (ltp->t_const) { 84012099Sjoerg /* %soperand of %s must be modifiable lvalue */ 84112099Sjoerg if (!tflag) 84212099Sjoerg warning(115, "", mp->m_name); 84312099Sjoerg } 84412099Sjoerg break; 84512099Sjoerg case AMPER: 84612099Sjoerg if (lt == ARRAY || lt == FUNC) { 84712099Sjoerg /* ok, a warning comes later (in bldamper()) */ 84812099Sjoerg } else if (!ln->tn_lvalue) { 84912099Sjoerg if (ln->tn_op == CVT && ln->tn_cast && 85012099Sjoerg ln->tn_left->tn_op == LOAD) { 85112099Sjoerg /* a cast does not yield an lvalue */ 85212099Sjoerg error(163); 85312099Sjoerg } 85412099Sjoerg /* %soperand of %s must be lvalue */ 85512099Sjoerg error(114, "", mp->m_name); 85612099Sjoerg return (0); 85712099Sjoerg } else if (issclt(lt)) { 85812099Sjoerg if (ltp->t_isfield) { 85912099Sjoerg /* cannot take address of bit-field */ 86012099Sjoerg error(112); 86112099Sjoerg return (0); 86212099Sjoerg } 86312099Sjoerg } else if (lt != STRUCT && lt != UNION) { 86412099Sjoerg /* unacceptable operand of %s */ 86512099Sjoerg error(111, mp->m_name); 86612099Sjoerg return (0); 86712099Sjoerg } 86812099Sjoerg if (ln->tn_op == NAME && ln->tn_sym->s_reg) { 86912099Sjoerg /* cannot take address of register %s */ 87012099Sjoerg error(113, ln->tn_sym->s_name); 87112099Sjoerg return (0); 87212099Sjoerg } 87312099Sjoerg break; 87412099Sjoerg case STAR: 87512099Sjoerg /* until now there were no type checks for this operator */ 87612099Sjoerg if (lt != PTR) { 87712099Sjoerg /* cannot dereference non-pointer type */ 87812099Sjoerg error(96); 87912099Sjoerg return (0); 88012099Sjoerg } 88112099Sjoerg break; 88212099Sjoerg case PLUS: 88312099Sjoerg /* operands have scalar types (checked above) */ 88412099Sjoerg if ((lt == PTR && !isityp(rt)) || (rt == PTR && !isityp(lt))) { 88512099Sjoerg incompat(op, lt, rt); 88612099Sjoerg return (0); 88712099Sjoerg } 88812099Sjoerg break; 88912099Sjoerg case MINUS: 89012099Sjoerg /* operands have scalar types (checked above) */ 89112099Sjoerg if (lt == PTR && (!isityp(rt) && rt != PTR)) { 89212099Sjoerg incompat(op, lt, rt); 89312099Sjoerg return (0); 89412099Sjoerg } else if (rt == PTR && lt != PTR) { 89512099Sjoerg incompat(op, lt, rt); 89612099Sjoerg return (0); 89712099Sjoerg } 89812099Sjoerg if (lt == PTR && rt == PTR) { 89912099Sjoerg if (!eqtype(lstp, rstp, 1, 0, NULL)) { 90012099Sjoerg /* illegal pointer subtraction */ 90112099Sjoerg error(116); 90212099Sjoerg } 90312099Sjoerg } 90412099Sjoerg break; 90512099Sjoerg case SHR: 90612099Sjoerg /* operands have integer types (checked above) */ 90712099Sjoerg if (pflag && !isutyp(lt)) { 90812099Sjoerg /* 90912099Sjoerg * The left operand is signed. This means that 91012099Sjoerg * the operation is (possibly) nonportable. 91112099Sjoerg */ 91212099Sjoerg /* bitwise operation on signed value nonportable */ 91312099Sjoerg if (ln->tn_op != CON) { 91412099Sjoerg /* possibly nonportable */ 91512099Sjoerg warning(117); 91612099Sjoerg } else if (ln->tn_val->v_quad < 0) { 91712099Sjoerg warning(120); 91812099Sjoerg } 91912099Sjoerg } else if (!tflag && !sflag && !isutyp(olt) && isutyp(ort)) { 92012099Sjoerg /* 92112099Sjoerg * The left operand would become unsigned in 92212099Sjoerg * traditional C. 92312099Sjoerg */ 92412099Sjoerg if (hflag && 92512099Sjoerg (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { 92612099Sjoerg /* semantics of %s change in ANSI C; use ... */ 92712099Sjoerg warning(118, mp->m_name); 92812099Sjoerg } 92912099Sjoerg } else if (!tflag && !sflag && !isutyp(olt) && !isutyp(ort) && 93012099Sjoerg psize(lt) < psize(rt)) { 93112099Sjoerg /* 93212099Sjoerg * In traditional C the left operand would be extended, 93312099Sjoerg * possibly with 1, and then shifted. 93412099Sjoerg */ 93512099Sjoerg if (hflag && 93612099Sjoerg (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { 93712099Sjoerg /* semantics of %s change in ANSI C; use ... */ 93812099Sjoerg warning(118, mp->m_name); 93912099Sjoerg } 94012099Sjoerg } 94112099Sjoerg goto shift; 94212099Sjoerg case SHL: 94312099Sjoerg /* 94412099Sjoerg * ANSI C does not perform balancing for shift operations, 94512099Sjoerg * but traditional C does. If the width of the right operand 94612099Sjoerg * is greather than the width of the left operand, than in 94712099Sjoerg * traditional C the left operand would be extendet to the 94812099Sjoerg * width of the right operand. For SHL this may result in 94912099Sjoerg * different results. 95012099Sjoerg */ 95112099Sjoerg if (psize(lt) < psize(rt)) { 95212099Sjoerg /* 95312099Sjoerg * XXX If both operands are constant make sure 95412099Sjoerg * that there is really a differencs between 95512099Sjoerg * ANSI C and traditional C. 95612099Sjoerg */ 95712099Sjoerg if (hflag) 95812099Sjoerg /* semantics of %s change in ANSI C; use ... */ 95912099Sjoerg warning(118, mp->m_name); 96012099Sjoerg } 96112099Sjoerg shift: 96212099Sjoerg if (rn->tn_op == CON) { 96312099Sjoerg if (!isutyp(rt) && rn->tn_val->v_quad < 0) { 96412099Sjoerg /* negative shift */ 96512099Sjoerg warning(121); 96691592Smarkm } else if ((uint64_t)rn->tn_val->v_quad == size(lt)) { 96712099Sjoerg /* shift equal to size fo object */ 96812099Sjoerg warning(267); 96991592Smarkm } else if ((uint64_t)rn->tn_val->v_quad > size(lt)) { 97012099Sjoerg /* shift greater than size of object */ 97112099Sjoerg warning(122); 97212099Sjoerg } 97312099Sjoerg } 97412099Sjoerg break; 97512099Sjoerg case EQ: 97612099Sjoerg case NE: 97712099Sjoerg /* 97812099Sjoerg * Accept some things which are allowed with EQ and NE, 97975697Sasmodai * but not with ordered comparisons. 98012099Sjoerg */ 98112099Sjoerg if (lt == PTR && ((rt == PTR && rst == VOID) || isityp(rt))) { 98212099Sjoerg if (rn->tn_op == CON && rn->tn_val->v_quad == 0) 98312099Sjoerg break; 98412099Sjoerg } 98512099Sjoerg if (rt == PTR && ((lt == PTR && lst == VOID) || isityp(lt))) { 98612099Sjoerg if (ln->tn_op == CON && ln->tn_val->v_quad == 0) 98712099Sjoerg break; 98812099Sjoerg } 98912099Sjoerg /* FALLTHROUGH */ 99012099Sjoerg case LT: 99112099Sjoerg case GT: 99212099Sjoerg case LE: 99312099Sjoerg case GE: 99412099Sjoerg if ((lt == PTR || rt == PTR) && lt != rt) { 99512099Sjoerg if (isityp(lt) || isityp(rt)) { 99612099Sjoerg /* illegal comb. of pointer and int., op %s */ 99712099Sjoerg warning(123, mp->m_name); 99812099Sjoerg } else { 99912099Sjoerg incompat(op, lt, rt); 100012099Sjoerg return (0); 100112099Sjoerg } 100212099Sjoerg } else if (lt == PTR && rt == PTR) { 100312099Sjoerg ptrcmpok(op, ln, rn); 100412099Sjoerg } 100512099Sjoerg break; 100612099Sjoerg case QUEST: 100712099Sjoerg if (!issclt(lt)) { 100812099Sjoerg /* first operand must have scalar type, op ? : */ 100912099Sjoerg error(170); 101012099Sjoerg return (0); 101112099Sjoerg } 101212099Sjoerg if (rn->tn_op != COLON) 101312099Sjoerg lerror("typeok() 2"); 101412099Sjoerg break; 101512099Sjoerg case COLON: 101612099Sjoerg 101712099Sjoerg if (isatyp(lt) && isatyp(rt)) 101812099Sjoerg break; 101912099Sjoerg 102012099Sjoerg if (lt == STRUCT && rt == STRUCT && ltp->t_str == rtp->t_str) 102112099Sjoerg break; 102212099Sjoerg if (lt == UNION && rt == UNION && ltp->t_str == rtp->t_str) 102312099Sjoerg break; 102412099Sjoerg 102512099Sjoerg /* combination of any pointer and 0, 0L or (void *)0 is ok */ 102612099Sjoerg if (lt == PTR && ((rt == PTR && rst == VOID) || isityp(rt))) { 102712099Sjoerg if (rn->tn_op == CON && rn->tn_val->v_quad == 0) 102812099Sjoerg break; 102912099Sjoerg } 103012099Sjoerg if (rt == PTR && ((lt == PTR && lst == VOID) || isityp(lt))) { 103112099Sjoerg if (ln->tn_op == CON && ln->tn_val->v_quad == 0) 103212099Sjoerg break; 103312099Sjoerg } 103412099Sjoerg 103512099Sjoerg if ((lt == PTR && isityp(rt)) || (isityp(lt) && rt == PTR)) { 103612099Sjoerg /* illegal comb. of ptr. and int., op %s */ 103712099Sjoerg warning(123, mp->m_name); 103812099Sjoerg break; 103912099Sjoerg } 104012099Sjoerg 104112099Sjoerg if (lt == VOID || rt == VOID) { 104212099Sjoerg if (lt != VOID || rt != VOID) 104312099Sjoerg /* incompatible types in conditional */ 104412099Sjoerg warning(126); 104512099Sjoerg break; 104612099Sjoerg } 104712099Sjoerg 104812099Sjoerg if (lt == PTR && rt == PTR && ((lst == VOID && rst == FUNC) || 104912099Sjoerg (lst == FUNC && rst == VOID))) { 105012099Sjoerg /* (void *)0 handled above */ 105112099Sjoerg if (sflag) 105212099Sjoerg /* ANSI C forbids conv. of %s to %s, op %s */ 105312099Sjoerg warning(305, "function pointer", "'void *'", 105412099Sjoerg mp->m_name); 105512099Sjoerg break; 105612099Sjoerg } 105712099Sjoerg 105812099Sjoerg if (rt == PTR && lt == PTR) { 105912099Sjoerg if (!eqtype(lstp, rstp, 1, 0, NULL)) 106012099Sjoerg illptrc(mp, ltp, rtp); 106112099Sjoerg break; 106212099Sjoerg } 106312099Sjoerg 106412099Sjoerg /* incompatible types in conditional */ 106512099Sjoerg error(126); 106612099Sjoerg return (0); 106712099Sjoerg 106812099Sjoerg case ASSIGN: 106912099Sjoerg case INIT: 107012099Sjoerg case FARG: 107112099Sjoerg case RETURN: 107212099Sjoerg if (!asgntypok(op, arg, ln, rn)) 107312099Sjoerg return (0); 107412099Sjoerg goto assign; 107512099Sjoerg case MULASS: 107612099Sjoerg case DIVASS: 107712099Sjoerg case MODASS: 107812099Sjoerg goto assign; 107912099Sjoerg case ADDASS: 108012099Sjoerg case SUBASS: 108112099Sjoerg /* operands have scalar types (checked above) */ 108212099Sjoerg if ((lt == PTR && !isityp(rt)) || rt == PTR) { 108312099Sjoerg incompat(op, lt, rt); 108412099Sjoerg return (0); 108512099Sjoerg } 108612099Sjoerg goto assign; 108712099Sjoerg case SHLASS: 108812099Sjoerg goto assign; 108912099Sjoerg case SHRASS: 109012099Sjoerg if (pflag && !isutyp(lt) && !(tflag && isutyp(rt))) { 109112099Sjoerg /* bitwise operation on s.v. possibly nonportabel */ 109212099Sjoerg warning(117); 109312099Sjoerg } 109412099Sjoerg goto assign; 109512099Sjoerg case ANDASS: 109612099Sjoerg case XORASS: 109712099Sjoerg case ORASS: 109812099Sjoerg goto assign; 109912099Sjoerg assign: 110012099Sjoerg if (!ln->tn_lvalue) { 110112099Sjoerg if (ln->tn_op == CVT && ln->tn_cast && 110212099Sjoerg ln->tn_left->tn_op == LOAD) { 110312099Sjoerg /* a cast does not yield an lvalue */ 110412099Sjoerg error(163); 110512099Sjoerg } 110612099Sjoerg /* %soperand of %s must be lvalue */ 110712099Sjoerg error(114, "left ", mp->m_name); 110812099Sjoerg return (0); 110912099Sjoerg } else if (ltp->t_const || ((lt == STRUCT || lt == UNION) && 111012099Sjoerg conmemb(ltp))) { 111112099Sjoerg /* %soperand of %s must be modifiable lvalue */ 111212099Sjoerg if (!tflag) 111312099Sjoerg warning(115, "left ", mp->m_name); 111412099Sjoerg } 111512099Sjoerg break; 111612099Sjoerg case COMMA: 111712099Sjoerg if (!modtab[ln->tn_op].m_sideeff) 111812099Sjoerg nulleff(ln); 111912099Sjoerg break; 112012099Sjoerg /* LINTED (enumeration values not handled in switch) */ 112191592Smarkm case CON: 112291592Smarkm case CASE: 112391592Smarkm case PUSH: 112491592Smarkm case LOAD: 112591592Smarkm case ICALL: 112691592Smarkm case CVT: 112791592Smarkm case CALL: 112891592Smarkm case FSEL: 112991592Smarkm case STRING: 113091592Smarkm case NAME: 113191592Smarkm case LOGOR: 113291592Smarkm case LOGAND: 113391592Smarkm case OR: 113491592Smarkm case XOR: 113591592Smarkm case AND: 113691592Smarkm case MOD: 113791592Smarkm case DIV: 113891592Smarkm case MULT: 113991592Smarkm case UMINUS: 114091592Smarkm case UPLUS: 114191592Smarkm case DEC: 114291592Smarkm case INC: 114391592Smarkm case COMPL: 114491592Smarkm case NOT: 114591592Smarkm case NOOP: 114691592Smarkm break; 114712099Sjoerg } 114812099Sjoerg 114912099Sjoerg if (mp->m_badeop && 115012099Sjoerg (ltp->t_isenum || (mp->m_binary && rtp->t_isenum))) { 115112099Sjoerg chkbeop(op, ln, rn); 115212099Sjoerg } else if (mp->m_enumop && (ltp->t_isenum && rtp->t_isenum)) { 115312099Sjoerg chkeop2(op, arg, ln, rn); 115412099Sjoerg } else if (mp->m_enumop && (ltp->t_isenum || rtp->t_isenum)) { 115512099Sjoerg chkeop1(op, arg, ln, rn); 115612099Sjoerg } 115712099Sjoerg 115812099Sjoerg return (1); 115912099Sjoerg} 116012099Sjoerg 116112099Sjoergstatic void 116291592Smarkmptrcmpok(op_t op, tnode_t *ln, tnode_t *rn) 116312099Sjoerg{ 116412099Sjoerg type_t *ltp, *rtp; 116512099Sjoerg tspec_t lt, rt; 116612099Sjoerg const char *lts, *rts; 116712099Sjoerg 116812099Sjoerg lt = (ltp = ln->tn_type)->t_subt->t_tspec; 116912099Sjoerg rt = (rtp = rn->tn_type)->t_subt->t_tspec; 117012099Sjoerg 117112099Sjoerg if (lt == VOID || rt == VOID) { 117212099Sjoerg if (sflag && (lt == FUNC || rt == FUNC)) { 117312099Sjoerg /* (void *)0 already handled in typeok() */ 117412099Sjoerg *(lt == FUNC ? <s : &rts) = "function pointer"; 117512099Sjoerg *(lt == VOID ? <s : &rts) = "'void *'"; 117675697Sasmodai /* ANSI C forbids comparison of %s with %s */ 117712099Sjoerg warning(274, lts, rts); 117812099Sjoerg } 117912099Sjoerg return; 118012099Sjoerg } 118112099Sjoerg 118212099Sjoerg if (!eqtype(ltp->t_subt, rtp->t_subt, 1, 0, NULL)) { 118312099Sjoerg illptrc(&modtab[op], ltp, rtp); 118412099Sjoerg return; 118512099Sjoerg } 118612099Sjoerg 118712099Sjoerg if (lt == FUNC && rt == FUNC) { 118812099Sjoerg if (sflag && op != EQ && op != NE) 118912099Sjoerg /* ANSI C forbids ordered comp. of func ptr */ 119012099Sjoerg warning(125); 119112099Sjoerg } 119212099Sjoerg} 119312099Sjoerg 119412099Sjoerg/* 119512099Sjoerg * Checks type compatibility for ASSIGN, INIT, FARG and RETURN 119612099Sjoerg * and prints warnings/errors if necessary. 119712099Sjoerg * If the types are (almost) compatible, 1 is returned, otherwise 0. 119812099Sjoerg */ 119912099Sjoergstatic int 120091592Smarkmasgntypok(op_t op, int arg, tnode_t *ln, tnode_t *rn) 120112099Sjoerg{ 120291592Smarkm tspec_t lt, rt, lst = NOTSPEC, rst = NOTSPEC; 120391592Smarkm type_t *ltp, *rtp, *lstp = NULL, *rstp = NULL; 120412099Sjoerg mod_t *mp; 120512099Sjoerg const char *lts, *rts; 120612099Sjoerg 120712099Sjoerg if ((lt = (ltp = ln->tn_type)->t_tspec) == PTR) 120812099Sjoerg lst = (lstp = ltp->t_subt)->t_tspec; 120912099Sjoerg if ((rt = (rtp = rn->tn_type)->t_tspec) == PTR) 121012099Sjoerg rst = (rstp = rtp->t_subt)->t_tspec; 121112099Sjoerg mp = &modtab[op]; 121212099Sjoerg 121312099Sjoerg if (isatyp(lt) && isatyp(rt)) 121412099Sjoerg return (1); 121512099Sjoerg 121612099Sjoerg if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION)) 121712099Sjoerg /* both are struct or union */ 121812099Sjoerg return (ltp->t_str == rtp->t_str); 121912099Sjoerg 122012099Sjoerg /* 0, 0L and (void *)0 may be assigned to any pointer */ 122112099Sjoerg if (lt == PTR && ((rt == PTR && rst == VOID) || isityp(rt))) { 122212099Sjoerg if (rn->tn_op == CON && rn->tn_val->v_quad == 0) 122312099Sjoerg return (1); 122412099Sjoerg } 122512099Sjoerg 122612099Sjoerg if (lt == PTR && rt == PTR && (lst == VOID || rst == VOID)) { 122712099Sjoerg /* two pointers, at least one pointer to void */ 122812099Sjoerg if (sflag && (lst == FUNC || rst == FUNC)) { 122912099Sjoerg /* comb. of ptr to func and ptr to void */ 123012099Sjoerg *(lst == FUNC ? <s : &rts) = "function pointer"; 123112099Sjoerg *(lst == VOID ? <s : &rts) = "'void *'"; 123212099Sjoerg switch (op) { 123312099Sjoerg case INIT: 123412099Sjoerg case RETURN: 123512099Sjoerg /* ANSI C forbids conversion of %s to %s */ 123612099Sjoerg warning(303, rts, lts); 123712099Sjoerg break; 123812099Sjoerg case FARG: 123912099Sjoerg /* ANSI C forbids conv. of %s to %s, arg #%d */ 124012099Sjoerg warning(304, rts, lts, arg); 124112099Sjoerg break; 124212099Sjoerg default: 124312099Sjoerg /* ANSI C forbids conv. of %s to %s, op %s */ 124412099Sjoerg warning(305, rts, lts, mp->m_name); 124512099Sjoerg break; 124612099Sjoerg } 124712099Sjoerg } 124812099Sjoerg } 124912099Sjoerg 125012099Sjoerg if (lt == PTR && rt == PTR && (lst == VOID || rst == VOID || 125112099Sjoerg eqtype(lstp, rstp, 1, 0, NULL))) { 125212099Sjoerg /* compatible pointer types (qualifiers ignored) */ 125312099Sjoerg if (!tflag && 125412099Sjoerg ((!lstp->t_const && rstp->t_const) || 125512099Sjoerg (!lstp->t_volatile && rstp->t_volatile))) { 125612099Sjoerg /* left side has not all qualifiers of right */ 125712099Sjoerg switch (op) { 125812099Sjoerg case INIT: 125912099Sjoerg case RETURN: 126012099Sjoerg /* incompatible pointer types */ 126112099Sjoerg warning(182); 126212099Sjoerg break; 126312099Sjoerg case FARG: 126412099Sjoerg /* argument has incompat. ptr. type, arg #%d */ 126512099Sjoerg warning(153, arg); 126612099Sjoerg break; 126712099Sjoerg default: 126812099Sjoerg /* operands have incompat. ptr. types, op %s */ 126912099Sjoerg warning(128, mp->m_name); 127012099Sjoerg break; 127112099Sjoerg } 127212099Sjoerg } 127312099Sjoerg return (1); 127412099Sjoerg } 127512099Sjoerg 127612099Sjoerg if ((lt == PTR && isityp(rt)) || (isityp(lt) && rt == PTR)) { 127712099Sjoerg switch (op) { 127812099Sjoerg case INIT: 127912099Sjoerg case RETURN: 128012099Sjoerg /* illegal combination of pointer and integer */ 128112099Sjoerg warning(183); 128212099Sjoerg break; 128312099Sjoerg case FARG: 128412099Sjoerg /* illegal comb. of ptr. and int., arg #%d */ 128512099Sjoerg warning(154, arg); 128612099Sjoerg break; 128712099Sjoerg default: 128812099Sjoerg /* illegal comb. of ptr. and int., op %s */ 128912099Sjoerg warning(123, mp->m_name); 129012099Sjoerg break; 129112099Sjoerg } 129212099Sjoerg return (1); 129312099Sjoerg } 129412099Sjoerg 129512099Sjoerg if (lt == PTR && rt == PTR) { 129612099Sjoerg switch (op) { 129712099Sjoerg case INIT: 129812099Sjoerg case RETURN: 129912099Sjoerg illptrc(NULL, ltp, rtp); 130012099Sjoerg break; 130112099Sjoerg case FARG: 130212099Sjoerg /* argument has incompatible pointer type, arg #%d */ 130312099Sjoerg warning(153, arg); 130412099Sjoerg break; 130512099Sjoerg default: 130612099Sjoerg illptrc(mp, ltp, rtp); 130712099Sjoerg break; 130812099Sjoerg } 130912099Sjoerg return (1); 131012099Sjoerg } 131112099Sjoerg 131212099Sjoerg switch (op) { 131312099Sjoerg case INIT: 131412099Sjoerg /* initialisation type mismatch */ 131512099Sjoerg error(185); 131612099Sjoerg break; 131712099Sjoerg case RETURN: 131812099Sjoerg /* return value type mismatch */ 131912099Sjoerg error(211); 132012099Sjoerg break; 132112099Sjoerg case FARG: 132212099Sjoerg /* argument is incompatible with prototype, arg #%d */ 132312099Sjoerg warning(155, arg); 132412099Sjoerg break; 132512099Sjoerg default: 132612099Sjoerg incompat(op, lt, rt); 132712099Sjoerg break; 132812099Sjoerg } 132912099Sjoerg 133012099Sjoerg return (0); 133112099Sjoerg} 133212099Sjoerg 133312099Sjoerg/* 133412099Sjoerg * Prints a warning if an operator, which should be senseless for an 133512099Sjoerg * enum type, is applied to an enum type. 133612099Sjoerg */ 133712099Sjoergstatic void 133891592Smarkmchkbeop(op_t op, tnode_t *ln, tnode_t *rn) 133912099Sjoerg{ 134012099Sjoerg mod_t *mp; 134112099Sjoerg 134212099Sjoerg if (!eflag) 134312099Sjoerg return; 134412099Sjoerg 134512099Sjoerg mp = &modtab[op]; 134612099Sjoerg 134712099Sjoerg if (!(ln->tn_type->t_isenum || 134812099Sjoerg (mp->m_binary && rn->tn_type->t_isenum))) { 134912099Sjoerg return; 135012099Sjoerg } 135112099Sjoerg 135212099Sjoerg /* 135312099Sjoerg * Enum as offset to a pointer is an exception (otherwise enums 135412099Sjoerg * could not be used as array indizes). 135512099Sjoerg */ 135612099Sjoerg if (op == PLUS && 135712099Sjoerg ((ln->tn_type->t_isenum && rn->tn_type->t_tspec == PTR) || 135812099Sjoerg (rn->tn_type->t_isenum && ln->tn_type->t_tspec == PTR))) { 135912099Sjoerg return; 136012099Sjoerg } 136112099Sjoerg 136212099Sjoerg /* dubious operation on enum, op %s */ 136312099Sjoerg warning(241, mp->m_name); 136412099Sjoerg 136512099Sjoerg} 136612099Sjoerg 136712099Sjoerg/* 136812099Sjoerg * Prints a warning if an operator is applied to two different enum types. 136912099Sjoerg */ 137012099Sjoergstatic void 137191592Smarkmchkeop2(op_t op, int arg, tnode_t *ln, tnode_t *rn) 137212099Sjoerg{ 137312099Sjoerg mod_t *mp; 137412099Sjoerg 137512099Sjoerg mp = &modtab[op]; 137612099Sjoerg 137712099Sjoerg if (ln->tn_type->t_enum != rn->tn_type->t_enum) { 137812099Sjoerg switch (op) { 137912099Sjoerg case INIT: 138012099Sjoerg /* enum type mismatch in initialisation */ 138112099Sjoerg warning(210); 138212099Sjoerg break; 138312099Sjoerg case FARG: 138412099Sjoerg /* enum type mismatch, arg #%d */ 138512099Sjoerg warning(156, arg); 138612099Sjoerg break; 138712099Sjoerg case RETURN: 138812099Sjoerg /* return value type mismatch */ 138912099Sjoerg warning(211); 139012099Sjoerg break; 139112099Sjoerg default: 139212099Sjoerg /* enum type mismatch, op %s */ 139312099Sjoerg warning(130, mp->m_name); 139412099Sjoerg break; 139512099Sjoerg } 139612099Sjoerg#if 0 139712099Sjoerg } else if (mp->m_comp && op != EQ && op != NE) { 139812099Sjoerg if (eflag) 139975697Sasmodai /* dubious comparisons of enums */ 140012099Sjoerg warning(243, mp->m_name); 140112099Sjoerg#endif 140212099Sjoerg } 140312099Sjoerg} 140412099Sjoerg 140512099Sjoerg/* 140612099Sjoerg * Prints a warning if an operator has both enum end other integer 140712099Sjoerg * types. 140812099Sjoerg */ 140912099Sjoergstatic void 141091592Smarkmchkeop1(op_t op, int arg, tnode_t *ln, tnode_t *rn) 141112099Sjoerg{ 141291592Smarkm 141312099Sjoerg if (!eflag) 141412099Sjoerg return; 141512099Sjoerg 141612099Sjoerg switch (op) { 141712099Sjoerg case INIT: 141812099Sjoerg /* 141912099Sjoerg * Initializations with 0 should be allowed. Otherwise, 142012099Sjoerg * we should complain about all uninitialized enums, 142112099Sjoerg * consequently. 142212099Sjoerg */ 142312099Sjoerg if (!rn->tn_type->t_isenum && rn->tn_op == CON && 142412099Sjoerg isityp(rn->tn_type->t_tspec) && rn->tn_val->v_quad == 0) { 142512099Sjoerg return; 142612099Sjoerg } 142712099Sjoerg /* initialisation of '%s' with '%s' */ 142812099Sjoerg warning(277, tyname(ln->tn_type), tyname(rn->tn_type)); 142912099Sjoerg break; 143012099Sjoerg case FARG: 143112099Sjoerg /* combination of '%s' and '%s', arg #%d */ 143212099Sjoerg warning(278, tyname(ln->tn_type), tyname(rn->tn_type), arg); 143312099Sjoerg break; 143412099Sjoerg case RETURN: 143512099Sjoerg /* combination of '%s' and '%s' in return */ 143612099Sjoerg warning(279, tyname(ln->tn_type), tyname(rn->tn_type)); 143712099Sjoerg break; 143812099Sjoerg default: 143912099Sjoerg /* combination of '%s' and %s, op %s */ 144012099Sjoerg warning(242, tyname(ln->tn_type), tyname(rn->tn_type), 144112099Sjoerg modtab[op].m_name); 144212099Sjoerg break; 144312099Sjoerg } 144412099Sjoerg} 144512099Sjoerg 144612099Sjoerg/* 144712099Sjoerg * Build and initialize a new node. 144812099Sjoerg */ 144912099Sjoergstatic tnode_t * 145091592Smarkmmktnode(op_t op, type_t *type, tnode_t *ln, tnode_t *rn) 145112099Sjoerg{ 145212099Sjoerg tnode_t *ntn; 145312099Sjoerg tspec_t t; 145412099Sjoerg 145512099Sjoerg ntn = getnode(); 145612099Sjoerg 145712099Sjoerg ntn->tn_op = op; 145812099Sjoerg ntn->tn_type = type; 145912099Sjoerg ntn->tn_left = ln; 146012099Sjoerg ntn->tn_right = rn; 146112099Sjoerg 146212099Sjoerg if (op == STAR || op == FSEL) { 146312099Sjoerg if (ln->tn_type->t_tspec == PTR) { 146412099Sjoerg t = ln->tn_type->t_subt->t_tspec; 146512099Sjoerg if (t != FUNC && t != VOID) 146612099Sjoerg ntn->tn_lvalue = 1; 146712099Sjoerg } else { 146812099Sjoerg lerror("mktnode() 2"); 146912099Sjoerg } 147012099Sjoerg } 147112099Sjoerg 147212099Sjoerg return (ntn); 147312099Sjoerg} 147412099Sjoerg 147512099Sjoerg/* 147612099Sjoerg * Performs usual conversion of operands to (unsigned) int. 147712099Sjoerg * 147812099Sjoerg * If tflag is set or the operand is a function argument with no 147912099Sjoerg * type information (no prototype or variable # of args), convert 148012099Sjoerg * float to double. 148112099Sjoerg */ 148212099Sjoergtnode_t * 148391592Smarkmpromote(op_t op, int farg, tnode_t *tn) 148412099Sjoerg{ 148512099Sjoerg tspec_t t; 148612099Sjoerg type_t *ntp; 148712099Sjoerg int len; 148812099Sjoerg 148912099Sjoerg t = tn->tn_type->t_tspec; 149012099Sjoerg 149112099Sjoerg if (!isatyp(t)) 149212099Sjoerg return (tn); 149312099Sjoerg 149412099Sjoerg if (!tflag) { 149512099Sjoerg /* 149612099Sjoerg * ANSI C requires that the result is always of type INT 149712099Sjoerg * if INT can represent all possible values of the previous 149812099Sjoerg * type. 149912099Sjoerg */ 150012099Sjoerg if (tn->tn_type->t_isfield) { 150112099Sjoerg len = tn->tn_type->t_flen; 150212099Sjoerg if (size(INT) > len) { 150312099Sjoerg t = INT; 150412099Sjoerg } else { 150512099Sjoerg if (size(INT) != len) 150612099Sjoerg lerror("promote() 1"); 150712099Sjoerg if (isutyp(t)) { 150812099Sjoerg t = UINT; 150912099Sjoerg } else { 151012099Sjoerg t = INT; 151112099Sjoerg } 151212099Sjoerg } 151312099Sjoerg } else if (t == CHAR || t == UCHAR || t == SCHAR) { 151412099Sjoerg t = (size(CHAR) < size(INT) || t != UCHAR) ? 151512099Sjoerg INT : UINT; 151612099Sjoerg } else if (t == SHORT || t == USHORT) { 151712099Sjoerg t = (size(SHORT) < size(INT) || t == SHORT) ? 151812099Sjoerg INT : UINT; 151912099Sjoerg } else if (t == ENUM) { 152012099Sjoerg t = INT; 152112099Sjoerg } else if (farg && t == FLOAT) { 152212099Sjoerg t = DOUBLE; 152312099Sjoerg } 152412099Sjoerg } else { 152512099Sjoerg /* 152612099Sjoerg * In traditional C, keep unsigned and promote FLOAT 152712099Sjoerg * to DOUBLE. 152812099Sjoerg */ 152912099Sjoerg if (t == UCHAR || t == USHORT) { 153012099Sjoerg t = UINT; 153112099Sjoerg } else if (t == CHAR || t == SCHAR || t == SHORT) { 153212099Sjoerg t = INT; 153312099Sjoerg } else if (t == FLOAT) { 153412099Sjoerg t = DOUBLE; 153512099Sjoerg } else if (t == ENUM) { 153612099Sjoerg t = INT; 153712099Sjoerg } 153812099Sjoerg } 153912099Sjoerg 154012099Sjoerg if (t != tn->tn_type->t_tspec) { 154112099Sjoerg ntp = tduptyp(tn->tn_type); 154212099Sjoerg ntp->t_tspec = t; 154312099Sjoerg /* 154412099Sjoerg * Keep t_isenum so we are later able to check compatibility 154512099Sjoerg * of enum types. 154612099Sjoerg */ 154712099Sjoerg tn = convert(op, 0, ntp, tn); 154812099Sjoerg } 154912099Sjoerg 155012099Sjoerg return (tn); 155112099Sjoerg} 155212099Sjoerg 155312099Sjoerg/* 155412099Sjoerg * Insert conversions which are necessary to give both operands the same 155512099Sjoerg * type. This is done in different ways for traditional C and ANIS C. 155612099Sjoerg */ 155712099Sjoergstatic void 155891592Smarkmbalance(op_t op, tnode_t **lnp, tnode_t **rnp) 155912099Sjoerg{ 156012099Sjoerg tspec_t lt, rt, t; 156112099Sjoerg int i, u; 156212099Sjoerg type_t *ntp; 156312099Sjoerg static tspec_t tl[] = { 156412099Sjoerg LDOUBLE, DOUBLE, FLOAT, UQUAD, QUAD, ULONG, LONG, UINT, INT, 156512099Sjoerg }; 156612099Sjoerg 156712099Sjoerg lt = (*lnp)->tn_type->t_tspec; 156812099Sjoerg rt = (*rnp)->tn_type->t_tspec; 156912099Sjoerg 157012099Sjoerg if (!isatyp(lt) || !isatyp(rt)) 157112099Sjoerg return; 157212099Sjoerg 157312099Sjoerg if (!tflag) { 157412099Sjoerg if (lt == rt) { 157512099Sjoerg t = lt; 157612099Sjoerg } else if (lt == LDOUBLE || rt == LDOUBLE) { 157712099Sjoerg t = LDOUBLE; 157812099Sjoerg } else if (lt == DOUBLE || rt == DOUBLE) { 157912099Sjoerg t = DOUBLE; 158012099Sjoerg } else if (lt == FLOAT || rt == FLOAT) { 158112099Sjoerg t = FLOAT; 158212099Sjoerg } else { 158312099Sjoerg /* 158412099Sjoerg * If type A has more bits than type B it should 158512099Sjoerg * be able to hold all possible values of type B. 158612099Sjoerg */ 158712099Sjoerg if (size(lt) > size(rt)) { 158812099Sjoerg t = lt; 158912099Sjoerg } else if (size(lt) < size(rt)) { 159012099Sjoerg t = rt; 159112099Sjoerg } else { 159212099Sjoerg for (i = 3; tl[i] != INT; i++) { 159312099Sjoerg if (tl[i] == lt || tl[i] == rt) 159412099Sjoerg break; 159512099Sjoerg } 159612099Sjoerg if ((isutyp(lt) || isutyp(rt)) && 159712099Sjoerg !isutyp(tl[i])) { 159812099Sjoerg i--; 159912099Sjoerg } 160012099Sjoerg t = tl[i]; 160112099Sjoerg } 160212099Sjoerg } 160312099Sjoerg } else { 160412099Sjoerg /* Keep unsigned in traditional C */ 160512099Sjoerg u = isutyp(lt) || isutyp(rt); 160612099Sjoerg for (i = 0; tl[i] != INT; i++) { 160712099Sjoerg if (lt == tl[i] || rt == tl[i]) 160812099Sjoerg break; 160912099Sjoerg } 161012099Sjoerg t = tl[i]; 161112099Sjoerg if (u && isityp(t) && !isutyp(t)) 161212099Sjoerg t = utyp(t); 161312099Sjoerg } 161412099Sjoerg 161512099Sjoerg if (t != lt) { 161612099Sjoerg ntp = tduptyp((*lnp)->tn_type); 161712099Sjoerg ntp->t_tspec = t; 161812099Sjoerg *lnp = convert(op, 0, ntp, *lnp); 161912099Sjoerg } 162012099Sjoerg if (t != rt) { 162112099Sjoerg ntp = tduptyp((*rnp)->tn_type); 162212099Sjoerg ntp->t_tspec = t; 162312099Sjoerg *rnp = convert(op, 0, ntp, *rnp); 162412099Sjoerg } 162512099Sjoerg} 162612099Sjoerg 162712099Sjoerg/* 162812099Sjoerg * Insert a conversion operator, which converts the type of the node 162912099Sjoerg * to another given type. 163012099Sjoerg * If op is FARG, arg is the number of the argument (used for warnings). 163112099Sjoerg */ 163212099Sjoergtnode_t * 163391592Smarkmconvert(op_t op, int arg, type_t *tp, tnode_t *tn) 163412099Sjoerg{ 163512099Sjoerg tnode_t *ntn; 163691592Smarkm tspec_t nt, ot, ost = NOTSPEC; 163712099Sjoerg 163812099Sjoerg if (tn->tn_lvalue) 163912099Sjoerg lerror("convert() 1"); 164012099Sjoerg 164112099Sjoerg nt = tp->t_tspec; 164212099Sjoerg if ((ot = tn->tn_type->t_tspec) == PTR) 164312099Sjoerg ost = tn->tn_type->t_subt->t_tspec; 164412099Sjoerg 164512099Sjoerg if (!tflag && !sflag && op == FARG) 164612099Sjoerg ptconv(arg, nt, ot, tp, tn); 164712099Sjoerg if (isityp(nt) && isityp(ot)) { 164812099Sjoerg iiconv(op, arg, nt, ot, tp, tn); 164912099Sjoerg } else if (nt == PTR && ((ot == PTR && ost == VOID) || isityp(ot)) && 165012099Sjoerg tn->tn_op == CON && tn->tn_val->v_quad == 0) { 165112099Sjoerg /* 0, 0L and (void *)0 may be assigned to any pointer. */ 165212099Sjoerg } else if (isityp(nt) && ot == PTR) { 165312099Sjoerg piconv(op, nt, tp, tn); 165412099Sjoerg } else if (nt == PTR && ot == PTR) { 165512099Sjoerg ppconv(op, tn, tp); 165612099Sjoerg } 165712099Sjoerg 165812099Sjoerg ntn = getnode(); 165912099Sjoerg ntn->tn_op = CVT; 166012099Sjoerg ntn->tn_type = tp; 166112099Sjoerg ntn->tn_cast = op == CVT; 166212099Sjoerg if (tn->tn_op != CON || nt == VOID) { 166312099Sjoerg ntn->tn_left = tn; 166412099Sjoerg } else { 166512099Sjoerg ntn->tn_op = CON; 166612099Sjoerg ntn->tn_val = tgetblk(sizeof (val_t)); 166712099Sjoerg cvtcon(op, arg, ntn->tn_type, ntn->tn_val, tn->tn_val); 166812099Sjoerg } 166912099Sjoerg 167012099Sjoerg return (ntn); 167112099Sjoerg} 167212099Sjoerg 167312099Sjoerg/* 167412099Sjoerg * Print a warning if a prototype causes a type conversion that is 167512099Sjoerg * different from what would happen to the same argument in the 167612099Sjoerg * absence of a prototype. 167712099Sjoerg * 167812099Sjoerg * Errors/Warnings about illegal type combinations are already printed 167912099Sjoerg * in asgntypok(). 168012099Sjoerg */ 168112099Sjoergstatic void 168291592Smarkmptconv(int arg, tspec_t nt, tspec_t ot, type_t *tp, tnode_t *tn) 168312099Sjoerg{ 168412099Sjoerg tnode_t *ptn; 168512099Sjoerg 168612099Sjoerg if (!isatyp(nt) || !isatyp(ot)) 168712099Sjoerg return; 168812099Sjoerg 168912099Sjoerg /* 169012099Sjoerg * If the type of the formal parameter is char/short, a warning 169112099Sjoerg * would be useless, because functions declared the old style 169212099Sjoerg * can't expect char/short arguments. 169312099Sjoerg */ 169412099Sjoerg if (nt == CHAR || nt == UCHAR || nt == SHORT || nt == USHORT) 169512099Sjoerg return; 169612099Sjoerg 169712099Sjoerg /* get default promotion */ 169812099Sjoerg ptn = promote(NOOP, 1, tn); 169912099Sjoerg ot = ptn->tn_type->t_tspec; 170012099Sjoerg 170112099Sjoerg /* return if types are the same with and without prototype */ 170212099Sjoerg if (nt == ot || (nt == ENUM && ot == INT)) 170312099Sjoerg return; 170412099Sjoerg 170512099Sjoerg if (isftyp(nt) != isftyp(ot) || psize(nt) != psize(ot)) { 170612099Sjoerg /* representation and/or width change */ 170712099Sjoerg if (styp(nt) != SHORT || !isityp(ot) || psize(ot) > psize(INT)) 170812099Sjoerg /* conversion to '%s' due to prototype, arg #%d */ 170912099Sjoerg warning(259, tyname(tp), arg); 171012099Sjoerg } else if (hflag) { 171112099Sjoerg /* 171212099Sjoerg * they differ in sign or base type (char, short, int, 171312099Sjoerg * long, long long, float, double, long double) 171412099Sjoerg * 171512099Sjoerg * if they differ only in sign and the argument is a constant 171612099Sjoerg * and the msb of the argument is not set, print no warning 171712099Sjoerg */ 171812099Sjoerg if (ptn->tn_op == CON && isityp(nt) && styp(nt) == styp(ot) && 171912099Sjoerg msb(ptn->tn_val->v_quad, ot, -1) == 0) { 172012099Sjoerg /* ok */ 172112099Sjoerg } else { 172212099Sjoerg /* conversion to '%s' due to prototype, arg #%d */ 172312099Sjoerg warning(259, tyname(tp), arg); 172412099Sjoerg } 172512099Sjoerg } 172612099Sjoerg} 172712099Sjoerg 172812099Sjoerg/* 172912099Sjoerg * Print warnings for conversions of integer types which my cause 173012099Sjoerg * problems. 173112099Sjoerg */ 173212099Sjoerg/* ARGSUSED */ 173312099Sjoergstatic void 173491592Smarkmiiconv(op_t op, int arg, tspec_t nt, tspec_t ot, type_t *tp, tnode_t *tn) 173512099Sjoerg{ 173612099Sjoerg if (tn->tn_op == CON) 173712099Sjoerg return; 173812099Sjoerg 173912099Sjoerg if (op == CVT) 174012099Sjoerg return; 174112099Sjoerg 174212099Sjoerg#if 0 174312099Sjoerg if (psize(nt) > psize(ot) && isutyp(nt) != isutyp(ot)) { 174412099Sjoerg /* conversion to %s may sign-extend incorrectly (, arg #%d) */ 174512099Sjoerg if (aflag && pflag) { 174612099Sjoerg if (op == FARG) { 174712099Sjoerg warning(297, tyname(tp), arg); 174812099Sjoerg } else { 174912099Sjoerg warning(131, tyname(tp)); 175012099Sjoerg } 175112099Sjoerg } 175212099Sjoerg } 175312099Sjoerg#endif 175412099Sjoerg 175512099Sjoerg if (psize(nt) < psize(ot) && 175612099Sjoerg (ot == LONG || ot == ULONG || ot == QUAD || ot == UQUAD || 175712099Sjoerg aflag > 1)) { 175812099Sjoerg /* conversion from '%s' may lose accuracy */ 175912099Sjoerg if (aflag) { 176012099Sjoerg if (op == FARG) { 176112099Sjoerg warning(298, tyname(tn->tn_type), arg); 176212099Sjoerg } else { 176312099Sjoerg warning(132, tyname(tn->tn_type)); 176412099Sjoerg } 176591592Smarkm } 176612099Sjoerg } 176712099Sjoerg} 176812099Sjoerg 176912099Sjoerg/* 177012099Sjoerg * Print warnings for dubious conversions of pointer to integer. 177112099Sjoerg */ 177212099Sjoergstatic void 177391592Smarkmpiconv(op_t op, tspec_t nt, type_t *tp, tnode_t *tn) 177412099Sjoerg{ 177591592Smarkm 177612099Sjoerg if (tn->tn_op == CON) 177712099Sjoerg return; 177812099Sjoerg 177912099Sjoerg if (op != CVT) { 178012099Sjoerg /* We got already an error. */ 178112099Sjoerg return; 178212099Sjoerg } 178312099Sjoerg 178412099Sjoerg if (psize(nt) < psize(PTR)) { 178512099Sjoerg if (pflag && size(nt) >= size(PTR)) { 178612099Sjoerg /* conv. of pointer to %s may lose bits */ 178712099Sjoerg warning(134, tyname(tp)); 178812099Sjoerg } else { 178912099Sjoerg /* conv. of pointer to %s loses bits */ 179012099Sjoerg warning(133, tyname(tp)); 179112099Sjoerg } 179212099Sjoerg } 179312099Sjoerg} 179412099Sjoerg 179512099Sjoerg/* 179612099Sjoerg * Print warnings for questionable pointer conversions. 179712099Sjoerg */ 179812099Sjoergstatic void 179991592Smarkmppconv(op_t op, tnode_t *tn, type_t *tp) 180012099Sjoerg{ 180112099Sjoerg tspec_t nt, ot; 180212099Sjoerg const char *nts, *ots; 180312099Sjoerg 180412099Sjoerg /* 180512099Sjoerg * We got already an error (pointers of different types 180612099Sjoerg * without a cast) or we will not get a warning. 180712099Sjoerg */ 180812099Sjoerg if (op != CVT) 180912099Sjoerg return; 181012099Sjoerg 181112099Sjoerg nt = tp->t_subt->t_tspec; 181212099Sjoerg ot = tn->tn_type->t_subt->t_tspec; 181312099Sjoerg 181412099Sjoerg if (nt == VOID || ot == VOID) { 181512099Sjoerg if (sflag && (nt == FUNC || ot == FUNC)) { 181612099Sjoerg /* (void *)0 already handled in convert() */ 181712099Sjoerg *(nt == FUNC ? &nts : &ots) = "function pointer"; 181812099Sjoerg *(nt == VOID ? &nts : &ots) = "'void *'"; 181912099Sjoerg /* ANSI C forbids conversion of %s to %s */ 182012099Sjoerg warning(303, ots, nts); 182112099Sjoerg } 182212099Sjoerg return; 182312099Sjoerg } else if (nt == FUNC && ot == FUNC) { 182412099Sjoerg return; 182512099Sjoerg } else if (nt == FUNC || ot == FUNC) { 182612099Sjoerg /* questionable conversion of function pointer */ 182712099Sjoerg warning(229); 182812099Sjoerg return; 182912099Sjoerg } 183091592Smarkm 183112099Sjoerg if (getbound(tp->t_subt) > getbound(tn->tn_type->t_subt)) { 183212099Sjoerg if (hflag) 183312099Sjoerg /* possible pointer alignment problem */ 183412099Sjoerg warning(135); 183512099Sjoerg } 183612099Sjoerg if (((nt == STRUCT || nt == UNION) && 183712099Sjoerg tp->t_subt->t_str != tn->tn_type->t_subt->t_str) || 183812099Sjoerg psize(nt) != psize(ot)) { 183912099Sjoerg if (cflag) { 184012099Sjoerg /* pointer casts may be troublesome */ 184112099Sjoerg warning(247); 184212099Sjoerg } 184312099Sjoerg } 184412099Sjoerg} 184512099Sjoerg 184612099Sjoerg/* 184712099Sjoerg * Converts a typed constant in a constant of another type. 184812099Sjoerg * 184912099Sjoerg * op operator which requires conversion 185012099Sjoerg * arg if op is FARG, # of argument 185112099Sjoerg * tp type in which to convert the constant 185212099Sjoerg * nv new constant 185312099Sjoerg * v old constant 185412099Sjoerg */ 185512099Sjoergvoid 185691592Smarkmcvtcon(op_t op, int arg, type_t *tp, val_t *nv, val_t *v) 185712099Sjoerg{ 185812099Sjoerg tspec_t ot, nt; 185991592Smarkm ldbl_t max = 0.0, min = 0.0; 186012099Sjoerg int sz, rchk; 186191592Smarkm int64_t xmask, xmsk1; 186212099Sjoerg int osz, nsz; 186312099Sjoerg 186412099Sjoerg ot = v->v_tspec; 186512099Sjoerg nt = nv->v_tspec = tp->t_tspec; 186612099Sjoerg rchk = 0; 186712099Sjoerg 186812099Sjoerg if (ot == FLOAT || ot == DOUBLE || ot == LDOUBLE) { 186912099Sjoerg switch (nt) { 187012099Sjoerg case CHAR: 187112099Sjoerg max = CHAR_MAX; min = CHAR_MIN; break; 187212099Sjoerg case UCHAR: 187312099Sjoerg max = UCHAR_MAX; min = 0; break; 187412099Sjoerg case SCHAR: 187512099Sjoerg max = SCHAR_MAX; min = SCHAR_MIN; break; 187612099Sjoerg case SHORT: 187712099Sjoerg max = SHRT_MAX; min = SHRT_MIN; break; 187812099Sjoerg case USHORT: 187912099Sjoerg max = USHRT_MAX; min = 0; break; 188012099Sjoerg case ENUM: 188112099Sjoerg case INT: 188212099Sjoerg max = INT_MAX; min = INT_MIN; break; 188312099Sjoerg case UINT: 188412099Sjoerg max = (u_int)UINT_MAX; min = 0; break; 188512099Sjoerg case LONG: 188612099Sjoerg max = LONG_MAX; min = LONG_MIN; break; 188712099Sjoerg case ULONG: 188812099Sjoerg max = (u_long)ULONG_MAX; min = 0; break; 188912099Sjoerg case QUAD: 189012099Sjoerg max = QUAD_MAX; min = QUAD_MIN; break; 189112099Sjoerg case UQUAD: 189291592Smarkm max = (uint64_t)UQUAD_MAX; min = 0; break; 189312099Sjoerg case FLOAT: 189412099Sjoerg max = FLT_MAX; min = -FLT_MAX; break; 189512099Sjoerg case DOUBLE: 189612099Sjoerg max = DBL_MAX; min = -DBL_MAX; break; 189712099Sjoerg case PTR: 189812099Sjoerg /* Got already an error because of float --> ptr */ 189912099Sjoerg case LDOUBLE: 190012099Sjoerg max = LDBL_MAX; min = -LDBL_MAX; break; 190112099Sjoerg default: 190212099Sjoerg lerror("cvtcon() 1"); 190312099Sjoerg } 190412099Sjoerg if (v->v_ldbl > max || v->v_ldbl < min) { 190512099Sjoerg if (nt == LDOUBLE) 190612099Sjoerg lerror("cvtcon() 2"); 190712099Sjoerg if (op == FARG) { 190812099Sjoerg /* conv. of %s to %s is out of rng., arg #%d */ 190912099Sjoerg warning(295, tyname(gettyp(ot)), tyname(tp), 191012099Sjoerg arg); 191112099Sjoerg } else { 191212099Sjoerg /* conversion of %s to %s is out of range */ 191312099Sjoerg warning(119, tyname(gettyp(ot)), tyname(tp)); 191412099Sjoerg } 191512099Sjoerg v->v_ldbl = v->v_ldbl > 0 ? max : min; 191612099Sjoerg } 191712099Sjoerg if (nt == FLOAT) { 191812099Sjoerg nv->v_ldbl = (float)v->v_ldbl; 191912099Sjoerg } else if (nt == DOUBLE) { 192012099Sjoerg nv->v_ldbl = (double)v->v_ldbl; 192112099Sjoerg } else if (nt == LDOUBLE) { 192212099Sjoerg nv->v_ldbl = v->v_ldbl; 192312099Sjoerg } else { 192412099Sjoerg nv->v_quad = (nt == PTR || isutyp(nt)) ? 192591592Smarkm (uint64_t)v->v_ldbl : (int64_t)v->v_ldbl; 192612099Sjoerg } 192712099Sjoerg } else { 192812099Sjoerg if (nt == FLOAT) { 192912099Sjoerg nv->v_ldbl = (ot == PTR || isutyp(ot)) ? 193091592Smarkm (float)(uint64_t)v->v_quad : (float)v->v_quad; 193112099Sjoerg } else if (nt == DOUBLE) { 193212099Sjoerg nv->v_ldbl = (ot == PTR || isutyp(ot)) ? 193391592Smarkm (double)(uint64_t)v->v_quad : (double)v->v_quad; 193412099Sjoerg } else if (nt == LDOUBLE) { 193512099Sjoerg nv->v_ldbl = (ot == PTR || isutyp(ot)) ? 193691592Smarkm (ldbl_t)(uint64_t)v->v_quad : (ldbl_t)v->v_quad; 193712099Sjoerg } else { 193812099Sjoerg rchk = 1; /* Check for lost precision. */ 193912099Sjoerg nv->v_quad = v->v_quad; 194012099Sjoerg } 194112099Sjoerg } 194212099Sjoerg 194312099Sjoerg if (v->v_ansiu && isftyp(nt)) { 194412099Sjoerg /* ANSI C treats constant as unsigned */ 194512099Sjoerg warning(157); 194612099Sjoerg v->v_ansiu = 0; 194712099Sjoerg } else if (v->v_ansiu && (isityp(nt) && !isutyp(nt) && 194812099Sjoerg psize(nt) > psize(ot))) { 194912099Sjoerg /* ANSI C treats constant as unsigned */ 195012099Sjoerg warning(157); 195112099Sjoerg v->v_ansiu = 0; 195212099Sjoerg } 195312099Sjoerg 195412099Sjoerg if (nt != FLOAT && nt != DOUBLE && nt != LDOUBLE) { 195512099Sjoerg sz = tp->t_isfield ? tp->t_flen : size(nt); 195612099Sjoerg nv->v_quad = xsign(nv->v_quad, nt, sz); 195712099Sjoerg } 195891592Smarkm 195912099Sjoerg if (rchk && op != CVT) { 196012099Sjoerg osz = size(ot); 196112099Sjoerg nsz = tp->t_isfield ? tp->t_flen : size(nt); 196212099Sjoerg xmask = qlmasks[nsz] ^ qlmasks[osz]; 196312099Sjoerg xmsk1 = qlmasks[nsz] ^ qlmasks[osz - 1]; 196412099Sjoerg /* 196512099Sjoerg * For bitwise operations we are not interested in the 196612099Sjoerg * value, but in the bits itself. 196712099Sjoerg */ 196812099Sjoerg if (op == ORASS || op == OR || op == XOR) { 196912099Sjoerg /* 197012099Sjoerg * Print a warning if bits which were set are 197112099Sjoerg * lost due to the conversion. 197212099Sjoerg * This can happen with operator ORASS only. 197312099Sjoerg */ 197412099Sjoerg if (nsz < osz && (v->v_quad & xmask) != 0) { 197512099Sjoerg /* constant truncated by conv., op %s */ 197612099Sjoerg warning(306, modtab[op].m_name); 197712099Sjoerg } 197812099Sjoerg } else if (op == ANDASS || op == AND) { 197912099Sjoerg /* 198012099Sjoerg * Print a warning if additional bits are not all 1 198112099Sjoerg * and the most significant bit of the old value is 1, 198212099Sjoerg * or if at least one (but not all) removed bit was 0. 198312099Sjoerg */ 198412099Sjoerg if (nsz > osz && 198512099Sjoerg (nv->v_quad & qbmasks[osz - 1]) != 0 && 198612099Sjoerg (nv->v_quad & xmask) != xmask) { 198712099Sjoerg /* 198812099Sjoerg * extra bits set to 0 in conversion 198912099Sjoerg * of '%s' to '%s', op %s 199012099Sjoerg */ 199112099Sjoerg warning(309, tyname(gettyp(ot)), 199212099Sjoerg tyname(tp), modtab[op].m_name); 199312099Sjoerg } else if (nsz < osz && 199412099Sjoerg (v->v_quad & xmask) != xmask && 199512099Sjoerg (v->v_quad & xmask) != 0) { 199612099Sjoerg /* const. truncated by conv., op %s */ 199712099Sjoerg warning(306, modtab[op].m_name); 199812099Sjoerg } 199912099Sjoerg } else if ((nt != PTR && isutyp(nt)) && 200012099Sjoerg (ot != PTR && !isutyp(ot)) && v->v_quad < 0) { 200112099Sjoerg if (op == ASSIGN) { 200212099Sjoerg /* assignment of negative constant to ... */ 200312099Sjoerg warning(164); 200412099Sjoerg } else if (op == INIT) { 200512099Sjoerg /* initialisation of unsigned with neg. ... */ 200612099Sjoerg warning(221); 200712099Sjoerg } else if (op == FARG) { 200812099Sjoerg /* conversion of neg. const. to ..., arg #%d */ 200912099Sjoerg warning(296, arg); 201012099Sjoerg } else if (modtab[op].m_comp) { 201112099Sjoerg /* we get this warning already in chkcomp() */ 201212099Sjoerg } else { 201312099Sjoerg /* conversion of negative constant to ... */ 201412099Sjoerg warning(222); 201512099Sjoerg } 201612099Sjoerg } else if (nv->v_quad != v->v_quad && nsz <= osz && 201712099Sjoerg (v->v_quad & xmask) != 0 && 201812099Sjoerg (isutyp(ot) || (v->v_quad & xmsk1) != xmsk1)) { 201912099Sjoerg /* 202012099Sjoerg * Loss of significant bit(s). All truncated bits 202112099Sjoerg * of unsigned types or all truncated bits plus the 202212099Sjoerg * msb of the target for signed types are considered 202312099Sjoerg * to be significant bits. Loss of significant bits 202412099Sjoerg * means that at least on of the bits was set in an 202512099Sjoerg * unsigned type or that at least one, but not all of 2026108470Sschweikh * the bits was set in a signed type. 202712099Sjoerg * Loss of significant bits means that it is not 202812099Sjoerg * possible, also not with necessary casts, to convert 2029108532Sschweikh * back to the original type. An example for a 203012099Sjoerg * necessary cast is: 203112099Sjoerg * char c; int i; c = 128; 203212099Sjoerg * i = c; ** yields -128 ** 203312099Sjoerg * i = (unsigned char)c; ** yields 128 ** 203412099Sjoerg */ 203512099Sjoerg if (op == ASSIGN && tp->t_isfield) { 203612099Sjoerg /* precision lost in bit-field assignment */ 203712099Sjoerg warning(166); 203812099Sjoerg } else if (op == ASSIGN) { 203912099Sjoerg /* constant truncated by assignment */ 204012099Sjoerg warning(165); 204112099Sjoerg } else if (op == INIT && tp->t_isfield) { 204212099Sjoerg /* bit-field initializer does not fit */ 204312099Sjoerg warning(180); 204412099Sjoerg } else if (op == INIT) { 204512099Sjoerg /* initializer does not fit */ 204612099Sjoerg warning(178); 204712099Sjoerg } else if (op == CASE) { 204812099Sjoerg /* case label affected by conversion */ 204912099Sjoerg warning(196); 205012099Sjoerg } else if (op == FARG) { 205112099Sjoerg /* conv. of %s to %s is out of rng., arg #%d */ 205212099Sjoerg warning(295, tyname(gettyp(ot)), tyname(tp), 205312099Sjoerg arg); 205412099Sjoerg } else { 205512099Sjoerg /* conversion of %s to %s is out of range */ 205612099Sjoerg warning(119, tyname(gettyp(ot)), tyname(tp)); 205712099Sjoerg } 205812099Sjoerg } else if (nv->v_quad != v->v_quad) { 205912099Sjoerg if (op == ASSIGN && tp->t_isfield) { 206012099Sjoerg /* precision lost in bit-field assignment */ 206112099Sjoerg warning(166); 206212099Sjoerg } else if (op == INIT && tp->t_isfield) { 206312099Sjoerg /* bit-field initializer out of range */ 206412099Sjoerg warning(11); 206512099Sjoerg } else if (op == CASE) { 206612099Sjoerg /* case label affected by conversion */ 206712099Sjoerg warning(196); 206812099Sjoerg } else if (op == FARG) { 206912099Sjoerg /* conv. of %s to %s is out of rng., arg #%d */ 207012099Sjoerg warning(295, tyname(gettyp(ot)), tyname(tp), 207112099Sjoerg arg); 207212099Sjoerg } else { 207312099Sjoerg /* conversion of %s to %s is out of range */ 207412099Sjoerg warning(119, tyname(gettyp(ot)), tyname(tp)); 207512099Sjoerg } 207612099Sjoerg } 207712099Sjoerg } 207812099Sjoerg} 207912099Sjoerg 208012099Sjoerg/* 208112099Sjoerg * Called if incompatible types were detected. 2082108532Sschweikh * Prints an appropriate warning. 208312099Sjoerg */ 208412099Sjoergstatic void 208591592Smarkmincompat(op_t op, tspec_t lt, tspec_t rt) 208612099Sjoerg{ 208712099Sjoerg mod_t *mp; 208812099Sjoerg 208912099Sjoerg mp = &modtab[op]; 209012099Sjoerg 209112099Sjoerg if (lt == VOID || (mp->m_binary && rt == VOID)) { 209212099Sjoerg /* void type illegal in expression */ 209312099Sjoerg error(109); 209412099Sjoerg } else if (op == ASSIGN) { 209512099Sjoerg if ((lt == STRUCT || lt == UNION) && 209612099Sjoerg (rt == STRUCT || rt == UNION)) { 209712099Sjoerg /* assignment of different structures */ 209812099Sjoerg error(240); 209912099Sjoerg } else { 210012099Sjoerg /* assignment type mismatch */ 210112099Sjoerg error(171); 210212099Sjoerg } 210312099Sjoerg } else if (mp->m_binary) { 210412099Sjoerg /* operands of %s have incompatible types */ 210512099Sjoerg error(107, mp->m_name); 210612099Sjoerg } else { 210712099Sjoerg /* operand of %s has incompatible type */ 210812099Sjoerg error(108, mp->m_name); 210912099Sjoerg } 211012099Sjoerg} 211112099Sjoerg 211212099Sjoerg/* 211312099Sjoerg * Called if incompatible pointer types are detected. 211412099Sjoerg * Print an appropriate warning. 211512099Sjoerg */ 211612099Sjoergstatic void 211791592Smarkmillptrc(mod_t *mp, type_t *ltp, type_t *rtp) 211812099Sjoerg{ 211912099Sjoerg tspec_t lt, rt; 212012099Sjoerg 212112099Sjoerg if (ltp->t_tspec != PTR || rtp->t_tspec != PTR) 212212099Sjoerg lerror("illptrc() 1"); 212312099Sjoerg 212412099Sjoerg lt = ltp->t_subt->t_tspec; 212512099Sjoerg rt = rtp->t_subt->t_tspec; 212612099Sjoerg 212712099Sjoerg if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION)) { 212812099Sjoerg if (mp == NULL) { 212912099Sjoerg /* illegal structure pointer combination */ 213012099Sjoerg warning(244); 213112099Sjoerg } else { 213212099Sjoerg /* illegal structure pointer combination, op %s */ 213312099Sjoerg warning(245, mp->m_name); 213412099Sjoerg } 213512099Sjoerg } else { 213612099Sjoerg if (mp == NULL) { 213712099Sjoerg /* illegal pointer combination */ 213812099Sjoerg warning(184); 213912099Sjoerg } else { 214012099Sjoerg /* illegal pointer combination, op %s */ 214112099Sjoerg warning(124, mp->m_name); 214212099Sjoerg } 214312099Sjoerg } 214412099Sjoerg} 214512099Sjoerg 214612099Sjoerg/* 214712099Sjoerg * Make sure type (*tpp)->t_subt has at least the qualifiers 214812099Sjoerg * of tp1->t_subt and tp2->t_subt. 214912099Sjoerg */ 215012099Sjoergstatic void 215191592Smarkmmrgqual(type_t **tpp, type_t *tp1, type_t *tp2) 215212099Sjoerg{ 215391592Smarkm 215412099Sjoerg if ((*tpp)->t_tspec != PTR || 215512099Sjoerg tp1->t_tspec != PTR || tp2->t_tspec != PTR) { 215612099Sjoerg lerror("mrgqual()"); 215712099Sjoerg } 215812099Sjoerg 215912099Sjoerg if ((*tpp)->t_subt->t_const == 216012099Sjoerg (tp1->t_subt->t_const | tp2->t_subt->t_const) && 216112099Sjoerg (*tpp)->t_subt->t_volatile == 216212099Sjoerg (tp1->t_subt->t_volatile | tp2->t_subt->t_volatile)) { 216312099Sjoerg return; 216412099Sjoerg } 216512099Sjoerg 216612099Sjoerg *tpp = tduptyp(*tpp); 216712099Sjoerg (*tpp)->t_subt = tduptyp((*tpp)->t_subt); 216812099Sjoerg (*tpp)->t_subt->t_const = 216912099Sjoerg tp1->t_subt->t_const | tp2->t_subt->t_const; 217012099Sjoerg (*tpp)->t_subt->t_volatile = 217112099Sjoerg tp1->t_subt->t_volatile | tp2->t_subt->t_volatile; 217212099Sjoerg} 217312099Sjoerg 217412099Sjoerg/* 217512099Sjoerg * Returns 1 if the given structure or union has a constant member 217612099Sjoerg * (maybe recursively). 217712099Sjoerg */ 217812099Sjoergstatic int 217991592Smarkmconmemb(type_t *tp) 218012099Sjoerg{ 218112099Sjoerg sym_t *m; 218212099Sjoerg tspec_t t; 218312099Sjoerg 218412099Sjoerg if ((t = tp->t_tspec) != STRUCT && t != UNION) 218512099Sjoerg lerror("conmemb()"); 218612099Sjoerg for (m = tp->t_str->memb; m != NULL; m = m->s_nxt) { 218712099Sjoerg tp = m->s_type; 218812099Sjoerg if (tp->t_const) 218912099Sjoerg return (1); 219012099Sjoerg if ((t = tp->t_tspec) == STRUCT || t == UNION) { 219112099Sjoerg if (conmemb(m->s_type)) 219212099Sjoerg return (1); 219312099Sjoerg } 219412099Sjoerg } 219512099Sjoerg return (0); 219612099Sjoerg} 219712099Sjoerg 219812099Sjoergconst char * 219991592Smarkmtyname(type_t *tp) 220012099Sjoerg{ 220112099Sjoerg tspec_t t; 220212099Sjoerg const char *s; 220312099Sjoerg 220412099Sjoerg if ((t = tp->t_tspec) == INT && tp->t_isenum) 220512099Sjoerg t = ENUM; 220612099Sjoerg 220712099Sjoerg switch (t) { 220812099Sjoerg case CHAR: s = "char"; break; 220912099Sjoerg case UCHAR: s = "unsigned char"; break; 221012099Sjoerg case SCHAR: s = "signed char"; break; 221112099Sjoerg case SHORT: s = "short"; break; 221212099Sjoerg case USHORT: s = "unsigned short"; break; 221312099Sjoerg case INT: s = "int"; break; 221412099Sjoerg case UINT: s = "unsigned int"; break; 221512099Sjoerg case LONG: s = "long"; break; 221612099Sjoerg case ULONG: s = "unsigned long"; break; 221712099Sjoerg case QUAD: s = "long long"; break; 221812099Sjoerg case UQUAD: s = "unsigned long long"; break; 221912099Sjoerg case FLOAT: s = "float"; break; 222012099Sjoerg case DOUBLE: s = "double"; break; 222112099Sjoerg case LDOUBLE: s = "long double"; break; 222212099Sjoerg case PTR: s = "pointer"; break; 222312099Sjoerg case ENUM: s = "enum"; break; 222412099Sjoerg case STRUCT: s = "struct"; break; 222512099Sjoerg case UNION: s = "union"; break; 222612099Sjoerg case FUNC: s = "function"; break; 222712099Sjoerg case ARRAY: s = "array"; break; 222812099Sjoerg default: 222912099Sjoerg lerror("tyname()"); 223012099Sjoerg } 223112099Sjoerg return (s); 223212099Sjoerg} 223312099Sjoerg 223412099Sjoerg/* 223512099Sjoerg * Create a new node for one of the operators POINT and ARROW. 223612099Sjoerg */ 223712099Sjoergstatic tnode_t * 223891592Smarkmbldstr(op_t op, tnode_t *ln, tnode_t *rn) 223912099Sjoerg{ 224012099Sjoerg tnode_t *ntn, *ctn; 224112099Sjoerg int nolval; 224212099Sjoerg 224312099Sjoerg if (rn->tn_op != NAME) 224412099Sjoerg lerror("bldstr() 1"); 224512099Sjoerg if (rn->tn_sym->s_value.v_tspec != INT) 224612099Sjoerg lerror("bldstr() 2"); 224712099Sjoerg if (rn->tn_sym->s_scl != MOS && rn->tn_sym->s_scl != MOU) 224812099Sjoerg lerror("bldstr() 3"); 224912099Sjoerg 225012099Sjoerg /* 225112099Sjoerg * Remember if the left operand is an lvalue (structure members 225212099Sjoerg * are lvalues if and only if the structure itself is an lvalue). 225312099Sjoerg */ 225412099Sjoerg nolval = op == POINT && !ln->tn_lvalue; 225512099Sjoerg 225612099Sjoerg if (op == POINT) { 225712099Sjoerg ln = bldamper(ln, 1); 225812099Sjoerg } else if (ln->tn_type->t_tspec != PTR) { 225912099Sjoerg if (!tflag || !isityp(ln->tn_type->t_tspec)) 226012099Sjoerg lerror("bldstr() 4"); 226112099Sjoerg ln = convert(NOOP, 0, tincref(gettyp(VOID), PTR), ln); 226212099Sjoerg } 226312099Sjoerg 226412099Sjoerg#if PTRDIFF_IS_LONG 226512099Sjoerg ctn = getinode(LONG, rn->tn_sym->s_value.v_quad / CHAR_BIT); 226612099Sjoerg#else 226712099Sjoerg ctn = getinode(INT, rn->tn_sym->s_value.v_quad / CHAR_BIT); 226812099Sjoerg#endif 226912099Sjoerg 227012099Sjoerg ntn = mktnode(PLUS, tincref(rn->tn_type, PTR), ln, ctn); 227112099Sjoerg if (ln->tn_op == CON) 227212099Sjoerg ntn = fold(ntn); 227312099Sjoerg 227412099Sjoerg if (rn->tn_type->t_isfield) { 227512099Sjoerg ntn = mktnode(FSEL, ntn->tn_type->t_subt, ntn, NULL); 227612099Sjoerg } else { 227712099Sjoerg ntn = mktnode(STAR, ntn->tn_type->t_subt, ntn, NULL); 227812099Sjoerg } 227912099Sjoerg 228012099Sjoerg if (nolval) 228112099Sjoerg ntn->tn_lvalue = 0; 228212099Sjoerg 228312099Sjoerg return (ntn); 228412099Sjoerg} 228512099Sjoerg 228612099Sjoerg/* 228712099Sjoerg * Create a node for INCAFT, INCBEF, DECAFT and DECBEF. 228812099Sjoerg */ 228912099Sjoergstatic tnode_t * 229091592Smarkmbldincdec(op_t op, tnode_t *ln) 229112099Sjoerg{ 229212099Sjoerg tnode_t *cn, *ntn; 229312099Sjoerg 229412099Sjoerg if (ln == NULL) 229512099Sjoerg lerror("bldincdec() 1"); 229612099Sjoerg 229712099Sjoerg if (ln->tn_type->t_tspec == PTR) { 229812099Sjoerg cn = plength(ln->tn_type); 229912099Sjoerg } else { 230091592Smarkm cn = getinode(INT, (int64_t)1); 230112099Sjoerg } 230212099Sjoerg ntn = mktnode(op, ln->tn_type, ln, cn); 230312099Sjoerg 230412099Sjoerg return (ntn); 230512099Sjoerg} 230612099Sjoerg 230712099Sjoerg/* 230812099Sjoerg * Create a tree node for the & operator 230912099Sjoerg */ 231012099Sjoergstatic tnode_t * 231191592Smarkmbldamper(tnode_t *tn, int noign) 231212099Sjoerg{ 231312099Sjoerg tnode_t *ntn; 231412099Sjoerg tspec_t t; 231591592Smarkm 231612099Sjoerg if (!noign && ((t = tn->tn_type->t_tspec) == ARRAY || t == FUNC)) { 231712099Sjoerg /* & before array or function: ignored */ 231812099Sjoerg if (tflag) 231912099Sjoerg warning(127); 232012099Sjoerg return (tn); 232112099Sjoerg } 232212099Sjoerg 232312099Sjoerg /* eliminate &* */ 232412099Sjoerg if (tn->tn_op == STAR && 232512099Sjoerg tn->tn_left->tn_type->t_tspec == PTR && 232612099Sjoerg tn->tn_left->tn_type->t_subt == tn->tn_type) { 232712099Sjoerg return (tn->tn_left); 232812099Sjoerg } 232991592Smarkm 233012099Sjoerg ntn = mktnode(AMPER, tincref(tn->tn_type, PTR), tn, NULL); 233112099Sjoerg 233212099Sjoerg return (ntn); 233312099Sjoerg} 233412099Sjoerg 233512099Sjoerg/* 233612099Sjoerg * Create a node for operators PLUS and MINUS. 233712099Sjoerg */ 233812099Sjoergstatic tnode_t * 233991592Smarkmbldplmi(op_t op, tnode_t *ln, tnode_t *rn) 234012099Sjoerg{ 234112099Sjoerg tnode_t *ntn, *ctn; 234212099Sjoerg type_t *tp; 234312099Sjoerg 234412099Sjoerg /* If pointer and integer, then pointer to the lhs. */ 234512099Sjoerg if (rn->tn_type->t_tspec == PTR && isityp(ln->tn_type->t_tspec)) { 234612099Sjoerg ntn = ln; 234712099Sjoerg ln = rn; 234812099Sjoerg rn = ntn; 234912099Sjoerg } 235012099Sjoerg 235112099Sjoerg if (ln->tn_type->t_tspec == PTR && rn->tn_type->t_tspec != PTR) { 235212099Sjoerg 235312099Sjoerg if (!isityp(rn->tn_type->t_tspec)) 235412099Sjoerg lerror("bldplmi() 1"); 235512099Sjoerg 235612099Sjoerg ctn = plength(ln->tn_type); 235712099Sjoerg if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec) 235812099Sjoerg rn = convert(NOOP, 0, ctn->tn_type, rn); 235912099Sjoerg rn = mktnode(MULT, rn->tn_type, rn, ctn); 236012099Sjoerg if (rn->tn_left->tn_op == CON) 236112099Sjoerg rn = fold(rn); 236212099Sjoerg ntn = mktnode(op, ln->tn_type, ln, rn); 236312099Sjoerg 236412099Sjoerg } else if (rn->tn_type->t_tspec == PTR) { 236512099Sjoerg 236612099Sjoerg if (ln->tn_type->t_tspec != PTR || op != MINUS) 236712099Sjoerg lerror("bldplmi() 2"); 236812099Sjoerg#if PTRDIFF_IS_LONG 236912099Sjoerg tp = gettyp(LONG); 237012099Sjoerg#else 237112099Sjoerg tp = gettyp(INT); 237212099Sjoerg#endif 237312099Sjoerg ntn = mktnode(op, tp, ln, rn); 237412099Sjoerg if (ln->tn_op == CON && rn->tn_op == CON) 237512099Sjoerg ntn = fold(ntn); 237612099Sjoerg ctn = plength(ln->tn_type); 237712099Sjoerg balance(NOOP, &ntn, &ctn); 237812099Sjoerg ntn = mktnode(DIV, tp, ntn, ctn); 237912099Sjoerg 238012099Sjoerg } else { 238112099Sjoerg 238212099Sjoerg ntn = mktnode(op, ln->tn_type, ln, rn); 238312099Sjoerg 238412099Sjoerg } 238512099Sjoerg return (ntn); 238612099Sjoerg} 238712099Sjoerg 238812099Sjoerg/* 238912099Sjoerg * Create a node for operators SHL and SHR. 239012099Sjoerg */ 239112099Sjoergstatic tnode_t * 239291592Smarkmbldshft(op_t op, tnode_t *ln, tnode_t *rn) 239312099Sjoerg{ 239412099Sjoerg tspec_t t; 239512099Sjoerg tnode_t *ntn; 239612099Sjoerg 239712099Sjoerg if ((t = rn->tn_type->t_tspec) != INT && t != UINT) 239812099Sjoerg rn = convert(CVT, 0, gettyp(INT), rn); 239912099Sjoerg ntn = mktnode(op, ln->tn_type, ln, rn); 240012099Sjoerg return (ntn); 240112099Sjoerg} 240212099Sjoerg 240312099Sjoerg/* 240412099Sjoerg * Create a node for COLON. 240512099Sjoerg */ 240612099Sjoergstatic tnode_t * 240791592Smarkmbldcol(tnode_t *ln, tnode_t *rn) 240812099Sjoerg{ 240912099Sjoerg tspec_t lt, rt, pdt; 241012099Sjoerg type_t *rtp; 241112099Sjoerg tnode_t *ntn; 241212099Sjoerg 241312099Sjoerg lt = ln->tn_type->t_tspec; 241412099Sjoerg rt = rn->tn_type->t_tspec; 241512099Sjoerg#if PTRDIFF_IS_LONG 241612099Sjoerg pdt = LONG; 241712099Sjoerg#else 241812099Sjoerg pdt = INT; 241912099Sjoerg#endif 242012099Sjoerg 242112099Sjoerg /* 242212099Sjoerg * Arithmetic types are balanced, all other type combinations 242312099Sjoerg * still need to be handled. 242412099Sjoerg */ 242512099Sjoerg if (isatyp(lt) && isatyp(rt)) { 242612099Sjoerg rtp = ln->tn_type; 242712099Sjoerg } else if (lt == VOID || rt == VOID) { 242812099Sjoerg rtp = gettyp(VOID); 242912099Sjoerg } else if (lt == STRUCT || lt == UNION) { 243012099Sjoerg /* Both types must be identical. */ 243112099Sjoerg if (rt != STRUCT && rt != UNION) 243212099Sjoerg lerror("bldcol() 1"); 243312099Sjoerg if (ln->tn_type->t_str != rn->tn_type->t_str) 243412099Sjoerg lerror("bldcol() 2"); 243512099Sjoerg if (incompl(ln->tn_type)) { 243612099Sjoerg /* unknown operand size, op %s */ 243712099Sjoerg error(138, modtab[COLON].m_name); 243812099Sjoerg return (NULL); 243912099Sjoerg } 244012099Sjoerg rtp = ln->tn_type; 244112099Sjoerg } else if (lt == PTR && isityp(rt)) { 244212099Sjoerg if (rt != pdt) { 244312099Sjoerg rn = convert(NOOP, 0, gettyp(pdt), rn); 244412099Sjoerg rt = pdt; 244512099Sjoerg } 244612099Sjoerg rtp = ln->tn_type; 244712099Sjoerg } else if (rt == PTR && isityp(lt)) { 244812099Sjoerg if (lt != pdt) { 244912099Sjoerg ln = convert(NOOP, 0, gettyp(pdt), ln); 245012099Sjoerg lt = pdt; 245112099Sjoerg } 245212099Sjoerg rtp = rn->tn_type; 245312099Sjoerg } else if (lt == PTR && ln->tn_type->t_subt->t_tspec == VOID) { 245412099Sjoerg if (rt != PTR) 245512099Sjoerg lerror("bldcol() 4"); 245612099Sjoerg rtp = ln->tn_type; 245712099Sjoerg mrgqual(&rtp, ln->tn_type, rn->tn_type); 245812099Sjoerg } else if (rt == PTR && rn->tn_type->t_subt->t_tspec == VOID) { 245912099Sjoerg if (lt != PTR) 246012099Sjoerg lerror("bldcol() 5"); 246112099Sjoerg rtp = rn->tn_type; 246212099Sjoerg mrgqual(&rtp, ln->tn_type, rn->tn_type); 246312099Sjoerg } else { 246412099Sjoerg if (lt != PTR || rt != PTR) 246512099Sjoerg lerror("bldcol() 6"); 246612099Sjoerg /* 246712099Sjoerg * XXX For now we simply take the left type. This is 246812099Sjoerg * probably wrong, if one type contains a functionprototype 246912099Sjoerg * and the other one, at the same place, only an old style 247012099Sjoerg * declaration. 247112099Sjoerg */ 247212099Sjoerg rtp = ln->tn_type; 247312099Sjoerg mrgqual(&rtp, ln->tn_type, rn->tn_type); 247412099Sjoerg } 247512099Sjoerg 247612099Sjoerg ntn = mktnode(COLON, rtp, ln, rn); 247712099Sjoerg 247812099Sjoerg return (ntn); 247912099Sjoerg} 248012099Sjoerg 248112099Sjoerg/* 248212099Sjoerg * Create a node for an assignment operator (both = and op= ). 248312099Sjoerg */ 248412099Sjoergstatic tnode_t * 248591592Smarkmbldasgn(op_t op, tnode_t *ln, tnode_t *rn) 248612099Sjoerg{ 248712099Sjoerg tspec_t lt, rt; 248812099Sjoerg tnode_t *ntn, *ctn; 248912099Sjoerg 249012099Sjoerg if (ln == NULL || rn == NULL) 249112099Sjoerg lerror("bldasgn() 1"); 249212099Sjoerg 249312099Sjoerg lt = ln->tn_type->t_tspec; 249412099Sjoerg rt = rn->tn_type->t_tspec; 249512099Sjoerg 249612099Sjoerg if ((op == ADDASS || op == SUBASS) && lt == PTR) { 249712099Sjoerg if (!isityp(rt)) 249812099Sjoerg lerror("bldasgn() 2"); 249912099Sjoerg ctn = plength(ln->tn_type); 250012099Sjoerg if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec) 250112099Sjoerg rn = convert(NOOP, 0, ctn->tn_type, rn); 250212099Sjoerg rn = mktnode(MULT, rn->tn_type, rn, ctn); 250312099Sjoerg if (rn->tn_left->tn_op == CON) 250412099Sjoerg rn = fold(rn); 250512099Sjoerg } 250612099Sjoerg 250712099Sjoerg if ((op == ASSIGN || op == RETURN) && (lt == STRUCT || rt == STRUCT)) { 250812099Sjoerg if (rt != lt || ln->tn_type->t_str != rn->tn_type->t_str) 250912099Sjoerg lerror("bldasgn() 3"); 251012099Sjoerg if (incompl(ln->tn_type)) { 251112099Sjoerg if (op == RETURN) { 251212099Sjoerg /* cannot return incomplete type */ 251312099Sjoerg error(212); 251412099Sjoerg } else { 251512099Sjoerg /* unknown operand size, op %s */ 251612099Sjoerg error(138, modtab[op].m_name); 251712099Sjoerg } 251812099Sjoerg return (NULL); 251912099Sjoerg } 252012099Sjoerg } 252112099Sjoerg 252212099Sjoerg if (op == SHLASS || op == SHRASS) { 252312099Sjoerg if (rt != INT) { 252412099Sjoerg rn = convert(NOOP, 0, gettyp(INT), rn); 252512099Sjoerg rt = INT; 252612099Sjoerg } 252712099Sjoerg } else { 252812099Sjoerg if (op == ASSIGN || lt != PTR) { 252912099Sjoerg if (lt != rt || 253012099Sjoerg (ln->tn_type->t_isfield && rn->tn_op == CON)) { 253112099Sjoerg rn = convert(op, 0, ln->tn_type, rn); 253212099Sjoerg rt = lt; 253312099Sjoerg } 253412099Sjoerg } 253512099Sjoerg } 253612099Sjoerg 253712099Sjoerg ntn = mktnode(op, ln->tn_type, ln, rn); 253812099Sjoerg 253912099Sjoerg return (ntn); 254012099Sjoerg} 254112099Sjoerg 254212099Sjoerg/* 254312099Sjoerg * Get length of type tp->t_subt. 254412099Sjoerg */ 254512099Sjoergstatic tnode_t * 254691592Smarkmplength(type_t *tp) 254712099Sjoerg{ 254812099Sjoerg int elem, elsz; 254912099Sjoerg tspec_t st; 255012099Sjoerg 255112099Sjoerg if (tp->t_tspec != PTR) 255212099Sjoerg lerror("plength() 1"); 255312099Sjoerg tp = tp->t_subt; 255412099Sjoerg 255512099Sjoerg elem = 1; 255612099Sjoerg elsz = 0; 255712099Sjoerg 255812099Sjoerg while (tp->t_tspec == ARRAY) { 255912099Sjoerg elem *= tp->t_dim; 256012099Sjoerg tp = tp->t_subt; 256112099Sjoerg } 256212099Sjoerg 256312099Sjoerg switch (tp->t_tspec) { 256412099Sjoerg case FUNC: 256512099Sjoerg /* pointer to function is not allowed here */ 256612099Sjoerg error(110); 256712099Sjoerg break; 256812099Sjoerg case VOID: 256912099Sjoerg /* cannot do pointer arithmetic on operand of ... */ 257012099Sjoerg (void)gnuism(136); 257112099Sjoerg break; 257212099Sjoerg case STRUCT: 257312099Sjoerg case UNION: 257412099Sjoerg if ((elsz = tp->t_str->size) == 0) 257512099Sjoerg /* cannot do pointer arithmetic on operand of ... */ 257612099Sjoerg error(136); 257712099Sjoerg break; 257812099Sjoerg case ENUM: 257912099Sjoerg if (incompl(tp)) { 258012099Sjoerg /* cannot do pointer arithmetic on operand of ... */ 258112099Sjoerg warning(136); 258212099Sjoerg } 258312099Sjoerg /* FALLTHROUGH */ 258412099Sjoerg default: 258512099Sjoerg if ((elsz = size(tp->t_tspec)) == 0) { 258612099Sjoerg /* cannot do pointer arithmetic on operand of ... */ 258712099Sjoerg error(136); 258812099Sjoerg } else if (elsz == -1) { 258912099Sjoerg lerror("plength() 2"); 259012099Sjoerg } 259112099Sjoerg break; 259212099Sjoerg } 259312099Sjoerg 259412099Sjoerg if (elem == 0 && elsz != 0) { 259512099Sjoerg /* cannot do pointer arithmetic on operand of ... */ 259612099Sjoerg error(136); 259712099Sjoerg } 259812099Sjoerg 259912099Sjoerg if (elsz == 0) 260012099Sjoerg elsz = CHAR_BIT; 260112099Sjoerg 260212099Sjoerg#if PTRDIFF_IS_LONG 260312099Sjoerg st = LONG; 260412099Sjoerg#else 260512099Sjoerg st = INT; 260612099Sjoerg#endif 260712099Sjoerg 260891592Smarkm return (getinode(st, (int64_t)(elem * elsz / CHAR_BIT))); 260912099Sjoerg} 261012099Sjoerg 261112099Sjoerg/* 261291592Smarkm * XXX 261391592Smarkm * Note: There appear to be a number of bugs in detecting overflow in 261491592Smarkm * this function. An audit and a set of proper regression tests are needed. 261591592Smarkm * --Perry Metzger, Nov. 16, 2001 261691592Smarkm */ 261791592Smarkm/* 261812099Sjoerg * Do only as much as necessary to compute constant expressions. 261912099Sjoerg * Called only if the operator allows folding and (both) operands 262012099Sjoerg * are constants. 262112099Sjoerg */ 262212099Sjoergstatic tnode_t * 262391592Smarkmfold(tnode_t *tn) 262412099Sjoerg{ 262512099Sjoerg val_t *v; 262612099Sjoerg tspec_t t; 262712099Sjoerg int utyp, ovfl; 262891592Smarkm int64_t sl, sr = 0, q = 0, mask; 262991592Smarkm uint64_t ul, ur = 0; 263012099Sjoerg tnode_t *cn; 263112099Sjoerg 263280284Sobrien if ((v = calloc(1, sizeof (val_t))) == NULL) 263380284Sobrien nomem(); 263412099Sjoerg v->v_tspec = t = tn->tn_type->t_tspec; 263512099Sjoerg 263612099Sjoerg utyp = t == PTR || isutyp(t); 263712099Sjoerg ul = sl = tn->tn_left->tn_val->v_quad; 263812099Sjoerg if (modtab[tn->tn_op].m_binary) 263912099Sjoerg ur = sr = tn->tn_right->tn_val->v_quad; 264012099Sjoerg 264191592Smarkm mask = qlmasks[size(t)]; 264212099Sjoerg ovfl = 0; 264312099Sjoerg 264412099Sjoerg switch (tn->tn_op) { 264512099Sjoerg case UPLUS: 264612099Sjoerg q = sl; 264712099Sjoerg break; 264812099Sjoerg case UMINUS: 264912099Sjoerg q = -sl; 265012099Sjoerg if (msb(q, t, -1) == msb(sl, t, -1)) 265112099Sjoerg ovfl = 1; 265212099Sjoerg break; 265312099Sjoerg case COMPL: 265412099Sjoerg q = ~sl; 265512099Sjoerg break; 265612099Sjoerg case MULT: 265791592Smarkm if (utyp) { 265891592Smarkm q = ul * ur; 265991592Smarkm if (q != (q & mask)) 266091592Smarkm ovfl = 1; 266191592Smarkm else if ((ul != 0) && ((q / ul) != ur)) 266291592Smarkm ovfl = 1; 266391592Smarkm } else { 266491592Smarkm q = sl * sr; 266591592Smarkm if (msb(q, t, -1) != (msb(sl, t, -1) ^ msb(sr, t, -1))) 266691592Smarkm ovfl = 1; 266791592Smarkm } 266812099Sjoerg break; 266912099Sjoerg case DIV: 267012099Sjoerg if (sr == 0) { 267112099Sjoerg /* division by 0 */ 267212099Sjoerg error(139); 267312099Sjoerg q = utyp ? UQUAD_MAX : QUAD_MAX; 267412099Sjoerg } else { 267512099Sjoerg q = utyp ? ul / ur : sl / sr; 267612099Sjoerg } 267712099Sjoerg break; 267812099Sjoerg case MOD: 267912099Sjoerg if (sr == 0) { 268012099Sjoerg /* modulus by 0 */ 268112099Sjoerg error(140); 268212099Sjoerg q = 0; 268312099Sjoerg } else { 268412099Sjoerg q = utyp ? ul % ur : sl % sr; 268512099Sjoerg } 268612099Sjoerg break; 268712099Sjoerg case PLUS: 268812099Sjoerg q = utyp ? ul + ur : sl + sr; 268912099Sjoerg if (msb(sl, t, -1) != 0 && msb(sr, t, -1) != 0) { 269012099Sjoerg if (msb(q, t, -1) == 0) 269112099Sjoerg ovfl = 1; 269212099Sjoerg } else if (msb(sl, t, -1) == 0 && msb(sr, t, -1) == 0) { 269312099Sjoerg if (msb(q, t, -1) != 0) 269412099Sjoerg ovfl = 1; 269512099Sjoerg } 269612099Sjoerg break; 269712099Sjoerg case MINUS: 269812099Sjoerg q = utyp ? ul - ur : sl - sr; 269912099Sjoerg if (msb(sl, t, -1) != 0 && msb(sr, t, -1) == 0) { 270012099Sjoerg if (msb(q, t, -1) == 0) 270112099Sjoerg ovfl = 1; 270212099Sjoerg } else if (msb(sl, t, -1) == 0 && msb(sr, t, -1) != 0) { 270312099Sjoerg if (msb(q, t, -1) != 0) 270412099Sjoerg ovfl = 1; 270512099Sjoerg } 270612099Sjoerg break; 270712099Sjoerg case SHL: 270812099Sjoerg q = utyp ? ul << sr : sl << sr; 270912099Sjoerg break; 271012099Sjoerg case SHR: 271112099Sjoerg /* 271291592Smarkm * The sign must be explicitly extended because 271312099Sjoerg * shifts of signed values are implementation dependent. 271412099Sjoerg */ 271512099Sjoerg q = ul >> sr; 271612099Sjoerg q = xsign(q, t, size(t) - (int)sr); 271712099Sjoerg break; 271812099Sjoerg case LT: 271912099Sjoerg q = utyp ? ul < ur : sl < sr; 272012099Sjoerg break; 272112099Sjoerg case LE: 272212099Sjoerg q = utyp ? ul <= ur : sl <= sr; 272312099Sjoerg break; 272412099Sjoerg case GE: 272512099Sjoerg q = utyp ? ul >= ur : sl >= sr; 272612099Sjoerg break; 272712099Sjoerg case GT: 272812099Sjoerg q = utyp ? ul > ur : sl > sr; 272912099Sjoerg break; 273012099Sjoerg case EQ: 273112099Sjoerg q = utyp ? ul == ur : sl == sr; 273212099Sjoerg break; 273312099Sjoerg case NE: 273412099Sjoerg q = utyp ? ul != ur : sl != sr; 273512099Sjoerg break; 273612099Sjoerg case AND: 273712099Sjoerg q = utyp ? ul & ur : sl & sr; 273812099Sjoerg break; 273912099Sjoerg case XOR: 274012099Sjoerg q = utyp ? ul ^ ur : sl ^ sr; 274112099Sjoerg break; 274212099Sjoerg case OR: 274312099Sjoerg q = utyp ? ul | ur : sl | sr; 274412099Sjoerg break; 274512099Sjoerg default: 274612099Sjoerg lerror("fold() 5"); 274712099Sjoerg } 274812099Sjoerg 274912099Sjoerg /* XXX does not work for quads. */ 275091592Smarkm if (ovfl || ((q | mask) != ~(uint64_t)0 && (q & ~mask) != 0)) { 275112099Sjoerg if (hflag) 275212099Sjoerg /* integer overflow detected, op %s */ 275312099Sjoerg warning(141, modtab[tn->tn_op].m_name); 275412099Sjoerg } 275512099Sjoerg 275612099Sjoerg v->v_quad = xsign(q, t, -1); 275712099Sjoerg 275812099Sjoerg cn = getcnode(tn->tn_type, v); 275912099Sjoerg 276012099Sjoerg return (cn); 276112099Sjoerg} 276212099Sjoerg 276312099Sjoerg/* 276412099Sjoerg * Same for operators whose operands are compared with 0 (test context). 276512099Sjoerg */ 276612099Sjoergstatic tnode_t * 276791592Smarkmfoldtst(tnode_t *tn) 276812099Sjoerg{ 276991592Smarkm int l, r = 0; 277012099Sjoerg val_t *v; 277112099Sjoerg 277280284Sobrien if ((v = calloc(1, sizeof (val_t))) == NULL) 277380284Sobrien nomem(); 277412099Sjoerg v->v_tspec = tn->tn_type->t_tspec; 277512099Sjoerg if (tn->tn_type->t_tspec != INT) 277612099Sjoerg lerror("foldtst() 1"); 277712099Sjoerg 277812099Sjoerg if (isftyp(tn->tn_left->tn_type->t_tspec)) { 277912099Sjoerg l = tn->tn_left->tn_val->v_ldbl != 0.0; 278012099Sjoerg } else { 278112099Sjoerg l = tn->tn_left->tn_val->v_quad != 0; 278212099Sjoerg } 278312099Sjoerg 278412099Sjoerg if (modtab[tn->tn_op].m_binary) { 278512099Sjoerg if (isftyp(tn->tn_right->tn_type->t_tspec)) { 278612099Sjoerg r = tn->tn_right->tn_val->v_ldbl != 0.0; 278712099Sjoerg } else { 278812099Sjoerg r = tn->tn_right->tn_val->v_quad != 0; 278912099Sjoerg } 279012099Sjoerg } 279112099Sjoerg 279212099Sjoerg switch (tn->tn_op) { 279312099Sjoerg case NOT: 279412099Sjoerg if (hflag) 279512099Sjoerg /* constant argument to NOT */ 279612099Sjoerg warning(239); 279712099Sjoerg v->v_quad = !l; 279812099Sjoerg break; 279912099Sjoerg case LOGAND: 280012099Sjoerg v->v_quad = l && r; 280112099Sjoerg break; 280212099Sjoerg case LOGOR: 280312099Sjoerg v->v_quad = l || r; 280412099Sjoerg break; 280512099Sjoerg default: 280612099Sjoerg lerror("foldtst() 1"); 280712099Sjoerg } 280812099Sjoerg 280912099Sjoerg return (getcnode(tn->tn_type, v)); 281012099Sjoerg} 281112099Sjoerg 281212099Sjoerg/* 281312099Sjoerg * Same for operands with floating point type. 281412099Sjoerg */ 281512099Sjoergstatic tnode_t * 281691592Smarkmfoldflt(tnode_t *tn) 281712099Sjoerg{ 281812099Sjoerg val_t *v; 281912099Sjoerg tspec_t t; 282091592Smarkm ldbl_t l, r = 0; 282112099Sjoerg 282280284Sobrien if ((v = calloc(1, sizeof (val_t))) == NULL) 282380284Sobrien nomem(); 282412099Sjoerg v->v_tspec = t = tn->tn_type->t_tspec; 282512099Sjoerg 282612099Sjoerg if (!isftyp(t)) 282712099Sjoerg lerror("foldflt() 1"); 282812099Sjoerg 282912099Sjoerg if (t != tn->tn_left->tn_type->t_tspec) 283012099Sjoerg lerror("foldflt() 2"); 283112099Sjoerg if (modtab[tn->tn_op].m_binary && t != tn->tn_right->tn_type->t_tspec) 283212099Sjoerg lerror("foldflt() 3"); 283312099Sjoerg 283412099Sjoerg l = tn->tn_left->tn_val->v_ldbl; 283512099Sjoerg if (modtab[tn->tn_op].m_binary) 283612099Sjoerg r = tn->tn_right->tn_val->v_ldbl; 283712099Sjoerg 283812099Sjoerg switch (tn->tn_op) { 283912099Sjoerg case UPLUS: 284012099Sjoerg v->v_ldbl = l; 284112099Sjoerg break; 284212099Sjoerg case UMINUS: 284312099Sjoerg v->v_ldbl = -l; 284412099Sjoerg break; 284512099Sjoerg case MULT: 284612099Sjoerg v->v_ldbl = l * r; 284712099Sjoerg break; 284812099Sjoerg case DIV: 284912099Sjoerg if (r == 0.0) { 285012099Sjoerg /* division by 0 */ 285112099Sjoerg error(139); 285212099Sjoerg if (t == FLOAT) { 285312099Sjoerg v->v_ldbl = l < 0 ? -FLT_MAX : FLT_MAX; 285412099Sjoerg } else if (t == DOUBLE) { 285512099Sjoerg v->v_ldbl = l < 0 ? -DBL_MAX : DBL_MAX; 285612099Sjoerg } else { 285712099Sjoerg v->v_ldbl = l < 0 ? -LDBL_MAX : LDBL_MAX; 285812099Sjoerg } 285912099Sjoerg } else { 286012099Sjoerg v->v_ldbl = l / r; 286112099Sjoerg } 286212099Sjoerg break; 286312099Sjoerg case PLUS: 286412099Sjoerg v->v_ldbl = l + r; 286512099Sjoerg break; 286612099Sjoerg case MINUS: 286712099Sjoerg v->v_ldbl = l - r; 286812099Sjoerg break; 286912099Sjoerg case LT: 287012099Sjoerg v->v_quad = l < r; 287112099Sjoerg break; 287212099Sjoerg case LE: 287312099Sjoerg v->v_quad = l <= r; 287412099Sjoerg break; 287512099Sjoerg case GE: 287612099Sjoerg v->v_quad = l >= r; 287712099Sjoerg break; 287812099Sjoerg case GT: 287912099Sjoerg v->v_quad = l > r; 288012099Sjoerg break; 288112099Sjoerg case EQ: 288212099Sjoerg v->v_quad = l == r; 288312099Sjoerg break; 288412099Sjoerg case NE: 288512099Sjoerg v->v_quad = l != r; 288612099Sjoerg break; 288712099Sjoerg default: 288812099Sjoerg lerror("foldflt() 4"); 288912099Sjoerg } 289012099Sjoerg 289112099Sjoerg if (isnan((double)v->v_ldbl)) 289212099Sjoerg lerror("foldflt() 5"); 289391592Smarkm if (!finite((double)v->v_ldbl) || 289412099Sjoerg (t == FLOAT && 289512099Sjoerg (v->v_ldbl > FLT_MAX || v->v_ldbl < -FLT_MAX)) || 289612099Sjoerg (t == DOUBLE && 289712099Sjoerg (v->v_ldbl > DBL_MAX || v->v_ldbl < -DBL_MAX))) { 289812099Sjoerg /* floating point overflow detected, op %s */ 289912099Sjoerg warning(142, modtab[tn->tn_op].m_name); 290012099Sjoerg if (t == FLOAT) { 290112099Sjoerg v->v_ldbl = v->v_ldbl < 0 ? -FLT_MAX : FLT_MAX; 290212099Sjoerg } else if (t == DOUBLE) { 290312099Sjoerg v->v_ldbl = v->v_ldbl < 0 ? -DBL_MAX : DBL_MAX; 290412099Sjoerg } else { 290512099Sjoerg v->v_ldbl = v->v_ldbl < 0 ? -LDBL_MAX: LDBL_MAX; 290612099Sjoerg } 290712099Sjoerg } 290812099Sjoerg 290912099Sjoerg return (getcnode(tn->tn_type, v)); 291012099Sjoerg} 291112099Sjoerg 291212099Sjoerg/* 291312099Sjoerg * Create a constant node for sizeof. 291412099Sjoerg */ 291512099Sjoergtnode_t * 291691592Smarkmbldszof(type_t *tp) 291712099Sjoerg{ 291812099Sjoerg int elem, elsz; 291912099Sjoerg tspec_t st; 292012099Sjoerg 292112099Sjoerg elem = 1; 292212099Sjoerg while (tp->t_tspec == ARRAY) { 292312099Sjoerg elem *= tp->t_dim; 292412099Sjoerg tp = tp->t_subt; 292512099Sjoerg } 292612099Sjoerg if (elem == 0) { 292712099Sjoerg /* cannot take size of incomplete type */ 292812099Sjoerg error(143); 292912099Sjoerg elem = 1; 293012099Sjoerg } 293112099Sjoerg switch (tp->t_tspec) { 293212099Sjoerg case FUNC: 293312099Sjoerg /* cannot take size of function */ 293412099Sjoerg error(144); 293512099Sjoerg elsz = 1; 293612099Sjoerg break; 293712099Sjoerg case STRUCT: 293812099Sjoerg case UNION: 293912099Sjoerg if (incompl(tp)) { 294012099Sjoerg /* cannot take size of incomplete type */ 294112099Sjoerg error(143); 294212099Sjoerg elsz = 1; 294312099Sjoerg } else { 294412099Sjoerg elsz = tp->t_str->size; 294512099Sjoerg } 294612099Sjoerg break; 294712099Sjoerg case ENUM: 294812099Sjoerg if (incompl(tp)) { 294912099Sjoerg /* cannot take size of incomplete type */ 295012099Sjoerg warning(143); 295112099Sjoerg } 295212099Sjoerg /* FALLTHROUGH */ 295312099Sjoerg default: 295412099Sjoerg if (tp->t_isfield) { 295512099Sjoerg /* cannot take size of bit-field */ 295612099Sjoerg error(145); 295712099Sjoerg } 295812099Sjoerg if (tp->t_tspec == VOID) { 295912099Sjoerg /* cannot take size of void */ 296012099Sjoerg error(146); 296112099Sjoerg elsz = 1; 296212099Sjoerg } else { 296312099Sjoerg elsz = size(tp->t_tspec); 296412099Sjoerg if (elsz <= 0) 296512099Sjoerg lerror("bldszof() 1"); 296612099Sjoerg } 296712099Sjoerg break; 296812099Sjoerg } 296912099Sjoerg 297012099Sjoerg#if SIZEOF_IS_ULONG 297112099Sjoerg st = ULONG; 297212099Sjoerg#else 297312099Sjoerg st = UINT; 297412099Sjoerg#endif 297512099Sjoerg 297691592Smarkm return (getinode(st, (int64_t)(elem * elsz / CHAR_BIT))); 297712099Sjoerg} 297812099Sjoerg 297912099Sjoerg/* 298012099Sjoerg * Type casts. 298112099Sjoerg */ 298212099Sjoergtnode_t * 298391592Smarkmcast(tnode_t *tn, type_t *tp) 298412099Sjoerg{ 298512099Sjoerg tspec_t nt, ot; 298612099Sjoerg 298712099Sjoerg if (tn == NULL) 298812099Sjoerg return (NULL); 298912099Sjoerg 299012099Sjoerg tn = cconv(tn); 299112099Sjoerg 299212099Sjoerg nt = tp->t_tspec; 299312099Sjoerg ot = tn->tn_type->t_tspec; 299412099Sjoerg 299512099Sjoerg if (nt == VOID) { 299612099Sjoerg /* 299712099Sjoerg * XXX ANSI C requires scalar types or void (Plauger&Brodie). 299812099Sjoerg * But this seams really questionable. 299912099Sjoerg */ 300012099Sjoerg } else if (nt == STRUCT || nt == UNION || nt == ARRAY || nt == FUNC) { 300112099Sjoerg /* invalid cast expression */ 300212099Sjoerg error(147); 300312099Sjoerg return (NULL); 300412099Sjoerg } else if (ot == STRUCT || ot == UNION) { 300512099Sjoerg /* invalid cast expression */ 300612099Sjoerg error(147); 300712099Sjoerg return (NULL); 300812099Sjoerg } else if (ot == VOID) { 300912099Sjoerg /* improper cast of void expression */ 301012099Sjoerg error(148); 301112099Sjoerg return (NULL); 301212099Sjoerg } else if (isityp(nt) && issclt(ot)) { 301312099Sjoerg /* ok */ 301412099Sjoerg } else if (isftyp(nt) && isatyp(ot)) { 301512099Sjoerg /* ok */ 301612099Sjoerg } else if (nt == PTR && isityp(ot)) { 301712099Sjoerg /* ok */ 301812099Sjoerg } else if (nt == PTR && ot == PTR) { 301912099Sjoerg if (!tp->t_subt->t_const && tn->tn_type->t_subt->t_const) { 302012099Sjoerg if (hflag) 302112099Sjoerg /* cast discards 'const' from ... */ 302212099Sjoerg warning(275); 302312099Sjoerg } 302412099Sjoerg } else { 302512099Sjoerg /* invalid cast expression */ 302612099Sjoerg error(147); 302712099Sjoerg return (NULL); 302812099Sjoerg } 302912099Sjoerg 303012099Sjoerg tn = convert(CVT, 0, tp, tn); 303112099Sjoerg tn->tn_cast = 1; 303212099Sjoerg 303312099Sjoerg return (tn); 303412099Sjoerg} 303512099Sjoerg 303612099Sjoerg/* 303712099Sjoerg * Create the node for a function argument. 303812099Sjoerg * All necessary conversions and type checks are done in funccall(), because 303912099Sjoerg * in funcarg() we have no information about expected argument types. 304012099Sjoerg */ 304112099Sjoergtnode_t * 304291592Smarkmfuncarg(tnode_t *args, tnode_t *arg) 304312099Sjoerg{ 304412099Sjoerg tnode_t *ntn; 304512099Sjoerg 304612099Sjoerg /* 304712099Sjoerg * If there was a serious error in the expression for the argument, 304812099Sjoerg * create a dummy argument so the positions of the remaining arguments 304912099Sjoerg * will not change. 305012099Sjoerg */ 305112099Sjoerg if (arg == NULL) 305291592Smarkm arg = getinode(INT, (int64_t)0); 305312099Sjoerg 305412099Sjoerg ntn = mktnode(PUSH, arg->tn_type, arg, args); 305512099Sjoerg 305612099Sjoerg return (ntn); 305712099Sjoerg} 305812099Sjoerg 305912099Sjoerg/* 306012099Sjoerg * Create the node for a function call. Also check types of 306112099Sjoerg * function arguments and insert conversions, if necessary. 306212099Sjoerg */ 306312099Sjoergtnode_t * 306491592Smarkmfunccall(tnode_t *func, tnode_t *args) 306512099Sjoerg{ 306612099Sjoerg tnode_t *ntn; 306712099Sjoerg op_t fcop; 306812099Sjoerg 306912099Sjoerg if (func == NULL) 307012099Sjoerg return (NULL); 307112099Sjoerg 307212099Sjoerg if (func->tn_op == NAME && func->tn_type->t_tspec == FUNC) { 307312099Sjoerg fcop = CALL; 307412099Sjoerg } else { 307512099Sjoerg fcop = ICALL; 307612099Sjoerg } 307712099Sjoerg 307812099Sjoerg /* 307912099Sjoerg * after cconv() func will always be a pointer to a function 308012099Sjoerg * if it is a valid function designator. 308112099Sjoerg */ 308212099Sjoerg func = cconv(func); 308312099Sjoerg 308412099Sjoerg if (func->tn_type->t_tspec != PTR || 308512099Sjoerg func->tn_type->t_subt->t_tspec != FUNC) { 308612099Sjoerg /* illegal function */ 308712099Sjoerg error(149); 308812099Sjoerg return (NULL); 308912099Sjoerg } 309012099Sjoerg 309112099Sjoerg args = chkfarg(func->tn_type->t_subt, args); 309212099Sjoerg 309312099Sjoerg ntn = mktnode(fcop, func->tn_type->t_subt->t_subt, func, args); 309412099Sjoerg 309512099Sjoerg return (ntn); 309612099Sjoerg} 309712099Sjoerg 309812099Sjoerg/* 309912099Sjoerg * Check types of all function arguments and insert conversions, 310012099Sjoerg * if necessary. 310112099Sjoerg */ 310212099Sjoergstatic tnode_t * 310391592Smarkmchkfarg(type_t *ftp, tnode_t *args) 310412099Sjoerg{ 310512099Sjoerg tnode_t *arg; 310612099Sjoerg sym_t *asym; 310712099Sjoerg tspec_t at; 310812099Sjoerg int narg, npar, n, i; 310912099Sjoerg 311012099Sjoerg /* get # of args in the prototype */ 311112099Sjoerg npar = 0; 311212099Sjoerg for (asym = ftp->t_args; asym != NULL; asym = asym->s_nxt) 311312099Sjoerg npar++; 311412099Sjoerg 311512099Sjoerg /* get # of args in function call */ 311612099Sjoerg narg = 0; 311712099Sjoerg for (arg = args; arg != NULL; arg = arg->tn_right) 311812099Sjoerg narg++; 311912099Sjoerg 312012099Sjoerg asym = ftp->t_args; 312112099Sjoerg if (ftp->t_proto && npar != narg && !(ftp->t_vararg && npar < narg)) { 312212099Sjoerg /* argument mismatch: %d arg%s passed, %d expected */ 312312099Sjoerg error(150, narg, narg > 1 ? "s" : "", npar); 312412099Sjoerg asym = NULL; 312512099Sjoerg } 312691592Smarkm 312712099Sjoerg for (n = 1; n <= narg; n++) { 312812099Sjoerg 312912099Sjoerg /* 313012099Sjoerg * The rightmost argument is at the top of the argument 313112099Sjoerg * subtree. 313212099Sjoerg */ 313391592Smarkm for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) 313491592Smarkm continue; 313512099Sjoerg 313612099Sjoerg /* some things which are always not allowd */ 313712099Sjoerg if ((at = arg->tn_left->tn_type->t_tspec) == VOID) { 313812099Sjoerg /* void expressions may not be arguments, arg #%d */ 313912099Sjoerg error(151, n); 314012099Sjoerg return (NULL); 314112099Sjoerg } else if ((at == STRUCT || at == UNION) && 314212099Sjoerg incompl(arg->tn_left->tn_type)) { 314312099Sjoerg /* argument cannot have unknown size, arg #%d */ 314412099Sjoerg error(152, n); 314512099Sjoerg return (NULL); 314612099Sjoerg } else if (isityp(at) && arg->tn_left->tn_type->t_isenum && 314712099Sjoerg incompl(arg->tn_left->tn_type)) { 314812099Sjoerg /* argument cannot have unknown size, arg #%d */ 314912099Sjoerg warning(152, n); 315012099Sjoerg } 315112099Sjoerg 315212099Sjoerg /* class conversions (arg in value context) */ 315312099Sjoerg arg->tn_left = cconv(arg->tn_left); 315412099Sjoerg 315512099Sjoerg if (asym != NULL) { 315612099Sjoerg arg->tn_left = parg(n, asym->s_type, arg->tn_left); 315712099Sjoerg } else { 315812099Sjoerg arg->tn_left = promote(NOOP, 1, arg->tn_left); 315912099Sjoerg } 316012099Sjoerg arg->tn_type = arg->tn_left->tn_type; 316112099Sjoerg 316212099Sjoerg if (asym != NULL) 316312099Sjoerg asym = asym->s_nxt; 316412099Sjoerg } 316512099Sjoerg 316612099Sjoerg return (args); 316712099Sjoerg} 316812099Sjoerg 316912099Sjoerg/* 317012099Sjoerg * Compare the type of an argument with the corresponding type of a 317112099Sjoerg * prototype parameter. If it is a valid combination, but both types 317212099Sjoerg * are not the same, insert a conversion to convert the argument into 317312099Sjoerg * the type of the parameter. 317412099Sjoerg */ 317512099Sjoergstatic tnode_t * 317691592Smarkmparg( int n, /* pos of arg */ 317791592Smarkm type_t *tp, /* expected type (from prototype) */ 317891592Smarkm tnode_t *tn) /* argument */ 317912099Sjoerg{ 318012099Sjoerg tnode_t *ln; 318112099Sjoerg int warn; 318212099Sjoerg 318380284Sobrien if ((ln = calloc(1, sizeof (tnode_t))) == NULL) 318480284Sobrien nomem(); 318512099Sjoerg ln->tn_type = tduptyp(tp); 318612099Sjoerg ln->tn_type->t_const = 0; 318712099Sjoerg ln->tn_lvalue = 1; 318812099Sjoerg if (typeok(FARG, n, ln, tn)) { 318912099Sjoerg if (!eqtype(tp, tn->tn_type, 1, 0, (warn = 0, &warn)) || warn) 319012099Sjoerg tn = convert(FARG, n, tp, tn); 319112099Sjoerg } 319212099Sjoerg free(ln); 319312099Sjoerg return (tn); 319412099Sjoerg} 319512099Sjoerg 319612099Sjoerg/* 319712099Sjoerg * Return the value of an integral constant expression. 319812099Sjoerg * If the expression is not constant or its type is not an integer 319912099Sjoerg * type, an error message is printed. 320012099Sjoerg */ 320112099Sjoergval_t * 320291592Smarkmconstant(tnode_t *tn) 320312099Sjoerg{ 320412099Sjoerg val_t *v; 320512099Sjoerg 320612099Sjoerg if (tn != NULL) 320712099Sjoerg tn = cconv(tn); 320812099Sjoerg if (tn != NULL) 320912099Sjoerg tn = promote(NOOP, 0, tn); 321012099Sjoerg 321180284Sobrien if ((v = calloc(1, sizeof (val_t))) == NULL) 321280284Sobrien nomem(); 321312099Sjoerg 321412099Sjoerg if (tn == NULL) { 321512099Sjoerg if (nerr == 0) 321612099Sjoerg lerror("constant() 1"); 321712099Sjoerg v->v_tspec = INT; 321812099Sjoerg v->v_quad = 1; 321912099Sjoerg return (v); 322012099Sjoerg } 322112099Sjoerg 322212099Sjoerg v->v_tspec = tn->tn_type->t_tspec; 322312099Sjoerg 322412099Sjoerg if (tn->tn_op == CON) { 322512099Sjoerg if (tn->tn_type->t_tspec != tn->tn_val->v_tspec) 322612099Sjoerg lerror("constant() 2"); 322712099Sjoerg if (isityp(tn->tn_val->v_tspec)) { 322812099Sjoerg v->v_ansiu = tn->tn_val->v_ansiu; 322912099Sjoerg v->v_quad = tn->tn_val->v_quad; 323012099Sjoerg return (v); 323112099Sjoerg } 323212099Sjoerg v->v_quad = tn->tn_val->v_ldbl; 323312099Sjoerg } else { 323412099Sjoerg v->v_quad = 1; 323512099Sjoerg } 323612099Sjoerg 323712099Sjoerg /* integral constant expression expected */ 323812099Sjoerg error(55); 323912099Sjoerg 324012099Sjoerg if (!isityp(v->v_tspec)) 324112099Sjoerg v->v_tspec = INT; 324212099Sjoerg 324312099Sjoerg return (v); 324412099Sjoerg} 324512099Sjoerg 324612099Sjoerg/* 324712099Sjoerg * Perform some tests on expressions which can't be done in build() and 324812099Sjoerg * functions called by build(). These tests must be done here because 324912099Sjoerg * we need some information about the context in which the operations 325012099Sjoerg * are performed. 325112099Sjoerg * After all tests are performed, expr() frees the memory which is used 325212099Sjoerg * for the expression. 325312099Sjoerg */ 325412099Sjoergvoid 325591592Smarkmexpr(tnode_t *tn, int vctx, int tctx) 325612099Sjoerg{ 325791592Smarkm 325812099Sjoerg if (tn == NULL && nerr == 0) 325912099Sjoerg lerror("expr() 1"); 326012099Sjoerg 326112099Sjoerg if (tn == NULL) { 326212099Sjoerg tfreeblk(); 326312099Sjoerg return; 326412099Sjoerg } 326512099Sjoerg 326612099Sjoerg /* expr() is also called in global initialisations */ 326712099Sjoerg if (dcs->d_ctx != EXTERN) 326812099Sjoerg chkreach(); 326912099Sjoerg 327012099Sjoerg chkmisc(tn, vctx, tctx, !tctx, 0, 0, 0); 327112099Sjoerg if (tn->tn_op == ASSIGN) { 327212099Sjoerg if (hflag && tctx) 327312099Sjoerg /* assignment in conditional context */ 327412099Sjoerg warning(159); 327512099Sjoerg } else if (tn->tn_op == CON) { 327612099Sjoerg if (hflag && tctx && !ccflg) 327712099Sjoerg /* constant in conditional context */ 327812099Sjoerg warning(161); 327912099Sjoerg } 328012099Sjoerg if (!modtab[tn->tn_op].m_sideeff) { 328112099Sjoerg /* 328212099Sjoerg * for left operands of COMMA this warning is already 328312099Sjoerg * printed 328412099Sjoerg */ 328512099Sjoerg if (tn->tn_op != COMMA && !vctx && !tctx) 328612099Sjoerg nulleff(tn); 328712099Sjoerg } 328812099Sjoerg if (dflag) 328912099Sjoerg displexpr(tn, 0); 329012099Sjoerg 329112099Sjoerg /* free the tree memory */ 329212099Sjoerg tfreeblk(); 329312099Sjoerg} 329412099Sjoerg 329512099Sjoergstatic void 329691592Smarkmnulleff(tnode_t *tn) 329712099Sjoerg{ 329891592Smarkm 329912099Sjoerg if (!hflag) 330012099Sjoerg return; 330112099Sjoerg 330212099Sjoerg while (!modtab[tn->tn_op].m_sideeff) { 330312099Sjoerg if (tn->tn_op == CVT && tn->tn_type->t_tspec == VOID) { 330412099Sjoerg tn = tn->tn_left; 330512099Sjoerg } else if (tn->tn_op == LOGAND || tn->tn_op == LOGOR) { 330612099Sjoerg /* 330712099Sjoerg * && and || have a side effect if the right operand 330812099Sjoerg * has a side effect. 330912099Sjoerg */ 331012099Sjoerg tn = tn->tn_right; 331112099Sjoerg } else if (tn->tn_op == QUEST) { 331212099Sjoerg /* 331312099Sjoerg * ? has a side effect if at least one of its right 331412099Sjoerg * operands has a side effect 331512099Sjoerg */ 331612099Sjoerg tn = tn->tn_right; 331791592Smarkm } else if (tn->tn_op == COLON || tn->tn_op == COMMA) { 331812099Sjoerg /* 331912099Sjoerg * : has a side effect if at least one of its operands 332012099Sjoerg * has a side effect 332112099Sjoerg */ 332212099Sjoerg if (modtab[tn->tn_left->tn_op].m_sideeff) { 332312099Sjoerg tn = tn->tn_left; 332412099Sjoerg } else if (modtab[tn->tn_right->tn_op].m_sideeff) { 332512099Sjoerg tn = tn->tn_right; 332612099Sjoerg } else { 332712099Sjoerg break; 332812099Sjoerg } 332912099Sjoerg } else { 333012099Sjoerg break; 333112099Sjoerg } 333212099Sjoerg } 333312099Sjoerg if (!modtab[tn->tn_op].m_sideeff) 333412099Sjoerg /* expression has null effect */ 333512099Sjoerg warning(129); 333612099Sjoerg} 333712099Sjoerg 333812099Sjoerg/* 333912099Sjoerg * Dump an expression to stdout 334012099Sjoerg * only used for debugging 334112099Sjoerg */ 334212099Sjoergstatic void 334391592Smarkmdisplexpr(tnode_t *tn, int offs) 334412099Sjoerg{ 334591592Smarkm uint64_t uq; 334612099Sjoerg 334712099Sjoerg if (tn == NULL) { 334812099Sjoerg (void)printf("%*s%s\n", offs, "", "NULL"); 334912099Sjoerg return; 335012099Sjoerg } 335112099Sjoerg (void)printf("%*sop %s ", offs, "", modtab[tn->tn_op].m_name); 335212099Sjoerg 335312099Sjoerg if (tn->tn_op == NAME) { 335412099Sjoerg (void)printf("%s: %s ", 335512099Sjoerg tn->tn_sym->s_name, scltoa(tn->tn_sym->s_scl)); 335612099Sjoerg } else if (tn->tn_op == CON && isftyp(tn->tn_type->t_tspec)) { 335712099Sjoerg (void)printf("%#g ", (double)tn->tn_val->v_ldbl); 335812099Sjoerg } else if (tn->tn_op == CON && isityp(tn->tn_type->t_tspec)) { 335912099Sjoerg uq = tn->tn_val->v_quad; 336012099Sjoerg (void)printf("0x %08lx %08lx ", (long)(uq >> 32) & 0xffffffffl, 336112099Sjoerg (long)uq & 0xffffffffl); 336212099Sjoerg } else if (tn->tn_op == CON) { 336312099Sjoerg if (tn->tn_type->t_tspec != PTR) 336412099Sjoerg lerror("displexpr() 1"); 336512099Sjoerg (void)printf("0x%0*lx ", (int)(sizeof (void *) * CHAR_BIT / 4), 336612099Sjoerg (u_long)tn->tn_val->v_quad); 336712099Sjoerg } else if (tn->tn_op == STRING) { 336812099Sjoerg if (tn->tn_strg->st_tspec == CHAR) { 336912099Sjoerg (void)printf("\"%s\"", tn->tn_strg->st_cp); 337012099Sjoerg } else { 337112099Sjoerg char *s; 337212099Sjoerg size_t n; 337312099Sjoerg n = MB_CUR_MAX * (tn->tn_strg->st_len + 1); 337480284Sobrien if ((s = malloc(n)) == NULL) 337580284Sobrien nomem(); 337612099Sjoerg (void)wcstombs(s, tn->tn_strg->st_wcp, n); 337712099Sjoerg (void)printf("L\"%s\"", s); 337812099Sjoerg free(s); 337912099Sjoerg } 338012099Sjoerg (void)printf(" "); 338112099Sjoerg } else if (tn->tn_op == FSEL) { 338212099Sjoerg (void)printf("o=%d, l=%d ", tn->tn_type->t_foffs, 338312099Sjoerg tn->tn_type->t_flen); 338412099Sjoerg } 338512099Sjoerg (void)printf("%s\n", ttos(tn->tn_type)); 338612099Sjoerg if (tn->tn_op == NAME || tn->tn_op == CON || tn->tn_op == STRING) 338712099Sjoerg return; 338812099Sjoerg displexpr(tn->tn_left, offs + 2); 338912099Sjoerg if (modtab[tn->tn_op].m_binary || 339012099Sjoerg (tn->tn_op == PUSH && tn->tn_right != NULL)) { 339112099Sjoerg displexpr(tn->tn_right, offs + 2); 339212099Sjoerg } 339312099Sjoerg} 339412099Sjoerg 339512099Sjoerg/* 339612099Sjoerg * Called by expr() to recursively perform some tests. 339712099Sjoerg */ 339812099Sjoerg/* ARGSUSED */ 339912099Sjoergvoid 340091592Smarkmchkmisc(tnode_t *tn, int vctx, int tctx, int eqwarn, int fcall, int rvdisc, 340191592Smarkm int szof) 340212099Sjoerg{ 340312099Sjoerg tnode_t *ln, *rn; 340412099Sjoerg mod_t *mp; 340512099Sjoerg int nrvdisc, cvctx, ctctx; 340612099Sjoerg op_t op; 340712099Sjoerg scl_t sc; 340812099Sjoerg dinfo_t *di; 340912099Sjoerg 341012099Sjoerg if (tn == NULL) 341112099Sjoerg return; 341212099Sjoerg 341312099Sjoerg ln = tn->tn_left; 341412099Sjoerg rn = tn->tn_right; 341512099Sjoerg mp = &modtab[op = tn->tn_op]; 341612099Sjoerg 341712099Sjoerg switch (op) { 341812099Sjoerg case AMPER: 341912099Sjoerg if (ln->tn_op == NAME && (reached || rchflg)) { 342012099Sjoerg if (!szof) 342112099Sjoerg setsflg(ln->tn_sym); 342212099Sjoerg setuflg(ln->tn_sym, fcall, szof); 342312099Sjoerg } 342412099Sjoerg if (ln->tn_op == STAR && ln->tn_left->tn_op == PLUS) 342512099Sjoerg /* check the range of array indices */ 342612099Sjoerg chkaidx(ln->tn_left, 1); 342712099Sjoerg break; 342812099Sjoerg case LOAD: 342912099Sjoerg if (ln->tn_op == STAR && ln->tn_left->tn_op == PLUS) 343012099Sjoerg /* check the range of array indices */ 343112099Sjoerg chkaidx(ln->tn_left, 0); 343212099Sjoerg /* FALLTHROUGH */ 343312099Sjoerg case PUSH: 343412099Sjoerg case INCBEF: 343512099Sjoerg case DECBEF: 343612099Sjoerg case INCAFT: 343712099Sjoerg case DECAFT: 343812099Sjoerg case ADDASS: 343912099Sjoerg case SUBASS: 344012099Sjoerg case MULASS: 344112099Sjoerg case DIVASS: 344212099Sjoerg case MODASS: 344312099Sjoerg case ANDASS: 344412099Sjoerg case ORASS: 344512099Sjoerg case XORASS: 344612099Sjoerg case SHLASS: 344712099Sjoerg case SHRASS: 344812099Sjoerg if (ln->tn_op == NAME && (reached || rchflg)) { 344912099Sjoerg sc = ln->tn_sym->s_scl; 345012099Sjoerg /* 3451108532Sschweikh * Look if there was an asm statement in one of the 345212099Sjoerg * compound statements we are in. If not, we don't 345312099Sjoerg * print a warning. 345412099Sjoerg */ 345512099Sjoerg for (di = dcs; di != NULL; di = di->d_nxt) { 345612099Sjoerg if (di->d_asm) 345712099Sjoerg break; 345812099Sjoerg } 345912099Sjoerg if (sc != EXTERN && sc != STATIC && 346012099Sjoerg !ln->tn_sym->s_set && !szof && di == NULL) { 346112099Sjoerg /* %s may be used before set */ 346212099Sjoerg warning(158, ln->tn_sym->s_name); 346312099Sjoerg setsflg(ln->tn_sym); 346412099Sjoerg } 346512099Sjoerg setuflg(ln->tn_sym, 0, 0); 346612099Sjoerg } 346712099Sjoerg break; 346812099Sjoerg case ASSIGN: 346912099Sjoerg if (ln->tn_op == NAME && !szof && (reached || rchflg)) { 347012099Sjoerg setsflg(ln->tn_sym); 347112099Sjoerg if (ln->tn_sym->s_scl == EXTERN) 347212099Sjoerg outusg(ln->tn_sym); 347312099Sjoerg } 347412099Sjoerg if (ln->tn_op == STAR && ln->tn_left->tn_op == PLUS) 347512099Sjoerg /* check the range of array indices */ 347612099Sjoerg chkaidx(ln->tn_left, 0); 347712099Sjoerg break; 347812099Sjoerg case CALL: 347912099Sjoerg if (ln->tn_op != AMPER || ln->tn_left->tn_op != NAME) 348012099Sjoerg lerror("chkmisc() 1"); 348112099Sjoerg if (!szof) 348212099Sjoerg outcall(tn, vctx || tctx, rvdisc); 348312099Sjoerg break; 348412099Sjoerg case EQ: 348512099Sjoerg /* equality operator "==" found where "=" was exp. */ 348612099Sjoerg if (hflag && eqwarn) 348712099Sjoerg warning(160); 348812099Sjoerg break; 348912099Sjoerg case CON: 349012099Sjoerg case NAME: 349112099Sjoerg case STRING: 349212099Sjoerg return; 349312099Sjoerg /* LINTED (enumeration values not handled in switch) */ 349491592Smarkm case OR: 349591592Smarkm case XOR: 349691592Smarkm case NE: 349791592Smarkm case GE: 349891592Smarkm case GT: 349991592Smarkm case LE: 350091592Smarkm case LT: 350191592Smarkm case SHR: 350291592Smarkm case SHL: 350391592Smarkm case MINUS: 350491592Smarkm case PLUS: 350591592Smarkm case MOD: 350691592Smarkm case DIV: 350791592Smarkm case MULT: 350891592Smarkm case STAR: 350991592Smarkm case UMINUS: 351091592Smarkm case UPLUS: 351191592Smarkm case DEC: 351291592Smarkm case INC: 351391592Smarkm case COMPL: 351491592Smarkm case NOT: 351591592Smarkm case POINT: 351691592Smarkm case ARROW: 351791592Smarkm case NOOP: 351891592Smarkm case AND: 351991592Smarkm case FARG: 352091592Smarkm case CASE: 352191592Smarkm case INIT: 352291592Smarkm case RETURN: 352391592Smarkm case ICALL: 352491592Smarkm case CVT: 352591592Smarkm case COMMA: 352691592Smarkm case FSEL: 352791592Smarkm case COLON: 352891592Smarkm case QUEST: 352991592Smarkm case LOGOR: 353091592Smarkm case LOGAND: 353191592Smarkm break; 353212099Sjoerg } 353312099Sjoerg 353412099Sjoerg cvctx = mp->m_vctx; 353512099Sjoerg ctctx = mp->m_tctx; 353612099Sjoerg /* 353712099Sjoerg * values of operands of ':' are not used if the type of at least 353812099Sjoerg * one of the operands (for gcc compatibility) is void 353912099Sjoerg * XXX test/value context of QUEST should probably be used as 354012099Sjoerg * context for both operands of COLON 354112099Sjoerg */ 354212099Sjoerg if (op == COLON && tn->tn_type->t_tspec == VOID) 354312099Sjoerg cvctx = ctctx = 0; 354412099Sjoerg nrvdisc = op == CVT && tn->tn_type->t_tspec == VOID; 354512099Sjoerg chkmisc(ln, cvctx, ctctx, mp->m_eqwarn, op == CALL, nrvdisc, szof); 354612099Sjoerg 354712099Sjoerg switch (op) { 354812099Sjoerg case PUSH: 354912099Sjoerg if (rn != NULL) 355012099Sjoerg chkmisc(rn, 0, 0, mp->m_eqwarn, 0, 0, szof); 355112099Sjoerg break; 355212099Sjoerg case LOGAND: 355312099Sjoerg case LOGOR: 355412099Sjoerg chkmisc(rn, 0, 1, mp->m_eqwarn, 0, 0, szof); 355512099Sjoerg break; 355612099Sjoerg case COLON: 355712099Sjoerg chkmisc(rn, cvctx, ctctx, mp->m_eqwarn, 0, 0, szof); 355812099Sjoerg break; 355991592Smarkm case COMMA: 356091592Smarkm chkmisc(rn, vctx, tctx, mp->m_eqwarn, 0, 0, szof); 356191592Smarkm break; 356212099Sjoerg default: 356312099Sjoerg if (mp->m_binary) 356412099Sjoerg chkmisc(rn, 1, 0, mp->m_eqwarn, 0, 0, szof); 356512099Sjoerg break; 356612099Sjoerg } 356712099Sjoerg 356812099Sjoerg} 356912099Sjoerg 357012099Sjoerg/* 357112099Sjoerg * Checks the range of array indices, if possible. 357212099Sjoerg * amper is set if only the address of the element is used. This 357312099Sjoerg * means that the index is allowd to refere to the first element 357412099Sjoerg * after the array. 357512099Sjoerg */ 357612099Sjoergstatic void 357791592Smarkmchkaidx(tnode_t *tn, int amper) 357812099Sjoerg{ 357912099Sjoerg int dim; 358012099Sjoerg tnode_t *ln, *rn; 358112099Sjoerg int elsz; 358291592Smarkm int64_t con; 358312099Sjoerg 358412099Sjoerg ln = tn->tn_left; 358512099Sjoerg rn = tn->tn_right; 358612099Sjoerg 358712099Sjoerg /* We can only check constant indices. */ 358812099Sjoerg if (rn->tn_op != CON) 358912099Sjoerg return; 359012099Sjoerg 359112099Sjoerg /* Return if the left node does not stem from an array. */ 359212099Sjoerg if (ln->tn_op != AMPER) 359312099Sjoerg return; 359412099Sjoerg if (ln->tn_left->tn_op != STRING && ln->tn_left->tn_op != NAME) 359512099Sjoerg return; 359612099Sjoerg if (ln->tn_left->tn_type->t_tspec != ARRAY) 359712099Sjoerg return; 359891592Smarkm 359912099Sjoerg /* 360012099Sjoerg * For incomplete array types, we can print a warning only if 360112099Sjoerg * the index is negative. 360212099Sjoerg */ 360312099Sjoerg if (incompl(ln->tn_left->tn_type) && rn->tn_val->v_quad >= 0) 360412099Sjoerg return; 360512099Sjoerg 360612099Sjoerg /* Get the size of one array element */ 360712099Sjoerg if ((elsz = length(ln->tn_type->t_subt, NULL)) == 0) 360812099Sjoerg return; 360912099Sjoerg elsz /= CHAR_BIT; 361012099Sjoerg 361112099Sjoerg /* Change the unit of the index from bytes to element size. */ 361212099Sjoerg if (isutyp(rn->tn_type->t_tspec)) { 361391592Smarkm con = (uint64_t)rn->tn_val->v_quad / elsz; 361412099Sjoerg } else { 361512099Sjoerg con = rn->tn_val->v_quad / elsz; 361612099Sjoerg } 361712099Sjoerg 361812099Sjoerg dim = ln->tn_left->tn_type->t_dim + (amper ? 1 : 0); 361912099Sjoerg 362012099Sjoerg if (!isutyp(rn->tn_type->t_tspec) && con < 0) { 362112099Sjoerg /* array subscript cannot be negative: %ld */ 362212099Sjoerg warning(167, (long)con); 362391592Smarkm } else if (dim > 0 && (uint64_t)con >= dim) { 362412099Sjoerg /* array subscript cannot be > %d: %ld */ 362512099Sjoerg warning(168, dim - 1, (long)con); 362612099Sjoerg } 362712099Sjoerg} 362812099Sjoerg 362912099Sjoerg/* 363075697Sasmodai * Check for ordered comparisons of unsigned values with 0. 363112099Sjoerg */ 363212099Sjoergstatic void 363391592Smarkmchkcomp(op_t op, tnode_t *ln, tnode_t *rn) 363412099Sjoerg{ 363512099Sjoerg tspec_t lt, rt; 363612099Sjoerg mod_t *mp; 363712099Sjoerg 363812099Sjoerg lt = ln->tn_type->t_tspec; 363912099Sjoerg rt = rn->tn_type->t_tspec; 364012099Sjoerg mp = &modtab[op]; 364112099Sjoerg 364212099Sjoerg if (ln->tn_op != CON && rn->tn_op != CON) 364312099Sjoerg return; 364412099Sjoerg 364512099Sjoerg if (!isityp(lt) || !isityp(rt)) 364612099Sjoerg return; 364712099Sjoerg 364812099Sjoerg if ((hflag || pflag) && lt == CHAR && rn->tn_op == CON && 364912099Sjoerg (rn->tn_val->v_quad < 0 || 365012099Sjoerg rn->tn_val->v_quad > ~(~0 << (CHAR_BIT - 1)))) { 365175697Sasmodai /* nonportable character comparison, op %s */ 365212099Sjoerg warning(230, mp->m_name); 365312099Sjoerg return; 365412099Sjoerg } 365512099Sjoerg if ((hflag || pflag) && rt == CHAR && ln->tn_op == CON && 365612099Sjoerg (ln->tn_val->v_quad < 0 || 365712099Sjoerg ln->tn_val->v_quad > ~(~0 << (CHAR_BIT - 1)))) { 365875697Sasmodai /* nonportable character comparison, op %s */ 365912099Sjoerg warning(230, mp->m_name); 366012099Sjoerg return; 366112099Sjoerg } 366212099Sjoerg if (isutyp(lt) && !isutyp(rt) && 366312099Sjoerg rn->tn_op == CON && rn->tn_val->v_quad <= 0) { 366412099Sjoerg if (rn->tn_val->v_quad < 0) { 366575697Sasmodai /* comparison of %s with %s, op %s */ 366612099Sjoerg warning(162, tyname(ln->tn_type), "negative constant", 366712099Sjoerg mp->m_name); 366812099Sjoerg } else if (op == LT || op == GE || (hflag && op == LE)) { 366975697Sasmodai /* comparison of %s with %s, op %s */ 367012099Sjoerg warning(162, tyname(ln->tn_type), "0", mp->m_name); 367112099Sjoerg } 367212099Sjoerg return; 367312099Sjoerg } 367412099Sjoerg if (isutyp(rt) && !isutyp(lt) && 367512099Sjoerg ln->tn_op == CON && ln->tn_val->v_quad <= 0) { 367612099Sjoerg if (ln->tn_val->v_quad < 0) { 367775697Sasmodai /* comparison of %s with %s, op %s */ 367812099Sjoerg warning(162, "negative constant", tyname(rn->tn_type), 367912099Sjoerg mp->m_name); 368012099Sjoerg } else if (op == GT || op == LE || (hflag && op == GE)) { 368175697Sasmodai /* comparison of %s with %s, op %s */ 368212099Sjoerg warning(162, "0", tyname(rn->tn_type), mp->m_name); 368312099Sjoerg } 368412099Sjoerg return; 368512099Sjoerg } 368612099Sjoerg} 368712099Sjoerg 368812099Sjoerg/* 368912099Sjoerg * Takes an expression an returns 0 if this expression can be used 369012099Sjoerg * for static initialisation, otherwise -1. 369112099Sjoerg * 369212099Sjoerg * Constant initialisation expressions must be costant or an address 369312099Sjoerg * of a static object with an optional offset. In the first case, 369412099Sjoerg * the result is returned in *offsp. In the second case, the static 369512099Sjoerg * object is returned in *symp and the offset in *offsp. 369612099Sjoerg * 369712099Sjoerg * The expression can consist of PLUS, MINUS, AMPER, NAME, STRING and 369812099Sjoerg * CON. Type conversions are allowed if they do not change binary 369912099Sjoerg * representation (including width). 370012099Sjoerg */ 370112099Sjoergint 370291592Smarkmconaddr(tnode_t *tn, sym_t **symp, ptrdiff_t *offsp) 370312099Sjoerg{ 370412099Sjoerg sym_t *sym; 370512099Sjoerg ptrdiff_t offs1, offs2; 370612099Sjoerg tspec_t t, ot; 370712099Sjoerg 370812099Sjoerg switch (tn->tn_op) { 370912099Sjoerg case MINUS: 371012099Sjoerg if (tn->tn_right->tn_op != CON) 371112099Sjoerg return (-1); 371212099Sjoerg /* FALLTHROUGH */ 371312099Sjoerg case PLUS: 371412099Sjoerg offs1 = offs2 = 0; 371512099Sjoerg if (tn->tn_left->tn_op == CON) { 371612099Sjoerg offs1 = (ptrdiff_t)tn->tn_left->tn_val->v_quad; 371712099Sjoerg if (conaddr(tn->tn_right, &sym, &offs2) == -1) 371812099Sjoerg return (-1); 371912099Sjoerg } else if (tn->tn_right->tn_op == CON) { 372012099Sjoerg offs2 = (ptrdiff_t)tn->tn_right->tn_val->v_quad; 372112099Sjoerg if (tn->tn_op == MINUS) 372212099Sjoerg offs2 = -offs2; 372312099Sjoerg if (conaddr(tn->tn_left, &sym, &offs1) == -1) 372412099Sjoerg return (-1); 372512099Sjoerg } else { 372612099Sjoerg return (-1); 372712099Sjoerg } 372812099Sjoerg *symp = sym; 372912099Sjoerg *offsp = offs1 + offs2; 373012099Sjoerg break; 373112099Sjoerg case AMPER: 373212099Sjoerg if (tn->tn_left->tn_op == NAME) { 373312099Sjoerg *symp = tn->tn_left->tn_sym; 373412099Sjoerg *offsp = 0; 373512099Sjoerg } else if (tn->tn_left->tn_op == STRING) { 373612099Sjoerg /* 373712099Sjoerg * If this would be the front end of a compiler we 373812099Sjoerg * would return a label instead of 0. 373912099Sjoerg */ 374012099Sjoerg *offsp = 0; 374112099Sjoerg } 374212099Sjoerg break; 374312099Sjoerg case CVT: 374412099Sjoerg t = tn->tn_type->t_tspec; 374512099Sjoerg ot = tn->tn_left->tn_type->t_tspec; 374612099Sjoerg if ((!isityp(t) && t != PTR) || (!isityp(ot) && ot != PTR)) { 374712099Sjoerg return (-1); 374812099Sjoerg } else if (psize(t) != psize(ot)) { 374912099Sjoerg return (-1); 375012099Sjoerg } 375112099Sjoerg if (conaddr(tn->tn_left, symp, offsp) == -1) 375212099Sjoerg return (-1); 375312099Sjoerg break; 375412099Sjoerg default: 375512099Sjoerg return (-1); 375612099Sjoerg } 375712099Sjoerg return (0); 375812099Sjoerg} 375912099Sjoerg 376012099Sjoerg/* 376112099Sjoerg * Concatenate two string constants. 376212099Sjoerg */ 376312099Sjoergstrg_t * 376491592Smarkmcatstrg(strg_t *strg1, strg_t *strg2) 376512099Sjoerg{ 376612099Sjoerg size_t len1, len2, len; 376712099Sjoerg 376812099Sjoerg if (strg1->st_tspec != strg2->st_tspec) { 376912099Sjoerg /* cannot concatenate wide and regular string literals */ 377012099Sjoerg error(292); 377112099Sjoerg return (strg1); 377212099Sjoerg } 377312099Sjoerg 377412099Sjoerg len = (len1 = strg1->st_len) + (len2 = strg2->st_len); 377512099Sjoerg 377612099Sjoerg if (strg1->st_tspec == CHAR) { 377780284Sobrien if ((strg1->st_cp = realloc(strg1->st_cp, len + 1)) == NULL) 377880284Sobrien nomem(); 377912099Sjoerg (void)memcpy(strg1->st_cp + len1, strg2->st_cp, len2 + 1); 378012099Sjoerg free(strg2->st_cp); 378112099Sjoerg } else { 378280284Sobrien if ((strg1->st_wcp = realloc(strg1->st_wcp, (len + 1) * 378380284Sobrien sizeof (wchar_t))) == NULL) 378480284Sobrien nomem(); 378512099Sjoerg (void)memcpy(strg1->st_wcp + len1, strg2->st_wcp, 378612099Sjoerg (len2 + 1) * sizeof (wchar_t)); 378712099Sjoerg free(strg2->st_wcp); 378812099Sjoerg } 3789224702Skevlo strg1->st_len = len; 379012099Sjoerg free(strg2); 379112099Sjoerg 379212099Sjoerg return (strg1); 379312099Sjoerg} 379412099Sjoerg 379512099Sjoerg/* 379612099Sjoerg * Print a warning if the given node has operands which should be 379712099Sjoerg * parenthesized. 379812099Sjoerg * 379912099Sjoerg * XXX Does not work if an operand is a constant expression. Constant 380012099Sjoerg * expressions are already folded. 380112099Sjoerg */ 380212099Sjoergstatic void 380391592Smarkmprecconf(tnode_t *tn) 380412099Sjoerg{ 380512099Sjoerg tnode_t *ln, *rn; 380691592Smarkm op_t lop, rop = NOOP; 380791592Smarkm int lparn, rparn = 0; 380812099Sjoerg mod_t *mp; 380912099Sjoerg int warn; 381012099Sjoerg 381112099Sjoerg if (!hflag) 381212099Sjoerg return; 381312099Sjoerg 381412099Sjoerg mp = &modtab[tn->tn_op]; 381512099Sjoerg 381612099Sjoerg lparn = 0; 381712099Sjoerg for (ln = tn->tn_left; ln->tn_op == CVT; ln = ln->tn_left) 381812099Sjoerg lparn |= ln->tn_parn; 381912099Sjoerg lparn |= ln->tn_parn; 382012099Sjoerg lop = ln->tn_op; 382112099Sjoerg 382212099Sjoerg if (mp->m_binary) { 382312099Sjoerg rparn = 0; 382412099Sjoerg for (rn = tn->tn_right; tn->tn_op == CVT; rn = rn->tn_left) 382512099Sjoerg rparn |= rn->tn_parn; 382612099Sjoerg rparn |= rn->tn_parn; 382712099Sjoerg rop = rn->tn_op; 382812099Sjoerg } 382912099Sjoerg 383012099Sjoerg warn = 0; 383112099Sjoerg 383212099Sjoerg switch (tn->tn_op) { 383312099Sjoerg case SHL: 383412099Sjoerg case SHR: 383512099Sjoerg if (!lparn && (lop == PLUS || lop == MINUS)) { 383612099Sjoerg warn = 1; 383712099Sjoerg } else if (!rparn && (rop == PLUS || rop == MINUS)) { 383812099Sjoerg warn = 1; 383912099Sjoerg } 384012099Sjoerg break; 384112099Sjoerg case LOGOR: 384212099Sjoerg if (!lparn && lop == LOGAND) { 384312099Sjoerg warn = 1; 384412099Sjoerg } else if (!rparn && rop == LOGAND) { 384512099Sjoerg warn = 1; 384612099Sjoerg } 384712099Sjoerg break; 384812099Sjoerg case AND: 384912099Sjoerg case XOR: 385012099Sjoerg case OR: 385112099Sjoerg if (!lparn && lop != tn->tn_op) { 385212099Sjoerg if (lop == PLUS || lop == MINUS) { 385312099Sjoerg warn = 1; 385412099Sjoerg } else if (lop == AND || lop == XOR) { 385512099Sjoerg warn = 1; 385612099Sjoerg } 385712099Sjoerg } 385812099Sjoerg if (!warn && !rparn && rop != tn->tn_op) { 385912099Sjoerg if (rop == PLUS || rop == MINUS) { 386012099Sjoerg warn = 1; 386112099Sjoerg } else if (rop == AND || rop == XOR) { 386212099Sjoerg warn = 1; 386312099Sjoerg } 386412099Sjoerg } 386512099Sjoerg break; 386612099Sjoerg /* LINTED (enumeration values not handled in switch) */ 386791592Smarkm case DECAFT: 386891592Smarkm case XORASS: 386991592Smarkm case SHLASS: 387091592Smarkm case NOOP: 387191592Smarkm case ARROW: 387291592Smarkm case ORASS: 387391592Smarkm case POINT: 387491592Smarkm case NAME: 387591592Smarkm case NOT: 387691592Smarkm case COMPL: 387791592Smarkm case CON: 387891592Smarkm case INC: 387991592Smarkm case STRING: 388091592Smarkm case DEC: 388191592Smarkm case INCBEF: 388291592Smarkm case DECBEF: 388391592Smarkm case INCAFT: 388491592Smarkm case FSEL: 388591592Smarkm case CALL: 388691592Smarkm case COMMA: 388791592Smarkm case CVT: 388891592Smarkm case ICALL: 388991592Smarkm case LOAD: 389091592Smarkm case PUSH: 389191592Smarkm case RETURN: 389291592Smarkm case INIT: 389391592Smarkm case CASE: 389491592Smarkm case FARG: 389591592Smarkm case SUBASS: 389691592Smarkm case ADDASS: 389791592Smarkm case MODASS: 389891592Smarkm case DIVASS: 389991592Smarkm case MULASS: 390091592Smarkm case ASSIGN: 390191592Smarkm case COLON: 390291592Smarkm case QUEST: 390391592Smarkm case LOGAND: 390491592Smarkm case NE: 390591592Smarkm case EQ: 390691592Smarkm case GE: 390791592Smarkm case GT: 390891592Smarkm case LE: 390991592Smarkm case LT: 391091592Smarkm case MINUS: 391191592Smarkm case PLUS: 391291592Smarkm case MOD: 391391592Smarkm case DIV: 391491592Smarkm case MULT: 391591592Smarkm case AMPER: 391691592Smarkm case STAR: 391791592Smarkm case UMINUS: 391891592Smarkm case SHRASS: 391991592Smarkm case UPLUS: 392091592Smarkm case ANDASS: 392191592Smarkm break; 392212099Sjoerg } 392312099Sjoerg 392412099Sjoerg if (warn) { 392512099Sjoerg /* precedence confusion possible: parenthesize! */ 392612099Sjoerg warning(169); 392712099Sjoerg } 392812099Sjoerg 392912099Sjoerg} 3930