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