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