tree.c revision 1.402
11.402Srillig/*	$NetBSD: tree.c,v 1.402 2021/12/21 15:33:20 rillig Exp $	*/
21.2Scgd
31.1Scgd/*
41.1Scgd * Copyright (c) 1994, 1995 Jochen Pohl
51.1Scgd * All Rights Reserved.
61.1Scgd *
71.1Scgd * Redistribution and use in source and binary forms, with or without
81.1Scgd * modification, are permitted provided that the following conditions
91.1Scgd * are met:
101.1Scgd * 1. Redistributions of source code must retain the above copyright
111.1Scgd *    notice, this list of conditions and the following disclaimer.
121.1Scgd * 2. Redistributions in binary form must reproduce the above copyright
131.1Scgd *    notice, this list of conditions and the following disclaimer in the
141.1Scgd *    documentation and/or other materials provided with the distribution.
151.1Scgd * 3. All advertising materials mentioning features or use of this software
161.1Scgd *    must display the following acknowledgement:
171.1Scgd *      This product includes software developed by Jochen Pohl for
181.1Scgd *	The NetBSD Project.
191.1Scgd * 4. The name of the author may not be used to endorse or promote products
201.1Scgd *    derived from this software without specific prior written permission.
211.1Scgd *
221.1Scgd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
231.1Scgd * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
241.1Scgd * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
251.1Scgd * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
261.1Scgd * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
271.1Scgd * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
281.1Scgd * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
291.1Scgd * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
301.1Scgd * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
311.1Scgd * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
321.1Scgd */
331.1Scgd
341.37Sjmc#if HAVE_NBTOOL_CONFIG_H
351.37Sjmc#include "nbtool_config.h"
361.37Sjmc#endif
371.37Sjmc
381.14Schristos#include <sys/cdefs.h>
391.23Stv#if defined(__RCSID) && !defined(lint)
401.402Srillig__RCSID("$NetBSD: tree.c,v 1.402 2021/12/21 15:33:20 rillig Exp $");
411.1Scgd#endif
421.1Scgd
431.1Scgd#include <float.h>
441.1Scgd#include <limits.h>
451.1Scgd#include <math.h>
461.49Schristos#include <signal.h>
471.92Srillig#include <stdlib.h>
481.92Srillig#include <string.h>
491.1Scgd
501.1Scgd#include "lint1.h"
511.15Stv#include "cgram.h"
521.1Scgd
531.318Srilligstatic	tnode_t	*build_integer_constant(tspec_t, int64_t);
541.149Srilligstatic	void	check_pointer_comparison(op_t,
551.149Srillig					 const tnode_t *, const tnode_t *);
561.154Srilligstatic	bool	check_assign_types_compatible(op_t, int,
571.149Srillig					      const tnode_t *, const tnode_t *);
581.149Srilligstatic	void	check_bad_enum_operation(op_t,
591.149Srillig					 const tnode_t *, const tnode_t *);
601.149Srilligstatic	void	check_enum_type_mismatch(op_t, int,
611.149Srillig				         const tnode_t *, const tnode_t *);
621.149Srilligstatic	void	check_enum_int_mismatch(op_t, int,
631.149Srillig					const tnode_t *, const tnode_t *);
641.395Srilligstatic	tnode_t	*new_tnode(op_t, bool, type_t *, tnode_t *, tnode_t *);
651.20Slukemstatic	void	balance(op_t, tnode_t **, tnode_t **);
661.246Srilligstatic	void	warn_incompatible_types(op_t, const type_t *, tspec_t,
671.246Srillig					const type_t *, tspec_t);
681.149Srilligstatic	void	warn_incompatible_pointers(const mod_t *,
691.149Srillig					   const type_t *, const type_t *);
701.149Srilligstatic	bool	has_constant_member(const type_t *);
711.100Srilligstatic	void	check_prototype_conversion(int, tspec_t, tspec_t, type_t *,
721.100Srillig					   tnode_t *);
731.100Srilligstatic	void	check_integer_conversion(op_t, int, tspec_t, tspec_t, type_t *,
741.100Srillig					 tnode_t *);
751.100Srilligstatic	void	check_pointer_integer_conversion(op_t, tspec_t, type_t *,
761.100Srillig						 tnode_t *);
771.273Srilligstatic	void	check_pointer_conversion(tnode_t *, type_t *);
781.395Srilligstatic	tnode_t	*build_struct_access(op_t, bool, tnode_t *, tnode_t *);
791.395Srilligstatic	tnode_t	*build_prepost_incdec(op_t, bool, tnode_t *);
801.395Srilligstatic	tnode_t	*build_real_imag(op_t, bool, tnode_t *);
811.395Srilligstatic	tnode_t	*build_address(bool, tnode_t *, bool);
821.395Srilligstatic	tnode_t	*build_plus_minus(op_t, bool, tnode_t *, tnode_t *);
831.395Srilligstatic	tnode_t	*build_bit_shift(op_t, bool, tnode_t *, tnode_t *);
841.395Srilligstatic	tnode_t	*build_colon(bool, tnode_t *, tnode_t *);
851.395Srilligstatic	tnode_t	*build_assignment(op_t, bool, tnode_t *, tnode_t *);
861.20Slukemstatic	tnode_t	*plength(type_t *);
871.20Slukemstatic	tnode_t	*fold(tnode_t *);
881.100Srilligstatic	tnode_t	*fold_test(tnode_t *);
891.100Srilligstatic	tnode_t	*fold_float(tnode_t *);
901.100Srilligstatic	tnode_t	*check_function_arguments(type_t *, tnode_t *);
911.100Srilligstatic	tnode_t	*check_prototype_argument(int, type_t *, tnode_t *);
921.149Srilligstatic	void	check_null_effect(const tnode_t *);
931.154Srilligstatic	void	check_array_index(tnode_t *, bool);
941.100Srilligstatic	void	check_integer_comparison(op_t, tnode_t *, tnode_t *);
951.100Srilligstatic	void	check_precedence_confusion(tnode_t *);
961.1Scgd
971.49Schristosextern sig_atomic_t fpe;
981.49Schristos
991.241Srilligstatic const char *
1001.260Srilligop_name(op_t op)
1011.241Srillig{
1021.241Srillig	return modtab[op].m_name;
1031.241Srillig}
1041.241Srillig
1051.257Srillig/* Build 'pointer to tp', 'array of tp' or 'function returning tp'. */
1061.1Scgdtype_t *
1071.257Srilligderive_type(type_t *tp, tspec_t t)
1081.1Scgd{
1091.1Scgd	type_t	*tp2;
1101.1Scgd
1111.259Srillig	tp2 = getblk(sizeof(*tp2));
1121.1Scgd	tp2->t_tspec = t;
1131.1Scgd	tp2->t_subt = tp;
1141.95Srillig	return tp2;
1151.1Scgd}
1161.1Scgd
1171.1Scgd/*
1181.365Srillig * Derive 'pointer to tp' or 'function returning tp'.
1191.365Srillig * The memory is freed at the end of the current expression.
1201.1Scgd */
1211.1Scgdtype_t *
1221.257Srilligexpr_derive_type(type_t *tp, tspec_t t)
1231.1Scgd{
1241.1Scgd	type_t	*tp2;
1251.1Scgd
1261.259Srillig	tp2 = expr_zalloc(sizeof(*tp2));
1271.1Scgd	tp2->t_tspec = t;
1281.1Scgd	tp2->t_subt = tp;
1291.95Srillig	return tp2;
1301.1Scgd}
1311.1Scgd
1321.1Scgd/*
1331.1Scgd * Create a node for a constant.
1341.1Scgd */
1351.1Scgdtnode_t *
1361.318Srilligbuild_constant(type_t *tp, val_t *v)
1371.1Scgd{
1381.1Scgd	tnode_t	*n;
1391.1Scgd
1401.256Srillig	n = expr_zalloc_tnode();
1411.1Scgd	n->tn_op = CON;
1421.1Scgd	n->tn_type = tp;
1431.259Srillig	n->tn_val = expr_zalloc(sizeof(*n->tn_val));
1441.1Scgd	n->tn_val->v_tspec = tp->t_tspec;
1451.289Srillig	n->tn_val->v_unsigned_since_c90 = v->v_unsigned_since_c90;
1461.1Scgd	n->tn_val->v_u = v->v_u;
1471.1Scgd	free(v);
1481.95Srillig	return n;
1491.1Scgd}
1501.1Scgd
1511.1Scgdstatic tnode_t *
1521.318Srilligbuild_integer_constant(tspec_t t, int64_t q)
1531.1Scgd{
1541.1Scgd	tnode_t	*n;
1551.1Scgd
1561.256Srillig	n = expr_zalloc_tnode();
1571.1Scgd	n->tn_op = CON;
1581.1Scgd	n->tn_type = gettyp(t);
1591.259Srillig	n->tn_val = expr_zalloc(sizeof(*n->tn_val));
1601.1Scgd	n->tn_val->v_tspec = t;
1611.1Scgd	n->tn_val->v_quad = q;
1621.95Srillig	return n;
1631.1Scgd}
1641.1Scgd
1651.167Srilligstatic void
1661.167Srilligfallback_symbol(sym_t *sym)
1671.167Srillig{
1681.167Srillig
1691.267Srillig	if (fallback_symbol_strict_bool(sym))
1701.167Srillig		return;
1711.167Srillig
1721.233Srillig	if (block_level > 0 && (strcmp(sym->s_name, "__FUNCTION__") == 0 ||
1731.167Srillig			   strcmp(sym->s_name, "__PRETTY_FUNCTION__") == 0)) {
1741.167Srillig		/* __FUNCTION__/__PRETTY_FUNCTION__ is a GCC extension */
1751.167Srillig		gnuism(316);
1761.257Srillig		sym->s_type = derive_type(gettyp(CHAR), PTR);
1771.167Srillig		sym->s_type->t_const = true;
1781.167Srillig		return;
1791.167Srillig	}
1801.167Srillig
1811.233Srillig	if (block_level > 0 && strcmp(sym->s_name, "__func__") == 0) {
1821.167Srillig		if (!Sflag)
1831.167Srillig			/* __func__ is a C9X feature */
1841.167Srillig			warning(317);
1851.257Srillig		sym->s_type = derive_type(gettyp(CHAR), PTR);
1861.167Srillig		sym->s_type->t_const = true;
1871.167Srillig		return;
1881.167Srillig	}
1891.167Srillig
1901.251Srillig	/* '%s' undefined */
1911.167Srillig	error(99, sym->s_name);
1921.167Srillig}
1931.167Srillig
1941.358Srillig/*
1951.361Srillig * Functions that are predeclared by GCC or other compilers can be called
1961.361Srillig * with arbitrary arguments.  Since lint usually runs after a successful
1971.361Srillig * compilation, it's the compiler's job to catch any errors.
1981.358Srillig */
1991.358Srilligbool
2001.361Srilligis_compiler_builtin(const char *name)
2011.303Srillig{
2021.361Srillig	/* https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html */
2031.362Srillig	if (gflag) {
2041.362Srillig		if (strncmp(name, "__atomic_", 9) == 0 ||
2051.362Srillig		    strncmp(name, "__builtin_", 10) == 0 ||
2061.400Srillig		    strcmp(name, "alloca") == 0 ||
2071.362Srillig		    /* obsolete but still in use, as of 2021 */
2081.362Srillig		    strncmp(name, "__sync_", 7) == 0)
2091.362Srillig			return true;
2101.362Srillig	}
2111.361Srillig
2121.361Srillig	/* https://software.intel.com/sites/landingpage/IntrinsicsGuide/ */
2131.361Srillig	if (strncmp(name, "_mm_", 4) == 0)
2141.361Srillig		return true;
2151.361Srillig
2161.361Srillig	return false;
2171.303Srillig}
2181.303Srillig
2191.372Srilligstatic bool
2201.372Srilligstr_endswith(const char *haystack, const char *needle)
2211.372Srillig{
2221.372Srillig	size_t hlen = strlen(haystack);
2231.372Srillig	size_t nlen = strlen(needle);
2241.372Srillig
2251.372Srillig	return nlen <= hlen &&
2261.372Srillig	       memcmp(haystack + hlen - nlen, needle, nlen) == 0;
2271.372Srillig}
2281.372Srillig
2291.372Srillig/* https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html */
2301.372Srilligstatic bool
2311.372Srilligis_gcc_bool_builtin(const char *name)
2321.372Srillig{
2331.372Srillig	return strncmp(name, "__builtin_", 10) == 0 &&
2341.372Srillig	       (str_endswith(name, "_overflow") ||
2351.372Srillig		str_endswith(name, "_overflow_p"));
2361.372Srillig}
2371.372Srillig
2381.371Srilligstatic void
2391.371Srilligbuild_name_call(sym_t *sym)
2401.371Srillig{
2411.371Srillig
2421.371Srillig	if (is_compiler_builtin(sym->s_name)) {
2431.371Srillig		/*
2441.371Srillig		 * Do not warn about these, just assume that
2451.371Srillig		 * they are regular functions compatible with
2461.371Srillig		 * non-prototype calling conventions.
2471.371Srillig		 */
2481.400Srillig		if (gflag && is_gcc_bool_builtin(sym->s_name))
2491.372Srillig			sym->s_type = gettyp(BOOL);
2501.372Srillig
2511.371Srillig	} else if (Sflag) {
2521.371Srillig		/* function '%s' implicitly declared to return int */
2531.371Srillig		error(215, sym->s_name);
2541.371Srillig	} else if (sflag) {
2551.371Srillig		/* function '%s' implicitly declared to return int */
2561.371Srillig		warning(215, sym->s_name);
2571.371Srillig	}
2581.371Srillig
2591.371Srillig	/* XXX if tflag is set, the symbol should be exported to level 0 */
2601.371Srillig	sym->s_type = derive_type(sym->s_type, FUNC);
2611.371Srillig}
2621.371Srillig
2631.402Srillig/* Create a node for a name (symbol table entry). */
2641.1Scgdtnode_t *
2651.399Srilligbuild_name(sym_t *sym, bool is_funcname)
2661.1Scgd{
2671.1Scgd	tnode_t	*n;
2681.1Scgd
2691.1Scgd	if (sym->s_scl == NOSCL) {
2701.1Scgd		sym->s_scl = EXTERN;
2711.1Scgd		sym->s_def = DECL;
2721.399Srillig		if (is_funcname)
2731.371Srillig			build_name_call(sym);
2741.399Srillig		else
2751.167Srillig			fallback_symbol(sym);
2761.1Scgd	}
2771.1Scgd
2781.242Srillig	lint_assert(sym->s_kind == FVFT || sym->s_kind == FMEMBER);
2791.1Scgd
2801.256Srillig	n = expr_zalloc_tnode();
2811.1Scgd	n->tn_type = sym->s_type;
2821.401Srillig	if (sym->s_scl == CTCONST) {
2831.401Srillig		n->tn_op = CON;
2841.401Srillig		n->tn_val = expr_zalloc(sizeof(*n->tn_val));
2851.401Srillig		*n->tn_val = sym->s_value;
2861.401Srillig	} else {
2871.1Scgd		n->tn_op = NAME;
2881.1Scgd		n->tn_sym = sym;
2891.1Scgd		if (sym->s_kind == FVFT && sym->s_type->t_tspec != FUNC)
2901.154Srillig			n->tn_lvalue = true;
2911.1Scgd	}
2921.1Scgd
2931.95Srillig	return n;
2941.1Scgd}
2951.1Scgd
2961.1Scgdtnode_t *
2971.318Srilligbuild_string(strg_t *strg)
2981.1Scgd{
2991.1Scgd	size_t	len;
3001.1Scgd	tnode_t	*n;
3011.365Srillig	type_t *tp;
3021.1Scgd
3031.1Scgd	len = strg->st_len;
3041.1Scgd
3051.256Srillig	n = expr_zalloc_tnode();
3061.1Scgd
3071.365Srillig	tp = expr_zalloc(sizeof(*tp));
3081.365Srillig	tp->t_tspec = ARRAY;
3091.365Srillig	tp->t_subt = gettyp(strg->st_tspec);
3101.378Srillig	tp->t_dim = (int)(len + 1);
3111.365Srillig
3121.1Scgd	n->tn_op = STRING;
3131.365Srillig	n->tn_type = tp;
3141.154Srillig	n->tn_lvalue = true;
3151.1Scgd
3161.259Srillig	n->tn_string = expr_zalloc(sizeof(*n->tn_string));
3171.104Srillig	n->tn_string->st_tspec = strg->st_tspec;
3181.104Srillig	n->tn_string->st_len = len;
3191.1Scgd
3201.1Scgd	if (strg->st_tspec == CHAR) {
3211.257Srillig		n->tn_string->st_cp = expr_zalloc(len + 1);
3221.104Srillig		(void)memcpy(n->tn_string->st_cp, strg->st_cp, len + 1);
3231.1Scgd		free(strg->st_cp);
3241.1Scgd	} else {
3251.259Srillig		size_t size = (len + 1) * sizeof(*n->tn_string->st_wcp);
3261.257Srillig		n->tn_string->st_wcp = expr_zalloc(size);
3271.250Srillig		(void)memcpy(n->tn_string->st_wcp, strg->st_wcp, size);
3281.1Scgd		free(strg->st_wcp);
3291.1Scgd	}
3301.1Scgd	free(strg);
3311.1Scgd
3321.95Srillig	return n;
3331.1Scgd}
3341.1Scgd
3351.1Scgd/*
3361.1Scgd * Returns a symbol which has the same name as the msym argument and is a
3371.1Scgd * member of the struct or union specified by the tn argument.
3381.1Scgd */
3391.398Srilligstatic sym_t *
3401.98Srilligstruct_or_union_member(tnode_t *tn, op_t op, sym_t *msym)
3411.1Scgd{
3421.208Srillig	struct_or_union	*str;
3431.1Scgd	type_t	*tp;
3441.1Scgd	sym_t	*sym, *csym;
3451.154Srillig	bool	eq;
3461.1Scgd	tspec_t	t;
3471.1Scgd
3481.1Scgd	/*
3491.182Srillig	 * Remove the member if it was unknown until now, which means
3501.182Srillig	 * that no defined struct or union has a member with the same name.
3511.1Scgd	 */
3521.1Scgd	if (msym->s_scl == NOSCL) {
3531.254Srillig		/* type '%s' does not have member '%s' */
3541.300Srillig		error(101, type_name(tn->tn_type), msym->s_name);
3551.1Scgd		rmsym(msym);
3561.102Srillig		msym->s_kind = FMEMBER;
3571.1Scgd		msym->s_scl = MOS;
3581.259Srillig		msym->s_styp = expr_zalloc(sizeof(*msym->s_styp));
3591.257Srillig		msym->s_styp->sou_tag = expr_zalloc(
3601.259Srillig		    sizeof(*msym->s_styp->sou_tag));
3611.208Srillig		msym->s_styp->sou_tag->s_name = unnamed;
3621.1Scgd		msym->s_value.v_tspec = INT;
3631.95Srillig		return msym;
3641.1Scgd	}
3651.1Scgd
3661.1Scgd	/* Set str to the tag of which msym is expected to be a member. */
3671.1Scgd	str = NULL;
3681.1Scgd	t = (tp = tn->tn_type)->t_tspec;
3691.1Scgd	if (op == POINT) {
3701.1Scgd		if (t == STRUCT || t == UNION)
3711.1Scgd			str = tp->t_str;
3721.1Scgd	} else if (op == ARROW && t == PTR) {
3731.1Scgd		t = (tp = tp->t_subt)->t_tspec;
3741.1Scgd		if (t == STRUCT || t == UNION)
3751.1Scgd			str = tp->t_str;
3761.1Scgd	}
3771.1Scgd
3781.1Scgd	/*
3791.182Srillig	 * If this struct/union has a member with the name of msym, return it.
3801.1Scgd	 */
3811.1Scgd	if (str != NULL) {
3821.1Scgd		for (sym = msym; sym != NULL; sym = sym->s_link) {
3831.1Scgd			if (sym->s_scl != MOS && sym->s_scl != MOU)
3841.1Scgd				continue;
3851.1Scgd			if (sym->s_styp != str)
3861.1Scgd				continue;
3871.1Scgd			if (strcmp(sym->s_name, msym->s_name) != 0)
3881.1Scgd				continue;
3891.95Srillig			return sym;
3901.1Scgd		}
3911.1Scgd	}
3921.1Scgd
3931.1Scgd	/*
3941.185Srillig	 * Set eq to false if there are struct/union members with the same
3951.185Srillig	 * name and different types and/or offsets.
3961.1Scgd	 */
3971.154Srillig	eq = true;
3981.1Scgd	for (csym = msym; csym != NULL; csym = csym->s_link) {
3991.1Scgd		if (csym->s_scl != MOS && csym->s_scl != MOU)
4001.1Scgd			continue;
4011.1Scgd		if (strcmp(msym->s_name, csym->s_name) != 0)
4021.1Scgd			continue;
4031.342Srillig		for (sym = csym->s_link; sym != NULL; sym = sym->s_link) {
4041.154Srillig			bool w;
4051.1Scgd
4061.1Scgd			if (sym->s_scl != MOS && sym->s_scl != MOU)
4071.1Scgd				continue;
4081.1Scgd			if (strcmp(csym->s_name, sym->s_name) != 0)
4091.1Scgd				continue;
4101.1Scgd			if (csym->s_value.v_quad != sym->s_value.v_quad) {
4111.154Srillig				eq = false;
4121.1Scgd				break;
4131.1Scgd			}
4141.154Srillig			w = false;
4151.154Srillig			eq = eqtype(csym->s_type, sym->s_type,
4161.154Srillig			    false, false, &w) && !w;
4171.1Scgd			if (!eq)
4181.1Scgd				break;
4191.105Srillig			if (csym->s_bitfield != sym->s_bitfield) {
4201.154Srillig				eq = false;
4211.1Scgd				break;
4221.1Scgd			}
4231.105Srillig			if (csym->s_bitfield) {
4241.1Scgd				type_t	*tp1, *tp2;
4251.1Scgd
4261.1Scgd				tp1 = csym->s_type;
4271.1Scgd				tp2 = sym->s_type;
4281.1Scgd				if (tp1->t_flen != tp2->t_flen) {
4291.154Srillig					eq = false;
4301.1Scgd					break;
4311.1Scgd				}
4321.1Scgd				if (tp1->t_foffs != tp2->t_foffs) {
4331.154Srillig					eq = false;
4341.1Scgd					break;
4351.1Scgd				}
4361.1Scgd			}
4371.1Scgd		}
4381.1Scgd		if (!eq)
4391.1Scgd			break;
4401.1Scgd	}
4411.1Scgd
4421.1Scgd	/*
4431.1Scgd	 * Now handle the case in which the left operand refers really
4441.1Scgd	 * to a struct/union, but the right operand is not member of it.
4451.1Scgd	 */
4461.1Scgd	if (str != NULL) {
4471.1Scgd		if (eq && tflag) {
4481.113Srillig			/* illegal member use: %s */
4491.1Scgd			warning(102, msym->s_name);
4501.1Scgd		} else {
4511.113Srillig			/* illegal member use: %s */
4521.1Scgd			error(102, msym->s_name);
4531.1Scgd		}
4541.95Srillig		return msym;
4551.1Scgd	}
4561.1Scgd
4571.1Scgd	/*
4581.1Scgd	 * Now the left operand of ARROW does not point to a struct/union
4591.1Scgd	 * or the left operand of POINT is no struct/union.
4601.1Scgd	 */
4611.1Scgd	if (eq) {
4621.1Scgd		if (op == POINT) {
4631.1Scgd			if (tflag) {
4641.310Srillig				/* left operand of '.' must be struct ... */
4651.310Srillig				warning(103, type_name(tn->tn_type));
4661.1Scgd			} else {
4671.310Srillig				/* left operand of '.' must be struct ... */
4681.310Srillig				error(103, type_name(tn->tn_type));
4691.1Scgd			}
4701.1Scgd		} else {
4711.1Scgd			if (tflag && tn->tn_type->t_tspec == PTR) {
4721.113Srillig				/* left operand of '->' must be pointer ... */
4731.115Srillig				warning(104, type_name(tn->tn_type));
4741.1Scgd			} else {
4751.113Srillig				/* left operand of '->' must be pointer ... */
4761.115Srillig				error(104, type_name(tn->tn_type));
4771.1Scgd			}
4781.1Scgd		}
4791.1Scgd	} else {
4801.1Scgd		if (tflag) {
4811.1Scgd			/* non-unique member requires struct/union %s */
4821.1Scgd			error(105, op == POINT ? "object" : "pointer");
4831.1Scgd		} else {
4841.108Srillig			/* unacceptable operand of '%s' */
4851.260Srillig			error(111, op_name(op));
4861.1Scgd		}
4871.1Scgd	}
4881.1Scgd
4891.95Srillig	return msym;
4901.1Scgd}
4911.1Scgd
4921.291Srilligtnode_t *
4931.291Srilligbuild_generic_selection(const tnode_t *expr,
4941.313Srillig			struct generic_association *sel)
4951.291Srillig{
4961.291Srillig	tnode_t *default_result = NULL;
4971.291Srillig
4981.313Srillig	for (; sel != NULL; sel = sel->ga_prev)
4991.292Srillig		if (expr != NULL &&
5001.313Srillig		    eqtype(sel->ga_arg, expr->tn_type, false, false, NULL))
5011.313Srillig			return sel->ga_result;
5021.313Srillig		else if (sel->ga_arg == NULL)
5031.313Srillig			default_result = sel->ga_result;
5041.291Srillig	return default_result;
5051.291Srillig}
5061.291Srillig
5071.1Scgd/*
5081.395Srillig * Create a tree node for a binary operator and its two operands. Also called
5091.395Srillig * for unary operators; in that case rn is NULL.
5101.1Scgd *
5111.395Srillig * Function calls, sizeof and casts are handled elsewhere.
5121.1Scgd */
5131.1Scgdtnode_t *
5141.395Srilligbuild_binary(tnode_t *ln, op_t op, bool sys, tnode_t *rn)
5151.1Scgd{
5161.240Srillig	const mod_t *mp;
5171.1Scgd	tnode_t	*ntn;
5181.219Srillig	type_t	*rettp;
5191.1Scgd
5201.1Scgd	mp = &modtab[op];
5211.1Scgd
5221.1Scgd	/* If there was an error in one of the operands, return. */
5231.1Scgd	if (ln == NULL || (mp->m_binary && rn == NULL))
5241.95Srillig		return NULL;
5251.1Scgd
5261.1Scgd	/*
5271.1Scgd	 * Apply class conversions to the left operand, but only if its
5281.106Srillig	 * value is needed or it is compared with null.
5291.1Scgd	 */
5301.164Srillig	if (mp->m_left_value_context || mp->m_left_test_context)
5311.1Scgd		ln = cconv(ln);
5321.1Scgd	/*
5331.1Scgd	 * The right operand is almost always in a test or value context,
5341.1Scgd	 * except if it is a struct or union member.
5351.1Scgd	 */
5361.1Scgd	if (mp->m_binary && op != ARROW && op != POINT)
5371.1Scgd		rn = cconv(rn);
5381.1Scgd
5391.1Scgd	/*
5401.17Smycroft	 * Print some warnings for comparisons of unsigned values with
5411.1Scgd	 * constants lower than or equal to null. This must be done
5421.1Scgd	 * before promote() because otherwise unsigned char and unsigned
5431.1Scgd	 * short would be promoted to int. Also types are tested to be
5441.1Scgd	 * CHAR, which would also become int.
5451.1Scgd	 */
5461.164Srillig	if (mp->m_comparison)
5471.100Srillig		check_integer_comparison(op, ln, rn);
5481.1Scgd
5491.1Scgd	/*
5501.1Scgd	 * Promote the left operand if it is in a test or value context
5511.1Scgd	 */
5521.164Srillig	if (mp->m_left_value_context || mp->m_left_test_context)
5531.172Srillig		ln = promote(op, false, ln);
5541.1Scgd	/*
5551.1Scgd	 * Promote the right operand, but only if it is no struct or
5561.1Scgd	 * union member, or if it is not to be assigned to the left operand
5571.1Scgd	 */
5581.1Scgd	if (mp->m_binary && op != ARROW && op != POINT &&
5591.333Srillig	    op != ASSIGN && op != RETURN && op != INIT) {
5601.172Srillig		rn = promote(op, false, rn);
5611.1Scgd	}
5621.1Scgd
5631.1Scgd	/*
5641.1Scgd	 * If the result of the operation is different for signed or
5651.1Scgd	 * unsigned operands and one of the operands is signed only in
5661.1Scgd	 * ANSI C, print a warning.
5671.1Scgd	 */
5681.164Srillig	if (mp->m_warn_if_left_unsigned_in_c90 &&
5691.289Srillig	    ln->tn_op == CON && ln->tn_val->v_unsigned_since_c90) {
5701.1Scgd		/* ANSI C treats constant as unsigned, op %s */
5711.1Scgd		warning(218, mp->m_name);
5721.289Srillig		ln->tn_val->v_unsigned_since_c90 = false;
5731.1Scgd	}
5741.164Srillig	if (mp->m_warn_if_right_unsigned_in_c90 &&
5751.289Srillig	    rn->tn_op == CON && rn->tn_val->v_unsigned_since_c90) {
5761.1Scgd		/* ANSI C treats constant as unsigned, op %s */
5771.1Scgd		warning(218, mp->m_name);
5781.289Srillig		rn->tn_val->v_unsigned_since_c90 = false;
5791.1Scgd	}
5801.1Scgd
5811.1Scgd	/* Make sure both operands are of the same type */
5821.164Srillig	if (mp->m_balance_operands || (tflag && (op == SHL || op == SHR)))
5831.1Scgd		balance(op, &ln, &rn);
5841.1Scgd
5851.1Scgd	/*
5861.1Scgd	 * Check types for compatibility with the operation and mutual
5871.106Srillig	 * compatibility. Return if there are serious problems.
5881.1Scgd	 */
5891.1Scgd	if (!typeok(op, 0, ln, rn))
5901.95Srillig		return NULL;
5911.1Scgd
5921.1Scgd	/* And now create the node. */
5931.1Scgd	switch (op) {
5941.1Scgd	case POINT:
5951.1Scgd	case ARROW:
5961.395Srillig		ntn = build_struct_access(op, sys, ln, rn);
5971.1Scgd		break;
5981.1Scgd	case INCAFT:
5991.1Scgd	case DECAFT:
6001.1Scgd	case INCBEF:
6011.1Scgd	case DECBEF:
6021.395Srillig		ntn = build_prepost_incdec(op, sys, ln);
6031.1Scgd		break;
6041.169Srillig	case ADDR:
6051.395Srillig		ntn = build_address(sys, ln, false);
6061.1Scgd		break;
6071.170Srillig	case INDIR:
6081.395Srillig		ntn = new_tnode(INDIR, sys, ln->tn_type->t_subt, ln, NULL);
6091.1Scgd		break;
6101.1Scgd	case PLUS:
6111.1Scgd	case MINUS:
6121.395Srillig		ntn = build_plus_minus(op, sys, ln, rn);
6131.1Scgd		break;
6141.1Scgd	case SHL:
6151.1Scgd	case SHR:
6161.395Srillig		ntn = build_bit_shift(op, sys, ln, rn);
6171.1Scgd		break;
6181.1Scgd	case COLON:
6191.395Srillig		ntn = build_colon(sys, ln, rn);
6201.1Scgd		break;
6211.1Scgd	case ASSIGN:
6221.1Scgd	case MULASS:
6231.1Scgd	case DIVASS:
6241.1Scgd	case MODASS:
6251.1Scgd	case ADDASS:
6261.1Scgd	case SUBASS:
6271.1Scgd	case SHLASS:
6281.1Scgd	case SHRASS:
6291.1Scgd	case ANDASS:
6301.1Scgd	case XORASS:
6311.1Scgd	case ORASS:
6321.1Scgd	case RETURN:
6331.333Srillig	case INIT:
6341.395Srillig		ntn = build_assignment(op, sys, ln, rn);
6351.1Scgd		break;
6361.1Scgd	case COMMA:
6371.1Scgd	case QUEST:
6381.395Srillig		ntn = new_tnode(op, sys, rn->tn_type, ln, rn);
6391.1Scgd		break;
6401.46Schristos	case REAL:
6411.46Schristos	case IMAG:
6421.395Srillig		ntn = build_real_imag(op, sys, ln);
6431.46Schristos		break;
6441.1Scgd	default:
6451.219Srillig		rettp = mp->m_returns_bool
6461.151Srillig		    ? gettyp(Tflag ? BOOL : INT) : ln->tn_type;
6471.107Srillig		lint_assert(mp->m_binary || rn == NULL);
6481.395Srillig		ntn = new_tnode(op, sys, rettp, ln, rn);
6491.1Scgd		break;
6501.1Scgd	}
6511.1Scgd
6521.21Swiz	/* Return if an error occurred. */
6531.1Scgd	if (ntn == NULL)
6541.95Srillig		return NULL;
6551.1Scgd
6561.1Scgd	/* Print a warning if precedence confusion is possible */
6571.133Srillig	if (mp->m_possible_precedence_confusion)
6581.100Srillig		check_precedence_confusion(ntn);
6591.1Scgd
6601.1Scgd	/*
6611.1Scgd	 * Print a warning if one of the operands is in a context where
6621.1Scgd	 * it is compared with null and if this operand is a constant.
6631.1Scgd	 */
6641.164Srillig	if (mp->m_left_test_context) {
6651.1Scgd		if (ln->tn_op == CON ||
6661.1Scgd		    ((mp->m_binary && op != QUEST) && rn->tn_op == CON)) {
6671.227Srillig			if (hflag && !constcond_flag &&
6681.227Srillig			    !ln->tn_system_dependent)
6691.1Scgd				/* constant in conditional context */
6701.1Scgd				warning(161);
6711.1Scgd		}
6721.1Scgd	}
6731.1Scgd
6741.1Scgd	/* Fold if the operator requires it */
6751.164Srillig	if (mp->m_fold_constant_operands) {
6761.1Scgd		if (ln->tn_op == CON && (!mp->m_binary || rn->tn_op == CON)) {
6771.164Srillig			if (mp->m_left_test_context) {
6781.100Srillig				ntn = fold_test(ntn);
6791.144Srillig			} else if (is_floating(ntn->tn_type->t_tspec)) {
6801.100Srillig				ntn = fold_float(ntn);
6811.1Scgd			} else {
6821.1Scgd				ntn = fold(ntn);
6831.1Scgd			}
6841.1Scgd		} else if (op == QUEST && ln->tn_op == CON) {
6851.154Srillig			ntn = ln->tn_val->v_quad != 0
6861.154Srillig			    ? rn->tn_left : rn->tn_right;
6871.1Scgd		}
6881.1Scgd	}
6891.1Scgd
6901.95Srillig	return ntn;
6911.1Scgd}
6921.1Scgd
6931.314Srilligtnode_t *
6941.395Srilligbuild_unary(op_t op, bool sys, tnode_t *tn)
6951.317Srillig{
6961.395Srillig	return build_binary(tn, op, sys, NULL);
6971.317Srillig}
6981.317Srillig
6991.317Srilligtnode_t *
7001.395Srilligbuild_member_access(tnode_t *ln, op_t op, bool sys, sbuf_t *member)
7011.314Srillig{
7021.314Srillig	sym_t	*msym;
7031.314Srillig
7041.314Srillig	if (ln == NULL)
7051.314Srillig		return NULL;
7061.314Srillig
7071.314Srillig	if (op == ARROW) {
7081.314Srillig		/* must do this before struct_or_union_member is called */
7091.314Srillig		ln = cconv(ln);
7101.314Srillig	}
7111.314Srillig	msym = struct_or_union_member(ln, op, getsym(member));
7121.399Srillig	return build_binary(ln, op, sys, build_name(msym, false));
7131.314Srillig}
7141.314Srillig
7151.1Scgd/*
7161.1Scgd * Perform class conversions.
7171.1Scgd *
7181.1Scgd * Arrays of type T are converted into pointers to type T.
7191.1Scgd * Functions are converted to pointers to functions.
7201.1Scgd * Lvalues are converted to rvalues.
7211.231Srillig *
7221.231Srillig * C99 6.3 "Conversions"
7231.231Srillig * C99 6.3.2 "Other operands"
7241.231Srillig * C99 6.3.2.1 "Lvalues, arrays, and function designators"
7251.1Scgd */
7261.1Scgdtnode_t *
7271.20Slukemcconv(tnode_t *tn)
7281.1Scgd{
7291.1Scgd	type_t	*tp;
7301.1Scgd
7311.1Scgd	/*
7321.1Scgd	 * Array-lvalue (array of type T) is converted into rvalue
7331.1Scgd	 * (pointer to type T)
7341.1Scgd	 */
7351.1Scgd	if (tn->tn_type->t_tspec == ARRAY) {
7361.1Scgd		if (!tn->tn_lvalue) {
7371.118Srillig			/* XXX print correct operator */
7381.1Scgd			/* %soperand of '%s' must be lvalue */
7391.261Srillig			gnuism(114, "", op_name(ADDR));
7401.1Scgd		}
7411.395Srillig		tn = new_tnode(ADDR, tn->tn_sys,
7421.257Srillig		    expr_derive_type(tn->tn_type->t_subt, PTR), tn, NULL);
7431.1Scgd	}
7441.1Scgd
7451.1Scgd	/*
7461.1Scgd	 * Expression of type function (function with return value of type T)
7471.1Scgd	 * in rvalue-expression (pointer to function with return value
7481.1Scgd	 * of type T)
7491.1Scgd	 */
7501.1Scgd	if (tn->tn_type->t_tspec == FUNC)
7511.395Srillig		tn = build_address(tn->tn_sys, tn, true);
7521.1Scgd
7531.1Scgd	/* lvalue to rvalue */
7541.1Scgd	if (tn->tn_lvalue) {
7551.258Srillig		tp = expr_dup_type(tn->tn_type);
7561.312Srillig		/* C99 6.3.2.1p2 sentence 2 says to remove the qualifiers. */
7571.154Srillig		tp->t_const = tp->t_volatile = false;
7581.395Srillig		tn = new_tnode(LOAD, tn->tn_sys, tp, tn, NULL);
7591.1Scgd	}
7601.1Scgd
7611.95Srillig	return tn;
7621.1Scgd}
7631.1Scgd
7641.266Srilligconst tnode_t *
7651.151Srilligbefore_conversion(const tnode_t *tn)
7661.151Srillig{
7671.151Srillig	while (tn->tn_op == CVT && !tn->tn_cast)
7681.151Srillig		tn = tn->tn_left;
7691.151Srillig	return tn;
7701.151Srillig}
7711.151Srillig
7721.190Srilligstatic bool
7731.190Srilligis_null_pointer(const tnode_t *tn)
7741.190Srillig{
7751.190Srillig	tspec_t t = tn->tn_type->t_tspec;
7761.190Srillig
7771.190Srillig	return ((t == PTR && tn->tn_type->t_subt->t_tspec == VOID) ||
7781.190Srillig		is_integer(t))
7791.190Srillig	       && (tn->tn_op == CON && tn->tn_val->v_quad == 0);
7801.190Srillig}
7811.190Srillig
7821.375Srillig/*
7831.375Srillig * Most errors required by ANSI C are reported in struct_or_union_member().
7841.375Srillig * Here we only check for totally wrong things.
7851.375Srillig */
7861.375Srilligstatic bool
7871.375Srilligtypeok_point(const tnode_t *ln, const type_t *ltp, tspec_t lt)
7881.375Srillig{
7891.375Srillig	if (lt == FUNC || lt == VOID || ltp->t_bitfield ||
7901.375Srillig	    ((lt != STRUCT && lt != UNION) && !ln->tn_lvalue)) {
7911.375Srillig		/* Without tflag we got already an error */
7921.375Srillig		if (tflag)
7931.375Srillig			/* unacceptable operand of '%s' */
7941.375Srillig			error(111, op_name(POINT));
7951.375Srillig		return false;
7961.375Srillig	}
7971.375Srillig	return true;
7981.375Srillig}
7991.375Srillig
8001.375Srilligstatic bool
8011.375Srilligtypeok_arrow(tspec_t lt)
8021.375Srillig{
8031.375Srillig	if (lt == PTR || (tflag && is_integer(lt)))
8041.375Srillig		return true;
8051.375Srillig
8061.375Srillig	/* Without tflag we got already an error */
8071.375Srillig	if (tflag)
8081.375Srillig		/* unacceptable operand of '%s' */
8091.375Srillig		error(111, op_name(ARROW));
8101.375Srillig	return false;
8111.375Srillig}
8121.375Srillig
8131.138Srilligstatic bool
8141.261Srilligtypeok_incdec(op_t op, const tnode_t *tn, const type_t *tp)
8151.138Srillig{
8161.138Srillig	/* operand has scalar type (checked in typeok) */
8171.149Srillig	if (!tn->tn_lvalue) {
8181.149Srillig		if (tn->tn_op == CVT && tn->tn_cast &&
8191.149Srillig		    tn->tn_left->tn_op == LOAD) {
8201.138Srillig			/* a cast does not yield an lvalue */
8211.138Srillig			error(163);
8221.138Srillig		}
8231.138Srillig		/* %soperand of '%s' must be lvalue */
8241.261Srillig		error(114, "", op_name(op));
8251.138Srillig		return false;
8261.149Srillig	} else if (tp->t_const) {
8271.138Srillig		if (!tflag)
8281.176Srillig			/* %soperand of '%s' must be modifiable lvalue */
8291.261Srillig			warning(115, "", op_name(op));
8301.138Srillig	}
8311.138Srillig	return true;
8321.138Srillig}
8331.138Srillig
8341.139Srilligstatic bool
8351.180Srilligtypeok_address(const mod_t *mp,
8361.342Srillig	       const tnode_t *tn, const type_t *tp, tspec_t t)
8371.139Srillig{
8381.149Srillig	if (t == ARRAY || t == FUNC) {
8391.168Srillig		/* ok, a warning comes later (in build_address()) */
8401.149Srillig	} else if (!tn->tn_lvalue) {
8411.149Srillig		if (tn->tn_op == CVT && tn->tn_cast &&
8421.149Srillig		    tn->tn_left->tn_op == LOAD) {
8431.139Srillig			/* a cast does not yield an lvalue */
8441.139Srillig			error(163);
8451.139Srillig		}
8461.139Srillig		/* %soperand of '%s' must be lvalue */
8471.139Srillig		error(114, "", mp->m_name);
8481.139Srillig		return false;
8491.149Srillig	} else if (is_scalar(t)) {
8501.149Srillig		if (tp->t_bitfield) {
8511.139Srillig			/* cannot take address of bit-field */
8521.139Srillig			error(112);
8531.139Srillig			return false;
8541.139Srillig		}
8551.149Srillig	} else if (t != STRUCT && t != UNION) {
8561.139Srillig		/* unacceptable operand of '%s' */
8571.139Srillig		error(111, mp->m_name);
8581.139Srillig		return false;
8591.139Srillig	}
8601.149Srillig	if (tn->tn_op == NAME && tn->tn_sym->s_reg) {
8611.139Srillig		/* cannot take address of register %s */
8621.149Srillig		error(113, tn->tn_sym->s_name);
8631.139Srillig		return false;
8641.139Srillig	}
8651.139Srillig	return true;
8661.139Srillig}
8671.139Srillig
8681.140Srilligstatic bool
8691.375Srilligtypeok_indir(tspec_t t)
8701.140Srillig{
8711.140Srillig	/* until now there were no type checks for this operator */
8721.149Srillig	if (t != PTR) {
8731.140Srillig		/* cannot dereference non-pointer type */
8741.140Srillig		error(96);
8751.140Srillig		return false;
8761.140Srillig	}
8771.140Srillig	return true;
8781.140Srillig}
8791.140Srillig
8801.140Srilligstatic bool
8811.246Srilligtypeok_plus(op_t op,
8821.246Srillig	    const type_t *ltp, tspec_t lt,
8831.246Srillig	    const type_t *rtp, tspec_t rt)
8841.140Srillig{
8851.140Srillig	/* operands have scalar types (checked above) */
8861.144Srillig	if ((lt == PTR && !is_integer(rt)) || (rt == PTR && !is_integer(lt))) {
8871.246Srillig		warn_incompatible_types(op, ltp, lt, rtp, rt);
8881.140Srillig		return false;
8891.140Srillig	}
8901.140Srillig	return true;
8911.140Srillig}
8921.140Srillig
8931.140Srilligstatic bool
8941.149Srilligtypeok_minus(op_t op,
8951.149Srillig	     const type_t *ltp, tspec_t lt,
8961.149Srillig	     const type_t *rtp, tspec_t rt)
8971.140Srillig{
8981.140Srillig	/* operands have scalar types (checked above) */
8991.144Srillig	if (lt == PTR && (!is_integer(rt) && rt != PTR)) {
9001.246Srillig		warn_incompatible_types(op, ltp, lt, rtp, rt);
9011.140Srillig		return false;
9021.140Srillig	} else if (rt == PTR && lt != PTR) {
9031.246Srillig		warn_incompatible_types(op, ltp, lt, rtp, rt);
9041.140Srillig		return false;
9051.140Srillig	}
9061.140Srillig	if (lt == PTR && rt == PTR) {
9071.172Srillig		if (!eqtype(ltp->t_subt, rtp->t_subt, true, false, NULL)) {
9081.140Srillig			/* illegal pointer subtraction */
9091.140Srillig			error(116);
9101.140Srillig		}
9111.140Srillig	}
9121.140Srillig	return true;
9131.140Srillig}
9141.140Srillig
9151.140Srilligstatic void
9161.149Srilligtypeok_shr(const mod_t *mp,
9171.149Srillig	   const tnode_t *ln, tspec_t lt,
9181.149Srillig	   const tnode_t *rn, tspec_t rt)
9191.140Srillig{
9201.143Srillig	tspec_t olt, ort;
9211.143Srillig
9221.151Srillig	olt = before_conversion(ln)->tn_type->t_tspec;
9231.151Srillig	ort = before_conversion(rn)->tn_type->t_tspec;
9241.143Srillig
9251.140Srillig	/* operands have integer types (checked above) */
9261.335Srillig	if (pflag && !is_uinteger(olt)) {
9271.140Srillig		/*
9281.140Srillig		 * The left operand is signed. This means that
9291.140Srillig		 * the operation is (possibly) nonportable.
9301.140Srillig		 */
9311.140Srillig		if (ln->tn_op != CON) {
9321.200Srillig			/* bitwise '%s' on signed value possibly nonportable */
9331.200Srillig			warning(117, mp->m_name);
9341.140Srillig		} else if (ln->tn_val->v_quad < 0) {
9351.200Srillig			/* bitwise '%s' on signed value nonportable */
9361.200Srillig			warning(120, mp->m_name);
9371.140Srillig		}
9381.144Srillig	} else if (!tflag && !sflag && !is_uinteger(olt) && is_uinteger(ort)) {
9391.140Srillig		/*
9401.140Srillig		 * The left operand would become unsigned in
9411.140Srillig		 * traditional C.
9421.140Srillig		 */
9431.271Srillig		if (hflag && !Sflag &&
9441.140Srillig		    (ln->tn_op != CON || ln->tn_val->v_quad < 0)) {
9451.177Srillig			/* semantics of '%s' change in ANSI C; use ... */
9461.140Srillig			warning(118, mp->m_name);
9471.140Srillig		}
9481.144Srillig	} else if (!tflag && !sflag && !is_uinteger(olt) && !is_uinteger(ort) &&
9491.228Srillig		   portable_size_in_bits(lt) < portable_size_in_bits(rt)) {
9501.140Srillig		/*
9511.140Srillig		 * In traditional C the left operand would be extended,
9521.140Srillig		 * possibly with 1, and then shifted.
9531.140Srillig		 */
9541.271Srillig		if (hflag && !Sflag &&
9551.140Srillig		    (ln->tn_op != CON || ln->tn_val->v_quad < 0)) {
9561.140Srillig			/* semantics of '%s' change in ANSI C; use ... */
9571.140Srillig			warning(118, mp->m_name);
9581.140Srillig		}
9591.140Srillig	}
9601.140Srillig}
9611.140Srillig
9621.140Srilligstatic void
9631.182Srilligtypeok_shl(const mod_t *mp, tspec_t lt, tspec_t rt)
9641.182Srillig{
9651.140Srillig	/*
9661.182Srillig	 * C90 does not perform balancing for shift operations,
9671.140Srillig	 * but traditional C does. If the width of the right operand
9681.182Srillig	 * is greater than the width of the left operand, then in
9691.140Srillig	 * traditional C the left operand would be extended to the
9701.140Srillig	 * width of the right operand. For SHL this may result in
9711.140Srillig	 * different results.
9721.140Srillig	 */
9731.228Srillig	if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) {
9741.140Srillig		/*
9751.140Srillig		 * XXX If both operands are constant, make sure
9761.140Srillig		 * that there is really a difference between
9771.140Srillig		 * ANSI C and traditional C.
9781.140Srillig		 */
9791.271Srillig		if (hflag && !Sflag)
9801.140Srillig			/* semantics of '%s' change in ANSI C; use ... */
9811.140Srillig			warning(118, mp->m_name);
9821.140Srillig	}
9831.140Srillig}
9841.140Srillig
9851.140Srilligstatic void
9861.149Srilligtypeok_shift(tspec_t lt, const tnode_t *rn, tspec_t rt)
9871.140Srillig{
9881.270Srillig	if (rn->tn_op != CON)
9891.270Srillig		return;
9901.270Srillig
9911.270Srillig	if (!is_uinteger(rt) && rn->tn_val->v_quad < 0) {
9921.270Srillig		/* negative shift */
9931.270Srillig		warning(121);
9941.270Srillig	} else if ((uint64_t)rn->tn_val->v_quad ==
9951.270Srillig		   (uint64_t)size_in_bits(lt)) {
9961.270Srillig		/* shift equal to size of object */
9971.270Srillig		warning(267);
9981.270Srillig	} else if ((uint64_t)rn->tn_val->v_quad > (uint64_t)size_in_bits(lt)) {
9991.270Srillig		/* shift amount %llu is greater than bit-size %llu of '%s' */
10001.270Srillig		warning(122, (unsigned long long)rn->tn_val->v_quad,
10011.270Srillig		    (unsigned long long)size_in_bits(lt),
10021.270Srillig		    tspec_name(lt));
10031.140Srillig	}
10041.140Srillig}
10051.140Srillig
10061.140Srilligstatic bool
10071.187Srilligis_typeok_eq(const tnode_t *ln, tspec_t lt, const tnode_t *rn, tspec_t rt)
10081.140Srillig{
10091.190Srillig	if (lt == PTR && is_null_pointer(rn))
10101.190Srillig		return true;
10111.190Srillig	if (rt == PTR && is_null_pointer(ln))
10121.190Srillig		return true;
10131.140Srillig	return false;
10141.140Srillig}
10151.140Srillig
10161.140Srilligstatic bool
10171.375Srilligtypeok_compare(op_t op,
10181.375Srillig	       const tnode_t *ln, const type_t *ltp, tspec_t lt,
10191.375Srillig	       const tnode_t *rn, const type_t *rtp, tspec_t rt)
10201.140Srillig{
10211.392Srillig	const char *lx, *rx;
10221.392Srillig
10231.178Srillig	if (lt == PTR && rt == PTR) {
10241.140Srillig		check_pointer_comparison(op, ln, rn);
10251.178Srillig		return true;
10261.140Srillig	}
10271.178Srillig
10281.178Srillig	if (lt != PTR && rt != PTR)
10291.178Srillig		return true;
10301.178Srillig
10311.178Srillig	if (!is_integer(lt) && !is_integer(rt)) {
10321.246Srillig		warn_incompatible_types(op, ltp, lt, rtp, rt);
10331.178Srillig		return false;
10341.178Srillig	}
10351.178Srillig
10361.392Srillig	lx = lt == PTR ? "pointer" : "integer";
10371.392Srillig	rx = rt == PTR ? "pointer" : "integer";
10381.396Srillig	/* illegal combination of %s '%s' and %s '%s', op '%s' */
10391.260Srillig	warning(123, lx, type_name(ltp), rx, type_name(rtp), op_name(op));
10401.140Srillig	return true;
10411.140Srillig}
10421.140Srillig
10431.140Srilligstatic bool
10441.373Srilligtypeok_quest(tspec_t lt, const tnode_t *rn)
10451.140Srillig{
10461.144Srillig	if (!is_scalar(lt)) {
10471.140Srillig		/* first operand must have scalar type, op ? : */
10481.140Srillig		error(170);
10491.140Srillig		return false;
10501.140Srillig	}
10511.373Srillig	lint_assert(before_conversion(rn)->tn_op == COLON);
10521.140Srillig	return true;
10531.140Srillig}
10541.140Srillig
10551.206Srilligstatic void
10561.212Srilligtypeok_colon_pointer(const mod_t *mp, const type_t *ltp, const type_t *rtp)
10571.206Srillig{
10581.206Srillig	type_t *lstp = ltp->t_subt;
10591.206Srillig	type_t *rstp = rtp->t_subt;
10601.206Srillig	tspec_t lst = lstp->t_tspec;
10611.206Srillig	tspec_t rst = rstp->t_tspec;
10621.206Srillig
10631.206Srillig	if ((lst == VOID && rst == FUNC) || (lst == FUNC && rst == VOID)) {
10641.206Srillig		/* (void *)0 handled above */
10651.206Srillig		if (sflag)
10661.377Srillig			/* ANSI C forbids conversion of %s to %s, op %s */
10671.206Srillig			warning(305, "function pointer", "'void *'",
10681.206Srillig			    mp->m_name);
10691.206Srillig		return;
10701.206Srillig	}
10711.206Srillig
10721.206Srillig	if (eqptrtype(lstp, rstp, true))
10731.206Srillig		return;
10741.206Srillig	if (!eqtype(lstp, rstp, true, false, NULL))
10751.206Srillig		warn_incompatible_pointers(mp, ltp, rtp);
10761.206Srillig}
10771.206Srillig
10781.140Srilligstatic bool
10791.149Srilligtypeok_colon(const mod_t *mp,
10801.149Srillig	     const tnode_t *ln, const type_t *ltp, tspec_t lt,
10811.149Srillig	     const tnode_t *rn, const type_t *rtp, tspec_t rt)
10821.140Srillig{
10831.142Srillig
10841.144Srillig	if (is_arithmetic(lt) && is_arithmetic(rt))
10851.140Srillig		return true;
10861.165Srillig	if (lt == BOOL && rt == BOOL)
10871.165Srillig		return true;
10881.140Srillig
10891.140Srillig	if (lt == STRUCT && rt == STRUCT && ltp->t_str == rtp->t_str)
10901.140Srillig		return true;
10911.140Srillig	if (lt == UNION && rt == UNION && ltp->t_str == rtp->t_str)
10921.140Srillig		return true;
10931.140Srillig
10941.190Srillig	if (lt == PTR && is_null_pointer(rn))
10951.190Srillig		return true;
10961.190Srillig	if (rt == PTR && is_null_pointer(ln))
10971.190Srillig		return true;
10981.140Srillig
10991.144Srillig	if ((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR)) {
11001.342Srillig		const char *lx = lt == PTR ? "pointer" : "integer";
11011.342Srillig		const char *rx = rt == PTR ? "pointer" : "integer";
11021.396Srillig		/* illegal combination of %s '%s' and %s '%s', op '%s' */
11031.140Srillig		warning(123, lx, type_name(ltp),
11041.140Srillig		    rx, type_name(rtp), mp->m_name);
11051.140Srillig		return true;
11061.140Srillig	}
11071.140Srillig
11081.140Srillig	if (lt == VOID || rt == VOID) {
11091.140Srillig		if (lt != VOID || rt != VOID)
11101.179Srillig			/* incompatible types '%s' and '%s' in conditional */
11111.179Srillig			warning(126, type_name(ltp), type_name(rtp));
11121.140Srillig		return true;
11131.140Srillig	}
11141.140Srillig
11151.206Srillig	if (lt == PTR && rt == PTR) {
11161.212Srillig		typeok_colon_pointer(mp, ltp, rtp);
11171.140Srillig		return true;
11181.140Srillig	}
11191.140Srillig
11201.179Srillig	/* incompatible types '%s' and '%s' in conditional */
11211.179Srillig	error(126, type_name(ltp), type_name(rtp));
11221.140Srillig	return false;
11231.140Srillig}
11241.140Srillig
11251.140Srilligstatic bool
11261.332Srilligtypeok_assign(op_t op, const tnode_t *ln, const type_t *ltp, tspec_t lt)
11271.140Srillig{
11281.332Srillig	if (op == RETURN || op == INIT || op == FARG)
11291.332Srillig		return true;
11301.332Srillig
11311.140Srillig	if (!ln->tn_lvalue) {
11321.140Srillig		if (ln->tn_op == CVT && ln->tn_cast &&
11331.140Srillig		    ln->tn_left->tn_op == LOAD) {
11341.140Srillig			/* a cast does not yield an lvalue */
11351.140Srillig			error(163);
11361.140Srillig		}
11371.140Srillig		/* %soperand of '%s' must be lvalue */
11381.332Srillig		error(114, "left ", op_name(op));
11391.140Srillig		return false;
11401.140Srillig	} else if (ltp->t_const || ((lt == STRUCT || lt == UNION) &&
11411.140Srillig				    has_constant_member(ltp))) {
11421.140Srillig		if (!tflag)
11431.140Srillig			/* %soperand of '%s' must be modifiable lvalue */
11441.332Srillig			warning(115, "left ", op_name(op));
11451.140Srillig	}
11461.140Srillig	return true;
11471.140Srillig}
11481.140Srillig
11491.150Srillig/* Check the types using the information from modtab[]. */
11501.150Srilligstatic bool
11511.246Srilligtypeok_scalar(op_t op, const mod_t *mp,
11521.246Srillig	      const type_t *ltp, tspec_t lt,
11531.246Srillig	      const type_t *rtp, tspec_t rt)
11541.1Scgd{
11551.165Srillig	if (mp->m_takes_bool && lt == BOOL && rt == BOOL)
11561.165Srillig		return true;
11571.93Srillig	if (mp->m_requires_integer) {
11581.144Srillig		if (!is_integer(lt) || (mp->m_binary && !is_integer(rt))) {
11591.246Srillig			warn_incompatible_types(op, ltp, lt, rtp, rt);
11601.141Srillig			return false;
11611.1Scgd		}
11621.93Srillig	} else if (mp->m_requires_integer_or_complex) {
11631.144Srillig		if ((!is_integer(lt) && !is_complex(lt)) ||
11641.144Srillig		    (mp->m_binary && (!is_integer(rt) && !is_complex(rt)))) {
11651.246Srillig			warn_incompatible_types(op, ltp, lt, rtp, rt);
11661.141Srillig			return false;
11671.46Schristos		}
11681.93Srillig	} else if (mp->m_requires_scalar) {
11691.144Srillig		if (!is_scalar(lt) || (mp->m_binary && !is_scalar(rt))) {
11701.246Srillig			warn_incompatible_types(op, ltp, lt, rtp, rt);
11711.141Srillig			return false;
11721.1Scgd		}
11731.93Srillig	} else if (mp->m_requires_arith) {
11741.144Srillig		if (!is_arithmetic(lt) ||
11751.144Srillig		    (mp->m_binary && !is_arithmetic(rt))) {
11761.246Srillig			warn_incompatible_types(op, ltp, lt, rtp, rt);
11771.141Srillig			return false;
11781.1Scgd		}
11791.1Scgd	}
11801.150Srillig	return true;
11811.150Srillig}
11821.1Scgd
11831.375Srillig/*
11841.375Srillig * Check the types for specific operators and type combinations.
11851.375Srillig *
11861.375Srillig * At this point, the operands already conform to the type requirements of
11871.375Srillig * the operator, such as being integer, floating or scalar.
11881.375Srillig */
11891.150Srilligstatic bool
11901.150Srilligtypeok_op(op_t op, const mod_t *mp, int arg,
11911.150Srillig	  const tnode_t *ln, const type_t *ltp, tspec_t lt,
11921.150Srillig	  const tnode_t *rn, const type_t *rtp, tspec_t rt)
11931.150Srillig{
11941.1Scgd	switch (op) {
11951.376Srillig	case ARROW:
11961.376Srillig		return typeok_arrow(lt);
11971.1Scgd	case POINT:
11981.375Srillig		return typeok_point(ln, ltp, lt);
11991.376Srillig	case INCBEF:
12001.376Srillig	case DECBEF:
12011.1Scgd	case INCAFT:
12021.1Scgd	case DECAFT:
12031.374Srillig		return typeok_incdec(op, ln, ltp);
12041.376Srillig	case INDIR:
12051.376Srillig		return typeok_indir(lt);
12061.169Srillig	case ADDR:
12071.374Srillig		return typeok_address(mp, ln, ltp, lt);
12081.1Scgd	case PLUS:
12091.374Srillig		return typeok_plus(op, ltp, lt, rtp, rt);
12101.1Scgd	case MINUS:
12111.374Srillig		return typeok_minus(op, ltp, lt, rtp, rt);
12121.376Srillig	case SHL:
12131.376Srillig		typeok_shl(mp, lt, rt);
12141.376Srillig		goto shift;
12151.1Scgd	case SHR:
12161.143Srillig		typeok_shr(mp, ln, lt, rn, rt);
12171.1Scgd	shift:
12181.140Srillig		typeok_shift(lt, rn, rt);
12191.1Scgd		break;
12201.376Srillig	case LT:
12211.376Srillig	case LE:
12221.376Srillig	case GT:
12231.376Srillig	case GE:
12241.376Srillig	compare:
12251.376Srillig		return typeok_compare(op, ln, ltp, lt, rn, rtp, rt);
12261.1Scgd	case EQ:
12271.1Scgd	case NE:
12281.187Srillig		if (is_typeok_eq(ln, lt, rn, rt))
12291.140Srillig			break;
12301.376Srillig		goto compare;
12311.1Scgd	case QUEST:
12321.374Srillig		return typeok_quest(lt, rn);
12331.1Scgd	case COLON:
12341.374Srillig		return typeok_colon(mp, ln, ltp, lt, rn, rtp, rt);
12351.1Scgd	case ASSIGN:
12361.1Scgd	case INIT:
12371.1Scgd	case FARG:
12381.1Scgd	case RETURN:
12391.100Srillig		if (!check_assign_types_compatible(op, arg, ln, rn))
12401.141Srillig			return false;
12411.1Scgd		goto assign;
12421.1Scgd	case MULASS:
12431.1Scgd	case DIVASS:
12441.1Scgd	case MODASS:
12451.1Scgd		goto assign;
12461.1Scgd	case ADDASS:
12471.1Scgd	case SUBASS:
12481.144Srillig		if ((lt == PTR && !is_integer(rt)) || rt == PTR) {
12491.246Srillig			warn_incompatible_types(op, ltp, lt, rtp, rt);
12501.141Srillig			return false;
12511.1Scgd		}
12521.1Scgd		goto assign;
12531.1Scgd	case SHLASS:
12541.1Scgd		goto assign;
12551.1Scgd	case SHRASS:
12561.144Srillig		if (pflag && !is_uinteger(lt) && !(tflag && is_uinteger(rt))) {
12571.200Srillig			/* bitwise '%s' on signed value possibly nonportable */
12581.200Srillig			warning(117, mp->m_name);
12591.1Scgd		}
12601.1Scgd		goto assign;
12611.1Scgd	case ANDASS:
12621.1Scgd	case XORASS:
12631.1Scgd	case ORASS:
12641.1Scgd	assign:
12651.374Srillig		return typeok_assign(op, ln, ltp, lt);
12661.1Scgd	case COMMA:
12671.164Srillig		if (!modtab[ln->tn_op].m_has_side_effect)
12681.100Srillig			check_null_effect(ln);
12691.1Scgd		break;
12701.375Srillig	default:
12711.14Schristos		break;
12721.1Scgd	}
12731.150Srillig	return true;
12741.150Srillig}
12751.1Scgd
12761.150Srilligstatic void
12771.150Srilligtypeok_enum(op_t op, const mod_t *mp, int arg,
12781.150Srillig	    const tnode_t *ln, const type_t *ltp,
12791.150Srillig	    const tnode_t *rn, const type_t *rtp)
12801.150Srillig{
12811.93Srillig	if (mp->m_bad_on_enum &&
12821.209Srillig	    (ltp->t_is_enum || (mp->m_binary && rtp->t_is_enum))) {
12831.100Srillig		check_bad_enum_operation(op, ln, rn);
12841.93Srillig	} else if (mp->m_valid_on_enum &&
12851.209Srillig		   (ltp->t_is_enum && rtp != NULL && rtp->t_is_enum)) {
12861.100Srillig		check_enum_type_mismatch(op, arg, ln, rn);
12871.93Srillig	} else if (mp->m_valid_on_enum &&
12881.209Srillig		   (ltp->t_is_enum || (rtp != NULL && rtp->t_is_enum))) {
12891.100Srillig		check_enum_int_mismatch(op, arg, ln, rn);
12901.1Scgd	}
12911.150Srillig}
12921.150Srillig
12931.150Srillig/* Perform most type checks. Return whether the types are ok. */
12941.150Srilligbool
12951.150Srilligtypeok(op_t op, int arg, const tnode_t *ln, const tnode_t *rn)
12961.150Srillig{
12971.240Srillig	const mod_t *mp;
12981.150Srillig	tspec_t	lt, rt;
12991.150Srillig	type_t	*ltp, *rtp;
13001.150Srillig
13011.150Srillig	mp = &modtab[op];
13021.150Srillig
13031.150Srillig	lint_assert((ltp = ln->tn_type) != NULL);
13041.150Srillig	lt = ltp->t_tspec;
13051.150Srillig
13061.150Srillig	if (mp->m_binary) {
13071.150Srillig		lint_assert((rtp = rn->tn_type) != NULL);
13081.150Srillig		rt = rtp->t_tspec;
13091.150Srillig	} else {
13101.150Srillig		rtp = NULL;
13111.150Srillig		rt = NOTSPEC;
13121.150Srillig	}
13131.150Srillig
13141.151Srillig	if (Tflag && !typeok_scalar_strict_bool(op, mp, arg, ln, rn))
13151.151Srillig		return false;
13161.246Srillig	if (!typeok_scalar(op, mp, ltp, lt, rtp, rt))
13171.150Srillig		return false;
13181.150Srillig
13191.150Srillig	if (!typeok_op(op, mp, arg, ln, ltp, lt, rn, rtp, rt))
13201.150Srillig		return false;
13211.1Scgd
13221.150Srillig	typeok_enum(op, mp, arg, ln, ltp, rn, rtp);
13231.141Srillig	return true;
13241.1Scgd}
13251.1Scgd
13261.1Scgdstatic void
13271.149Srilligcheck_pointer_comparison(op_t op, const tnode_t *ln, const tnode_t *rn)
13281.1Scgd{
13291.1Scgd	type_t	*ltp, *rtp;
13301.187Srillig	tspec_t	lst, rst;
13311.188Srillig	const	char *lsts, *rsts;
13321.1Scgd
13331.187Srillig	lst = (ltp = ln->tn_type)->t_subt->t_tspec;
13341.187Srillig	rst = (rtp = rn->tn_type)->t_subt->t_tspec;
13351.1Scgd
13361.187Srillig	if (lst == VOID || rst == VOID) {
13371.187Srillig		if (sflag && (lst == FUNC || rst == FUNC)) {
13381.1Scgd			/* (void *)0 already handled in typeok() */
13391.188Srillig			*(lst == FUNC ? &lsts : &rsts) = "function pointer";
13401.188Srillig			*(lst == VOID ? &lsts : &rsts) = "'void *'";
13411.17Smycroft			/* ANSI C forbids comparison of %s with %s */
13421.188Srillig			warning(274, lsts, rsts);
13431.1Scgd		}
13441.1Scgd		return;
13451.1Scgd	}
13461.1Scgd
13471.172Srillig	if (!eqtype(ltp->t_subt, rtp->t_subt, true, false, NULL)) {
13481.98Srillig		warn_incompatible_pointers(&modtab[op], ltp, rtp);
13491.1Scgd		return;
13501.1Scgd	}
13511.1Scgd
13521.187Srillig	if (lst == FUNC && rst == FUNC) {
13531.1Scgd		if (sflag && op != EQ && op != NE)
13541.108Srillig			/* ANSI C forbids ordered comparisons of ... */
13551.1Scgd			warning(125);
13561.1Scgd	}
13571.1Scgd}
13581.1Scgd
13591.331Srilligstatic bool
13601.336Srilligis_direct_function_call(const tnode_t *tn, const char **out_name)
13611.331Srillig{
13621.336Srillig
13631.336Srillig	if (!(tn->tn_op == CALL &&
13641.336Srillig	      tn->tn_left->tn_op == ADDR &&
13651.336Srillig	      tn->tn_left->tn_left->tn_op == NAME))
13661.336Srillig		return false;
13671.336Srillig
13681.336Srillig	*out_name = tn->tn_left->tn_left->tn_sym->s_name;
13691.336Srillig	return true;
13701.336Srillig}
13711.336Srillig
13721.336Srilligstatic bool
13731.336Srilligis_unconst_function(const char *name)
13741.336Srillig{
13751.336Srillig
13761.336Srillig	return strcmp(name, "memchr") == 0 ||
13771.336Srillig	       strcmp(name, "strchr") == 0 ||
13781.336Srillig	       strcmp(name, "strpbrk") == 0 ||
13791.336Srillig	       strcmp(name, "strrchr") == 0 ||
13801.336Srillig	       strcmp(name, "strstr") == 0;
13811.331Srillig}
13821.331Srillig
13831.331Srilligstatic bool
13841.331Srilligis_const_char_pointer(const tnode_t *tn)
13851.331Srillig{
13861.331Srillig	const type_t *tp;
13871.331Srillig
13881.331Srillig	/*
13891.331Srillig	 * For traditional reasons, C99 6.4.5p5 defines that string literals
13901.331Srillig	 * have type 'char[]'.  They are often implicitly converted to
13911.331Srillig	 * 'char *', for example when they are passed as function arguments.
13921.331Srillig	 *
13931.331Srillig	 * C99 6.4.5p6 further defines that modifying a string that is
13941.331Srillig	 * constructed from a string literal invokes undefined behavior.
13951.331Srillig	 *
13961.331Srillig	 * Out of these reasons, string literals are treated as 'effectively
13971.331Srillig	 * const' here.
13981.331Srillig	 */
13991.331Srillig	if (tn->tn_op == CVT &&
14001.331Srillig	    tn->tn_left->tn_op == ADDR &&
14011.331Srillig	    tn->tn_left->tn_left->tn_op == STRING)
14021.331Srillig		return true;
14031.331Srillig
14041.331Srillig	tp = before_conversion(tn)->tn_type;
14051.331Srillig	return tp->t_tspec == PTR &&
14061.331Srillig	       tp->t_subt->t_tspec == CHAR &&
14071.331Srillig	       tp->t_subt->t_const;
14081.331Srillig}
14091.331Srillig
14101.331Srilligstatic bool
14111.384Srilligis_const_pointer(const tnode_t *tn)
14121.384Srillig{
14131.384Srillig	const type_t *tp;
14141.384Srillig
14151.384Srillig	tp = before_conversion(tn)->tn_type;
14161.384Srillig	return tp->t_tspec == PTR && tp->t_subt->t_const;
14171.384Srillig}
14181.384Srillig
14191.384Srilligstatic bool
14201.384Srilligis_first_arg_const_char_pointer(const tnode_t *tn)
14211.331Srillig{
14221.336Srillig	const tnode_t *an;
14231.336Srillig
14241.336Srillig	an = tn->tn_right;
14251.336Srillig	if (an == NULL)
14261.336Srillig		return false;
14271.336Srillig
14281.336Srillig	while (an->tn_right != NULL)
14291.336Srillig		an = an->tn_right;
14301.336Srillig	return is_const_char_pointer(an->tn_left);
14311.331Srillig}
14321.331Srillig
14331.384Srilligstatic bool
14341.384Srilligis_second_arg_const_pointer(const tnode_t *tn)
14351.384Srillig{
14361.384Srillig	const tnode_t *an;
14371.384Srillig
14381.384Srillig	an = tn->tn_right;
14391.384Srillig	if (an == NULL || an->tn_right == NULL)
14401.384Srillig		return false;
14411.384Srillig
14421.384Srillig	while (an->tn_right->tn_right != NULL)
14431.384Srillig		an = an->tn_right;
14441.384Srillig	return is_const_pointer(an->tn_left);
14451.384Srillig}
14461.384Srillig
14471.331Srilligstatic void
14481.378Srilligcheck_unconst_function(const type_t *lstp, const tnode_t *rn)
14491.331Srillig{
14501.336Srillig	const char *function_name;
14511.336Srillig
14521.331Srillig	if (lstp->t_tspec == CHAR && !lstp->t_const &&
14531.336Srillig	    is_direct_function_call(rn, &function_name) &&
14541.336Srillig	    is_unconst_function(function_name) &&
14551.384Srillig	    is_first_arg_const_char_pointer(rn)) {
14561.384Srillig		/* call to '%s' effectively discards 'const' from argument */
14571.384Srillig		warning(346, function_name);
14581.384Srillig	}
14591.384Srillig
14601.384Srillig	if (!lstp->t_const &&
14611.384Srillig	    is_direct_function_call(rn, &function_name) &&
14621.384Srillig	    strcmp(function_name, "bsearch") == 0 &&
14631.384Srillig	    is_second_arg_const_pointer(rn)) {
14641.331Srillig		/* call to '%s' effectively discards 'const' from argument */
14651.336Srillig		warning(346, function_name);
14661.331Srillig	}
14671.331Srillig}
14681.331Srillig
14691.369Srilligstatic void
14701.369Srilligcheck_assign_void_pointer(op_t op, int arg,
14711.369Srillig			  tspec_t lt, tspec_t lst,
14721.369Srillig			  tspec_t rt, tspec_t rst)
14731.1Scgd{
14741.369Srillig	const char *lts, *rts;
14751.1Scgd
14761.369Srillig	if (!(lt == PTR && rt == PTR && (lst == VOID || rst == VOID)))
14771.369Srillig		return;
14781.369Srillig	/* two pointers, at least one pointer to void */
14791.1Scgd
14801.369Srillig	if (!(sflag && (lst == FUNC || rst == FUNC)))
14811.369Srillig		return;
14821.369Srillig	/* comb. of ptr to func and ptr to void */
14831.148Srillig
14841.369Srillig	*(lst == FUNC ? &lts : &rts) = "function pointer";
14851.369Srillig	*(lst == VOID ? &lts : &rts) = "'void *'";
14861.1Scgd
14871.369Srillig	switch (op) {
14881.369Srillig	case INIT:
14891.369Srillig	case RETURN:
14901.369Srillig		/* ANSI C forbids conversion of %s to %s */
14911.369Srillig		warning(303, rts, lts);
14921.369Srillig		break;
14931.369Srillig	case FARG:
14941.377Srillig		/* ANSI C forbids conversion of %s to %s, arg #%d */
14951.369Srillig		warning(304, rts, lts, arg);
14961.369Srillig		break;
14971.369Srillig	default:
14981.377Srillig		/* ANSI C forbids conversion of %s to %s, op %s */
14991.369Srillig		warning(305, rts, lts, op_name(op));
15001.369Srillig		break;
15011.1Scgd	}
15021.369Srillig}
15031.1Scgd
15041.369Srilligstatic bool
15051.369Srilligcheck_assign_void_pointer_compat(op_t op, int arg,
15061.369Srillig				 const type_t *const ltp, tspec_t const lt,
15071.369Srillig				 const type_t *const lstp, tspec_t const lst,
15081.369Srillig				 const tnode_t *const rn,
15091.369Srillig				 const type_t *const rtp, tspec_t const rt,
15101.369Srillig				 const type_t *const rstp, tspec_t const rst)
15111.369Srillig{
15121.369Srillig	if (!(lt == PTR && rt == PTR && (lst == VOID || rst == VOID ||
15131.369Srillig					 eqtype(lstp, rstp, true, false, NULL))))
15141.369Srillig		return false;
15151.82Schristos
15161.369Srillig	/* compatible pointer types (qualifiers ignored) */
15171.369Srillig	if (!tflag &&
15181.369Srillig	    ((!lstp->t_const && rstp->t_const) ||
15191.369Srillig	     (!lstp->t_volatile && rstp->t_volatile))) {
15201.369Srillig		/* left side has not all qualifiers of right */
15211.1Scgd		switch (op) {
15221.1Scgd		case INIT:
15231.1Scgd		case RETURN:
15241.369Srillig			/* incompatible pointer types (%s != %s) */
15251.369Srillig			warning(182, type_name(lstp), type_name(rstp));
15261.1Scgd			break;
15271.1Scgd		case FARG:
15281.369Srillig			/* converting '%s' to incompatible '%s' ... */
15291.369Srillig			warning(153,
15301.369Srillig			    type_name(rtp), type_name(ltp), arg);
15311.1Scgd			break;
15321.1Scgd		default:
15331.369Srillig			/* operands have incompatible pointer type... */
15341.369Srillig			warning(128, op_name(op),
15351.369Srillig			    type_name(lstp), type_name(rstp));
15361.1Scgd			break;
15371.1Scgd		}
15381.1Scgd	}
15391.1Scgd
15401.369Srillig	if (!tflag)
15411.378Srillig		check_unconst_function(lstp, rn);
15421.369Srillig
15431.369Srillig	return true;
15441.369Srillig}
15451.369Srillig
15461.369Srilligstatic bool
15471.369Srilligcheck_assign_pointer_integer(op_t op, int arg,
15481.369Srillig			     const type_t *const ltp, tspec_t const lt,
15491.369Srillig			     const type_t *const rtp, tspec_t const rt)
15501.369Srillig{
15511.392Srillig	const char *lx, *rx;
15521.392Srillig
15531.369Srillig	if (!((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR)))
15541.369Srillig		return false;
15551.369Srillig
15561.392Srillig	lx = lt == PTR ? "pointer" : "integer";
15571.392Srillig	rx = rt == PTR ? "pointer" : "integer";
15581.369Srillig
15591.369Srillig	switch (op) {
15601.369Srillig	case INIT:
15611.369Srillig	case RETURN:
15621.369Srillig		/* illegal combination of %s (%s) and %s (%s) */
15631.369Srillig		warning(183, lx, type_name(ltp), rx, type_name(rtp));
15641.369Srillig		break;
15651.369Srillig	case FARG:
15661.377Srillig		/* illegal combination of %s (%s) and %s (%s), arg #%d */
15671.369Srillig		warning(154,
15681.369Srillig		    lx, type_name(ltp), rx, type_name(rtp), arg);
15691.369Srillig		break;
15701.369Srillig	default:
15711.396Srillig		/* illegal combination of %s '%s' and %s '%s', op '%s' */
15721.369Srillig		warning(123,
15731.369Srillig		    lx, type_name(ltp), rx, type_name(rtp), op_name(op));
15741.369Srillig		break;
15751.369Srillig	}
15761.369Srillig	return true;
15771.369Srillig}
15781.369Srillig
15791.369Srilligstatic bool
15801.369Srilligcheck_assign_pointer(op_t op, int arg,
15811.369Srillig		     const type_t *ltp, tspec_t lt,
15821.369Srillig		     const type_t *rtp, tspec_t rt)
15831.369Srillig{
15841.369Srillig	if (!(lt == PTR && rt == PTR))
15851.369Srillig		return false;
15861.369Srillig
15871.369Srillig	switch (op) {
15881.369Srillig	case RETURN:
15891.369Srillig		warn_incompatible_pointers(NULL, ltp, rtp);
15901.369Srillig		break;
15911.369Srillig	case FARG:
15921.369Srillig		/* converting '%s' to incompatible '%s' for ... */
15931.369Srillig		warning(153, type_name(rtp), type_name(ltp), arg);
15941.369Srillig		break;
15951.369Srillig	default:
15961.369Srillig		warn_incompatible_pointers(&modtab[op], ltp, rtp);
15971.369Srillig		break;
15981.1Scgd	}
15991.369Srillig	return true;
16001.369Srillig}
16011.1Scgd
16021.369Srilligstatic void
16031.369Srilligwarn_assign(op_t op, int arg,
16041.369Srillig	    const type_t *ltp, tspec_t lt,
16051.369Srillig	    const type_t *rtp, tspec_t rt)
16061.369Srillig{
16071.1Scgd	switch (op) {
16081.1Scgd	case INIT:
16091.234Srillig		/* cannot initialize '%s' from '%s' */
16101.115Srillig		error(185, type_name(ltp), type_name(rtp));
16111.1Scgd		break;
16121.1Scgd	case RETURN:
16131.108Srillig		/* return value type mismatch (%s) and (%s) */
16141.115Srillig		error(211, type_name(ltp), type_name(rtp));
16151.1Scgd		break;
16161.1Scgd	case FARG:
16171.293Srillig		/* passing '%s' to incompatible '%s', arg #%d */
16181.293Srillig		warning(155, type_name(rtp), type_name(ltp), arg);
16191.1Scgd		break;
16201.1Scgd	default:
16211.246Srillig		warn_incompatible_types(op, ltp, lt, rtp, rt);
16221.1Scgd		break;
16231.1Scgd	}
16241.369Srillig}
16251.369Srillig
16261.369Srillig/*
16271.369Srillig * Checks type compatibility for ASSIGN, INIT, FARG and RETURN
16281.369Srillig * and prints warnings/errors if necessary.
16291.369Srillig * Returns whether the types are (almost) compatible.
16301.369Srillig */
16311.369Srilligstatic bool
16321.369Srilligcheck_assign_types_compatible(op_t op, int arg,
16331.369Srillig			      const tnode_t *ln, const tnode_t *rn)
16341.369Srillig{
16351.369Srillig	tspec_t	lt, rt, lst = NOTSPEC, rst = NOTSPEC;
16361.369Srillig	type_t	*ltp, *rtp, *lstp = NULL, *rstp = NULL;
16371.369Srillig
16381.369Srillig	if ((lt = (ltp = ln->tn_type)->t_tspec) == PTR)
16391.369Srillig		lst = (lstp = ltp->t_subt)->t_tspec;
16401.369Srillig	if ((rt = (rtp = rn->tn_type)->t_tspec) == PTR)
16411.369Srillig		rst = (rstp = rtp->t_subt)->t_tspec;
16421.369Srillig
16431.369Srillig	if (lt == BOOL && is_scalar(rt))	/* C99 6.3.1.2 */
16441.369Srillig		return true;
16451.369Srillig
16461.369Srillig	if (is_arithmetic(lt) && (is_arithmetic(rt) || rt == BOOL))
16471.369Srillig		return true;
16481.369Srillig
16491.369Srillig	if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION))
16501.369Srillig		/* both are struct or union */
16511.369Srillig		return ltp->t_str == rtp->t_str;
16521.369Srillig
16531.369Srillig	/* a null pointer may be assigned to any pointer */
16541.369Srillig	if (lt == PTR && is_null_pointer(rn))
16551.369Srillig		return true;
16561.369Srillig
16571.369Srillig	check_assign_void_pointer(op, arg, lt, lst, rt, rst);
16581.369Srillig
16591.369Srillig	if (check_assign_void_pointer_compat(op, arg,
16601.369Srillig	    ltp, lt, lstp, lst, rn, rtp, rt, rstp, rst))
16611.369Srillig		return true;
16621.369Srillig
16631.369Srillig	if (check_assign_pointer_integer(op, arg, ltp, lt, rtp, rt))
16641.369Srillig		return true;
16651.369Srillig
16661.369Srillig	if (check_assign_pointer(op, arg, ltp, lt, rtp, rt))
16671.369Srillig		return true;
16681.1Scgd
16691.369Srillig	warn_assign(op, arg, ltp, lt, rtp, rt);
16701.154Srillig	return false;
16711.1Scgd}
16721.1Scgd
16731.182Srillig/* Prints a warning if a strange operator is used on an enum type. */
16741.1Scgdstatic void
16751.149Srilligcheck_bad_enum_operation(op_t op, const tnode_t *ln, const tnode_t *rn)
16761.1Scgd{
16771.1Scgd
16781.1Scgd	if (!eflag)
16791.1Scgd		return;
16801.1Scgd
16811.1Scgd	/*
16821.1Scgd	 * Enum as offset to a pointer is an exception (otherwise enums
16831.127Srillig	 * could not be used as array indices).
16841.1Scgd	 */
16851.1Scgd	if (op == PLUS &&
16861.209Srillig	    ((ln->tn_type->t_is_enum && rn->tn_type->t_tspec == PTR) ||
16871.209Srillig	     (rn->tn_type->t_is_enum && ln->tn_type->t_tspec == PTR))) {
16881.1Scgd		return;
16891.1Scgd	}
16901.1Scgd
16911.1Scgd	/* dubious operation on enum, op %s */
16921.260Srillig	warning(241, op_name(op));
16931.1Scgd}
16941.1Scgd
16951.1Scgd/*
16961.1Scgd * Prints a warning if an operator is applied to two different enum types.
16971.1Scgd */
16981.1Scgdstatic void
16991.149Srilligcheck_enum_type_mismatch(op_t op, int arg, const tnode_t *ln, const tnode_t *rn)
17001.1Scgd{
17011.240Srillig	const mod_t *mp;
17021.1Scgd
17031.1Scgd	mp = &modtab[op];
17041.1Scgd
17051.1Scgd	if (ln->tn_type->t_enum != rn->tn_type->t_enum) {
17061.1Scgd		switch (op) {
17071.1Scgd		case INIT:
17081.214Srillig			/* enum type mismatch between '%s' and '%s' in ... */
17091.214Srillig			warning(210,
17101.214Srillig			    type_name(ln->tn_type), type_name(rn->tn_type));
17111.1Scgd			break;
17121.1Scgd		case FARG:
17131.152Srillig			/* enum type mismatch, arg #%d (%s != %s) */
17141.152Srillig			warning(156, arg,
17151.152Srillig			    type_name(ln->tn_type), type_name(rn->tn_type));
17161.1Scgd			break;
17171.1Scgd		case RETURN:
17181.108Srillig			/* return value type mismatch (%s) and (%s) */
17191.115Srillig			warning(211,
17201.115Srillig			    type_name(ln->tn_type), type_name(rn->tn_type));
17211.1Scgd			break;
17221.1Scgd		default:
17231.224Srillig			/* enum type mismatch: '%s' '%s' '%s' */
17241.224Srillig			warning(130, type_name(ln->tn_type), mp->m_name,
17251.224Srillig			    type_name(rn->tn_type));
17261.1Scgd			break;
17271.1Scgd		}
17281.164Srillig	} else if (Pflag && mp->m_comparison && op != EQ && op != NE) {
17291.1Scgd		if (eflag)
17301.108Srillig			/* dubious comparison of enums, op %s */
17311.1Scgd			warning(243, mp->m_name);
17321.1Scgd	}
17331.1Scgd}
17341.1Scgd
17351.182Srillig/* Prints a warning if the operands mix between enum and integer. */
17361.1Scgdstatic void
17371.149Srilligcheck_enum_int_mismatch(op_t op, int arg, const tnode_t *ln, const tnode_t *rn)
17381.1Scgd{
17391.20Slukem
17401.1Scgd	if (!eflag)
17411.1Scgd		return;
17421.1Scgd
17431.1Scgd	switch (op) {
17441.1Scgd	case INIT:
17451.1Scgd		/*
17461.182Srillig		 * Initialization with 0 is allowed. Otherwise, all implicit
17471.182Srillig		 * initializations would need to be warned upon as well.
17481.1Scgd		 */
17491.209Srillig		if (!rn->tn_type->t_is_enum && rn->tn_op == CON &&
17501.144Srillig		    is_integer(rn->tn_type->t_tspec) &&
17511.90Srillig		    rn->tn_val->v_quad == 0) {
17521.1Scgd			return;
17531.1Scgd		}
17541.218Srillig		/* initialization of '%s' with '%s' */
17551.115Srillig		warning(277, type_name(ln->tn_type), type_name(rn->tn_type));
17561.1Scgd		break;
17571.1Scgd	case FARG:
17581.1Scgd		/* combination of '%s' and '%s', arg #%d */
17591.115Srillig		warning(278,
17601.115Srillig		    type_name(ln->tn_type), type_name(rn->tn_type), arg);
17611.1Scgd		break;
17621.1Scgd	case RETURN:
17631.1Scgd		/* combination of '%s' and '%s' in return */
17641.115Srillig		warning(279, type_name(ln->tn_type), type_name(rn->tn_type));
17651.1Scgd		break;
17661.1Scgd	default:
17671.108Srillig		/* combination of '%s' and '%s', op %s */
17681.115Srillig		warning(242, type_name(ln->tn_type), type_name(rn->tn_type),
17691.260Srillig		    op_name(op));
17701.1Scgd		break;
17711.1Scgd	}
17721.1Scgd}
17731.1Scgd
17741.386Srilligstatic void
17751.386Srilligcheck_enum_array_index(const tnode_t *ln, const tnode_t *rn)
17761.386Srillig{
17771.389Srillig	int max_array_index;
17781.389Srillig	int64_t max_enum_value;
17791.389Srillig	const struct sym *ec, *max_ec;
17801.390Schristos	const type_t *lt, *rt;
17811.386Srillig
17821.390Schristos	if (ln->tn_op != ADDR || ln->tn_left->tn_op != NAME)
17831.386Srillig		return;
17841.390Schristos
17851.390Schristos	lt = ln->tn_left->tn_type;
17861.390Schristos	if (lt->t_tspec != ARRAY || lt->t_incomplete_array)
17871.386Srillig		return;
17881.390Schristos
17891.391Srillig	if (rn->tn_op != CVT || !rn->tn_type->t_is_enum)
17901.391Srillig		return;
17911.391Srillig	if (rn->tn_left->tn_op != LOAD)
17921.386Srillig		return;
17931.390Schristos
17941.390Schristos	rt = rn->tn_left->tn_type;
17951.390Schristos	ec = rt->t_enum->en_first_enumerator;
17961.389Srillig	max_ec = ec;
17971.389Srillig	lint_assert(ec != NULL);
17981.389Srillig	for (ec = ec->s_next; ec != NULL; ec = ec->s_next)
17991.389Srillig		if (ec->s_value.v_quad > max_ec->s_value.v_quad)
18001.389Srillig			max_ec = ec;
18011.389Srillig
18021.389Srillig	max_enum_value = max_ec->s_value.v_quad;
18031.389Srillig	lint_assert(INT_MIN <= max_enum_value && max_enum_value <= INT_MAX);
18041.386Srillig
18051.390Schristos	max_array_index = lt->t_dim - 1;
18061.386Srillig	if (max_enum_value == max_array_index)
18071.386Srillig		return;
18081.386Srillig
18091.389Srillig	/*
18101.389Srillig	 * If the largest enum constant is named '*_NUM_*', it is typically
18111.389Srillig	 * not part of the allowed enum values but a marker for the number
18121.389Srillig	 * of actual enum values.
18131.389Srillig	 */
18141.389Srillig	if (max_enum_value == max_array_index + 1 &&
18151.389Srillig	    (strstr(max_ec->s_name, "NUM") != NULL ||
18161.389Srillig	     strstr(max_ec->s_name, "num") != NULL))
18171.389Srillig		return;
18181.389Srillig
18191.386Srillig	/* maximum value %d of '%s' does not match maximum array index %d */
18201.390Schristos	warning(348, (int)max_enum_value, type_name(rt), max_array_index);
18211.389Srillig	print_previous_declaration(-1, max_ec);
18221.386Srillig}
18231.386Srillig
18241.1Scgd/*
18251.1Scgd * Build and initialize a new node.
18261.1Scgd */
18271.1Scgdstatic tnode_t *
18281.395Srillignew_tnode(op_t op, bool sys, type_t *type, tnode_t *ln, tnode_t *rn)
18291.1Scgd{
18301.1Scgd	tnode_t	*ntn;
18311.1Scgd	tspec_t	t;
18321.309Srillig#if 0 /* not yet */
18331.63Schristos	size_t l;
18341.63Schristos	uint64_t rnum;
18351.64Schristos#endif
18361.1Scgd
18371.256Srillig	ntn = expr_zalloc_tnode();
18381.1Scgd
18391.1Scgd	ntn->tn_op = op;
18401.1Scgd	ntn->tn_type = type;
18411.395Srillig	ntn->tn_sys = sys;
18421.1Scgd	ntn->tn_left = ln;
18431.1Scgd	ntn->tn_right = rn;
18441.1Scgd
18451.63Schristos	switch (op) {
18461.309Srillig#if 0 /* not yet */
18471.63Schristos	case SHR:
18481.63Schristos		if (rn->tn_op != CON)
18491.63Schristos			break;
18501.63Schristos		rnum = rn->tn_val->v_quad;
18511.236Srillig		l = type_size_in_bits(ln->tn_type) / CHAR_SIZE;
18521.63Schristos		t = ln->tn_type->t_tspec;
18531.63Schristos		switch (l) {
18541.63Schristos		case 8:
18551.63Schristos			if (rnum >= 56)
18561.63Schristos				t = UCHAR;
18571.63Schristos			else if (rnum >= 48)
18581.63Schristos				t = USHORT;
18591.63Schristos			else if (rnum >= 32)
18601.63Schristos				t = UINT;
18611.63Schristos			break;
18621.63Schristos		case 4:
18631.63Schristos			if (rnum >= 24)
18641.63Schristos				t = UCHAR;
18651.63Schristos			else if (rnum >= 16)
18661.63Schristos				t = USHORT;
18671.63Schristos			break;
18681.63Schristos		case 2:
18691.63Schristos			if (rnum >= 8)
18701.63Schristos				t = UCHAR;
18711.63Schristos			break;
18721.63Schristos		default:
18731.63Schristos			break;
18741.63Schristos		}
18751.63Schristos		if (t != ln->tn_type->t_tspec)
18761.63Schristos			ntn->tn_type->t_tspec = t;
18771.63Schristos		break;
18781.64Schristos#endif
18791.170Srillig	case INDIR:
18801.63Schristos	case FSEL:
18811.107Srillig		lint_assert(ln->tn_type->t_tspec == PTR);
18821.107Srillig		t = ln->tn_type->t_subt->t_tspec;
18831.107Srillig		if (t != FUNC && t != VOID)
18841.154Srillig			ntn->tn_lvalue = true;
18851.63Schristos		break;
18861.63Schristos	default:
18871.63Schristos		break;
18881.1Scgd	}
18891.1Scgd
18901.63Schristos	return ntn;
18911.1Scgd}
18921.1Scgd
18931.1Scgd/*
18941.182Srillig * Performs the "integer promotions" (C99 6.3.1.1p2), which convert small
18951.182Srillig * integer types to either int or unsigned int.
18961.1Scgd *
18971.182Srillig * If tflag is set or the operand is a function argument with no type
18981.182Srillig * information (no prototype or variable # of args), converts float to double.
18991.1Scgd */
19001.1Scgdtnode_t *
19011.154Srilligpromote(op_t op, bool farg, tnode_t *tn)
19021.1Scgd{
19031.1Scgd	tspec_t	t;
19041.1Scgd	type_t	*ntp;
19051.353Srillig	unsigned int len;
19061.1Scgd
19071.1Scgd	t = tn->tn_type->t_tspec;
19081.1Scgd
19091.144Srillig	if (!is_arithmetic(t))
19101.95Srillig		return tn;
19111.1Scgd
19121.1Scgd	if (!tflag) {
19131.1Scgd		/*
19141.281Srillig		 * C99 6.3.1.1p2 requires for types with lower rank than int
19151.281Srillig		 * that "If an int can represent all the values of the
19161.281Srillig		 * original type, the value is converted to an int; otherwise
19171.281Srillig		 * it is converted to an unsigned int", and that "All other
19181.281Srillig		 * types are unchanged by the integer promotions".
19191.1Scgd		 */
19201.120Srillig		if (tn->tn_type->t_bitfield) {
19211.1Scgd			len = tn->tn_type->t_flen;
19221.281Srillig			if (len < size_in_bits(INT)) {
19231.1Scgd				t = INT;
19241.281Srillig			} else if (len == size_in_bits(INT)) {
19251.281Srillig				t = is_uinteger(t) ? UINT : INT;
19261.1Scgd			}
19271.1Scgd		} else if (t == CHAR || t == UCHAR || t == SCHAR) {
19281.228Srillig			t = (size_in_bits(CHAR) < size_in_bits(INT)
19291.228Srillig			     || t != UCHAR) ? INT : UINT;
19301.1Scgd		} else if (t == SHORT || t == USHORT) {
19311.228Srillig			t = (size_in_bits(SHORT) < size_in_bits(INT)
19321.228Srillig			     || t == SHORT) ? INT : UINT;
19331.1Scgd		} else if (t == ENUM) {
19341.1Scgd			t = INT;
19351.1Scgd		} else if (farg && t == FLOAT) {
19361.1Scgd			t = DOUBLE;
19371.1Scgd		}
19381.1Scgd	} else {
19391.1Scgd		/*
19401.1Scgd		 * In traditional C, keep unsigned and promote FLOAT
19411.1Scgd		 * to DOUBLE.
19421.1Scgd		 */
19431.1Scgd		if (t == UCHAR || t == USHORT) {
19441.1Scgd			t = UINT;
19451.1Scgd		} else if (t == CHAR || t == SCHAR || t == SHORT) {
19461.1Scgd			t = INT;
19471.1Scgd		} else if (t == FLOAT) {
19481.1Scgd			t = DOUBLE;
19491.1Scgd		} else if (t == ENUM) {
19501.1Scgd			t = INT;
19511.1Scgd		}
19521.1Scgd	}
19531.1Scgd
19541.1Scgd	if (t != tn->tn_type->t_tspec) {
19551.258Srillig		ntp = expr_dup_type(tn->tn_type);
19561.1Scgd		ntp->t_tspec = t;
19571.1Scgd		/*
19581.299Srillig		 * Keep t_is_enum even though t_tspec gets converted from
19591.299Srillig		 * ENUM to INT, so we are later able to check compatibility
19601.1Scgd		 * of enum types.
19611.1Scgd		 */
19621.1Scgd		tn = convert(op, 0, ntp, tn);
19631.1Scgd	}
19641.1Scgd
19651.95Srillig	return tn;
19661.1Scgd}
19671.1Scgd
19681.1Scgd/*
19691.182Srillig * Apply the "usual arithmetic conversions" (C99 6.3.1.8).
19701.182Srillig *
19711.182Srillig * This gives both operands the same type.
19721.182Srillig * This is done in different ways for traditional C and C90.
19731.1Scgd */
19741.1Scgdstatic void
19751.20Slukembalance(op_t op, tnode_t **lnp, tnode_t **rnp)
19761.1Scgd{
19771.1Scgd	tspec_t	lt, rt, t;
19781.154Srillig	int	i;
19791.154Srillig	bool	u;
19801.1Scgd	type_t	*ntp;
19811.182Srillig	static const tspec_t tl[] = {
19821.323Srillig		LDOUBLE, DOUBLE, FLOAT,
19831.323Srillig#ifdef INT128_SIZE
19841.323Srillig		UINT128, INT128,
19851.323Srillig#endif
19861.323Srillig		UQUAD, QUAD,
19871.323Srillig		ULONG, LONG,
19881.323Srillig		UINT, INT,
19891.1Scgd	};
19901.1Scgd
19911.1Scgd	lt = (*lnp)->tn_type->t_tspec;
19921.1Scgd	rt = (*rnp)->tn_type->t_tspec;
19931.1Scgd
19941.144Srillig	if (!is_arithmetic(lt) || !is_arithmetic(rt))
19951.1Scgd		return;
19961.1Scgd
19971.1Scgd	if (!tflag) {
19981.1Scgd		if (lt == rt) {
19991.1Scgd			t = lt;
20001.53Smatt		} else if (lt == LCOMPLEX || rt == LCOMPLEX) {
20011.53Smatt			t = LCOMPLEX;
20021.53Smatt		} else if (lt == DCOMPLEX || rt == DCOMPLEX) {
20031.53Smatt			t = DCOMPLEX;
20041.53Smatt		} else if (lt == FCOMPLEX || rt == FCOMPLEX) {
20051.53Smatt			t = FCOMPLEX;
20061.1Scgd		} else if (lt == LDOUBLE || rt == LDOUBLE) {
20071.1Scgd			t = LDOUBLE;
20081.1Scgd		} else if (lt == DOUBLE || rt == DOUBLE) {
20091.1Scgd			t = DOUBLE;
20101.1Scgd		} else if (lt == FLOAT || rt == FLOAT) {
20111.1Scgd			t = FLOAT;
20121.1Scgd		} else {
20131.1Scgd			/*
20141.1Scgd			 * If type A has more bits than type B it should
20151.1Scgd			 * be able to hold all possible values of type B.
20161.1Scgd			 */
20171.228Srillig			if (size_in_bits(lt) > size_in_bits(rt)) {
20181.1Scgd				t = lt;
20191.228Srillig			} else if (size_in_bits(lt) < size_in_bits(rt)) {
20201.1Scgd				t = rt;
20211.1Scgd			} else {
20221.1Scgd				for (i = 3; tl[i] != INT; i++) {
20231.1Scgd					if (tl[i] == lt || tl[i] == rt)
20241.1Scgd						break;
20251.1Scgd				}
20261.144Srillig				if ((is_uinteger(lt) || is_uinteger(rt)) &&
20271.144Srillig				    !is_uinteger(tl[i])) {
20281.1Scgd					i--;
20291.1Scgd				}
20301.1Scgd				t = tl[i];
20311.1Scgd			}
20321.1Scgd		}
20331.1Scgd	} else {
20341.1Scgd		/* Keep unsigned in traditional C */
20351.144Srillig		u = is_uinteger(lt) || is_uinteger(rt);
20361.1Scgd		for (i = 0; tl[i] != INT; i++) {
20371.1Scgd			if (lt == tl[i] || rt == tl[i])
20381.1Scgd				break;
20391.1Scgd		}
20401.1Scgd		t = tl[i];
20411.144Srillig		if (u && is_integer(t) && !is_uinteger(t))
20421.114Srillig			t = unsigned_type(t);
20431.1Scgd	}
20441.1Scgd
20451.1Scgd	if (t != lt) {
20461.258Srillig		ntp = expr_dup_type((*lnp)->tn_type);
20471.1Scgd		ntp->t_tspec = t;
20481.1Scgd		*lnp = convert(op, 0, ntp, *lnp);
20491.1Scgd	}
20501.1Scgd	if (t != rt) {
20511.258Srillig		ntp = expr_dup_type((*rnp)->tn_type);
20521.1Scgd		ntp->t_tspec = t;
20531.1Scgd		*rnp = convert(op, 0, ntp, *rnp);
20541.1Scgd	}
20551.1Scgd}
20561.1Scgd
20571.1Scgd/*
20581.1Scgd * Insert a conversion operator, which converts the type of the node
20591.1Scgd * to another given type.
20601.1Scgd * If op is FARG, arg is the number of the argument (used for warnings).
20611.1Scgd */
20621.1Scgdtnode_t *
20631.20Slukemconvert(op_t op, int arg, type_t *tp, tnode_t *tn)
20641.1Scgd{
20651.1Scgd	tnode_t	*ntn;
20661.190Srillig	tspec_t	nt, ot;
20671.1Scgd
20681.1Scgd	nt = tp->t_tspec;
20691.190Srillig	ot = tn->tn_type->t_tspec;
20701.1Scgd
20711.1Scgd	if (!tflag && !sflag && op == FARG)
20721.100Srillig		check_prototype_conversion(arg, nt, ot, tp, tn);
20731.144Srillig	if (is_integer(nt) && is_integer(ot)) {
20741.100Srillig		check_integer_conversion(op, arg, nt, ot, tp, tn);
20751.190Srillig	} else if (nt == PTR && is_null_pointer(tn)) {
20761.190Srillig		/* a null pointer may be assigned to any pointer. */
20771.148Srillig	} else if (is_integer(nt) && nt != BOOL && ot == PTR) {
20781.100Srillig		check_pointer_integer_conversion(op, nt, tp, tn);
20791.273Srillig	} else if (nt == PTR && ot == PTR && op == CVT) {
20801.273Srillig		check_pointer_conversion(tn, tp);
20811.1Scgd	}
20821.1Scgd
20831.256Srillig	ntn = expr_zalloc_tnode();
20841.1Scgd	ntn->tn_op = CVT;
20851.1Scgd	ntn->tn_type = tp;
20861.1Scgd	ntn->tn_cast = op == CVT;
20871.395Srillig	ntn->tn_sys |= tn->tn_sys;
20881.76Schristos	ntn->tn_right = NULL;
20891.1Scgd	if (tn->tn_op != CON || nt == VOID) {
20901.1Scgd		ntn->tn_left = tn;
20911.1Scgd	} else {
20921.1Scgd		ntn->tn_op = CON;
20931.259Srillig		ntn->tn_val = expr_zalloc(sizeof(*ntn->tn_val));
20941.146Srillig		convert_constant(op, arg, ntn->tn_type, ntn->tn_val,
20951.146Srillig		    tn->tn_val);
20961.1Scgd	}
20971.1Scgd
20981.95Srillig	return ntn;
20991.1Scgd}
21001.1Scgd
21011.364Srilligstatic bool
21021.366Srilligshould_warn_about_prototype_conversion(tspec_t nt,
21031.366Srillig				       tspec_t ot, const tnode_t *ptn)
21041.344Srillig{
21051.344Srillig
21061.367Srillig	if (nt == ot)
21071.367Srillig		return false;
21081.367Srillig
21091.367Srillig	if (nt == ENUM && ot == INT)
21101.367Srillig		return false;
21111.367Srillig
21121.364Srillig	if (is_floating(nt) != is_floating(ot) ||
21131.364Srillig	    portable_size_in_bits(nt) != portable_size_in_bits(ot)) {
21141.364Srillig		/* representation and/or width change */
21151.364Srillig		if (!is_integer(ot))
21161.364Srillig			return true;
21171.383Srillig		/*
21181.383Srillig		 * XXX: Investigate whether this rule makes sense; see
21191.383Srillig		 * tests/usr.bin/xlint/lint1/platform_long.c.
21201.383Srillig		 */
21211.364Srillig		return portable_size_in_bits(ot) > portable_size_in_bits(INT);
21221.364Srillig	}
21231.364Srillig
21241.344Srillig	if (!hflag)
21251.364Srillig		return false;
21261.344Srillig
21271.344Srillig	/*
21281.344Srillig	 * If the types differ only in sign and the argument has the same
21291.344Srillig	 * representation in both types, print no warning.
21301.344Srillig	 */
21311.344Srillig	if (ptn->tn_op == CON && is_integer(nt) &&
21321.344Srillig	    signed_type(nt) == signed_type(ot) &&
21331.348Srillig	    !msb(ptn->tn_val->v_quad, ot))
21341.364Srillig		return false;
21351.344Srillig
21361.364Srillig	return true;
21371.344Srillig}
21381.344Srillig
21391.344Srillig/*
21401.367Srillig * Warn if a prototype causes a type conversion that is different from what
21411.367Srillig * would happen to the same argument in the absence of a prototype.  This
21421.367Srillig * check is intended for code that needs to stay compatible with pre-C90 C.
21431.1Scgd *
21441.182Srillig * Errors/warnings about illegal type combinations are already printed
21451.100Srillig * in check_assign_types_compatible().
21461.1Scgd */
21471.1Scgdstatic void
21481.100Srilligcheck_prototype_conversion(int arg, tspec_t nt, tspec_t ot, type_t *tp,
21491.100Srillig			   tnode_t *tn)
21501.1Scgd{
21511.1Scgd	tnode_t	*ptn;
21521.1Scgd
21531.144Srillig	if (!is_arithmetic(nt) || !is_arithmetic(ot))
21541.1Scgd		return;
21551.1Scgd
21561.1Scgd	/*
21571.1Scgd	 * If the type of the formal parameter is char/short, a warning
21581.1Scgd	 * would be useless, because functions declared the old style
21591.1Scgd	 * can't expect char/short arguments.
21601.1Scgd	 */
21611.368Srillig	if (nt == CHAR || nt == SCHAR || nt == UCHAR ||
21621.368Srillig	    nt == SHORT || nt == USHORT)
21631.1Scgd		return;
21641.1Scgd
21651.367Srillig	/* apply the default promotion */
21661.172Srillig	ptn = promote(NOOP, true, tn);
21671.1Scgd	ot = ptn->tn_type->t_tspec;
21681.1Scgd
21691.366Srillig	if (should_warn_about_prototype_conversion(nt, ot, ptn)) {
21701.364Srillig		/* argument #%d is converted from '%s' to '%s' ... */
21711.364Srillig		warning(259, arg, type_name(tn->tn_type), type_name(tp));
21721.364Srillig	}
21731.1Scgd}
21741.1Scgd
21751.1Scgd/*
21761.96Srillig * Print warnings for conversions of integer types which may cause problems.
21771.1Scgd */
21781.1Scgdstatic void
21791.100Srilligcheck_integer_conversion(op_t op, int arg, tspec_t nt, tspec_t ot, type_t *tp,
21801.100Srillig			 tnode_t *tn)
21811.1Scgd{
21821.115Srillig
21831.1Scgd	if (tn->tn_op == CON)
21841.1Scgd		return;
21851.1Scgd
21861.1Scgd	if (op == CVT)
21871.1Scgd		return;
21881.1Scgd
21891.268Srillig	if (Sflag && nt == BOOL)
21901.268Srillig		return;		/* See C99 6.3.1.2 */
21911.268Srillig
21921.228Srillig	if (Pflag && portable_size_in_bits(nt) > portable_size_in_bits(ot) &&
21931.144Srillig	    is_uinteger(nt) != is_uinteger(ot)) {
21941.154Srillig		if (aflag > 0 && pflag) {
21951.1Scgd			if (op == FARG) {
21961.113Srillig				/* conversion to '%s' may sign-extend ... */
21971.115Srillig				warning(297, type_name(tp), arg);
21981.1Scgd			} else {
21991.113Srillig				/* conversion to '%s' may sign-extend ... */
22001.115Srillig				warning(131, type_name(tp));
22011.1Scgd			}
22021.1Scgd		}
22031.1Scgd	}
22041.51Schristos
22051.228Srillig	if (Pflag && portable_size_in_bits(nt) > portable_size_in_bits(ot)) {
22061.51Schristos		switch (tn->tn_op) {
22071.51Schristos		case PLUS:
22081.51Schristos		case MINUS:
22091.51Schristos		case MULT:
22101.51Schristos		case SHL:
22111.113Srillig			/* suggest cast from '%s' to '%s' on op %s to ... */
22121.115Srillig			warning(324, type_name(gettyp(ot)), type_name(tp),
22131.290Srillig			    op_name(tn->tn_op));
22141.51Schristos			break;
22151.51Schristos		default:
22161.51Schristos			break;
22171.51Schristos		}
22181.51Schristos	}
22191.1Scgd
22201.228Srillig	if (portable_size_in_bits(nt) < portable_size_in_bits(ot) &&
22211.1Scgd	    (ot == LONG || ot == ULONG || ot == QUAD || ot == UQUAD ||
22221.1Scgd	     aflag > 1)) {
22231.1Scgd		/* conversion from '%s' may lose accuracy */
22241.154Srillig		if (aflag > 0) {
22251.1Scgd			if (op == FARG) {
22261.377Srillig				/* conversion from '%s' to '%s' may ... */
22271.39Schristos				warning(298,
22281.115Srillig				    type_name(tn->tn_type), type_name(tp), arg);
22291.1Scgd			} else {
22301.377Srillig				/* conversion from '%s' to '%s' may ... */
22311.39Schristos				warning(132,
22321.115Srillig				    type_name(tn->tn_type), type_name(tp));
22331.1Scgd			}
22341.20Slukem		}
22351.1Scgd	}
22361.1Scgd}
22371.1Scgd
22381.1Scgd/*
22391.1Scgd * Print warnings for dubious conversions of pointer to integer.
22401.1Scgd */
22411.1Scgdstatic void
22421.100Srilligcheck_pointer_integer_conversion(op_t op, tspec_t nt, type_t *tp, tnode_t *tn)
22431.1Scgd{
22441.20Slukem
22451.1Scgd	if (tn->tn_op == CON)
22461.1Scgd		return;
22471.166Srillig	if (op != CVT)
22481.166Srillig		return;		/* We got already an error. */
22491.228Srillig	if (portable_size_in_bits(nt) >= portable_size_in_bits(PTR))
22501.1Scgd		return;
22511.1Scgd
22521.228Srillig	if (pflag && size_in_bits(nt) >= size_in_bits(PTR)) {
22531.166Srillig		/* conversion of pointer to '%s' may lose bits */
22541.166Srillig		warning(134, type_name(tp));
22551.166Srillig	} else {
22561.166Srillig		/* conversion of pointer to '%s' loses bits */
22571.166Srillig		warning(133, type_name(tp));
22581.1Scgd	}
22591.1Scgd}
22601.1Scgd
22611.247Srilligstatic bool
22621.273Srilligshould_warn_about_pointer_cast(const type_t *nstp, tspec_t nst,
22631.273Srillig			       const type_t *ostp, tspec_t ost)
22641.247Srillig{
22651.272Srillig	/*
22661.272Srillig	 * Casting a pointer to 'struct S' to a pointer to another struct that
22671.272Srillig	 * has 'struct S' as its first member is ok, see msg_247.c, 'struct
22681.272Srillig	 * counter'.
22691.272Srillig	 */
22701.272Srillig	if (nst == STRUCT && ost == STRUCT &&
22711.273Srillig	    nstp->t_str->sou_first_member != NULL &&
22721.273Srillig	    nstp->t_str->sou_first_member->s_type == ostp)
22731.272Srillig		return false;
22741.272Srillig
22751.274Srillig	if (is_incomplete(nstp) || is_incomplete(ostp))
22761.274Srillig		return false;
22771.274Srillig
22781.273Srillig	if ((nst == STRUCT || nst == UNION) && nstp->t_str != ostp->t_str)
22791.273Srillig		return true;
22801.247Srillig
22811.249Srillig	if (nst == CHAR || nst == UCHAR)
22821.249Srillig		return false;	/* for the sake of traditional C code */
22831.316Srillig	if (ost == CHAR || ost == UCHAR)
22841.316Srillig		return false;	/* for the sake of traditional C code */
22851.249Srillig
22861.247Srillig	return portable_size_in_bits(nst) != portable_size_in_bits(ost);
22871.247Srillig}
22881.247Srillig
22891.1Scgd/*
22901.248Srillig * Warn about questionable pointer conversions.
22911.1Scgd */
22921.1Scgdstatic void
22931.273Srilligcheck_pointer_conversion(tnode_t *tn, type_t *ntp)
22941.1Scgd{
22951.273Srillig	const type_t *nstp, *otp, *ostp;
22961.248Srillig	tspec_t nst, ost;
22971.248Srillig	const char *nts, *ots;
22981.1Scgd
22991.273Srillig	nstp = ntp->t_subt;
23001.273Srillig	otp = tn->tn_type;
23011.273Srillig	ostp = otp->t_subt;
23021.273Srillig	nst = nstp->t_tspec;
23031.273Srillig	ost = ostp->t_tspec;
23041.248Srillig
23051.248Srillig	if (nst == VOID || ost == VOID) {
23061.248Srillig		if (sflag && (nst == FUNC || ost == FUNC)) {
23071.248Srillig			/* null pointers are already handled in convert() */
23081.248Srillig			*(nst == FUNC ? &nts : &ots) = "function pointer";
23091.248Srillig			*(nst == VOID ? &nts : &ots) = "'void *'";
23101.1Scgd			/* ANSI C forbids conversion of %s to %s */
23111.1Scgd			warning(303, ots, nts);
23121.1Scgd		}
23131.1Scgd		return;
23141.248Srillig	} else if (nst == FUNC && ost == FUNC) {
23151.1Scgd		return;
23161.248Srillig	} else if (nst == FUNC || ost == FUNC) {
23171.223Srillig		/* converting '%s' to '%s' is questionable */
23181.273Srillig		warning(229, type_name(otp), type_name(ntp));
23191.1Scgd		return;
23201.1Scgd	}
23211.20Slukem
23221.277Srillig	if (hflag && alignment_in_bits(nstp) > alignment_in_bits(ostp) &&
23231.316Srillig	    ost != CHAR && ost != UCHAR &&
23241.277Srillig	    !is_incomplete(ostp)) {
23251.222Srillig		/* converting '%s' to '%s' may cause alignment problem */
23261.273Srillig		warning(135, type_name(otp), type_name(ntp));
23271.1Scgd	}
23281.221Srillig
23291.273Srillig	if (cflag && should_warn_about_pointer_cast(nstp, nst, ostp, ost)) {
23301.247Srillig		/* pointer cast from '%s' to '%s' may be troublesome */
23311.273Srillig		warning(247, type_name(otp), type_name(ntp));
23321.1Scgd	}
23331.1Scgd}
23341.1Scgd
23351.282Srilligstatic void
23361.285Srilligconvert_constant_floating(op_t op, int arg, tspec_t ot, const type_t *tp,
23371.285Srillig			  tspec_t nt, val_t *v, val_t *nv)
23381.282Srillig{
23391.282Srillig	ldbl_t	max = 0.0, min = 0.0;
23401.282Srillig
23411.282Srillig	switch (nt) {
23421.282Srillig	case CHAR:
23431.282Srillig		max = TARG_CHAR_MAX;	min = TARG_CHAR_MIN;	break;
23441.282Srillig	case UCHAR:
23451.282Srillig		max = TARG_UCHAR_MAX;	min = 0;		break;
23461.282Srillig	case SCHAR:
23471.282Srillig		max = TARG_SCHAR_MAX;	min = TARG_SCHAR_MIN;	break;
23481.282Srillig	case SHORT:
23491.282Srillig		max = TARG_SHRT_MAX;	min = TARG_SHRT_MIN;	break;
23501.282Srillig	case USHORT:
23511.282Srillig		max = TARG_USHRT_MAX;	min = 0;		break;
23521.282Srillig	case ENUM:
23531.282Srillig	case INT:
23541.282Srillig		max = TARG_INT_MAX;	min = TARG_INT_MIN;	break;
23551.282Srillig	case UINT:
23561.354Srillig		max = TARG_UINT_MAX;	min = 0;		break;
23571.282Srillig	case LONG:
23581.282Srillig		max = TARG_LONG_MAX;	min = TARG_LONG_MIN;	break;
23591.282Srillig	case ULONG:
23601.354Srillig		max = TARG_ULONG_MAX;	min = 0;		break;
23611.282Srillig	case QUAD:
23621.282Srillig		max = QUAD_MAX;		min = QUAD_MIN;		break;
23631.282Srillig	case UQUAD:
23641.354Srillig		max = UQUAD_MAX;	min = 0;		break;
23651.282Srillig	case FLOAT:
23661.282Srillig	case FCOMPLEX:
23671.282Srillig		max = FLT_MAX;		min = -FLT_MAX;		break;
23681.282Srillig	case DOUBLE:
23691.282Srillig	case DCOMPLEX:
23701.282Srillig		max = DBL_MAX;		min = -DBL_MAX;		break;
23711.282Srillig	case PTR:
23721.282Srillig		/* Got already an error because of float --> ptr */
23731.282Srillig	case LDOUBLE:
23741.282Srillig	case LCOMPLEX:
23751.378Srillig		/* LINTED 248 */
23761.378Srillig		max = LDBL_MAX;		min = -max;		break;
23771.282Srillig	default:
23781.282Srillig		lint_assert(/*CONSTCOND*/false);
23791.282Srillig	}
23801.282Srillig	if (v->v_ldbl > max || v->v_ldbl < min) {
23811.282Srillig		lint_assert(nt != LDOUBLE);
23821.282Srillig		if (op == FARG) {
23831.377Srillig			/* conversion of '%s' to '%s' is out of range, ... */
23841.282Srillig			warning(295,
23851.282Srillig			    type_name(gettyp(ot)), type_name(tp), arg);
23861.282Srillig		} else {
23871.282Srillig			/* conversion of '%s' to '%s' is out of range */
23881.282Srillig			warning(119,
23891.282Srillig			    type_name(gettyp(ot)), type_name(tp));
23901.282Srillig		}
23911.282Srillig		v->v_ldbl = v->v_ldbl > 0 ? max : min;
23921.282Srillig	}
23931.357Srillig
23941.282Srillig	if (nt == FLOAT) {
23951.282Srillig		nv->v_ldbl = (float)v->v_ldbl;
23961.282Srillig	} else if (nt == DOUBLE) {
23971.282Srillig		nv->v_ldbl = (double)v->v_ldbl;
23981.282Srillig	} else if (nt == LDOUBLE) {
23991.282Srillig		nv->v_ldbl = v->v_ldbl;
24001.282Srillig	} else {
24011.357Srillig		nv->v_quad = (int64_t)v->v_ldbl;
24021.282Srillig	}
24031.282Srillig}
24041.282Srillig
24051.286Srilligstatic bool
24061.286Srilligconvert_constant_to_floating(tspec_t nt, val_t *nv,
24071.286Srillig			     tspec_t ot, const val_t *v)
24081.286Srillig{
24091.286Srillig	if (nt == FLOAT) {
24101.286Srillig		nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ?
24111.286Srillig		    (float)(uint64_t)v->v_quad : (float)v->v_quad;
24121.286Srillig	} else if (nt == DOUBLE) {
24131.286Srillig		nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ?
24141.286Srillig		    (double)(uint64_t)v->v_quad : (double)v->v_quad;
24151.286Srillig	} else if (nt == LDOUBLE) {
24161.286Srillig		nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ?
24171.286Srillig		    (ldbl_t)(uint64_t)v->v_quad : (ldbl_t)v->v_quad;
24181.286Srillig	} else
24191.286Srillig		return false;
24201.286Srillig	return true;
24211.286Srillig}
24221.286Srillig
24231.285Srillig/*
24241.285Srillig * Print a warning if bits which were set are lost due to the conversion.
24251.285Srillig * This can happen with operator ORASS only.
24261.285Srillig */
24271.285Srilligstatic void
24281.285Srilligconvert_constant_check_range_bitor(size_t nsz, size_t osz, const val_t *v,
24291.285Srillig				   uint64_t xmask, op_t op)
24301.285Srillig{
24311.285Srillig	if (nsz < osz && (v->v_quad & xmask) != 0) {
24321.377Srillig		/* constant truncated by conversion, op %s */
24331.285Srillig		warning(306, op_name(op));
24341.285Srillig	}
24351.285Srillig}
24361.285Srillig
24371.285Srillig/*
24381.285Srillig * Print a warning if additional bits are not all 1
24391.285Srillig * and the most significant bit of the old value is 1,
24401.285Srillig * or if at least one (but not all) removed bit was 0.
24411.285Srillig */
24421.285Srilligstatic void
24431.285Srilligconvert_constant_check_range_bitand(size_t nsz, size_t osz,
24441.285Srillig				    uint64_t xmask, const val_t *nv,
24451.285Srillig				    tspec_t ot, const val_t *v,
24461.285Srillig				    const type_t *tp, op_t op)
24471.285Srillig{
24481.285Srillig	if (nsz > osz &&
24491.378Srillig	    (nv->v_quad & bit((unsigned int)(osz - 1))) != 0 &&
24501.285Srillig	    (nv->v_quad & xmask) != xmask) {
24511.285Srillig		/* extra bits set to 0 in conversion of '%s' to '%s', ... */
24521.285Srillig		warning(309, type_name(gettyp(ot)),
24531.285Srillig		    type_name(tp), op_name(op));
24541.285Srillig	} else if (nsz < osz &&
24551.285Srillig		   (v->v_quad & xmask) != xmask &&
24561.285Srillig		   (v->v_quad & xmask) != 0) {
24571.285Srillig		/* constant truncated by conversion, op %s */
24581.285Srillig		warning(306, op_name(op));
24591.285Srillig	}
24601.285Srillig}
24611.285Srillig
24621.285Srilligstatic void
24631.285Srilligconvert_constant_check_range_signed(op_t op, int arg)
24641.285Srillig{
24651.285Srillig	if (op == ASSIGN) {
24661.285Srillig		/* assignment of negative constant to unsigned type */
24671.285Srillig		warning(164);
24681.285Srillig	} else if (op == INIT) {
24691.285Srillig		/* initialization of unsigned with negative constant */
24701.285Srillig		warning(221);
24711.285Srillig	} else if (op == FARG) {
24721.285Srillig		/* conversion of negative constant to unsigned type, ... */
24731.285Srillig		warning(296, arg);
24741.285Srillig	} else if (modtab[op].m_comparison) {
24751.285Srillig		/* handled by check_integer_comparison() */
24761.285Srillig	} else {
24771.285Srillig		/* conversion of negative constant to unsigned type */
24781.285Srillig		warning(222);
24791.285Srillig	}
24801.285Srillig}
24811.285Srillig
24821.285Srillig/*
24831.285Srillig * Loss of significant bit(s). All truncated bits
24841.285Srillig * of unsigned types or all truncated bits plus the
24851.285Srillig * msb of the target for signed types are considered
24861.285Srillig * to be significant bits. Loss of significant bits
24871.295Srillig * means that at least one of the bits was set in an
24881.295Srillig * unsigned type or that at least one but not all of
24891.295Srillig * the bits was set in a signed type.
24901.285Srillig * Loss of significant bits means that it is not
24911.285Srillig * possible, also not with necessary casts, to convert
24921.285Srillig * back to the original type. A example for a
24931.285Srillig * necessary cast is:
24941.285Srillig *	char c;	int	i; c = 128;
24951.285Srillig *	i = c;			** yields -128 **
24961.285Srillig *	i = (unsigned char)c;	** yields 128 **
24971.285Srillig */
24981.285Srilligstatic void
24991.285Srilligconvert_constant_check_range_truncated(op_t op, int arg, const type_t *tp,
25001.285Srillig				       tspec_t ot)
25011.285Srillig{
25021.285Srillig	if (op == ASSIGN && tp->t_bitfield) {
25031.285Srillig		/* precision lost in bit-field assignment */
25041.285Srillig		warning(166);
25051.285Srillig	} else if (op == ASSIGN) {
25061.285Srillig		/* constant truncated by assignment */
25071.285Srillig		warning(165);
25081.285Srillig	} else if (op == INIT && tp->t_bitfield) {
25091.285Srillig		/* bit-field initializer does not fit */
25101.285Srillig		warning(180);
25111.285Srillig	} else if (op == INIT) {
25121.285Srillig		/* initializer does not fit */
25131.285Srillig		warning(178);
25141.285Srillig	} else if (op == CASE) {
25151.285Srillig		/* case label affected by conversion */
25161.285Srillig		warning(196);
25171.285Srillig	} else if (op == FARG) {
25181.285Srillig		/* conversion of '%s' to '%s' is out of range, arg #%d */
25191.285Srillig		warning(295,
25201.285Srillig		    type_name(gettyp(ot)), type_name(tp), arg);
25211.285Srillig	} else {
25221.285Srillig		/* conversion of '%s' to '%s' is out of range */
25231.285Srillig		warning(119,
25241.285Srillig		    type_name(gettyp(ot)), type_name(tp));
25251.285Srillig	}
25261.285Srillig}
25271.285Srillig
25281.285Srilligstatic void
25291.285Srilligconvert_constant_check_range_loss(op_t op, int arg, const type_t *tp,
25301.285Srillig				  tspec_t ot)
25311.285Srillig{
25321.285Srillig	if (op == ASSIGN && tp->t_bitfield) {
25331.285Srillig		/* precision lost in bit-field assignment */
25341.285Srillig		warning(166);
25351.285Srillig	} else if (op == INIT && tp->t_bitfield) {
25361.285Srillig		/* bit-field initializer out of range */
25371.285Srillig		warning(11);
25381.285Srillig	} else if (op == CASE) {
25391.285Srillig		/* case label affected by conversion */
25401.285Srillig		warning(196);
25411.285Srillig	} else if (op == FARG) {
25421.285Srillig		/* conversion of '%s' to '%s' is out of range, arg #%d */
25431.285Srillig		warning(295,
25441.285Srillig		    type_name(gettyp(ot)), type_name(tp), arg);
25451.285Srillig	} else {
25461.285Srillig		/* conversion of '%s' to '%s' is out of range */
25471.285Srillig		warning(119,
25481.285Srillig		    type_name(gettyp(ot)), type_name(tp));
25491.285Srillig	}
25501.285Srillig}
25511.285Srillig
25521.283Srilligstatic void
25531.285Srilligconvert_constant_check_range(tspec_t ot, const type_t *tp, tspec_t nt,
25541.285Srillig			     op_t op, int arg, const val_t *v, val_t *nv)
25551.283Srillig{
25561.378Srillig	unsigned int osz, nsz;
25571.378Srillig	uint64_t xmask, xmsk1;
25581.283Srillig
25591.283Srillig	osz = size_in_bits(ot);
25601.283Srillig	nsz = tp->t_bitfield ? tp->t_flen : size_in_bits(nt);
25611.287Srillig	xmask = value_bits(nsz) ^ value_bits(osz);
25621.287Srillig	xmsk1 = value_bits(nsz) ^ value_bits(osz - 1);
25631.283Srillig	/*
25641.283Srillig	 * For bitwise operations we are not interested in the
25651.283Srillig	 * value, but in the bits itself.
25661.283Srillig	 */
25671.283Srillig	if (op == ORASS || op == BITOR || op == BITXOR) {
25681.285Srillig		convert_constant_check_range_bitor(nsz, osz, v, xmask, op);
25691.283Srillig	} else if (op == ANDASS || op == BITAND) {
25701.285Srillig		convert_constant_check_range_bitand(nsz, osz, xmask, nv, ot,
25711.285Srillig		    v, tp, op);
25721.283Srillig	} else if ((nt != PTR && is_uinteger(nt)) &&
25731.283Srillig		   (ot != PTR && !is_uinteger(ot)) &&
25741.283Srillig		   v->v_quad < 0) {
25751.285Srillig		convert_constant_check_range_signed(op, arg);
25761.283Srillig	} else if (nv->v_quad != v->v_quad && nsz <= osz &&
25771.283Srillig		   (v->v_quad & xmask) != 0 &&
25781.283Srillig		   (is_uinteger(ot) || (v->v_quad & xmsk1) != xmsk1)) {
25791.285Srillig		convert_constant_check_range_truncated(op, arg, tp, ot);
25801.283Srillig	} else if (nv->v_quad != v->v_quad) {
25811.285Srillig		convert_constant_check_range_loss(op, arg, tp, ot);
25821.283Srillig	}
25831.283Srillig}
25841.283Srillig
25851.1Scgd/*
25861.166Srillig * Converts a typed constant to a constant of another type.
25871.1Scgd *
25881.1Scgd * op		operator which requires conversion
25891.1Scgd * arg		if op is FARG, # of argument
25901.1Scgd * tp		type in which to convert the constant
25911.1Scgd * nv		new constant
25921.1Scgd * v		old constant
25931.1Scgd */
25941.1Scgdvoid
25951.253Srilligconvert_constant(op_t op, int arg, const type_t *tp, val_t *nv, val_t *v)
25961.1Scgd{
25971.378Srillig	tspec_t ot, nt;
25981.378Srillig	unsigned int sz;
25991.378Srillig	bool range_check;
26001.1Scgd
26011.276Srillig	/*
26021.276Srillig	 * TODO: make 'v' const; the name of this function does not suggest
26031.276Srillig	 *  that it modifies 'v'.
26041.276Srillig	 */
26051.1Scgd	ot = v->v_tspec;
26061.1Scgd	nt = nv->v_tspec = tp->t_tspec;
26071.283Srillig	range_check = false;
26081.1Scgd
26091.147Srillig	if (nt == BOOL) {	/* C99 6.3.1.2 */
26101.289Srillig		nv->v_unsigned_since_c90 = false;
26111.230Srillig		nv->v_quad = is_nonzero_val(v) ? 1 : 0;
26121.147Srillig		return;
26131.147Srillig	}
26141.147Srillig
26151.1Scgd	if (ot == FLOAT || ot == DOUBLE || ot == LDOUBLE) {
26161.282Srillig		convert_constant_floating(op, arg, ot, tp, nt, v, nv);
26171.286Srillig	} else if (!convert_constant_to_floating(nt, nv, ot, v)) {
26181.286Srillig		range_check = true;	/* Check for lost precision. */
26191.286Srillig		nv->v_quad = v->v_quad;
26201.1Scgd	}
26211.1Scgd
26221.289Srillig	if ((v->v_unsigned_since_c90 && is_floating(nt)) ||
26231.289Srillig	    (v->v_unsigned_since_c90 && (is_integer(nt) && !is_uinteger(nt) &&
26241.284Srillig			    portable_size_in_bits(nt) >
26251.284Srillig			    portable_size_in_bits(ot)))) {
26261.1Scgd		/* ANSI C treats constant as unsigned */
26271.1Scgd		warning(157);
26281.289Srillig		v->v_unsigned_since_c90 = false;
26291.1Scgd	}
26301.1Scgd
26311.297Srillig	if (is_integer(nt)) {
26321.228Srillig		sz = tp->t_bitfield ? tp->t_flen : size_in_bits(nt);
26331.298Srillig		nv->v_quad = convert_integer(nv->v_quad, nt, sz);
26341.1Scgd	}
26351.20Slukem
26361.283Srillig	if (range_check && op != CVT)
26371.283Srillig		convert_constant_check_range(ot, tp, nt, op, arg, v, nv);
26381.1Scgd}
26391.1Scgd
26401.1Scgd/*
26411.1Scgd * Called if incompatible types were detected.
26421.1Scgd * Prints a appropriate warning.
26431.1Scgd */
26441.1Scgdstatic void
26451.246Srilligwarn_incompatible_types(op_t op,
26461.246Srillig			const type_t *ltp, tspec_t lt,
26471.246Srillig			const type_t *rtp, tspec_t rt)
26481.1Scgd{
26491.240Srillig	const mod_t *mp;
26501.1Scgd
26511.1Scgd	mp = &modtab[op];
26521.1Scgd
26531.1Scgd	if (lt == VOID || (mp->m_binary && rt == VOID)) {
26541.1Scgd		/* void type illegal in expression */
26551.110Srillig		error(109);
26561.1Scgd	} else if (op == ASSIGN) {
26571.1Scgd		if ((lt == STRUCT || lt == UNION) &&
26581.1Scgd		    (rt == STRUCT || rt == UNION)) {
26591.110Srillig			/* assignment of different structures (%s != %s) */
26601.111Srillig			error(240, tspec_name(lt), tspec_name(rt));
26611.1Scgd		} else {
26621.246Srillig			/* cannot assign to '%s' from '%s' */
26631.246Srillig			error(171, type_name(ltp), type_name(rtp));
26641.1Scgd		}
26651.1Scgd	} else if (mp->m_binary) {
26661.110Srillig		/* operands of '%s' have incompatible types (%s != %s) */
26671.111Srillig		error(107, mp->m_name, tspec_name(lt), tspec_name(rt));
26681.1Scgd	} else {
26691.137Srillig		lint_assert(rt == NOTSPEC);
26701.137Srillig		/* operand of '%s' has invalid type (%s) */
26711.137Srillig		error(108, mp->m_name, tspec_name(lt));
26721.1Scgd	}
26731.1Scgd}
26741.1Scgd
26751.1Scgd/*
26761.1Scgd * Called if incompatible pointer types are detected.
26771.1Scgd * Print an appropriate warning.
26781.1Scgd */
26791.1Scgdstatic void
26801.149Srilligwarn_incompatible_pointers(const mod_t *mp,
26811.149Srillig			   const type_t *ltp, const type_t *rtp)
26821.1Scgd{
26831.1Scgd	tspec_t	lt, rt;
26841.1Scgd
26851.107Srillig	lint_assert(ltp->t_tspec == PTR);
26861.107Srillig	lint_assert(rtp->t_tspec == PTR);
26871.1Scgd
26881.1Scgd	lt = ltp->t_subt->t_tspec;
26891.1Scgd	rt = rtp->t_subt->t_tspec;
26901.1Scgd
26911.1Scgd	if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION)) {
26921.1Scgd		if (mp == NULL) {
26931.1Scgd			/* illegal structure pointer combination */
26941.1Scgd			warning(244);
26951.1Scgd		} else {
26961.225Srillig			/* incompatible structure pointers: '%s' '%s' '%s' */
26971.225Srillig			warning(245, type_name(ltp), mp->m_name, type_name(rtp));
26981.1Scgd		}
26991.1Scgd	} else {
27001.1Scgd		if (mp == NULL) {
27011.334Srillig			/* illegal combination of '%s' and '%s' */
27021.334Srillig			warning(184, type_name(ltp), type_name(rtp));
27031.1Scgd		} else {
27041.334Srillig			/* illegal combination of '%s' and '%s', op '%s' */
27051.117Srillig			warning(124,
27061.117Srillig			    type_name(ltp), type_name(rtp), mp->m_name);
27071.1Scgd		}
27081.1Scgd	}
27091.1Scgd}
27101.1Scgd
27111.263Srillig/* Return a type based on tp1, with added qualifiers from tp2. */
27121.263Srilligstatic type_t *
27131.263Srilligmerge_qualifiers(type_t *tp1, const type_t *tp2)
27141.1Scgd{
27151.263Srillig	type_t *ntp, *nstp;
27161.392Srillig	bool c1, c2, v1, v2;
27171.20Slukem
27181.107Srillig	lint_assert(tp1->t_tspec == PTR);
27191.107Srillig	lint_assert(tp2->t_tspec == PTR);
27201.1Scgd
27211.392Srillig	c1 = tp1->t_subt->t_const;
27221.392Srillig	c2 = tp2->t_subt->t_const;
27231.392Srillig	v1 = tp1->t_subt->t_volatile;
27241.392Srillig	v2 = tp2->t_subt->t_volatile;
27251.263Srillig
27261.264Srillig	if (c1 == (c1 | c2) && v1 == (v1 | v2))
27271.263Srillig		return tp1;
27281.263Srillig
27291.263Srillig	nstp = expr_dup_type(tp1->t_subt);
27301.264Srillig	nstp->t_const |= c2;
27311.264Srillig	nstp->t_volatile |= v2;
27321.263Srillig
27331.263Srillig	ntp = expr_dup_type(tp1);
27341.263Srillig	ntp->t_subt = nstp;
27351.263Srillig	return ntp;
27361.1Scgd}
27371.1Scgd
27381.1Scgd/*
27391.185Srillig * Returns true if the given structure or union has a constant member
27401.1Scgd * (maybe recursively).
27411.1Scgd */
27421.149Srilligstatic bool
27431.149Srillighas_constant_member(const type_t *tp)
27441.1Scgd{
27451.321Srillig	sym_t *m;
27461.1Scgd
27471.321Srillig	lint_assert(is_struct_or_union(tp->t_tspec));
27481.107Srillig
27491.208Srillig	for (m = tp->t_str->sou_first_member; m != NULL; m = m->s_next) {
27501.321Srillig		const type_t *mtp = m->s_type;
27511.321Srillig		if (mtp->t_const)
27521.321Srillig			return true;
27531.321Srillig		if (is_struct_or_union(mtp->t_tspec) &&
27541.321Srillig		    has_constant_member(mtp))
27551.149Srillig			return true;
27561.1Scgd	}
27571.149Srillig	return false;
27581.1Scgd}
27591.1Scgd
27601.1Scgd/*
27611.1Scgd * Create a new node for one of the operators POINT and ARROW.
27621.1Scgd */
27631.1Scgdstatic tnode_t *
27641.395Srilligbuild_struct_access(op_t op, bool sys, tnode_t *ln, tnode_t *rn)
27651.1Scgd{
27661.1Scgd	tnode_t	*ntn, *ctn;
27671.154Srillig	bool	nolval;
27681.1Scgd
27691.107Srillig	lint_assert(rn->tn_op == NAME);
27701.107Srillig	lint_assert(rn->tn_sym->s_value.v_tspec == INT);
27711.107Srillig	lint_assert(rn->tn_sym->s_scl == MOS || rn->tn_sym->s_scl == MOU);
27721.1Scgd
27731.1Scgd	/*
27741.1Scgd	 * Remember if the left operand is an lvalue (structure members
27751.1Scgd	 * are lvalues if and only if the structure itself is an lvalue).
27761.1Scgd	 */
27771.1Scgd	nolval = op == POINT && !ln->tn_lvalue;
27781.1Scgd
27791.1Scgd	if (op == POINT) {
27801.395Srillig		ln = build_address(sys, ln, true);
27811.1Scgd	} else if (ln->tn_type->t_tspec != PTR) {
27821.107Srillig		lint_assert(tflag);
27831.144Srillig		lint_assert(is_integer(ln->tn_type->t_tspec));
27841.257Srillig		ln = convert(NOOP, 0, expr_derive_type(gettyp(VOID), PTR), ln);
27851.1Scgd	}
27861.1Scgd
27871.318Srillig	ctn = build_integer_constant(PTRDIFF_TSPEC,
27881.136Srillig	    rn->tn_sym->s_value.v_quad / CHAR_SIZE);
27891.1Scgd
27901.395Srillig	ntn = new_tnode(PLUS, sys, expr_derive_type(rn->tn_type, PTR),
27911.395Srillig	    ln, ctn);
27921.1Scgd	if (ln->tn_op == CON)
27931.1Scgd		ntn = fold(ntn);
27941.1Scgd
27951.120Srillig	if (rn->tn_type->t_bitfield) {
27961.395Srillig		ntn = new_tnode(FSEL, sys, ntn->tn_type->t_subt, ntn, NULL);
27971.1Scgd	} else {
27981.395Srillig		ntn = new_tnode(INDIR, sys, ntn->tn_type->t_subt, ntn, NULL);
27991.1Scgd	}
28001.1Scgd
28011.1Scgd	if (nolval)
28021.154Srillig		ntn->tn_lvalue = false;
28031.1Scgd
28041.95Srillig	return ntn;
28051.1Scgd}
28061.1Scgd
28071.1Scgd/*
28081.1Scgd * Create a node for INCAFT, INCBEF, DECAFT and DECBEF.
28091.1Scgd */
28101.1Scgdstatic tnode_t *
28111.395Srilligbuild_prepost_incdec(op_t op, bool sys, tnode_t *ln)
28121.1Scgd{
28131.1Scgd	tnode_t	*cn, *ntn;
28141.1Scgd
28151.107Srillig	lint_assert(ln != NULL);
28161.1Scgd
28171.1Scgd	if (ln->tn_type->t_tspec == PTR) {
28181.1Scgd		cn = plength(ln->tn_type);
28191.1Scgd	} else {
28201.318Srillig		cn = build_integer_constant(INT, (int64_t)1);
28211.1Scgd	}
28221.395Srillig	ntn = new_tnode(op, sys, ln->tn_type, ln, cn);
28231.1Scgd
28241.95Srillig	return ntn;
28251.1Scgd}
28261.1Scgd
28271.1Scgd/*
28281.46Schristos * Create a node for REAL, IMAG
28291.46Schristos */
28301.46Schristosstatic tnode_t *
28311.395Srilligbuild_real_imag(op_t op, bool sys, tnode_t *ln)
28321.46Schristos{
28331.46Schristos	tnode_t	*cn, *ntn;
28341.46Schristos
28351.107Srillig	lint_assert(ln != NULL);
28361.46Schristos
28371.275Srillig	if (ln->tn_op == NAME) {
28381.275Srillig		/*
28391.275Srillig		 * This may be too much, but it avoids wrong warnings.
28401.275Srillig		 * See d_c99_complex_split.c.
28411.275Srillig		 */
28421.275Srillig		mark_as_used(ln->tn_sym, false, false);
28431.275Srillig		mark_as_set(ln->tn_sym);
28441.275Srillig	}
28451.275Srillig
28461.46Schristos	switch (ln->tn_type->t_tspec) {
28471.52Smatt	case LCOMPLEX:
28481.182Srillig		/* XXX: integer and LDOUBLE don't match. */
28491.318Srillig		cn = build_integer_constant(LDOUBLE, (int64_t)1);
28501.52Smatt		break;
28511.46Schristos	case DCOMPLEX:
28521.257Srillig		/* XXX: integer and DOUBLE don't match. */
28531.318Srillig		cn = build_integer_constant(DOUBLE, (int64_t)1);
28541.46Schristos		break;
28551.46Schristos	case FCOMPLEX:
28561.257Srillig		/* XXX: integer and FLOAT don't match. */
28571.318Srillig		cn = build_integer_constant(FLOAT, (int64_t)1);
28581.46Schristos		break;
28591.46Schristos	default:
28601.113Srillig		/* __%s__ is illegal for type %s */
28611.47Schristos		error(276, op == REAL ? "real" : "imag",
28621.115Srillig		    type_name(ln->tn_type));
28631.46Schristos		return NULL;
28641.46Schristos	}
28651.395Srillig	ntn = new_tnode(op, sys, cn->tn_type, ln, cn);
28661.154Srillig	ntn->tn_lvalue = true;
28671.46Schristos
28681.95Srillig	return ntn;
28691.46Schristos}
28701.342Srillig
28711.46Schristos/*
28721.182Srillig * Create a tree node for the unary & operator
28731.1Scgd */
28741.1Scgdstatic tnode_t *
28751.395Srilligbuild_address(bool sys, tnode_t *tn, bool noign)
28761.1Scgd{
28771.1Scgd	tspec_t	t;
28781.20Slukem
28791.1Scgd	if (!noign && ((t = tn->tn_type->t_tspec) == ARRAY || t == FUNC)) {
28801.1Scgd		if (tflag)
28811.113Srillig			/* '&' before array or function: ignored */
28821.1Scgd			warning(127);
28831.95Srillig		return tn;
28841.1Scgd	}
28851.1Scgd
28861.1Scgd	/* eliminate &* */
28871.170Srillig	if (tn->tn_op == INDIR &&
28881.1Scgd	    tn->tn_left->tn_type->t_tspec == PTR &&
28891.1Scgd	    tn->tn_left->tn_type->t_subt == tn->tn_type) {
28901.95Srillig		return tn->tn_left;
28911.1Scgd	}
28921.20Slukem
28931.395Srillig	return new_tnode(ADDR, sys, expr_derive_type(tn->tn_type, PTR),
28941.395Srillig	    tn, NULL);
28951.1Scgd}
28961.1Scgd
28971.1Scgd/*
28981.1Scgd * Create a node for operators PLUS and MINUS.
28991.1Scgd */
29001.1Scgdstatic tnode_t *
29011.395Srilligbuild_plus_minus(op_t op, bool sys, tnode_t *ln, tnode_t *rn)
29021.1Scgd{
29031.1Scgd	tnode_t	*ntn, *ctn;
29041.1Scgd	type_t	*tp;
29051.1Scgd
29061.1Scgd	/* If pointer and integer, then pointer to the lhs. */
29071.144Srillig	if (rn->tn_type->t_tspec == PTR && is_integer(ln->tn_type->t_tspec)) {
29081.1Scgd		ntn = ln;
29091.1Scgd		ln = rn;
29101.1Scgd		rn = ntn;
29111.1Scgd	}
29121.1Scgd
29131.1Scgd	if (ln->tn_type->t_tspec == PTR && rn->tn_type->t_tspec != PTR) {
29141.144Srillig		lint_assert(is_integer(rn->tn_type->t_tspec));
29151.1Scgd
29161.266Srillig		check_ctype_macro_invocation(ln, rn);
29171.386Srillig		check_enum_array_index(ln, rn);
29181.266Srillig
29191.1Scgd		ctn = plength(ln->tn_type);
29201.1Scgd		if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec)
29211.1Scgd			rn = convert(NOOP, 0, ctn->tn_type, rn);
29221.395Srillig		rn = new_tnode(MULT, sys, rn->tn_type, rn, ctn);
29231.1Scgd		if (rn->tn_left->tn_op == CON)
29241.1Scgd			rn = fold(rn);
29251.395Srillig		ntn = new_tnode(op, sys, ln->tn_type, ln, rn);
29261.1Scgd
29271.1Scgd	} else if (rn->tn_type->t_tspec == PTR) {
29281.1Scgd
29291.107Srillig		lint_assert(ln->tn_type->t_tspec == PTR);
29301.107Srillig		lint_assert(op == MINUS);
29311.191Srillig		tp = gettyp(PTRDIFF_TSPEC);
29321.395Srillig		ntn = new_tnode(op, sys, tp, ln, rn);
29331.1Scgd		if (ln->tn_op == CON && rn->tn_op == CON)
29341.1Scgd			ntn = fold(ntn);
29351.1Scgd		ctn = plength(ln->tn_type);
29361.1Scgd		balance(NOOP, &ntn, &ctn);
29371.395Srillig		ntn = new_tnode(DIV, sys, tp, ntn, ctn);
29381.1Scgd
29391.1Scgd	} else {
29401.1Scgd
29411.395Srillig		ntn = new_tnode(op, sys, ln->tn_type, ln, rn);
29421.1Scgd
29431.1Scgd	}
29441.95Srillig	return ntn;
29451.1Scgd}
29461.1Scgd
29471.1Scgd/*
29481.1Scgd * Create a node for operators SHL and SHR.
29491.1Scgd */
29501.1Scgdstatic tnode_t *
29511.395Srilligbuild_bit_shift(op_t op, bool sys, tnode_t *ln, tnode_t *rn)
29521.1Scgd{
29531.1Scgd	tspec_t	t;
29541.1Scgd	tnode_t	*ntn;
29551.1Scgd
29561.1Scgd	if ((t = rn->tn_type->t_tspec) != INT && t != UINT)
29571.1Scgd		rn = convert(CVT, 0, gettyp(INT), rn);
29581.395Srillig	ntn = new_tnode(op, sys, ln->tn_type, ln, rn);
29591.95Srillig	return ntn;
29601.1Scgd}
29611.1Scgd
29621.1Scgd/*
29631.1Scgd * Create a node for COLON.
29641.1Scgd */
29651.1Scgdstatic tnode_t *
29661.395Srilligbuild_colon(bool sys, tnode_t *ln, tnode_t *rn)
29671.1Scgd{
29681.1Scgd	tspec_t	lt, rt, pdt;
29691.262Srillig	type_t	*tp;
29701.1Scgd	tnode_t	*ntn;
29711.1Scgd
29721.1Scgd	lt = ln->tn_type->t_tspec;
29731.1Scgd	rt = rn->tn_type->t_tspec;
29741.191Srillig	pdt = PTRDIFF_TSPEC;
29751.1Scgd
29761.1Scgd	/*
29771.1Scgd	 * Arithmetic types are balanced, all other type combinations
29781.1Scgd	 * still need to be handled.
29791.1Scgd	 */
29801.144Srillig	if (is_arithmetic(lt) && is_arithmetic(rt)) {
29811.262Srillig		tp = ln->tn_type;
29821.165Srillig	} else if (lt == BOOL && rt == BOOL) {
29831.262Srillig		tp = ln->tn_type;
29841.1Scgd	} else if (lt == VOID || rt == VOID) {
29851.262Srillig		tp = gettyp(VOID);
29861.1Scgd	} else if (lt == STRUCT || lt == UNION) {
29871.1Scgd		/* Both types must be identical. */
29881.107Srillig		lint_assert(rt == STRUCT || rt == UNION);
29891.107Srillig		lint_assert(ln->tn_type->t_str == rn->tn_type->t_str);
29901.194Srillig		if (is_incomplete(ln->tn_type)) {
29911.1Scgd			/* unknown operand size, op %s */
29921.261Srillig			error(138, op_name(COLON));
29931.95Srillig			return NULL;
29941.1Scgd		}
29951.262Srillig		tp = ln->tn_type;
29961.144Srillig	} else if (lt == PTR && is_integer(rt)) {
29971.1Scgd		if (rt != pdt) {
29981.1Scgd			rn = convert(NOOP, 0, gettyp(pdt), rn);
29991.1Scgd			rt = pdt;
30001.1Scgd		}
30011.262Srillig		tp = ln->tn_type;
30021.144Srillig	} else if (rt == PTR && is_integer(lt)) {
30031.1Scgd		if (lt != pdt) {
30041.1Scgd			ln = convert(NOOP, 0, gettyp(pdt), ln);
30051.1Scgd			lt = pdt;
30061.1Scgd		}
30071.262Srillig		tp = rn->tn_type;
30081.1Scgd	} else if (lt == PTR && ln->tn_type->t_subt->t_tspec == VOID) {
30091.263Srillig		tp = merge_qualifiers(rn->tn_type, ln->tn_type);
30101.1Scgd	} else if (rt == PTR && rn->tn_type->t_subt->t_tspec == VOID) {
30111.263Srillig		tp = merge_qualifiers(ln->tn_type, rn->tn_type);
30121.1Scgd	} else {
30131.1Scgd		/*
30141.1Scgd		 * XXX For now we simply take the left type. This is
30151.106Srillig		 * probably wrong, if one type contains a function prototype
30161.1Scgd		 * and the other one, at the same place, only an old style
30171.1Scgd		 * declaration.
30181.1Scgd		 */
30191.263Srillig		tp = merge_qualifiers(ln->tn_type, rn->tn_type);
30201.1Scgd	}
30211.1Scgd
30221.395Srillig	ntn = new_tnode(COLON, sys, tp, ln, rn);
30231.1Scgd
30241.95Srillig	return ntn;
30251.1Scgd}
30261.1Scgd
30271.1Scgd/*
30281.1Scgd * Create a node for an assignment operator (both = and op= ).
30291.1Scgd */
30301.1Scgdstatic tnode_t *
30311.395Srilligbuild_assignment(op_t op, bool sys, tnode_t *ln, tnode_t *rn)
30321.1Scgd{
30331.1Scgd	tspec_t	lt, rt;
30341.1Scgd	tnode_t	*ntn, *ctn;
30351.1Scgd
30361.107Srillig	lint_assert(ln != NULL);
30371.107Srillig	lint_assert(rn != NULL);
30381.1Scgd
30391.1Scgd	lt = ln->tn_type->t_tspec;
30401.1Scgd	rt = rn->tn_type->t_tspec;
30411.1Scgd
30421.1Scgd	if ((op == ADDASS || op == SUBASS) && lt == PTR) {
30431.144Srillig		lint_assert(is_integer(rt));
30441.1Scgd		ctn = plength(ln->tn_type);
30451.1Scgd		if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec)
30461.1Scgd			rn = convert(NOOP, 0, ctn->tn_type, rn);
30471.395Srillig		rn = new_tnode(MULT, sys, rn->tn_type, rn, ctn);
30481.1Scgd		if (rn->tn_left->tn_op == CON)
30491.1Scgd			rn = fold(rn);
30501.1Scgd	}
30511.1Scgd
30521.333Srillig	if ((op == ASSIGN || op == RETURN || op == INIT) &&
30531.333Srillig	    (lt == STRUCT || rt == STRUCT)) {
30541.107Srillig		lint_assert(lt == rt);
30551.107Srillig		lint_assert(ln->tn_type->t_str == rn->tn_type->t_str);
30561.194Srillig		if (is_incomplete(ln->tn_type)) {
30571.1Scgd			if (op == RETURN) {
30581.1Scgd				/* cannot return incomplete type */
30591.1Scgd				error(212);
30601.1Scgd			} else {
30611.1Scgd				/* unknown operand size, op %s */
30621.260Srillig				error(138, op_name(op));
30631.1Scgd			}
30641.95Srillig			return NULL;
30651.1Scgd		}
30661.1Scgd	}
30671.1Scgd
30681.40Schristos	if (op == SHLASS) {
30691.228Srillig		if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) {
30701.40Schristos			if (hflag)
30711.108Srillig				/* semantics of '%s' change in ANSI C; ... */
30721.40Schristos				warning(118, "<<=");
30731.1Scgd		}
30741.40Schristos	} else if (op != SHRASS) {
30751.1Scgd		if (op == ASSIGN || lt != PTR) {
30761.1Scgd			if (lt != rt ||
30771.120Srillig			    (ln->tn_type->t_bitfield && rn->tn_op == CON)) {
30781.1Scgd				rn = convert(op, 0, ln->tn_type, rn);
30791.1Scgd				rt = lt;
30801.1Scgd			}
30811.1Scgd		}
30821.1Scgd	}
30831.1Scgd
30841.395Srillig	ntn = new_tnode(op, sys, ln->tn_type, ln, rn);
30851.1Scgd
30861.95Srillig	return ntn;
30871.1Scgd}
30881.1Scgd
30891.1Scgd/*
30901.352Srillig * Get length of type tp->t_subt, as a constant expression of type ptrdiff_t
30911.352Srillig * as seen from the target platform.
30921.1Scgd */
30931.1Scgdstatic tnode_t *
30941.20Slukemplength(type_t *tp)
30951.1Scgd{
30961.352Srillig	int elem, elsz_in_bits;
30971.1Scgd
30981.107Srillig	lint_assert(tp->t_tspec == PTR);
30991.1Scgd	tp = tp->t_subt;
31001.1Scgd
31011.1Scgd	elem = 1;
31021.352Srillig	elsz_in_bits = 0;
31031.1Scgd
31041.1Scgd	while (tp->t_tspec == ARRAY) {
31051.1Scgd		elem *= tp->t_dim;
31061.1Scgd		tp = tp->t_subt;
31071.1Scgd	}
31081.1Scgd
31091.1Scgd	switch (tp->t_tspec) {
31101.1Scgd	case FUNC:
31111.1Scgd		/* pointer to function is not allowed here */
31121.1Scgd		error(110);
31131.1Scgd		break;
31141.1Scgd	case VOID:
31151.177Srillig		/* cannot do pointer arithmetic on operand of unknown size */
31161.118Srillig		gnuism(136);
31171.1Scgd		break;
31181.1Scgd	case STRUCT:
31191.1Scgd	case UNION:
31201.352Srillig		if ((elsz_in_bits = tp->t_str->sou_size_in_bits) == 0)
31211.1Scgd			/* cannot do pointer arithmetic on operand of ... */
31221.1Scgd			error(136);
31231.1Scgd		break;
31241.1Scgd	case ENUM:
31251.194Srillig		if (is_incomplete(tp)) {
31261.1Scgd			/* cannot do pointer arithmetic on operand of ... */
31271.1Scgd			warning(136);
31281.1Scgd		}
31291.1Scgd		/* FALLTHROUGH */
31301.1Scgd	default:
31311.352Srillig		if ((elsz_in_bits = size_in_bits(tp->t_tspec)) == 0) {
31321.1Scgd			/* cannot do pointer arithmetic on operand of ... */
31331.1Scgd			error(136);
31341.107Srillig		} else {
31351.352Srillig			lint_assert(elsz_in_bits != -1);
31361.1Scgd		}
31371.1Scgd		break;
31381.1Scgd	}
31391.1Scgd
31401.352Srillig	if (elem == 0 && elsz_in_bits != 0) {
31411.177Srillig		/* cannot do pointer arithmetic on operand of unknown size */
31421.1Scgd		error(136);
31431.1Scgd	}
31441.1Scgd
31451.352Srillig	if (elsz_in_bits == 0)
31461.352Srillig		elsz_in_bits = CHAR_SIZE;
31471.1Scgd
31481.318Srillig	return build_integer_constant(PTRDIFF_TSPEC,
31491.352Srillig	    (int64_t)(elem * elsz_in_bits / CHAR_SIZE));
31501.1Scgd}
31511.1Scgd
31521.1Scgd/*
31531.22Sperry * XXX
31541.22Sperry * Note: There appear to be a number of bugs in detecting overflow in
31551.22Sperry * this function. An audit and a set of proper regression tests are needed.
31561.22Sperry *     --Perry Metzger, Nov. 16, 2001
31571.22Sperry */
31581.22Sperry/*
31591.1Scgd * Do only as much as necessary to compute constant expressions.
31601.182Srillig * Called only if the operator allows folding and all operands are constants.
31611.1Scgd */
31621.1Scgdstatic tnode_t *
31631.20Slukemfold(tnode_t *tn)
31641.1Scgd{
31651.339Srillig	val_t *v;
31661.339Srillig	tspec_t t;
31671.339Srillig	bool utyp, ovfl;
31681.339Srillig	int64_t sl, sr = 0, q = 0, mask;
31691.25Sthorpej	uint64_t ul, ur = 0;
31701.339Srillig	tnode_t *cn;
31711.1Scgd
31721.259Srillig	v = xcalloc(1, sizeof(*v));
31731.345Srillig	v->v_tspec = tn->tn_type->t_tspec;
31741.1Scgd
31751.345Srillig	t = tn->tn_left->tn_type->t_tspec;
31761.345Srillig	utyp = !is_integer(t) || is_uinteger(t);
31771.1Scgd	ul = sl = tn->tn_left->tn_val->v_quad;
31781.346Srillig	if (is_binary(tn))
31791.1Scgd		ur = sr = tn->tn_right->tn_val->v_quad;
31801.1Scgd
31811.287Srillig	mask = value_bits(size_in_bits(t));
31821.154Srillig	ovfl = false;
31831.1Scgd
31841.1Scgd	switch (tn->tn_op) {
31851.1Scgd	case UPLUS:
31861.1Scgd		q = sl;
31871.1Scgd		break;
31881.1Scgd	case UMINUS:
31891.1Scgd		q = -sl;
31901.348Srillig		if (sl != 0 && msb(q, t) == msb(sl, t))
31911.154Srillig			ovfl = true;
31921.1Scgd		break;
31931.1Scgd	case COMPL:
31941.1Scgd		q = ~sl;
31951.1Scgd		break;
31961.1Scgd	case MULT:
31971.22Sperry		if (utyp) {
31981.22Sperry			q = ul * ur;
31991.22Sperry			if (q != (q & mask))
32001.154Srillig				ovfl = true;
32011.22Sperry			else if ((ul != 0) && ((q / ul) != ur))
32021.154Srillig				ovfl = true;
32031.22Sperry		} else {
32041.22Sperry			q = sl * sr;
32051.348Srillig			if (msb(q, t) != (msb(sl, t) ^ msb(sr, t)))
32061.154Srillig				ovfl = true;
32071.22Sperry		}
32081.1Scgd		break;
32091.1Scgd	case DIV:
32101.1Scgd		if (sr == 0) {
32111.1Scgd			/* division by 0 */
32121.1Scgd			error(139);
32131.378Srillig			q = utyp ? -1 : INT64_MAX;
32141.1Scgd		} else {
32151.57Schristos			q = utyp ? (int64_t)(ul / ur) : sl / sr;
32161.1Scgd		}
32171.1Scgd		break;
32181.1Scgd	case MOD:
32191.1Scgd		if (sr == 0) {
32201.1Scgd			/* modulus by 0 */
32211.1Scgd			error(140);
32221.1Scgd			q = 0;
32231.1Scgd		} else {
32241.57Schristos			q = utyp ? (int64_t)(ul % ur) : sl % sr;
32251.1Scgd		}
32261.1Scgd		break;
32271.1Scgd	case PLUS:
32281.57Schristos		q = utyp ? (int64_t)(ul + ur) : sl + sr;
32291.349Srillig		if (msb(sl, t) && msb(sr, t) && !msb(q, t))
32301.349Srillig			ovfl = true;
32311.349Srillig		if (!utyp && !msb(sl, t) && !msb(sr, t) && msb(q, t))
32321.349Srillig			ovfl = true;
32331.1Scgd		break;
32341.1Scgd	case MINUS:
32351.57Schristos		q = utyp ? (int64_t)(ul - ur) : sl - sr;
32361.348Srillig		if (!utyp && msb(sl, t) && !msb(sr, t) && !msb(q, t))
32371.347Srillig			ovfl = true;
32381.348Srillig		if (!msb(sl, t) && msb(sr, t) && msb(q, t))
32391.347Srillig			ovfl = true;
32401.1Scgd		break;
32411.1Scgd	case SHL:
32421.57Schristos		q = utyp ? (int64_t)(ul << sr) : sl << sr;
32431.1Scgd		break;
32441.1Scgd	case SHR:
32451.1Scgd		/*
32461.22Sperry		 * The sign must be explicitly extended because
32471.1Scgd		 * shifts of signed values are implementation dependent.
32481.1Scgd		 */
32491.1Scgd		q = ul >> sr;
32501.298Srillig		q = convert_integer(q, t, size_in_bits(t) - (int)sr);
32511.1Scgd		break;
32521.1Scgd	case LT:
32531.154Srillig		q = (utyp ? ul < ur : sl < sr) ? 1 : 0;
32541.1Scgd		break;
32551.1Scgd	case LE:
32561.154Srillig		q = (utyp ? ul <= ur : sl <= sr) ? 1 : 0;
32571.1Scgd		break;
32581.1Scgd	case GE:
32591.154Srillig		q = (utyp ? ul >= ur : sl >= sr) ? 1 : 0;
32601.1Scgd		break;
32611.1Scgd	case GT:
32621.154Srillig		q = (utyp ? ul > ur : sl > sr) ? 1 : 0;
32631.1Scgd		break;
32641.1Scgd	case EQ:
32651.154Srillig		q = (utyp ? ul == ur : sl == sr) ? 1 : 0;
32661.1Scgd		break;
32671.1Scgd	case NE:
32681.154Srillig		q = (utyp ? ul != ur : sl != sr) ? 1 : 0;
32691.1Scgd		break;
32701.171Srillig	case BITAND:
32711.57Schristos		q = utyp ? (int64_t)(ul & ur) : sl & sr;
32721.1Scgd		break;
32731.171Srillig	case BITXOR:
32741.57Schristos		q = utyp ? (int64_t)(ul ^ ur) : sl ^ sr;
32751.1Scgd		break;
32761.171Srillig	case BITOR:
32771.57Schristos		q = utyp ? (int64_t)(ul | ur) : sl | sr;
32781.1Scgd		break;
32791.1Scgd	default:
32801.157Srillig		lint_assert(/*CONSTCOND*/false);
32811.1Scgd	}
32821.1Scgd
32831.1Scgd	/* XXX does not work for quads. */
32841.339Srillig	if (ovfl ||
32851.339Srillig	    ((uint64_t)(q | mask) != ~(uint64_t)0 && (q & ~mask) != 0)) {
32861.1Scgd		if (hflag)
32871.350Srillig			/* integer overflow detected, op '%s' */
32881.261Srillig			warning(141, op_name(tn->tn_op));
32891.1Scgd	}
32901.1Scgd
32911.356Srillig	v->v_quad = convert_integer(q, t, 0);
32921.1Scgd
32931.318Srillig	cn = build_constant(tn->tn_type, v);
32941.227Srillig	if (tn->tn_left->tn_system_dependent)
32951.227Srillig		cn->tn_system_dependent = true;
32961.346Srillig	if (is_binary(tn) && tn->tn_right->tn_system_dependent)
32971.227Srillig		cn->tn_system_dependent = true;
32981.1Scgd
32991.95Srillig	return cn;
33001.1Scgd}
33011.1Scgd
33021.1Scgd/*
33031.182Srillig * Fold constant nodes, as much as is needed for comparing the value with 0
33041.182Srillig * (test context, for controlling expressions).
33051.1Scgd */
33061.1Scgdstatic tnode_t *
33071.100Srilligfold_test(tnode_t *tn)
33081.1Scgd{
33091.153Srillig	bool	l, r;
33101.1Scgd	val_t	*v;
33111.1Scgd
33121.259Srillig	v = xcalloc(1, sizeof(*v));
33131.1Scgd	v->v_tspec = tn->tn_type->t_tspec;
33141.151Srillig	lint_assert(v->v_tspec == INT || (Tflag && v->v_tspec == BOOL));
33151.1Scgd
33161.229Srillig	l = constant_is_nonzero(tn->tn_left);
33171.346Srillig	r = is_binary(tn) && constant_is_nonzero(tn->tn_right);
33181.1Scgd
33191.1Scgd	switch (tn->tn_op) {
33201.1Scgd	case NOT:
33211.98Srillig		if (hflag && !constcond_flag)
33221.265Srillig			/* constant argument to '!' */
33231.1Scgd			warning(239);
33241.154Srillig		v->v_quad = !l ? 1 : 0;
33251.1Scgd		break;
33261.1Scgd	case LOGAND:
33271.154Srillig		v->v_quad = l && r ? 1 : 0;
33281.1Scgd		break;
33291.1Scgd	case LOGOR:
33301.154Srillig		v->v_quad = l || r ? 1 : 0;
33311.1Scgd		break;
33321.1Scgd	default:
33331.157Srillig		lint_assert(/*CONSTCOND*/false);
33341.1Scgd	}
33351.1Scgd
33361.318Srillig	return build_constant(tn->tn_type, v);
33371.1Scgd}
33381.1Scgd
33391.378Srilligstatic ldbl_t
33401.378Srilligfloating_error_value(tspec_t t, ldbl_t lv)
33411.378Srillig{
33421.378Srillig	if (t == FLOAT) {
33431.378Srillig		return lv < 0 ? -FLT_MAX : FLT_MAX;
33441.378Srillig	} else if (t == DOUBLE) {
33451.378Srillig		return lv < 0 ? -DBL_MAX : DBL_MAX;
33461.378Srillig	} else {
33471.378Srillig		/* LINTED 248: floating-point constant out of range */
33481.378Srillig		ldbl_t max = LDBL_MAX;
33491.378Srillig		return lv < 0 ? -max : max;
33501.378Srillig	}
33511.378Srillig}
33521.378Srillig
33531.1Scgd/*
33541.182Srillig * Fold constant nodes having operands with floating point type.
33551.1Scgd */
33561.1Scgdstatic tnode_t *
33571.100Srilligfold_float(tnode_t *tn)
33581.1Scgd{
33591.1Scgd	val_t	*v;
33601.1Scgd	tspec_t	t;
33611.343Srillig	ldbl_t	lv, rv = 0;
33621.1Scgd
33631.157Srillig	fpe = 0;
33641.259Srillig	v = xcalloc(1, sizeof(*v));
33651.1Scgd	v->v_tspec = t = tn->tn_type->t_tspec;
33661.1Scgd
33671.144Srillig	lint_assert(is_floating(t));
33681.107Srillig	lint_assert(t == tn->tn_left->tn_type->t_tspec);
33691.346Srillig	lint_assert(!is_binary(tn) || t == tn->tn_right->tn_type->t_tspec);
33701.1Scgd
33711.343Srillig	lv = tn->tn_left->tn_val->v_ldbl;
33721.346Srillig	if (is_binary(tn))
33731.343Srillig		rv = tn->tn_right->tn_val->v_ldbl;
33741.1Scgd
33751.1Scgd	switch (tn->tn_op) {
33761.1Scgd	case UPLUS:
33771.343Srillig		v->v_ldbl = lv;
33781.1Scgd		break;
33791.1Scgd	case UMINUS:
33801.343Srillig		v->v_ldbl = -lv;
33811.1Scgd		break;
33821.1Scgd	case MULT:
33831.343Srillig		v->v_ldbl = lv * rv;
33841.1Scgd		break;
33851.1Scgd	case DIV:
33861.343Srillig		if (rv == 0.0) {
33871.1Scgd			/* division by 0 */
33881.1Scgd			error(139);
33891.378Srillig			v->v_ldbl = floating_error_value(t, lv);
33901.1Scgd		} else {
33911.343Srillig			v->v_ldbl = lv / rv;
33921.1Scgd		}
33931.1Scgd		break;
33941.1Scgd	case PLUS:
33951.343Srillig		v->v_ldbl = lv + rv;
33961.1Scgd		break;
33971.1Scgd	case MINUS:
33981.343Srillig		v->v_ldbl = lv - rv;
33991.1Scgd		break;
34001.1Scgd	case LT:
34011.343Srillig		v->v_quad = lv < rv ? 1 : 0;
34021.1Scgd		break;
34031.1Scgd	case LE:
34041.343Srillig		v->v_quad = lv <= rv ? 1 : 0;
34051.1Scgd		break;
34061.1Scgd	case GE:
34071.343Srillig		v->v_quad = lv >= rv ? 1 : 0;
34081.1Scgd		break;
34091.1Scgd	case GT:
34101.343Srillig		v->v_quad = lv > rv ? 1 : 0;
34111.1Scgd		break;
34121.1Scgd	case EQ:
34131.343Srillig		v->v_quad = lv == rv ? 1 : 0;
34141.1Scgd		break;
34151.1Scgd	case NE:
34161.343Srillig		v->v_quad = lv != rv ? 1 : 0;
34171.1Scgd		break;
34181.1Scgd	default:
34191.157Srillig		lint_assert(/*CONSTCOND*/false);
34201.1Scgd	}
34211.1Scgd
34221.172Srillig	lint_assert(fpe != 0 || isnan((double)v->v_ldbl) == 0);
34231.382Sjmcneill	if (fpe != 0 || isfinite((double)v->v_ldbl) == 0 ||
34241.1Scgd	    (t == FLOAT &&
34251.1Scgd	     (v->v_ldbl > FLT_MAX || v->v_ldbl < -FLT_MAX)) ||
34261.1Scgd	    (t == DOUBLE &&
34271.1Scgd	     (v->v_ldbl > DBL_MAX || v->v_ldbl < -DBL_MAX))) {
34281.1Scgd		/* floating point overflow detected, op %s */
34291.261Srillig		warning(142, op_name(tn->tn_op));
34301.378Srillig		v->v_ldbl = floating_error_value(t, v->v_ldbl);
34311.342Srillig		fpe = 0;
34321.1Scgd	}
34331.1Scgd
34341.318Srillig	return build_constant(tn->tn_type, v);
34351.1Scgd}
34361.1Scgd
34371.62Schristos
34381.1Scgd/*
34391.1Scgd * Create a constant node for sizeof.
34401.1Scgd */
34411.1Scgdtnode_t *
34421.253Srilligbuild_sizeof(const type_t *tp)
34431.1Scgd{
34441.355Srillig	unsigned int size_in_bytes = type_size_in_bits(tp) / CHAR_SIZE;
34451.318Srillig	tnode_t *tn = build_integer_constant(SIZEOF_TSPEC, size_in_bytes);
34461.227Srillig	tn->tn_system_dependent = true;
34471.227Srillig	return tn;
34481.62Schristos}
34491.62Schristos
34501.84Schristos/*
34511.84Schristos * Create a constant node for offsetof.
34521.84Schristos */
34531.378Srillig/* ARGSUSED */ /* See implementation comments. */
34541.84Schristostnode_t *
34551.253Srilligbuild_offsetof(const type_t *tp, const sym_t *sym)
34561.84Schristos{
34571.392Srillig	unsigned int offset_in_bytes;
34581.392Srillig	tnode_t *tn;
34591.392Srillig
34601.392Srillig	if (!is_struct_or_union(tp->t_tspec))
34611.113Srillig		/* unacceptable operand of '%s' */
34621.84Schristos		error(111, "offsetof");
34631.89Srillig
34641.393Srillig	/* XXX: wrong size, no checking for sym fixme */
34651.392Srillig	offset_in_bytes = type_size_in_bits(tp) / CHAR_SIZE;
34661.392Srillig	tn = build_integer_constant(SIZEOF_TSPEC, offset_in_bytes);
34671.227Srillig	tn->tn_system_dependent = true;
34681.227Srillig	return tn;
34691.84Schristos}
34701.84Schristos
34711.355Srilligunsigned int
34721.253Srilligtype_size_in_bits(const type_t *tp)
34731.62Schristos{
34741.355Srillig	unsigned int elem, elsz;
34751.154Srillig	bool	flex;
34761.1Scgd
34771.1Scgd	elem = 1;
34781.154Srillig	flex = false;
34791.1Scgd	while (tp->t_tspec == ARRAY) {
34801.154Srillig		flex = true;	/* allow c99 flex arrays [] [0] */
34811.1Scgd		elem *= tp->t_dim;
34821.1Scgd		tp = tp->t_subt;
34831.1Scgd	}
34841.1Scgd	if (elem == 0) {
34851.77Schristos		if (!flex) {
34861.108Srillig			/* cannot take size/alignment of incomplete type */
34871.77Schristos			error(143);
34881.77Schristos			elem = 1;
34891.77Schristos		}
34901.1Scgd	}
34911.1Scgd	switch (tp->t_tspec) {
34921.1Scgd	case FUNC:
34931.108Srillig		/* cannot take size/alignment of function */
34941.1Scgd		error(144);
34951.1Scgd		elsz = 1;
34961.1Scgd		break;
34971.1Scgd	case STRUCT:
34981.1Scgd	case UNION:
34991.194Srillig		if (is_incomplete(tp)) {
35001.108Srillig			/* cannot take size/alignment of incomplete type */
35011.1Scgd			error(143);
35021.1Scgd			elsz = 1;
35031.1Scgd		} else {
35041.237Srillig			elsz = tp->t_str->sou_size_in_bits;
35051.1Scgd		}
35061.1Scgd		break;
35071.1Scgd	case ENUM:
35081.194Srillig		if (is_incomplete(tp)) {
35091.108Srillig			/* cannot take size/alignment of incomplete type */
35101.1Scgd			warning(143);
35111.1Scgd		}
35121.1Scgd		/* FALLTHROUGH */
35131.1Scgd	default:
35141.120Srillig		if (tp->t_bitfield) {
35151.108Srillig			/* cannot take size/alignment of bit-field */
35161.1Scgd			error(145);
35171.1Scgd		}
35181.1Scgd		if (tp->t_tspec == VOID) {
35191.108Srillig			/* cannot take size/alignment of void */
35201.1Scgd			error(146);
35211.1Scgd			elsz = 1;
35221.1Scgd		} else {
35231.228Srillig			elsz = size_in_bits(tp->t_tspec);
35241.107Srillig			lint_assert(elsz > 0);
35251.1Scgd		}
35261.1Scgd		break;
35271.1Scgd	}
35281.1Scgd
35291.355Srillig	return elem * elsz;
35301.1Scgd}
35311.1Scgd
35321.59Schristostnode_t *
35331.253Srilligbuild_alignof(const type_t *tp)
35341.59Schristos{
35351.59Schristos	switch (tp->t_tspec) {
35361.59Schristos	case ARRAY:
35371.59Schristos		break;
35381.59Schristos
35391.59Schristos	case FUNC:
35401.108Srillig		/* cannot take size/alignment of function */
35411.59Schristos		error(144);
35421.59Schristos		return 0;
35431.59Schristos
35441.59Schristos	case STRUCT:
35451.59Schristos	case UNION:
35461.194Srillig		if (is_incomplete(tp)) {
35471.108Srillig			/* cannot take size/alignment of incomplete type */
35481.59Schristos			error(143);
35491.59Schristos			return 0;
35501.59Schristos		}
35511.59Schristos		break;
35521.59Schristos	case ENUM:
35531.59Schristos		break;
35541.59Schristos	default:
35551.120Srillig		if (tp->t_bitfield) {
35561.108Srillig			/* cannot take size/alignment of bit-field */
35571.59Schristos			error(145);
35581.59Schristos			return 0;
35591.59Schristos		}
35601.59Schristos		if (tp->t_tspec == VOID) {
35611.108Srillig			/* cannot take size/alignment of void */
35621.59Schristos			error(146);
35631.59Schristos			return 0;
35641.59Schristos		}
35651.59Schristos		break;
35661.59Schristos	}
35671.59Schristos
35681.318Srillig	return build_integer_constant(SIZEOF_TSPEC,
35691.220Srillig	    (int64_t)alignment_in_bits(tp) / CHAR_SIZE);
35701.59Schristos}
35711.59Schristos
35721.59Schristos/*
35731.1Scgd * Type casts.
35741.1Scgd */
35751.1Scgdtnode_t *
35761.20Slukemcast(tnode_t *tn, type_t *tp)
35771.1Scgd{
35781.1Scgd	tspec_t	nt, ot;
35791.1Scgd
35801.1Scgd	if (tn == NULL)
35811.95Srillig		return NULL;
35821.1Scgd
35831.232Srillig	/*
35841.232Srillig	 * XXX: checking for tp == NULL is only a quick fix for PR 22119.
35851.232Srillig	 *  The proper fix needs to be investigated properly.
35861.232Srillig	 *  See d_pr_22119.c for how to get here.
35871.232Srillig	 */
35881.232Srillig	if (tp == NULL)
35891.232Srillig		return NULL;
35901.232Srillig
35911.1Scgd	tn = cconv(tn);
35921.1Scgd
35931.1Scgd	nt = tp->t_tspec;
35941.1Scgd	ot = tn->tn_type->t_tspec;
35951.1Scgd
35961.1Scgd	if (nt == VOID) {
35971.1Scgd		/*
35981.106Srillig		 * XXX ANSI C requires scalar types or void (Plauger & Brodie).
35991.182Srillig		 * But this seems really questionable.
36001.1Scgd		 */
36011.83Schristos	} else if (nt == UNION) {
36021.83Schristos		sym_t *m;
36031.208Srillig		struct_or_union *str = tp->t_str;
36041.329Srillig		if (!gflag) {
36051.329Srillig			/* union cast is a GCC extension */
36061.83Schristos			error(328);
36071.83Schristos			return NULL;
36081.83Schristos		}
36091.208Srillig		for (m = str->sou_first_member; m != NULL; m = m->s_next) {
36101.330Srillig			if (eqtype(m->s_type, tn->tn_type,
36111.330Srillig			    false, false, NULL)) {
36121.256Srillig				tn = expr_zalloc_tnode();
36131.83Schristos				tn->tn_op = CVT;
36141.83Schristos				tn->tn_type = tp;
36151.154Srillig				tn->tn_cast = true;
36161.83Schristos				tn->tn_right = NULL;
36171.83Schristos				return tn;
36181.83Schristos			}
36191.83Schristos		}
36201.113Srillig		/* type '%s' is not a member of '%s' */
36211.115Srillig		error(329, type_name(tn->tn_type), type_name(tp));
36221.83Schristos		return NULL;
36231.83Schristos	} else if (nt == STRUCT || nt == ARRAY || nt == FUNC) {
36241.328Srillig		/* Casting to a struct is an undocumented GCC extension. */
36251.328Srillig		if (!(gflag && nt == STRUCT))
36261.319Srillig			goto invalid_cast;
36271.1Scgd	} else if (ot == STRUCT || ot == UNION) {
36281.319Srillig		goto invalid_cast;
36291.1Scgd	} else if (ot == VOID) {
36301.1Scgd		/* improper cast of void expression */
36311.1Scgd		error(148);
36321.95Srillig		return NULL;
36331.144Srillig	} else if (is_integer(nt) && is_scalar(ot)) {
36341.1Scgd		/* ok */
36351.144Srillig	} else if (is_floating(nt) && is_arithmetic(ot)) {
36361.1Scgd		/* ok */
36371.144Srillig	} else if (nt == PTR && is_integer(ot)) {
36381.1Scgd		/* ok */
36391.1Scgd	} else if (nt == PTR && ot == PTR) {
36401.7Sjpo		if (!tp->t_subt->t_const && tn->tn_type->t_subt->t_const) {
36411.7Sjpo			if (hflag)
36421.196Srillig				/* cast discards 'const' from type '%s' */
36431.196Srillig				warning(275, type_name(tn->tn_type));
36441.7Sjpo		}
36451.319Srillig	} else
36461.319Srillig		goto invalid_cast;
36471.1Scgd
36481.1Scgd	tn = convert(CVT, 0, tp, tn);
36491.154Srillig	tn->tn_cast = true;
36501.1Scgd
36511.95Srillig	return tn;
36521.319Srillig
36531.319Srilliginvalid_cast:
36541.319Srillig	/* invalid cast from '%s' to '%s' */
36551.319Srillig	error(147, type_name(tn->tn_type), type_name(tp));
36561.319Srillig	return NULL;
36571.1Scgd}
36581.1Scgd
36591.1Scgd/*
36601.1Scgd * Create the node for a function argument.
36611.122Srillig * All necessary conversions and type checks are done in
36621.318Srillig * build_function_call because build_function_argument has no
36631.122Srillig * information about expected argument types.
36641.1Scgd */
36651.1Scgdtnode_t *
36661.318Srilligbuild_function_argument(tnode_t *args, tnode_t *arg)
36671.1Scgd{
36681.1Scgd	tnode_t	*ntn;
36691.1Scgd
36701.1Scgd	/*
36711.1Scgd	 * If there was a serious error in the expression for the argument,
36721.1Scgd	 * create a dummy argument so the positions of the remaining arguments
36731.1Scgd	 * will not change.
36741.1Scgd	 */
36751.1Scgd	if (arg == NULL)
36761.318Srillig		arg = build_integer_constant(INT, 0);
36771.1Scgd
36781.395Srillig	ntn = new_tnode(PUSH, arg->tn_sys, arg->tn_type, arg, args);
36791.1Scgd
36801.95Srillig	return ntn;
36811.1Scgd}
36821.1Scgd
36831.1Scgd/*
36841.1Scgd * Create the node for a function call. Also check types of
36851.1Scgd * function arguments and insert conversions, if necessary.
36861.1Scgd */
36871.1Scgdtnode_t *
36881.395Srilligbuild_function_call(tnode_t *func, bool sys, tnode_t *args)
36891.1Scgd{
36901.1Scgd	tnode_t	*ntn;
36911.1Scgd	op_t	fcop;
36921.1Scgd
36931.1Scgd	if (func == NULL)
36941.95Srillig		return NULL;
36951.1Scgd
36961.1Scgd	if (func->tn_op == NAME && func->tn_type->t_tspec == FUNC) {
36971.1Scgd		fcop = CALL;
36981.1Scgd	} else {
36991.1Scgd		fcop = ICALL;
37001.1Scgd	}
37011.1Scgd
37021.266Srillig	check_ctype_function_call(func, args);
37031.266Srillig
37041.1Scgd	/*
37051.1Scgd	 * after cconv() func will always be a pointer to a function
37061.1Scgd	 * if it is a valid function designator.
37071.1Scgd	 */
37081.1Scgd	func = cconv(func);
37091.1Scgd
37101.1Scgd	if (func->tn_type->t_tspec != PTR ||
37111.1Scgd	    func->tn_type->t_subt->t_tspec != FUNC) {
37121.108Srillig		/* illegal function (type %s) */
37131.115Srillig		error(149, type_name(func->tn_type));
37141.95Srillig		return NULL;
37151.1Scgd	}
37161.1Scgd
37171.100Srillig	args = check_function_arguments(func->tn_type->t_subt, args);
37181.1Scgd
37191.395Srillig	ntn = new_tnode(fcop, sys, func->tn_type->t_subt->t_subt, func, args);
37201.1Scgd
37211.95Srillig	return ntn;
37221.1Scgd}
37231.1Scgd
37241.1Scgd/*
37251.1Scgd * Check types of all function arguments and insert conversions,
37261.1Scgd * if necessary.
37271.1Scgd */
37281.1Scgdstatic tnode_t *
37291.100Srilligcheck_function_arguments(type_t *ftp, tnode_t *args)
37301.1Scgd{
37311.1Scgd	tnode_t	*arg;
37321.1Scgd	sym_t	*asym;
37331.1Scgd	tspec_t	at;
37341.1Scgd	int	narg, npar, n, i;
37351.1Scgd
37361.1Scgd	/* get # of args in the prototype */
37371.1Scgd	npar = 0;
37381.101Srillig	for (asym = ftp->t_args; asym != NULL; asym = asym->s_next)
37391.1Scgd		npar++;
37401.1Scgd
37411.1Scgd	/* get # of args in function call */
37421.1Scgd	narg = 0;
37431.1Scgd	for (arg = args; arg != NULL; arg = arg->tn_right)
37441.1Scgd		narg++;
37451.1Scgd
37461.1Scgd	asym = ftp->t_args;
37471.1Scgd	if (ftp->t_proto && npar != narg && !(ftp->t_vararg && npar < narg)) {
37481.1Scgd		/* argument mismatch: %d arg%s passed, %d expected */
37491.1Scgd		error(150, narg, narg > 1 ? "s" : "", npar);
37501.1Scgd		asym = NULL;
37511.1Scgd	}
37521.20Slukem
37531.1Scgd	for (n = 1; n <= narg; n++) {
37541.1Scgd
37551.1Scgd		/*
37561.1Scgd		 * The rightmost argument is at the top of the argument
37571.1Scgd		 * subtree.
37581.1Scgd		 */
37591.20Slukem		for (i = narg, arg = args; i > n; i--, arg = arg->tn_right)
37601.20Slukem			continue;
37611.1Scgd
37621.106Srillig		/* some things which are always not allowed */
37631.1Scgd		if ((at = arg->tn_left->tn_type->t_tspec) == VOID) {
37641.1Scgd			/* void expressions may not be arguments, arg #%d */
37651.1Scgd			error(151, n);
37661.95Srillig			return NULL;
37671.1Scgd		} else if ((at == STRUCT || at == UNION) &&
37681.194Srillig			   is_incomplete(arg->tn_left->tn_type)) {
37691.1Scgd			/* argument cannot have unknown size, arg #%d */
37701.1Scgd			error(152, n);
37711.95Srillig			return NULL;
37721.144Srillig		} else if (is_integer(at) &&
37731.209Srillig			   arg->tn_left->tn_type->t_is_enum &&
37741.194Srillig			   is_incomplete(arg->tn_left->tn_type)) {
37751.1Scgd			/* argument cannot have unknown size, arg #%d */
37761.1Scgd			warning(152, n);
37771.1Scgd		}
37781.1Scgd
37791.1Scgd		/* class conversions (arg in value context) */
37801.1Scgd		arg->tn_left = cconv(arg->tn_left);
37811.1Scgd
37821.1Scgd		if (asym != NULL) {
37831.100Srillig			arg->tn_left = check_prototype_argument(
37841.100Srillig			    n, asym->s_type, arg->tn_left);
37851.1Scgd		} else {
37861.172Srillig			arg->tn_left = promote(NOOP, true, arg->tn_left);
37871.1Scgd		}
37881.1Scgd		arg->tn_type = arg->tn_left->tn_type;
37891.1Scgd
37901.1Scgd		if (asym != NULL)
37911.101Srillig			asym = asym->s_next;
37921.1Scgd	}
37931.1Scgd
37941.95Srillig	return args;
37951.1Scgd}
37961.1Scgd
37971.1Scgd/*
37981.1Scgd * Compare the type of an argument with the corresponding type of a
37991.1Scgd * prototype parameter. If it is a valid combination, but both types
38001.1Scgd * are not the same, insert a conversion to convert the argument into
38011.1Scgd * the type of the parameter.
38021.1Scgd */
38031.1Scgdstatic tnode_t *
38041.100Srilligcheck_prototype_argument(
38051.100Srillig	int	n,		/* pos of arg */
38061.20Slukem	type_t	*tp,		/* expected type (from prototype) */
38071.20Slukem	tnode_t	*tn)		/* argument */
38081.1Scgd{
38091.1Scgd	tnode_t	*ln;
38101.154Srillig	bool	dowarn;
38111.1Scgd
38121.259Srillig	ln = xcalloc(1, sizeof(*ln));
38131.320Srillig	ln->tn_type = expr_unqualified_type(tp);
38141.154Srillig	ln->tn_lvalue = true;
38151.1Scgd	if (typeok(FARG, n, ln, tn)) {
38161.154Srillig		if (!eqtype(tp, tn->tn_type,
38171.154Srillig		    true, false, (dowarn = false, &dowarn)) || dowarn)
38181.1Scgd			tn = convert(FARG, n, tp, tn);
38191.1Scgd	}
38201.1Scgd	free(ln);
38211.95Srillig	return tn;
38221.1Scgd}
38231.1Scgd
38241.1Scgd/*
38251.1Scgd * Return the value of an integral constant expression.
38261.1Scgd * If the expression is not constant or its type is not an integer
38271.1Scgd * type, an error message is printed.
38281.1Scgd */
38291.1Scgdval_t *
38301.154Srilligconstant(tnode_t *tn, bool required)
38311.1Scgd{
38321.1Scgd	val_t	*v;
38331.1Scgd
38341.1Scgd	if (tn != NULL)
38351.1Scgd		tn = cconv(tn);
38361.1Scgd	if (tn != NULL)
38371.172Srillig		tn = promote(NOOP, false, tn);
38381.1Scgd
38391.259Srillig	v = xcalloc(1, sizeof(*v));
38401.1Scgd
38411.1Scgd	if (tn == NULL) {
38421.107Srillig		lint_assert(nerr != 0);
38431.325Srillig		debug_step("constant node is null; returning 1 instead");
38441.1Scgd		v->v_tspec = INT;
38451.1Scgd		v->v_quad = 1;
38461.95Srillig		return v;
38471.1Scgd	}
38481.1Scgd
38491.1Scgd	v->v_tspec = tn->tn_type->t_tspec;
38501.1Scgd
38511.1Scgd	if (tn->tn_op == CON) {
38521.107Srillig		lint_assert(tn->tn_type->t_tspec == tn->tn_val->v_tspec);
38531.144Srillig		if (is_integer(tn->tn_val->v_tspec)) {
38541.289Srillig			v->v_unsigned_since_c90 =
38551.289Srillig			    tn->tn_val->v_unsigned_since_c90;
38561.1Scgd			v->v_quad = tn->tn_val->v_quad;
38571.95Srillig			return v;
38581.1Scgd		}
38591.1Scgd		v->v_quad = tn->tn_val->v_ldbl;
38601.1Scgd	} else {
38611.1Scgd		v->v_quad = 1;
38621.1Scgd	}
38631.1Scgd
38641.31Schristos	if (required)
38651.113Srillig		/* integral constant expression expected */
38661.31Schristos		error(55);
38671.31Schristos	else
38681.113Srillig		/* variable array dimension is a C99/GCC extension */
38691.45Schristos		c99ism(318);
38701.1Scgd
38711.144Srillig	if (!is_integer(v->v_tspec))
38721.1Scgd		v->v_tspec = INT;
38731.1Scgd
38741.95Srillig	return v;
38751.1Scgd}
38761.1Scgd
38771.211Srilligstatic bool
38781.211Srilligis_constcond_false(const tnode_t *tn, tspec_t t)
38791.211Srillig{
38801.211Srillig	return (t == BOOL || t == INT) &&
38811.211Srillig	       tn->tn_op == CON && tn->tn_val->v_quad == 0;
38821.211Srillig}
38831.211Srillig
38841.1Scgd/*
38851.317Srillig * Perform some tests on expressions which can't be done in build_binary()
38861.317Srillig * and functions called by build_binary(). These tests must be done here
38871.317Srillig * because we need some information about the context in which the operations
38881.1Scgd * are performed.
38891.217Srillig * After all tests are performed and dofreeblk is true, expr() frees the
38901.217Srillig * memory which is used for the expression.
38911.1Scgd */
38921.1Scgdvoid
38931.280Srilligexpr(tnode_t *tn, bool vctx, bool tctx, bool dofreeblk, bool is_do_while)
38941.1Scgd{
38951.20Slukem
38961.305Srillig	if (tn == NULL) {	/* in case of errors */
38971.257Srillig		expr_free_all();
38981.1Scgd		return;
38991.1Scgd	}
39001.1Scgd
39011.218Srillig	/* expr() is also called in global initializations */
39021.280Srillig	if (dcs->d_ctx != EXTERN && !is_do_while)
39031.98Srillig		check_statement_reachable();
39041.1Scgd
39051.172Srillig	check_expr_misc(tn, vctx, tctx, !tctx, false, false, false);
39061.1Scgd	if (tn->tn_op == ASSIGN) {
39071.1Scgd		if (hflag && tctx)
39081.1Scgd			/* assignment in conditional context */
39091.1Scgd			warning(159);
39101.1Scgd	} else if (tn->tn_op == CON) {
39111.202Srillig		if (hflag && tctx && !constcond_flag &&
39121.227Srillig		    !tn->tn_system_dependent &&
39131.280Srillig		    !(is_do_while &&
39141.211Srillig		      is_constcond_false(tn, tn->tn_type->t_tspec)))
39151.1Scgd			/* constant in conditional context */
39161.1Scgd			warning(161);
39171.1Scgd	}
39181.164Srillig	if (!modtab[tn->tn_op].m_has_side_effect) {
39191.1Scgd		/*
39201.1Scgd		 * for left operands of COMMA this warning is already
39211.1Scgd		 * printed
39221.1Scgd		 */
39231.1Scgd		if (tn->tn_op != COMMA && !vctx && !tctx)
39241.100Srillig			check_null_effect(tn);
39251.1Scgd	}
39261.326Srillig	debug_node(tn);
39271.1Scgd
39281.1Scgd	/* free the tree memory */
39291.54Sdholland	if (dofreeblk)
39301.257Srillig		expr_free_all();
39311.1Scgd}
39321.1Scgd
39331.197Srilligstatic bool
39341.393Srillighas_side_effect(const tnode_t *tn) /* NOLINT(misc-no-recursion) */
39351.1Scgd{
39361.199Srillig	op_t op = tn->tn_op;
39371.199Srillig
39381.199Srillig	if (modtab[op].m_has_side_effect)
39391.199Srillig		return true;
39401.199Srillig
39411.199Srillig	if (op == CVT && tn->tn_type->t_tspec == VOID)
39421.199Srillig		return has_side_effect(tn->tn_left);
39431.199Srillig
39441.199Srillig	/* XXX: Why not has_side_effect(tn->tn_left) as well? */
39451.199Srillig	if (op == LOGAND || op == LOGOR)
39461.199Srillig		return has_side_effect(tn->tn_right);
39471.199Srillig
39481.199Srillig	/* XXX: Why not has_side_effect(tn->tn_left) as well? */
39491.199Srillig	if (op == QUEST)
39501.199Srillig		return has_side_effect(tn->tn_right);
39511.199Srillig
39521.199Srillig	if (op == COLON || op == COMMA) {
39531.199Srillig		return has_side_effect(tn->tn_left) ||
39541.199Srillig		       has_side_effect(tn->tn_right);
39551.1Scgd	}
39561.197Srillig
39571.199Srillig	return false;
39581.197Srillig}
39591.197Srillig
39601.341Srilligstatic bool
39611.341Srilligis_void_cast(const tnode_t *tn)
39621.341Srillig{
39631.341Srillig
39641.341Srillig	return tn->tn_op == CVT && tn->tn_cast &&
39651.341Srillig	       tn->tn_type->t_tspec == VOID;
39661.341Srillig}
39671.341Srillig
39681.341Srilligstatic bool
39691.341Srilligis_local_symbol(const tnode_t *tn)
39701.341Srillig{
39711.341Srillig
39721.341Srillig	return tn->tn_op == LOAD &&
39731.341Srillig	       tn->tn_left->tn_op == NAME &&
39741.341Srillig	       tn->tn_left->tn_sym->s_scl == AUTO;
39751.341Srillig}
39761.341Srillig
39771.341Srilligstatic bool
39781.341Srilligis_int_constant_zero(const tnode_t *tn)
39791.341Srillig{
39801.341Srillig
39811.341Srillig	return tn->tn_op == CON &&
39821.341Srillig	       tn->tn_type->t_tspec == INT &&
39831.341Srillig	       tn->tn_val->v_quad == 0;
39841.341Srillig}
39851.341Srillig
39861.197Srilligstatic void
39871.197Srilligcheck_null_effect(const tnode_t *tn)
39881.197Srillig{
39891.197Srillig
39901.341Srillig	if (!hflag)
39911.341Srillig		return;
39921.342Srillig	if (has_side_effect(tn))
39931.341Srillig		return;
39941.341Srillig	if (is_void_cast(tn) && is_local_symbol(tn->tn_left))
39951.341Srillig		return;
39961.341Srillig	if (is_void_cast(tn) && is_int_constant_zero(tn->tn_left))
39971.341Srillig		return;
39981.341Srillig
39991.341Srillig	/* expression has null effect */
40001.341Srillig	warning(129);
40011.1Scgd}
40021.1Scgd
40031.370Srilligstatic void
40041.370Srilligcheck_expr_addr(const tnode_t *ln, bool szof, bool fcall)
40051.370Srillig{
40061.370Srillig	/* XXX: Taking warn_about_unreachable into account here feels wrong. */
40071.370Srillig	if (ln->tn_op == NAME && (reached || !warn_about_unreachable)) {
40081.370Srillig		if (!szof)
40091.370Srillig			mark_as_set(ln->tn_sym);
40101.370Srillig		mark_as_used(ln->tn_sym, fcall, szof);
40111.370Srillig	}
40121.370Srillig	if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS)
40131.370Srillig		/* check the range of array indices */
40141.370Srillig		check_array_index(ln->tn_left, true);
40151.370Srillig}
40161.370Srillig
40171.370Srilligstatic void
40181.370Srilligcheck_expr_load(const tnode_t *ln)
40191.370Srillig{
40201.370Srillig	if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS)
40211.370Srillig		/* check the range of array indices */
40221.370Srillig		check_array_index(ln->tn_left, false);
40231.370Srillig}
40241.370Srillig
40251.370Srilligstatic void
40261.370Srilligcheck_expr_side_effect(const tnode_t *ln, bool szof)
40271.1Scgd{
40281.370Srillig	scl_t sc;
40291.370Srillig	dinfo_t *di;
40301.370Srillig
40311.370Srillig	/* XXX: Taking warn_about_unreachable into account here feels wrong. */
40321.370Srillig	if (ln->tn_op == NAME && (reached || !warn_about_unreachable)) {
40331.370Srillig		sc = ln->tn_sym->s_scl;
40341.370Srillig		/*
40351.370Srillig		 * Look if there was a asm statement in one of the
40361.370Srillig		 * compound statements we are in. If not, we don't
40371.370Srillig		 * print a warning.
40381.370Srillig		 */
40391.370Srillig		for (di = dcs; di != NULL; di = di->d_next) {
40401.370Srillig			if (di->d_asm)
40411.370Srillig				break;
40421.370Srillig		}
40431.370Srillig		if (sc != EXTERN && sc != STATIC &&
40441.370Srillig		    !ln->tn_sym->s_set && !szof && di == NULL) {
40451.370Srillig			/* %s may be used before set */
40461.370Srillig			warning(158, ln->tn_sym->s_name);
40471.370Srillig			mark_as_set(ln->tn_sym);
40481.370Srillig		}
40491.370Srillig		mark_as_used(ln->tn_sym, false, false);
40501.370Srillig	}
40511.370Srillig}
40521.1Scgd
40531.370Srilligstatic void
40541.370Srilligcheck_expr_assign(const tnode_t *ln, bool szof)
40551.370Srillig{
40561.370Srillig	/* XXX: Taking warn_about_unreachable into account here feels wrong. */
40571.370Srillig	if (ln->tn_op == NAME && !szof && (reached || !warn_about_unreachable)) {
40581.370Srillig		mark_as_set(ln->tn_sym);
40591.370Srillig		if (ln->tn_sym->s_scl == EXTERN)
40601.370Srillig			outusg(ln->tn_sym);
40611.370Srillig	}
40621.370Srillig	if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS)
40631.370Srillig		/* check the range of array indices */
40641.370Srillig		check_array_index(ln->tn_left, false);
40651.370Srillig}
40661.1Scgd
40671.370Srilligstatic void
40681.370Srilligcheck_expr_call(const tnode_t *tn, const tnode_t *ln,
40691.381Srillig		bool szof, bool vctx, bool tctx, bool retval_discarded)
40701.370Srillig{
40711.370Srillig	lint_assert(ln->tn_op == ADDR);
40721.370Srillig	lint_assert(ln->tn_left->tn_op == NAME);
40731.370Srillig	if (!szof &&
40741.370Srillig	    !is_compiler_builtin(ln->tn_left->tn_sym->s_name))
40751.381Srillig		outcall(tn, vctx || tctx, retval_discarded);
40761.370Srillig}
40771.1Scgd
40781.370Srilligstatic bool
40791.370Srilligcheck_expr_op(const tnode_t *tn, op_t op, const tnode_t *ln,
40801.381Srillig	      bool szof, bool fcall, bool vctx, bool tctx,
40811.381Srillig	      bool retval_discarded, bool eqwarn)
40821.370Srillig{
40831.1Scgd	switch (op) {
40841.169Srillig	case ADDR:
40851.370Srillig		check_expr_addr(ln, szof, fcall);
40861.1Scgd		break;
40871.1Scgd	case LOAD:
40881.370Srillig		check_expr_load(ln);
40891.1Scgd		/* FALLTHROUGH */
40901.1Scgd	case PUSH:
40911.1Scgd	case INCBEF:
40921.1Scgd	case DECBEF:
40931.1Scgd	case INCAFT:
40941.1Scgd	case DECAFT:
40951.1Scgd	case ADDASS:
40961.1Scgd	case SUBASS:
40971.1Scgd	case MULASS:
40981.1Scgd	case DIVASS:
40991.1Scgd	case MODASS:
41001.1Scgd	case ANDASS:
41011.1Scgd	case ORASS:
41021.1Scgd	case XORASS:
41031.1Scgd	case SHLASS:
41041.1Scgd	case SHRASS:
41051.46Schristos	case REAL:
41061.46Schristos	case IMAG:
41071.370Srillig		check_expr_side_effect(ln, szof);
41081.1Scgd		break;
41091.1Scgd	case ASSIGN:
41101.370Srillig		check_expr_assign(ln, szof);
41111.1Scgd		break;
41121.1Scgd	case CALL:
41131.381Srillig		check_expr_call(tn, ln, szof, vctx, tctx, retval_discarded);
41141.1Scgd		break;
41151.1Scgd	case EQ:
41161.1Scgd		if (hflag && eqwarn)
41171.113Srillig			/* operator '==' found where '=' was expected */
41181.1Scgd			warning(160);
41191.1Scgd		break;
41201.1Scgd	case CON:
41211.1Scgd	case NAME:
41221.1Scgd	case STRING:
41231.370Srillig		return false;
41241.73Schristos		/* LINTED206: (enumeration values not handled in switch) */
41251.171Srillig	case BITOR:
41261.171Srillig	case BITXOR:
41271.14Schristos	case NE:
41281.14Schristos	case GE:
41291.14Schristos	case GT:
41301.14Schristos	case LE:
41311.14Schristos	case LT:
41321.14Schristos	case SHR:
41331.14Schristos	case SHL:
41341.14Schristos	case MINUS:
41351.14Schristos	case PLUS:
41361.14Schristos	case MOD:
41371.14Schristos	case DIV:
41381.14Schristos	case MULT:
41391.170Srillig	case INDIR:
41401.14Schristos	case UMINUS:
41411.14Schristos	case UPLUS:
41421.14Schristos	case DEC:
41431.14Schristos	case INC:
41441.14Schristos	case COMPL:
41451.14Schristos	case NOT:
41461.14Schristos	case POINT:
41471.14Schristos	case ARROW:
41481.14Schristos	case NOOP:
41491.171Srillig	case BITAND:
41501.14Schristos	case FARG:
41511.14Schristos	case CASE:
41521.14Schristos	case INIT:
41531.14Schristos	case RETURN:
41541.14Schristos	case ICALL:
41551.14Schristos	case CVT:
41561.14Schristos	case COMMA:
41571.14Schristos	case FSEL:
41581.14Schristos	case COLON:
41591.14Schristos	case QUEST:
41601.14Schristos	case LOGOR:
41611.14Schristos	case LOGAND:
41621.14Schristos		break;
41631.1Scgd	}
41641.370Srillig	return true;
41651.370Srillig}
41661.370Srillig
41671.370Srillig/* ARGSUSED */
41681.370Srilligvoid
41691.370Srilligcheck_expr_misc(const tnode_t *tn, bool vctx, bool tctx,
41701.381Srillig		bool eqwarn, bool fcall, bool retval_discarded, bool szof)
41711.370Srillig{
41721.392Srillig	tnode_t *ln, *rn;
41731.370Srillig	const mod_t *mp;
41741.392Srillig	op_t op;
41751.392Srillig	bool cvctx, ctctx, eq, discard;
41761.370Srillig
41771.370Srillig	if (tn == NULL)
41781.370Srillig		return;
41791.370Srillig
41801.370Srillig	ln = tn->tn_left;
41811.370Srillig	rn = tn->tn_right;
41821.370Srillig	mp = &modtab[op = tn->tn_op];
41831.370Srillig
41841.370Srillig	if (!check_expr_op(tn, op, ln,
41851.381Srillig	    szof, fcall, vctx, tctx, retval_discarded, eqwarn))
41861.370Srillig		return;
41871.1Scgd
41881.392Srillig	cvctx = mp->m_left_value_context;
41891.392Srillig	ctctx = mp->m_left_test_context;
41901.392Srillig	eq = mp->m_warn_if_operand_eq &&
41911.392Srillig	     !ln->tn_parenthesized &&
41921.392Srillig	     rn != NULL && !rn->tn_parenthesized;
41931.173Srillig
41941.1Scgd	/*
41951.1Scgd	 * values of operands of ':' are not used if the type of at least
41961.1Scgd	 * one of the operands (for gcc compatibility) is void
41971.1Scgd	 * XXX test/value context of QUEST should probably be used as
41981.1Scgd	 * context for both operands of COLON
41991.1Scgd	 */
42001.1Scgd	if (op == COLON && tn->tn_type->t_tspec == VOID)
42011.154Srillig		cvctx = ctctx = false;
42021.392Srillig	discard = op == CVT && tn->tn_type->t_tspec == VOID;
42031.173Srillig	check_expr_misc(ln, cvctx, ctctx, eq, op == CALL, discard, szof);
42041.1Scgd
42051.1Scgd	switch (op) {
42061.1Scgd	case PUSH:
42071.1Scgd		if (rn != NULL)
42081.173Srillig			check_expr_misc(rn, false, false, eq, false, false,
42091.173Srillig			    szof);
42101.1Scgd		break;
42111.1Scgd	case LOGAND:
42121.1Scgd	case LOGOR:
42131.173Srillig		check_expr_misc(rn, false, true, eq, false, false, szof);
42141.1Scgd		break;
42151.1Scgd	case COLON:
42161.173Srillig		check_expr_misc(rn, cvctx, ctctx, eq, false, false, szof);
42171.19Smycroft		break;
42181.19Smycroft	case COMMA:
42191.173Srillig		check_expr_misc(rn, vctx, tctx, eq, false, false, szof);
42201.1Scgd		break;
42211.1Scgd	default:
42221.1Scgd		if (mp->m_binary)
42231.173Srillig			check_expr_misc(rn, true, false, eq, false, false,
42241.173Srillig			    szof);
42251.1Scgd		break;
42261.1Scgd	}
42271.1Scgd}
42281.1Scgd
42291.1Scgd/*
42301.1Scgd * Checks the range of array indices, if possible.
42311.1Scgd * amper is set if only the address of the element is used. This
42321.106Srillig * means that the index is allowed to refer to the first element
42331.1Scgd * after the array.
42341.1Scgd */
42351.1Scgdstatic void
42361.154Srilligcheck_array_index(tnode_t *tn, bool amper)
42371.1Scgd{
42381.1Scgd	int	dim;
42391.1Scgd	tnode_t	*ln, *rn;
42401.1Scgd	int	elsz;
42411.25Sthorpej	int64_t	con;
42421.1Scgd
42431.1Scgd	ln = tn->tn_left;
42441.1Scgd	rn = tn->tn_right;
42451.1Scgd
42461.1Scgd	/* We can only check constant indices. */
42471.1Scgd	if (rn->tn_op != CON)
42481.1Scgd		return;
42491.1Scgd
42501.1Scgd	/* Return if the left node does not stem from an array. */
42511.169Srillig	if (ln->tn_op != ADDR)
42521.1Scgd		return;
42531.1Scgd	if (ln->tn_left->tn_op != STRING && ln->tn_left->tn_op != NAME)
42541.1Scgd		return;
42551.1Scgd	if (ln->tn_left->tn_type->t_tspec != ARRAY)
42561.1Scgd		return;
42571.20Slukem
42581.1Scgd	/*
42591.1Scgd	 * For incomplete array types, we can print a warning only if
42601.1Scgd	 * the index is negative.
42611.1Scgd	 */
42621.194Srillig	if (is_incomplete(ln->tn_left->tn_type) && rn->tn_val->v_quad >= 0)
42631.1Scgd		return;
42641.1Scgd
42651.1Scgd	/* Get the size of one array element */
42661.1Scgd	if ((elsz = length(ln->tn_type->t_subt, NULL)) == 0)
42671.1Scgd		return;
42681.136Srillig	elsz /= CHAR_SIZE;
42691.1Scgd
42701.1Scgd	/* Change the unit of the index from bytes to element size. */
42711.144Srillig	if (is_uinteger(rn->tn_type->t_tspec)) {
42721.25Sthorpej		con = (uint64_t)rn->tn_val->v_quad / elsz;
42731.1Scgd	} else {
42741.1Scgd		con = rn->tn_val->v_quad / elsz;
42751.1Scgd	}
42761.1Scgd
42771.1Scgd	dim = ln->tn_left->tn_type->t_dim + (amper ? 1 : 0);
42781.1Scgd
42791.144Srillig	if (!is_uinteger(rn->tn_type->t_tspec) && con < 0) {
42801.1Scgd		/* array subscript cannot be negative: %ld */
42811.1Scgd		warning(167, (long)con);
42821.57Schristos	} else if (dim > 0 && (uint64_t)con >= (uint64_t)dim) {
42831.1Scgd		/* array subscript cannot be > %d: %ld */
42841.1Scgd		warning(168, dim - 1, (long)con);
42851.1Scgd	}
42861.1Scgd}
42871.1Scgd
42881.359Srilligstatic bool
42891.359Srilligis_out_of_char_range(const tnode_t *tn)
42901.359Srillig{
42911.359Srillig	return tn->tn_op == CON &&
42921.360Srillig	       !(0 <= tn->tn_val->v_quad &&
42931.360Srillig		 tn->tn_val->v_quad < 1 << (CHAR_SIZE - 1));
42941.359Srillig}
42951.359Srillig
42961.1Scgd/*
42971.17Smycroft * Check for ordered comparisons of unsigned values with 0.
42981.1Scgd */
42991.1Scgdstatic void
43001.100Srilligcheck_integer_comparison(op_t op, tnode_t *ln, tnode_t *rn)
43011.1Scgd{
43021.1Scgd	tspec_t	lt, rt;
43031.1Scgd
43041.1Scgd	lt = ln->tn_type->t_tspec;
43051.1Scgd	rt = rn->tn_type->t_tspec;
43061.1Scgd
43071.1Scgd	if (ln->tn_op != CON && rn->tn_op != CON)
43081.1Scgd		return;
43091.1Scgd
43101.144Srillig	if (!is_integer(lt) || !is_integer(rt))
43111.1Scgd		return;
43121.1Scgd
43131.385Srillig	if (hflag || pflag) {
43141.385Srillig		if (lt == CHAR && is_out_of_char_range(rn)) {
43151.385Srillig			/* nonportable character comparison '%s %d' */
43161.385Srillig			warning(230, op_name(op), (int)rn->tn_val->v_quad);
43171.385Srillig			return;
43181.385Srillig		}
43191.385Srillig		if (rt == CHAR && is_out_of_char_range(ln)) {
43201.385Srillig			/* nonportable character comparison '%s %d' */
43211.385Srillig			warning(230, op_name(op), (int)ln->tn_val->v_quad);
43221.385Srillig			return;
43231.385Srillig		}
43241.1Scgd	}
43251.385Srillig
43261.144Srillig	if (is_uinteger(lt) && !is_uinteger(rt) &&
43271.1Scgd	    rn->tn_op == CON && rn->tn_val->v_quad <= 0) {
43281.1Scgd		if (rn->tn_val->v_quad < 0) {
43291.17Smycroft			/* comparison of %s with %s, op %s */
43301.115Srillig			warning(162, type_name(ln->tn_type),
43311.261Srillig			    "negative constant", op_name(op));
43321.379Srillig		} else if (op == LT || op == GE) {
43331.17Smycroft			/* comparison of %s with %s, op %s */
43341.261Srillig			warning(162, type_name(ln->tn_type), "0", op_name(op));
43351.1Scgd		}
43361.1Scgd		return;
43371.1Scgd	}
43381.144Srillig	if (is_uinteger(rt) && !is_uinteger(lt) &&
43391.1Scgd	    ln->tn_op == CON && ln->tn_val->v_quad <= 0) {
43401.1Scgd		if (ln->tn_val->v_quad < 0) {
43411.17Smycroft			/* comparison of %s with %s, op %s */
43421.26Schristos			warning(162, "negative constant",
43431.261Srillig			    type_name(rn->tn_type), op_name(op));
43441.379Srillig		} else if (op == GT || op == LE) {
43451.17Smycroft			/* comparison of %s with %s, op %s */
43461.261Srillig			warning(162, "0", type_name(rn->tn_type), op_name(op));
43471.1Scgd		}
43481.1Scgd		return;
43491.1Scgd	}
43501.1Scgd}
43511.1Scgd
43521.1Scgd/*
43531.218Srillig * Return whether the expression can be used for static initialization.
43541.1Scgd *
43551.218Srillig * Constant initialization expressions must be constant or an address
43561.1Scgd * of a static object with an optional offset. In the first case,
43571.1Scgd * the result is returned in *offsp. In the second case, the static
43581.1Scgd * object is returned in *symp and the offset in *offsp.
43591.1Scgd *
43601.169Srillig * The expression can consist of PLUS, MINUS, ADDR, NAME, STRING and
43611.1Scgd * CON. Type conversions are allowed if they do not change binary
43621.1Scgd * representation (including width).
43631.278Srillig *
43641.278Srillig * C99 6.6 "Constant expressions"
43651.278Srillig * C99 6.7.8p4 restricts initializers for static storage duration
43661.1Scgd */
43671.174Srilligbool
43681.253Srilligconstant_addr(const tnode_t *tn, const sym_t **symp, ptrdiff_t *offsp)
43691.1Scgd{
43701.253Srillig	const sym_t *sym;
43711.1Scgd	ptrdiff_t offs1, offs2;
43721.1Scgd	tspec_t	t, ot;
43731.1Scgd
43741.1Scgd	switch (tn->tn_op) {
43751.1Scgd	case MINUS:
43761.28Schristos		if (tn->tn_right->tn_op == CVT)
43771.174Srillig			return constant_addr(tn->tn_right, symp, offsp);
43781.28Schristos		else if (tn->tn_right->tn_op != CON)
43791.174Srillig			return false;
43801.1Scgd		/* FALLTHROUGH */
43811.1Scgd	case PLUS:
43821.1Scgd		offs1 = offs2 = 0;
43831.1Scgd		if (tn->tn_left->tn_op == CON) {
43841.1Scgd			offs1 = (ptrdiff_t)tn->tn_left->tn_val->v_quad;
43851.174Srillig			if (!constant_addr(tn->tn_right, &sym, &offs2))
43861.174Srillig				return false;
43871.1Scgd		} else if (tn->tn_right->tn_op == CON) {
43881.1Scgd			offs2 = (ptrdiff_t)tn->tn_right->tn_val->v_quad;
43891.1Scgd			if (tn->tn_op == MINUS)
43901.1Scgd				offs2 = -offs2;
43911.174Srillig			if (!constant_addr(tn->tn_left, &sym, &offs1))
43921.174Srillig				return false;
43931.1Scgd		} else {
43941.174Srillig			return false;
43951.1Scgd		}
43961.1Scgd		*symp = sym;
43971.1Scgd		*offsp = offs1 + offs2;
43981.215Srillig		return true;
43991.169Srillig	case ADDR:
44001.1Scgd		if (tn->tn_left->tn_op == NAME) {
44011.1Scgd			*symp = tn->tn_left->tn_sym;
44021.1Scgd			*offsp = 0;
44031.215Srillig			return true;
44041.215Srillig		} else {
44051.1Scgd			/*
44061.1Scgd			 * If this would be the front end of a compiler we
44071.215Srillig			 * would return a label instead of 0, at least if
44081.215Srillig			 * 'tn->tn_left->tn_op == STRING'.
44091.1Scgd			 */
44101.215Srillig			*symp = NULL;
44111.1Scgd			*offsp = 0;
44121.215Srillig			return true;
44131.1Scgd		}
44141.1Scgd	case CVT:
44151.1Scgd		t = tn->tn_type->t_tspec;
44161.1Scgd		ot = tn->tn_left->tn_type->t_tspec;
44171.144Srillig		if ((!is_integer(t) && t != PTR) ||
44181.144Srillig		    (!is_integer(ot) && ot != PTR)) {
44191.174Srillig			return false;
44201.90Srillig		}
44211.380Srillig#if 0
44221.89Srillig		/*
44231.27Schristos		 * consider:
44241.97Srillig		 *	struct foo {
44251.97Srillig		 *		unsigned char a;
44261.97Srillig		 *	} f = {
44271.353Srillig		 *		(unsigned char)(unsigned long)
44281.353Srillig		 *		    (&(((struct foo *)0)->a))
44291.27Schristos		 *	};
44301.353Srillig		 * since psize(unsigned long) != psize(unsigned char),
44311.353Srillig		 * this fails.
44321.27Schristos		 */
44331.27Schristos		else if (psize(t) != psize(ot))
44341.95Srillig			return -1;
44351.27Schristos#endif
44361.215Srillig		return constant_addr(tn->tn_left, symp, offsp);
44371.1Scgd	default:
44381.174Srillig		return false;
44391.1Scgd	}
44401.1Scgd}
44411.1Scgd
44421.351Srillig/* Append s2 to s1, then free s2. */
44431.1Scgdstrg_t *
44441.351Srilligcat_strings(strg_t *s1, strg_t *s2)
44451.1Scgd{
44461.351Srillig	size_t len1, len2, sz;
44471.1Scgd
44481.351Srillig	if (s1->st_tspec != s2->st_tspec) {
44491.1Scgd		/* cannot concatenate wide and regular string literals */
44501.1Scgd		error(292);
44511.351Srillig		return s1;
44521.1Scgd	}
44531.1Scgd
44541.351Srillig	len1 = s1->st_len;
44551.351Srillig	len2 = s2->st_len;
44561.66Schristos
44571.351Srillig	if (s1->st_tspec == CHAR) {
44581.351Srillig		sz = sizeof(*s1->st_cp);
44591.351Srillig		s1->st_cp = xrealloc(s1->st_cp, (len1 + len2 + 1) * sz);
44601.351Srillig		memcpy(s1->st_cp + len1, s2->st_cp, (len2 + 1) * sz);
44611.351Srillig		free(s2->st_cp);
44621.351Srillig	} else {
44631.351Srillig		sz = sizeof(*s1->st_wcp);
44641.351Srillig		s1->st_wcp = xrealloc(s1->st_wcp, (len1 + len2 + 1) * sz);
44651.351Srillig		memcpy(s1->st_wcp + len1, s2->st_wcp, (len2 + 1) * sz);
44661.351Srillig		free(s2->st_wcp);
44671.351Srillig	}
44681.66Schristos
44691.351Srillig	s1->st_len = len1 + len2;
44701.351Srillig	free(s2);
44711.1Scgd
44721.351Srillig	return s1;
44731.1Scgd}
44741.1Scgd
44751.134Srilligstatic bool
44761.134Srilligis_confusing_precedence(op_t op, op_t lop, bool lparen, op_t rop, bool rparen)
44771.134Srillig{
44781.134Srillig
44791.134Srillig	if (op == SHL || op == SHR) {
44801.145Srillig		if (!lparen && (lop == PLUS || lop == MINUS))
44811.134Srillig			return true;
44821.145Srillig		if (!rparen && (rop == PLUS || rop == MINUS))
44831.134Srillig			return true;
44841.134Srillig		return false;
44851.134Srillig	}
44861.134Srillig
44871.134Srillig	if (op == LOGOR) {
44881.145Srillig		if (!lparen && lop == LOGAND)
44891.134Srillig			return true;
44901.145Srillig		if (!rparen && rop == LOGAND)
44911.134Srillig			return true;
44921.134Srillig		return false;
44931.134Srillig	}
44941.134Srillig
44951.171Srillig	lint_assert(op == BITAND || op == BITXOR || op == BITOR);
44961.134Srillig	if (!lparen && lop != op) {
44971.145Srillig		if (lop == PLUS || lop == MINUS)
44981.134Srillig			return true;
44991.171Srillig		if (lop == BITAND || lop == BITXOR)
45001.134Srillig			return true;
45011.134Srillig	}
45021.134Srillig	if (!rparen && rop != op) {
45031.145Srillig		if (rop == PLUS || rop == MINUS)
45041.134Srillig			return true;
45051.171Srillig		if (rop == BITAND || rop == BITXOR)
45061.134Srillig			return true;
45071.134Srillig	}
45081.134Srillig	return false;
45091.134Srillig}
45101.134Srillig
45111.1Scgd/*
45121.1Scgd * Print a warning if the given node has operands which should be
45131.1Scgd * parenthesized.
45141.1Scgd *
45151.1Scgd * XXX Does not work if an operand is a constant expression. Constant
45161.1Scgd * expressions are already folded.
45171.1Scgd */
45181.1Scgdstatic void
45191.100Srilligcheck_precedence_confusion(tnode_t *tn)
45201.1Scgd{
45211.135Srillig	tnode_t *ln, *rn;
45221.1Scgd
45231.1Scgd	if (!hflag)
45241.1Scgd		return;
45251.1Scgd
45261.326Srillig	debug_node(tn);
45271.1Scgd
45281.346Srillig	lint_assert(is_binary(tn));
45291.1Scgd	for (ln = tn->tn_left; ln->tn_op == CVT; ln = ln->tn_left)
45301.135Srillig		continue;
45311.133Srillig	for (rn = tn->tn_right; rn->tn_op == CVT; rn = rn->tn_left)
45321.135Srillig		continue;
45331.1Scgd
45341.135Srillig	if (is_confusing_precedence(tn->tn_op,
45351.135Srillig	    ln->tn_op, ln->tn_parenthesized,
45361.135Srillig	    rn->tn_op, rn->tn_parenthesized)) {
45371.1Scgd		/* precedence confusion possible: parenthesize! */
45381.1Scgd		warning(169);
45391.1Scgd	}
45401.1Scgd}
4541