1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci * sparse/evaluate.c
3f08c3bdfSopenharmony_ci *
4f08c3bdfSopenharmony_ci * Copyright (C) 2003 Transmeta Corp.
5f08c3bdfSopenharmony_ci *               2003-2004 Linus Torvalds
6f08c3bdfSopenharmony_ci *
7f08c3bdfSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
8f08c3bdfSopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
9f08c3bdfSopenharmony_ci * in the Software without restriction, including without limitation the rights
10f08c3bdfSopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11f08c3bdfSopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
12f08c3bdfSopenharmony_ci * furnished to do so, subject to the following conditions:
13f08c3bdfSopenharmony_ci *
14f08c3bdfSopenharmony_ci * The above copyright notice and this permission notice shall be included in
15f08c3bdfSopenharmony_ci * all copies or substantial portions of the Software.
16f08c3bdfSopenharmony_ci *
17f08c3bdfSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18f08c3bdfSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19f08c3bdfSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20f08c3bdfSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21f08c3bdfSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22f08c3bdfSopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23f08c3bdfSopenharmony_ci * THE SOFTWARE.
24f08c3bdfSopenharmony_ci *
25f08c3bdfSopenharmony_ci * Evaluate constant expressions.
26f08c3bdfSopenharmony_ci */
27f08c3bdfSopenharmony_ci#include <stdlib.h>
28f08c3bdfSopenharmony_ci#include <stdarg.h>
29f08c3bdfSopenharmony_ci#include <stddef.h>
30f08c3bdfSopenharmony_ci#include <stdio.h>
31f08c3bdfSopenharmony_ci#include <string.h>
32f08c3bdfSopenharmony_ci#include <ctype.h>
33f08c3bdfSopenharmony_ci#include <unistd.h>
34f08c3bdfSopenharmony_ci#include <fcntl.h>
35f08c3bdfSopenharmony_ci#include <limits.h>
36f08c3bdfSopenharmony_ci
37f08c3bdfSopenharmony_ci#include "evaluate.h"
38f08c3bdfSopenharmony_ci#include "lib.h"
39f08c3bdfSopenharmony_ci#include "allocate.h"
40f08c3bdfSopenharmony_ci#include "parse.h"
41f08c3bdfSopenharmony_ci#include "token.h"
42f08c3bdfSopenharmony_ci#include "symbol.h"
43f08c3bdfSopenharmony_ci#include "target.h"
44f08c3bdfSopenharmony_ci#include "expression.h"
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_cistruct symbol *current_fn;
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_cistruct ident bad_address_space = { .len = 6, .name = "bad AS", };
49f08c3bdfSopenharmony_ci
50f08c3bdfSopenharmony_cistatic struct symbol *degenerate(struct expression *expr);
51f08c3bdfSopenharmony_cistatic struct symbol *evaluate_symbol(struct symbol *sym);
52f08c3bdfSopenharmony_ci
53f08c3bdfSopenharmony_cistatic inline int valid_expr_type(struct expression *expr)
54f08c3bdfSopenharmony_ci{
55f08c3bdfSopenharmony_ci	return expr && valid_type(expr->ctype);
56f08c3bdfSopenharmony_ci}
57f08c3bdfSopenharmony_ci
58f08c3bdfSopenharmony_cistatic inline int valid_subexpr_type(struct expression *expr)
59f08c3bdfSopenharmony_ci{
60f08c3bdfSopenharmony_ci	return valid_expr_type(expr->left)
61f08c3bdfSopenharmony_ci	    && valid_expr_type(expr->right);
62f08c3bdfSopenharmony_ci}
63f08c3bdfSopenharmony_ci
64f08c3bdfSopenharmony_cistatic struct symbol *unqualify_type(struct symbol *ctype)
65f08c3bdfSopenharmony_ci{
66f08c3bdfSopenharmony_ci	if (!ctype)
67f08c3bdfSopenharmony_ci		return ctype;
68f08c3bdfSopenharmony_ci	if (ctype->type == SYM_NODE && (ctype->ctype.modifiers & MOD_QUALIFIER)) {
69f08c3bdfSopenharmony_ci		struct symbol *unqual = alloc_symbol(ctype->pos, 0);
70f08c3bdfSopenharmony_ci
71f08c3bdfSopenharmony_ci		*unqual = *ctype;
72f08c3bdfSopenharmony_ci		unqual->ctype.modifiers &= ~MOD_QUALIFIER;
73f08c3bdfSopenharmony_ci		return unqual;
74f08c3bdfSopenharmony_ci	}
75f08c3bdfSopenharmony_ci	return ctype;
76f08c3bdfSopenharmony_ci}
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_cistatic struct symbol *evaluate_symbol_expression(struct expression *expr)
79f08c3bdfSopenharmony_ci{
80f08c3bdfSopenharmony_ci	struct expression *addr;
81f08c3bdfSopenharmony_ci	struct symbol *sym = expr->symbol;
82f08c3bdfSopenharmony_ci	struct symbol *base_type;
83f08c3bdfSopenharmony_ci
84f08c3bdfSopenharmony_ci	if (!sym) {
85f08c3bdfSopenharmony_ci		expression_error(expr, "undefined identifier '%s'", show_ident(expr->symbol_name));
86f08c3bdfSopenharmony_ci		return NULL;
87f08c3bdfSopenharmony_ci	}
88f08c3bdfSopenharmony_ci
89f08c3bdfSopenharmony_ci	examine_symbol_type(sym);
90f08c3bdfSopenharmony_ci
91f08c3bdfSopenharmony_ci	base_type = get_base_type(sym);
92f08c3bdfSopenharmony_ci	if (!base_type) {
93f08c3bdfSopenharmony_ci		expression_error(expr, "identifier '%s' has no type", show_ident(expr->symbol_name));
94f08c3bdfSopenharmony_ci		return NULL;
95f08c3bdfSopenharmony_ci	}
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_ci	addr = alloc_expression(expr->pos, EXPR_SYMBOL);
98f08c3bdfSopenharmony_ci	addr->symbol = sym;
99f08c3bdfSopenharmony_ci	addr->symbol_name = expr->symbol_name;
100f08c3bdfSopenharmony_ci	addr->ctype = &lazy_ptr_ctype;	/* Lazy evaluation: we need to do a proper job if somebody does &sym */
101f08c3bdfSopenharmony_ci	addr->flags = expr->flags;
102f08c3bdfSopenharmony_ci	expr->type = EXPR_PREOP;
103f08c3bdfSopenharmony_ci	expr->op = '*';
104f08c3bdfSopenharmony_ci	expr->unop = addr;
105f08c3bdfSopenharmony_ci	expr->flags = CEF_NONE;
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_ci	/* The type of a symbol is the symbol itself! */
108f08c3bdfSopenharmony_ci	expr->ctype = sym;
109f08c3bdfSopenharmony_ci	return sym;
110f08c3bdfSopenharmony_ci}
111f08c3bdfSopenharmony_ci
112f08c3bdfSopenharmony_cistatic struct symbol *evaluate_string(struct expression *expr)
113f08c3bdfSopenharmony_ci{
114f08c3bdfSopenharmony_ci	struct symbol *sym = alloc_symbol(expr->pos, SYM_NODE);
115f08c3bdfSopenharmony_ci	struct symbol *array = alloc_symbol(expr->pos, SYM_ARRAY);
116f08c3bdfSopenharmony_ci	struct expression *addr = alloc_expression(expr->pos, EXPR_SYMBOL);
117f08c3bdfSopenharmony_ci	struct expression *initstr = alloc_expression(expr->pos, EXPR_STRING);
118f08c3bdfSopenharmony_ci	unsigned int length = expr->string->length;
119f08c3bdfSopenharmony_ci	struct symbol *char_type = expr->wide ? wchar_ctype : &char_ctype;
120f08c3bdfSopenharmony_ci
121f08c3bdfSopenharmony_ci	sym->array_size = alloc_const_expression(expr->pos, length);
122f08c3bdfSopenharmony_ci	sym->bit_size = length * char_type->bit_size;
123f08c3bdfSopenharmony_ci	sym->ctype.alignment = 1;
124f08c3bdfSopenharmony_ci	sym->string = 1;
125f08c3bdfSopenharmony_ci	sym->ctype.modifiers = MOD_STATIC;
126f08c3bdfSopenharmony_ci	sym->ctype.base_type = array;
127f08c3bdfSopenharmony_ci	sym->initializer = initstr;
128f08c3bdfSopenharmony_ci	sym->examined = 1;
129f08c3bdfSopenharmony_ci	sym->evaluated = 1;
130f08c3bdfSopenharmony_ci
131f08c3bdfSopenharmony_ci	initstr->ctype = sym;
132f08c3bdfSopenharmony_ci	initstr->string = expr->string;
133f08c3bdfSopenharmony_ci
134f08c3bdfSopenharmony_ci	array->array_size = sym->array_size;
135f08c3bdfSopenharmony_ci	array->bit_size = sym->bit_size;
136f08c3bdfSopenharmony_ci	array->ctype.alignment = char_type->ctype.alignment;
137f08c3bdfSopenharmony_ci	array->ctype.modifiers = MOD_STATIC;
138f08c3bdfSopenharmony_ci	array->ctype.base_type = char_type;
139f08c3bdfSopenharmony_ci	array->examined = 1;
140f08c3bdfSopenharmony_ci	array->evaluated = 1;
141f08c3bdfSopenharmony_ci
142f08c3bdfSopenharmony_ci	addr->symbol = sym;
143f08c3bdfSopenharmony_ci	addr->ctype = &lazy_ptr_ctype;
144f08c3bdfSopenharmony_ci	addr->flags = CEF_ADDR;
145f08c3bdfSopenharmony_ci
146f08c3bdfSopenharmony_ci	expr->type = EXPR_PREOP;
147f08c3bdfSopenharmony_ci	expr->op = '*';
148f08c3bdfSopenharmony_ci	expr->unop = addr;
149f08c3bdfSopenharmony_ci	expr->ctype = sym;
150f08c3bdfSopenharmony_ci	return sym;
151f08c3bdfSopenharmony_ci}
152f08c3bdfSopenharmony_ci
153f08c3bdfSopenharmony_ci/* type has come from classify_type and is an integer type */
154f08c3bdfSopenharmony_cistatic inline struct symbol *integer_promotion(struct symbol *type)
155f08c3bdfSopenharmony_ci{
156f08c3bdfSopenharmony_ci	unsigned long mod =  type->ctype.modifiers;
157f08c3bdfSopenharmony_ci	int width = type->bit_size;
158f08c3bdfSopenharmony_ci
159f08c3bdfSopenharmony_ci	/*
160f08c3bdfSopenharmony_ci	 * Bitfields always promote to the base type,
161f08c3bdfSopenharmony_ci	 * even if the bitfield might be bigger than
162f08c3bdfSopenharmony_ci	 * an "int".
163f08c3bdfSopenharmony_ci	 */
164f08c3bdfSopenharmony_ci	if (type->type == SYM_BITFIELD) {
165f08c3bdfSopenharmony_ci		type = type->ctype.base_type;
166f08c3bdfSopenharmony_ci	}
167f08c3bdfSopenharmony_ci	mod = type->ctype.modifiers;
168f08c3bdfSopenharmony_ci	if (width < bits_in_int)
169f08c3bdfSopenharmony_ci		return &int_ctype;
170f08c3bdfSopenharmony_ci
171f08c3bdfSopenharmony_ci	/* If char/short has as many bits as int, it still gets "promoted" */
172f08c3bdfSopenharmony_ci	if (type->rank < 0) {
173f08c3bdfSopenharmony_ci		if (mod & MOD_UNSIGNED)
174f08c3bdfSopenharmony_ci			return &uint_ctype;
175f08c3bdfSopenharmony_ci		return &int_ctype;
176f08c3bdfSopenharmony_ci	}
177f08c3bdfSopenharmony_ci	return type;
178f08c3bdfSopenharmony_ci}
179f08c3bdfSopenharmony_ci
180f08c3bdfSopenharmony_ci/*
181f08c3bdfSopenharmony_ci * After integer promotons:
182f08c3bdfSopenharmony_ci * If both types are the same
183f08c3bdfSopenharmony_ci *   -> no conversion needed
184f08c3bdfSopenharmony_ci * If the types have the same signedness (their rank must be different)
185f08c3bdfSopenharmony_ci *   -> convert to the type of the highest rank
186f08c3bdfSopenharmony_ci * If rank(unsigned type) >= rank(signed type)
187f08c3bdfSopenharmony_ci *   -> convert to the unsigned type
188f08c3bdfSopenharmony_ci * If size(signed type) > size(unsigned type)
189f08c3bdfSopenharmony_ci *   -> convert to the signed type
190f08c3bdfSopenharmony_ci * Otherwise
191f08c3bdfSopenharmony_ci *   -> convert to the unsigned type corresponding to the signed type.
192f08c3bdfSopenharmony_ci */
193f08c3bdfSopenharmony_cistatic struct symbol *bigger_int_type(struct symbol *left, struct symbol *right)
194f08c3bdfSopenharmony_ci{
195f08c3bdfSopenharmony_ci	static struct symbol *unsigned_types[] = {
196f08c3bdfSopenharmony_ci		[0] = &uint_ctype,
197f08c3bdfSopenharmony_ci		[1] = &ulong_ctype,
198f08c3bdfSopenharmony_ci		[2] = &ullong_ctype,
199f08c3bdfSopenharmony_ci		[3] = &uint128_ctype,
200f08c3bdfSopenharmony_ci	};
201f08c3bdfSopenharmony_ci	unsigned long lmod, rmod;
202f08c3bdfSopenharmony_ci	struct symbol *stype, *utype;
203f08c3bdfSopenharmony_ci
204f08c3bdfSopenharmony_ci	left = integer_promotion(left);
205f08c3bdfSopenharmony_ci	right = integer_promotion(right);
206f08c3bdfSopenharmony_ci
207f08c3bdfSopenharmony_ci	if (left == right)
208f08c3bdfSopenharmony_ci		return left;
209f08c3bdfSopenharmony_ci
210f08c3bdfSopenharmony_ci	lmod = left->ctype.modifiers;
211f08c3bdfSopenharmony_ci	rmod = right->ctype.modifiers;
212f08c3bdfSopenharmony_ci	if (((lmod ^ rmod) & MOD_UNSIGNED) == 0)
213f08c3bdfSopenharmony_ci		return (left->rank > right->rank) ? left : right;
214f08c3bdfSopenharmony_ci	if (lmod & MOD_UNSIGNED) {
215f08c3bdfSopenharmony_ci		utype = left;
216f08c3bdfSopenharmony_ci		stype = right;
217f08c3bdfSopenharmony_ci	} else {
218f08c3bdfSopenharmony_ci		stype = left;
219f08c3bdfSopenharmony_ci		utype = right;
220f08c3bdfSopenharmony_ci	}
221f08c3bdfSopenharmony_ci	if (utype->rank >= stype->rank)
222f08c3bdfSopenharmony_ci		return utype;
223f08c3bdfSopenharmony_ci	if (stype->bit_size > utype->bit_size)
224f08c3bdfSopenharmony_ci		return stype;
225f08c3bdfSopenharmony_ci	utype = unsigned_types[stype->rank];
226f08c3bdfSopenharmony_ci	return utype;
227f08c3bdfSopenharmony_ci}
228f08c3bdfSopenharmony_ci
229f08c3bdfSopenharmony_cistatic struct symbol *base_type(struct symbol *node, unsigned long *modp, struct ident **asp)
230f08c3bdfSopenharmony_ci{
231f08c3bdfSopenharmony_ci	unsigned long mod = 0;
232f08c3bdfSopenharmony_ci	struct ident *as = NULL;
233f08c3bdfSopenharmony_ci
234f08c3bdfSopenharmony_ci	while (node) {
235f08c3bdfSopenharmony_ci		mod |= node->ctype.modifiers;
236f08c3bdfSopenharmony_ci		combine_address_space(node->pos, &as, node->ctype.as);
237f08c3bdfSopenharmony_ci		if (node->type == SYM_NODE) {
238f08c3bdfSopenharmony_ci			node = node->ctype.base_type;
239f08c3bdfSopenharmony_ci			continue;
240f08c3bdfSopenharmony_ci		}
241f08c3bdfSopenharmony_ci		break;
242f08c3bdfSopenharmony_ci	}
243f08c3bdfSopenharmony_ci	*modp = mod & ~MOD_IGNORE;
244f08c3bdfSopenharmony_ci	*asp = as;
245f08c3bdfSopenharmony_ci	return node;
246f08c3bdfSopenharmony_ci}
247f08c3bdfSopenharmony_ci
248f08c3bdfSopenharmony_cistatic int is_same_type(struct expression *expr, struct symbol *new)
249f08c3bdfSopenharmony_ci{
250f08c3bdfSopenharmony_ci	struct symbol *old = expr->ctype;
251f08c3bdfSopenharmony_ci	unsigned long oldmod, newmod;
252f08c3bdfSopenharmony_ci	struct ident *oldas, *newas;
253f08c3bdfSopenharmony_ci
254f08c3bdfSopenharmony_ci	old = base_type(old, &oldmod, &oldas);
255f08c3bdfSopenharmony_ci	new = base_type(new, &newmod, &newas);
256f08c3bdfSopenharmony_ci
257f08c3bdfSopenharmony_ci	/* Same base type, same address space? */
258f08c3bdfSopenharmony_ci	if (old == new && oldas == newas) {
259f08c3bdfSopenharmony_ci		unsigned long difmod;
260f08c3bdfSopenharmony_ci
261f08c3bdfSopenharmony_ci		/* Check the modifier bits. */
262f08c3bdfSopenharmony_ci		difmod = (oldmod ^ newmod) & ~MOD_NOCAST;
263f08c3bdfSopenharmony_ci
264f08c3bdfSopenharmony_ci		/* Exact same type? */
265f08c3bdfSopenharmony_ci		if (!difmod)
266f08c3bdfSopenharmony_ci			return 1;
267f08c3bdfSopenharmony_ci
268f08c3bdfSopenharmony_ci		/*
269f08c3bdfSopenharmony_ci		 * Not the same type, but differs only in "const".
270f08c3bdfSopenharmony_ci		 * Don't warn about MOD_NOCAST.
271f08c3bdfSopenharmony_ci		 */
272f08c3bdfSopenharmony_ci		if (difmod == MOD_CONST)
273f08c3bdfSopenharmony_ci			return 0;
274f08c3bdfSopenharmony_ci	}
275f08c3bdfSopenharmony_ci	if ((oldmod | newmod) & MOD_NOCAST) {
276f08c3bdfSopenharmony_ci		const char *tofrom = "to/from";
277f08c3bdfSopenharmony_ci		if (!(newmod & MOD_NOCAST))
278f08c3bdfSopenharmony_ci			tofrom = "from";
279f08c3bdfSopenharmony_ci		if (!(oldmod & MOD_NOCAST))
280f08c3bdfSopenharmony_ci			tofrom = "to";
281f08c3bdfSopenharmony_ci		warning(expr->pos, "implicit cast %s nocast type", tofrom);
282f08c3bdfSopenharmony_ci	}
283f08c3bdfSopenharmony_ci	return 0;
284f08c3bdfSopenharmony_ci}
285f08c3bdfSopenharmony_ci
286f08c3bdfSopenharmony_cistatic void
287f08c3bdfSopenharmony_ciwarn_for_different_enum_types (struct position pos,
288f08c3bdfSopenharmony_ci			       struct symbol *typea,
289f08c3bdfSopenharmony_ci			       struct symbol *typeb)
290f08c3bdfSopenharmony_ci{
291f08c3bdfSopenharmony_ci	if (!Wenum_mismatch)
292f08c3bdfSopenharmony_ci		return;
293f08c3bdfSopenharmony_ci	if (typea->type == SYM_NODE)
294f08c3bdfSopenharmony_ci		typea = typea->ctype.base_type;
295f08c3bdfSopenharmony_ci	if (typeb->type == SYM_NODE)
296f08c3bdfSopenharmony_ci		typeb = typeb->ctype.base_type;
297f08c3bdfSopenharmony_ci
298f08c3bdfSopenharmony_ci	if (typea == typeb)
299f08c3bdfSopenharmony_ci		return;
300f08c3bdfSopenharmony_ci
301f08c3bdfSopenharmony_ci	if (typea->type == SYM_ENUM && typeb->type == SYM_ENUM) {
302f08c3bdfSopenharmony_ci		warning(pos, "mixing different enum types:");
303f08c3bdfSopenharmony_ci		info(pos, "   %s", show_typename(typea));
304f08c3bdfSopenharmony_ci		info(pos, "   %s", show_typename(typeb));
305f08c3bdfSopenharmony_ci	}
306f08c3bdfSopenharmony_ci}
307f08c3bdfSopenharmony_ci
308f08c3bdfSopenharmony_cistatic int cast_flags(struct expression *expr, struct expression *target);
309f08c3bdfSopenharmony_cistatic struct symbol *cast_to_bool(struct expression *expr);
310f08c3bdfSopenharmony_ci
311f08c3bdfSopenharmony_ci/*
312f08c3bdfSopenharmony_ci * This gets called for implicit casts in assignments and
313f08c3bdfSopenharmony_ci * integer promotion.
314f08c3bdfSopenharmony_ci */
315f08c3bdfSopenharmony_cistatic struct expression * cast_to(struct expression *old, struct symbol *type)
316f08c3bdfSopenharmony_ci{
317f08c3bdfSopenharmony_ci	struct expression *expr;
318f08c3bdfSopenharmony_ci
319f08c3bdfSopenharmony_ci	warn_for_different_enum_types (old->pos, old->ctype, type);
320f08c3bdfSopenharmony_ci
321f08c3bdfSopenharmony_ci	if (old->ctype != &null_ctype && is_same_type(old, type))
322f08c3bdfSopenharmony_ci		return old;
323f08c3bdfSopenharmony_ci
324f08c3bdfSopenharmony_ci	expr = alloc_expression(old->pos, EXPR_IMPLIED_CAST);
325f08c3bdfSopenharmony_ci	expr->ctype = type;
326f08c3bdfSopenharmony_ci	expr->cast_type = type;
327f08c3bdfSopenharmony_ci	expr->cast_expression = old;
328f08c3bdfSopenharmony_ci	expr->flags = cast_flags(expr, old);
329f08c3bdfSopenharmony_ci
330f08c3bdfSopenharmony_ci	if (is_bool_type(type))
331f08c3bdfSopenharmony_ci		cast_to_bool(expr);
332f08c3bdfSopenharmony_ci
333f08c3bdfSopenharmony_ci	return expr;
334f08c3bdfSopenharmony_ci}
335f08c3bdfSopenharmony_ci
336f08c3bdfSopenharmony_cienum {
337f08c3bdfSopenharmony_ci	TYPE_NUM = 1,
338f08c3bdfSopenharmony_ci	TYPE_BITFIELD = 2,
339f08c3bdfSopenharmony_ci	TYPE_RESTRICT = 4,
340f08c3bdfSopenharmony_ci	TYPE_FLOAT = 8,
341f08c3bdfSopenharmony_ci	TYPE_PTR = 16,
342f08c3bdfSopenharmony_ci	TYPE_COMPOUND = 32,
343f08c3bdfSopenharmony_ci	TYPE_FOULED = 64,
344f08c3bdfSopenharmony_ci	TYPE_FN = 128,
345f08c3bdfSopenharmony_ci};
346f08c3bdfSopenharmony_ci
347f08c3bdfSopenharmony_cistatic inline int classify_type(struct symbol *type, struct symbol **base)
348f08c3bdfSopenharmony_ci{
349f08c3bdfSopenharmony_ci	static int type_class[SYM_BAD + 1] = {
350f08c3bdfSopenharmony_ci		[SYM_PTR] = TYPE_PTR,
351f08c3bdfSopenharmony_ci		[SYM_FN] = TYPE_PTR | TYPE_FN,
352f08c3bdfSopenharmony_ci		[SYM_ARRAY] = TYPE_PTR | TYPE_COMPOUND,
353f08c3bdfSopenharmony_ci		[SYM_STRUCT] = TYPE_COMPOUND,
354f08c3bdfSopenharmony_ci		[SYM_UNION] = TYPE_COMPOUND,
355f08c3bdfSopenharmony_ci		[SYM_BITFIELD] = TYPE_NUM | TYPE_BITFIELD,
356f08c3bdfSopenharmony_ci		[SYM_RESTRICT] = TYPE_NUM | TYPE_RESTRICT,
357f08c3bdfSopenharmony_ci		[SYM_FOULED] = TYPE_NUM | TYPE_RESTRICT | TYPE_FOULED,
358f08c3bdfSopenharmony_ci	};
359f08c3bdfSopenharmony_ci	if (type->type == SYM_NODE)
360f08c3bdfSopenharmony_ci		type = type->ctype.base_type;
361f08c3bdfSopenharmony_ci	if (type->type == SYM_TYPEOF) {
362f08c3bdfSopenharmony_ci		type = examine_symbol_type(type);
363f08c3bdfSopenharmony_ci		if (type->type == SYM_NODE)
364f08c3bdfSopenharmony_ci			type = type->ctype.base_type;
365f08c3bdfSopenharmony_ci	}
366f08c3bdfSopenharmony_ci	if (type->type == SYM_ENUM)
367f08c3bdfSopenharmony_ci		type = type->ctype.base_type;
368f08c3bdfSopenharmony_ci	*base = type;
369f08c3bdfSopenharmony_ci	if (type->type == SYM_BASETYPE) {
370f08c3bdfSopenharmony_ci		if (type->ctype.base_type == &int_type)
371f08c3bdfSopenharmony_ci			return TYPE_NUM;
372f08c3bdfSopenharmony_ci		if (type->ctype.base_type == &fp_type)
373f08c3bdfSopenharmony_ci			return TYPE_NUM | TYPE_FLOAT;
374f08c3bdfSopenharmony_ci	}
375f08c3bdfSopenharmony_ci	return type_class[type->type];
376f08c3bdfSopenharmony_ci}
377f08c3bdfSopenharmony_ci
378f08c3bdfSopenharmony_ci#define is_int(class) ((class & (TYPE_NUM | TYPE_FLOAT)) == TYPE_NUM)
379f08c3bdfSopenharmony_ci
380f08c3bdfSopenharmony_cistatic inline int is_string_type(struct symbol *type)
381f08c3bdfSopenharmony_ci{
382f08c3bdfSopenharmony_ci	if (type->type == SYM_NODE)
383f08c3bdfSopenharmony_ci		type = type->ctype.base_type;
384f08c3bdfSopenharmony_ci	if (type->type != SYM_ARRAY)
385f08c3bdfSopenharmony_ci		return 0;
386f08c3bdfSopenharmony_ci	type = type->ctype.base_type;
387f08c3bdfSopenharmony_ci	return is_byte_type(type) || is_wchar_type(type);
388f08c3bdfSopenharmony_ci}
389f08c3bdfSopenharmony_ci
390f08c3bdfSopenharmony_cistatic struct symbol *bad_expr_type(struct expression *expr)
391f08c3bdfSopenharmony_ci{
392f08c3bdfSopenharmony_ci	switch (expr->type) {
393f08c3bdfSopenharmony_ci	case EXPR_BINOP:
394f08c3bdfSopenharmony_ci	case EXPR_COMPARE:
395f08c3bdfSopenharmony_ci		if (!valid_subexpr_type(expr))
396f08c3bdfSopenharmony_ci			break;
397f08c3bdfSopenharmony_ci		sparse_error(expr->pos, "incompatible types for operation (%s):", show_special(expr->op));
398f08c3bdfSopenharmony_ci		info(expr->pos, "   %s", show_typename(expr->left->ctype));
399f08c3bdfSopenharmony_ci		info(expr->pos, "   %s", show_typename(expr->right->ctype));
400f08c3bdfSopenharmony_ci		break;
401f08c3bdfSopenharmony_ci	case EXPR_PREOP:
402f08c3bdfSopenharmony_ci	case EXPR_POSTOP:
403f08c3bdfSopenharmony_ci		if (!valid_expr_type(expr->unop))
404f08c3bdfSopenharmony_ci			break;
405f08c3bdfSopenharmony_ci		sparse_error(expr->pos, "incompatible type for operation (%s):", show_special(expr->op));
406f08c3bdfSopenharmony_ci		info(expr->pos, "   %s", show_typename(expr->unop->ctype));
407f08c3bdfSopenharmony_ci		break;
408f08c3bdfSopenharmony_ci	default:
409f08c3bdfSopenharmony_ci		break;
410f08c3bdfSopenharmony_ci	}
411f08c3bdfSopenharmony_ci
412f08c3bdfSopenharmony_ci	expr->flags = CEF_NONE;
413f08c3bdfSopenharmony_ci	return expr->ctype = &bad_ctype;
414f08c3bdfSopenharmony_ci}
415f08c3bdfSopenharmony_ci
416f08c3bdfSopenharmony_cistatic int restricted_value(struct expression *v, struct symbol *type)
417f08c3bdfSopenharmony_ci{
418f08c3bdfSopenharmony_ci	if (v->type != EXPR_VALUE)
419f08c3bdfSopenharmony_ci		return 1;
420f08c3bdfSopenharmony_ci	if (v->value != 0)
421f08c3bdfSopenharmony_ci		return 1;
422f08c3bdfSopenharmony_ci	return 0;
423f08c3bdfSopenharmony_ci}
424f08c3bdfSopenharmony_ci
425f08c3bdfSopenharmony_cistatic int restricted_binop(int op, struct symbol *type)
426f08c3bdfSopenharmony_ci{
427f08c3bdfSopenharmony_ci	switch (op) {
428f08c3bdfSopenharmony_ci		case '&':
429f08c3bdfSopenharmony_ci		case '=':
430f08c3bdfSopenharmony_ci		case SPECIAL_AND_ASSIGN:
431f08c3bdfSopenharmony_ci		case SPECIAL_OR_ASSIGN:
432f08c3bdfSopenharmony_ci		case SPECIAL_XOR_ASSIGN:
433f08c3bdfSopenharmony_ci			return 1;	/* unfoul */
434f08c3bdfSopenharmony_ci		case '|':
435f08c3bdfSopenharmony_ci		case '^':
436f08c3bdfSopenharmony_ci		case '?':
437f08c3bdfSopenharmony_ci			return 2;	/* keep fouled */
438f08c3bdfSopenharmony_ci		case SPECIAL_EQUAL:
439f08c3bdfSopenharmony_ci		case SPECIAL_NOTEQUAL:
440f08c3bdfSopenharmony_ci			return 3;	/* warn if fouled */
441f08c3bdfSopenharmony_ci		default:
442f08c3bdfSopenharmony_ci			return 0;	/* warn */
443f08c3bdfSopenharmony_ci	}
444f08c3bdfSopenharmony_ci}
445f08c3bdfSopenharmony_ci
446f08c3bdfSopenharmony_cistatic int restricted_unop(int op, struct symbol **type)
447f08c3bdfSopenharmony_ci{
448f08c3bdfSopenharmony_ci	if (op == '~') {
449f08c3bdfSopenharmony_ci		if ((*type)->bit_size < bits_in_int)
450f08c3bdfSopenharmony_ci			*type = befoul(*type);
451f08c3bdfSopenharmony_ci		return 0;
452f08c3bdfSopenharmony_ci	} if (op == '+')
453f08c3bdfSopenharmony_ci		return 0;
454f08c3bdfSopenharmony_ci	return 1;
455f08c3bdfSopenharmony_ci}
456f08c3bdfSopenharmony_ci
457f08c3bdfSopenharmony_ci/* type should be SYM_FOULED */
458f08c3bdfSopenharmony_cistatic inline struct symbol *unfoul(struct symbol *type)
459f08c3bdfSopenharmony_ci{
460f08c3bdfSopenharmony_ci	return type->ctype.base_type;
461f08c3bdfSopenharmony_ci}
462f08c3bdfSopenharmony_ci
463f08c3bdfSopenharmony_cistatic struct symbol *restricted_binop_type(int op,
464f08c3bdfSopenharmony_ci					struct expression *left,
465f08c3bdfSopenharmony_ci					struct expression *right,
466f08c3bdfSopenharmony_ci					int lclass, int rclass,
467f08c3bdfSopenharmony_ci					struct symbol *ltype,
468f08c3bdfSopenharmony_ci					struct symbol *rtype)
469f08c3bdfSopenharmony_ci{
470f08c3bdfSopenharmony_ci	struct symbol *ctype = NULL;
471f08c3bdfSopenharmony_ci	if (lclass & TYPE_RESTRICT) {
472f08c3bdfSopenharmony_ci		if (rclass & TYPE_RESTRICT) {
473f08c3bdfSopenharmony_ci			if (ltype == rtype) {
474f08c3bdfSopenharmony_ci				ctype = ltype;
475f08c3bdfSopenharmony_ci			} else if (lclass & TYPE_FOULED) {
476f08c3bdfSopenharmony_ci				if (unfoul(ltype) == rtype)
477f08c3bdfSopenharmony_ci					ctype = ltype;
478f08c3bdfSopenharmony_ci			} else if (rclass & TYPE_FOULED) {
479f08c3bdfSopenharmony_ci				if (unfoul(rtype) == ltype)
480f08c3bdfSopenharmony_ci					ctype = rtype;
481f08c3bdfSopenharmony_ci			}
482f08c3bdfSopenharmony_ci		} else {
483f08c3bdfSopenharmony_ci			if (!restricted_value(right, ltype))
484f08c3bdfSopenharmony_ci				ctype = ltype;
485f08c3bdfSopenharmony_ci		}
486f08c3bdfSopenharmony_ci	} else if (!restricted_value(left, rtype))
487f08c3bdfSopenharmony_ci		ctype = rtype;
488f08c3bdfSopenharmony_ci
489f08c3bdfSopenharmony_ci	if (ctype) {
490f08c3bdfSopenharmony_ci		switch (restricted_binop(op, ctype)) {
491f08c3bdfSopenharmony_ci		case 1:
492f08c3bdfSopenharmony_ci			if ((lclass ^ rclass) & TYPE_FOULED)
493f08c3bdfSopenharmony_ci				ctype = unfoul(ctype);
494f08c3bdfSopenharmony_ci			break;
495f08c3bdfSopenharmony_ci		case 3:
496f08c3bdfSopenharmony_ci			if (!(lclass & rclass & TYPE_FOULED))
497f08c3bdfSopenharmony_ci				break;
498f08c3bdfSopenharmony_ci		case 0:
499f08c3bdfSopenharmony_ci			ctype = NULL;
500f08c3bdfSopenharmony_ci		default:
501f08c3bdfSopenharmony_ci			break;
502f08c3bdfSopenharmony_ci		}
503f08c3bdfSopenharmony_ci	}
504f08c3bdfSopenharmony_ci
505f08c3bdfSopenharmony_ci	return ctype;
506f08c3bdfSopenharmony_ci}
507f08c3bdfSopenharmony_ci
508f08c3bdfSopenharmony_cistatic inline void unrestrict(struct expression *expr,
509f08c3bdfSopenharmony_ci			      int class, struct symbol **ctype)
510f08c3bdfSopenharmony_ci{
511f08c3bdfSopenharmony_ci	if (class & TYPE_RESTRICT) {
512f08c3bdfSopenharmony_ci		if (class & TYPE_FOULED)
513f08c3bdfSopenharmony_ci			*ctype = unfoul(*ctype);
514f08c3bdfSopenharmony_ci		warning(expr->pos, "%s degrades to integer",
515f08c3bdfSopenharmony_ci			show_typename(*ctype));
516f08c3bdfSopenharmony_ci		*ctype = (*ctype)->ctype.base_type; /* get to arithmetic type */
517f08c3bdfSopenharmony_ci	}
518f08c3bdfSopenharmony_ci}
519f08c3bdfSopenharmony_ci
520f08c3bdfSopenharmony_cistatic struct symbol *usual_conversions(int op,
521f08c3bdfSopenharmony_ci					struct expression *left,
522f08c3bdfSopenharmony_ci					struct expression *right,
523f08c3bdfSopenharmony_ci					int lclass, int rclass,
524f08c3bdfSopenharmony_ci					struct symbol *ltype,
525f08c3bdfSopenharmony_ci					struct symbol *rtype)
526f08c3bdfSopenharmony_ci{
527f08c3bdfSopenharmony_ci	struct symbol *ctype;
528f08c3bdfSopenharmony_ci
529f08c3bdfSopenharmony_ci	warn_for_different_enum_types(right->pos, left->ctype, right->ctype);
530f08c3bdfSopenharmony_ci
531f08c3bdfSopenharmony_ci	if ((lclass | rclass) & TYPE_RESTRICT)
532f08c3bdfSopenharmony_ci		goto Restr;
533f08c3bdfSopenharmony_ci
534f08c3bdfSopenharmony_ciNormal:
535f08c3bdfSopenharmony_ci	if (!(lclass & TYPE_FLOAT)) {
536f08c3bdfSopenharmony_ci		if (!(rclass & TYPE_FLOAT))
537f08c3bdfSopenharmony_ci			return bigger_int_type(ltype, rtype);
538f08c3bdfSopenharmony_ci		else
539f08c3bdfSopenharmony_ci			return rtype;
540f08c3bdfSopenharmony_ci	} else if (rclass & TYPE_FLOAT) {
541f08c3bdfSopenharmony_ci		if (rtype->rank > ltype->rank)
542f08c3bdfSopenharmony_ci			return rtype;
543f08c3bdfSopenharmony_ci		else
544f08c3bdfSopenharmony_ci			return ltype;
545f08c3bdfSopenharmony_ci	} else
546f08c3bdfSopenharmony_ci		return ltype;
547f08c3bdfSopenharmony_ci
548f08c3bdfSopenharmony_ciRestr:
549f08c3bdfSopenharmony_ci	ctype = restricted_binop_type(op, left, right,
550f08c3bdfSopenharmony_ci				      lclass, rclass, ltype, rtype);
551f08c3bdfSopenharmony_ci	if (ctype)
552f08c3bdfSopenharmony_ci		return ctype;
553f08c3bdfSopenharmony_ci
554f08c3bdfSopenharmony_ci	unrestrict(left, lclass, &ltype);
555f08c3bdfSopenharmony_ci	unrestrict(right, rclass, &rtype);
556f08c3bdfSopenharmony_ci
557f08c3bdfSopenharmony_ci	goto Normal;
558f08c3bdfSopenharmony_ci}
559f08c3bdfSopenharmony_ci
560f08c3bdfSopenharmony_cistatic inline int lvalue_expression(struct expression *expr)
561f08c3bdfSopenharmony_ci{
562f08c3bdfSopenharmony_ci	return expr->type == EXPR_PREOP && expr->op == '*';
563f08c3bdfSopenharmony_ci}
564f08c3bdfSopenharmony_ci
565f08c3bdfSopenharmony_cistatic struct symbol *evaluate_ptr_add(struct expression *expr, struct symbol *itype)
566f08c3bdfSopenharmony_ci{
567f08c3bdfSopenharmony_ci	struct expression *index = expr->right;
568f08c3bdfSopenharmony_ci	struct symbol *ctype, *base;
569f08c3bdfSopenharmony_ci	int multiply;
570f08c3bdfSopenharmony_ci
571f08c3bdfSopenharmony_ci	classify_type(degenerate(expr->left), &ctype);
572f08c3bdfSopenharmony_ci	base = examine_pointer_target(ctype);
573f08c3bdfSopenharmony_ci
574f08c3bdfSopenharmony_ci	/*
575f08c3bdfSopenharmony_ci	 * An address constant +/- an integer constant expression
576f08c3bdfSopenharmony_ci	 * yields an address constant again [6.6(7)].
577f08c3bdfSopenharmony_ci	 */
578f08c3bdfSopenharmony_ci	if ((expr->left->flags & CEF_ADDR) && (expr->right->flags & CEF_ICE))
579f08c3bdfSopenharmony_ci		expr->flags = CEF_ADDR;
580f08c3bdfSopenharmony_ci
581f08c3bdfSopenharmony_ci	if (!base) {
582f08c3bdfSopenharmony_ci		expression_error(expr, "missing type information");
583f08c3bdfSopenharmony_ci		return NULL;
584f08c3bdfSopenharmony_ci	}
585f08c3bdfSopenharmony_ci	if (is_function(base)) {
586f08c3bdfSopenharmony_ci		expression_error(expr, "arithmetics on pointers to functions");
587f08c3bdfSopenharmony_ci		return NULL;
588f08c3bdfSopenharmony_ci	}
589f08c3bdfSopenharmony_ci
590f08c3bdfSopenharmony_ci	/* Get the size of whatever the pointer points to */
591f08c3bdfSopenharmony_ci	multiply = is_void_type(base) ? 1 : bits_to_bytes(base->bit_size);
592f08c3bdfSopenharmony_ci
593f08c3bdfSopenharmony_ci	if (ctype == &null_ctype)
594f08c3bdfSopenharmony_ci		ctype = &ptr_ctype;
595f08c3bdfSopenharmony_ci	expr->ctype = ctype;
596f08c3bdfSopenharmony_ci
597f08c3bdfSopenharmony_ci	if (multiply == 1 && itype->bit_size == bits_in_pointer)
598f08c3bdfSopenharmony_ci		return ctype;
599f08c3bdfSopenharmony_ci
600f08c3bdfSopenharmony_ci	if (index->type == EXPR_VALUE) {
601f08c3bdfSopenharmony_ci		struct expression *val = alloc_expression(expr->pos, EXPR_VALUE);
602f08c3bdfSopenharmony_ci		unsigned long long v = index->value, mask;
603f08c3bdfSopenharmony_ci		mask = 1ULL << (itype->bit_size - 1);
604f08c3bdfSopenharmony_ci		if (v & mask)
605f08c3bdfSopenharmony_ci			v |= -mask;
606f08c3bdfSopenharmony_ci		else
607f08c3bdfSopenharmony_ci			v &= mask - 1;
608f08c3bdfSopenharmony_ci		v *= multiply;
609f08c3bdfSopenharmony_ci		mask = 1ULL << (bits_in_pointer - 1);
610f08c3bdfSopenharmony_ci		v &= mask | (mask - 1);
611f08c3bdfSopenharmony_ci		val->value = v;
612f08c3bdfSopenharmony_ci		val->ctype = ssize_t_ctype;
613f08c3bdfSopenharmony_ci		expr->right = val;
614f08c3bdfSopenharmony_ci		return ctype;
615f08c3bdfSopenharmony_ci	}
616f08c3bdfSopenharmony_ci
617f08c3bdfSopenharmony_ci	if (itype->bit_size != bits_in_pointer)
618f08c3bdfSopenharmony_ci		index = cast_to(index, ssize_t_ctype);
619f08c3bdfSopenharmony_ci
620f08c3bdfSopenharmony_ci	if (multiply > 1) {
621f08c3bdfSopenharmony_ci		struct expression *val = alloc_expression(expr->pos, EXPR_VALUE);
622f08c3bdfSopenharmony_ci		struct expression *mul = alloc_expression(expr->pos, EXPR_BINOP);
623f08c3bdfSopenharmony_ci
624f08c3bdfSopenharmony_ci		val->ctype = ssize_t_ctype;
625f08c3bdfSopenharmony_ci		val->value = multiply;
626f08c3bdfSopenharmony_ci
627f08c3bdfSopenharmony_ci		mul->op = '*';
628f08c3bdfSopenharmony_ci		mul->ctype = ssize_t_ctype;
629f08c3bdfSopenharmony_ci		mul->left = index;
630f08c3bdfSopenharmony_ci		mul->right = val;
631f08c3bdfSopenharmony_ci		index = mul;
632f08c3bdfSopenharmony_ci	}
633f08c3bdfSopenharmony_ci
634f08c3bdfSopenharmony_ci	expr->right = index;
635f08c3bdfSopenharmony_ci	return ctype;
636f08c3bdfSopenharmony_ci}
637f08c3bdfSopenharmony_ci
638f08c3bdfSopenharmony_cistatic void examine_fn_arguments(struct symbol *fn);
639f08c3bdfSopenharmony_ci
640f08c3bdfSopenharmony_ci#define MOD_IGN (MOD_QUALIFIER | MOD_FUN_ATTR)
641f08c3bdfSopenharmony_ci
642f08c3bdfSopenharmony_ciconst char *type_difference(struct ctype *c1, struct ctype *c2,
643f08c3bdfSopenharmony_ci	unsigned long mod1, unsigned long mod2)
644f08c3bdfSopenharmony_ci{
645f08c3bdfSopenharmony_ci	struct ident *as1 = c1->as, *as2 = c2->as;
646f08c3bdfSopenharmony_ci	struct symbol *t1 = c1->base_type;
647f08c3bdfSopenharmony_ci	struct symbol *t2 = c2->base_type;
648f08c3bdfSopenharmony_ci	int move1 = 1, move2 = 1;
649f08c3bdfSopenharmony_ci	mod1 |= c1->modifiers;
650f08c3bdfSopenharmony_ci	mod2 |= c2->modifiers;
651f08c3bdfSopenharmony_ci	for (;;) {
652f08c3bdfSopenharmony_ci		unsigned long diff;
653f08c3bdfSopenharmony_ci		int type;
654f08c3bdfSopenharmony_ci		struct symbol *base1 = t1->ctype.base_type;
655f08c3bdfSopenharmony_ci		struct symbol *base2 = t2->ctype.base_type;
656f08c3bdfSopenharmony_ci
657f08c3bdfSopenharmony_ci		/*
658f08c3bdfSopenharmony_ci		 * FIXME! Collect alignment and context too here!
659f08c3bdfSopenharmony_ci		 */
660f08c3bdfSopenharmony_ci		if (move1) {
661f08c3bdfSopenharmony_ci			if (t1 && t1->type != SYM_PTR) {
662f08c3bdfSopenharmony_ci				mod1 |= t1->ctype.modifiers;
663f08c3bdfSopenharmony_ci				combine_address_space(t1->pos, &as1, t1->ctype.as);
664f08c3bdfSopenharmony_ci			}
665f08c3bdfSopenharmony_ci			move1 = 0;
666f08c3bdfSopenharmony_ci		}
667f08c3bdfSopenharmony_ci
668f08c3bdfSopenharmony_ci		if (move2) {
669f08c3bdfSopenharmony_ci			if (t2 && t2->type != SYM_PTR) {
670f08c3bdfSopenharmony_ci				mod2 |= t2->ctype.modifiers;
671f08c3bdfSopenharmony_ci				combine_address_space(t2->pos, &as2, t2->ctype.as);
672f08c3bdfSopenharmony_ci			}
673f08c3bdfSopenharmony_ci			move2 = 0;
674f08c3bdfSopenharmony_ci		}
675f08c3bdfSopenharmony_ci
676f08c3bdfSopenharmony_ci		if (t1 == t2)
677f08c3bdfSopenharmony_ci			break;
678f08c3bdfSopenharmony_ci		if (!t1 || !t2)
679f08c3bdfSopenharmony_ci			return "different types";
680f08c3bdfSopenharmony_ci
681f08c3bdfSopenharmony_ci		if (t1->type == SYM_NODE || t1->type == SYM_ENUM) {
682f08c3bdfSopenharmony_ci			t1 = base1;
683f08c3bdfSopenharmony_ci			move1 = 1;
684f08c3bdfSopenharmony_ci			if (!t1)
685f08c3bdfSopenharmony_ci				return "bad types";
686f08c3bdfSopenharmony_ci			continue;
687f08c3bdfSopenharmony_ci		}
688f08c3bdfSopenharmony_ci
689f08c3bdfSopenharmony_ci		if (t2->type == SYM_NODE || t2->type == SYM_ENUM) {
690f08c3bdfSopenharmony_ci			t2 = base2;
691f08c3bdfSopenharmony_ci			move2 = 1;
692f08c3bdfSopenharmony_ci			if (!t2)
693f08c3bdfSopenharmony_ci				return "bad types";
694f08c3bdfSopenharmony_ci			continue;
695f08c3bdfSopenharmony_ci		}
696f08c3bdfSopenharmony_ci
697f08c3bdfSopenharmony_ci		move1 = move2 = 1;
698f08c3bdfSopenharmony_ci		type = t1->type;
699f08c3bdfSopenharmony_ci		if (type != t2->type)
700f08c3bdfSopenharmony_ci			return "different base types";
701f08c3bdfSopenharmony_ci
702f08c3bdfSopenharmony_ci		switch (type) {
703f08c3bdfSopenharmony_ci		default:
704f08c3bdfSopenharmony_ci			sparse_error(t1->pos,
705f08c3bdfSopenharmony_ci				     "internal error: bad type in derived(%d)",
706f08c3bdfSopenharmony_ci				     type);
707f08c3bdfSopenharmony_ci			return "bad types";
708f08c3bdfSopenharmony_ci		case SYM_RESTRICT:
709f08c3bdfSopenharmony_ci			return "different base types";
710f08c3bdfSopenharmony_ci		case SYM_UNION:
711f08c3bdfSopenharmony_ci		case SYM_STRUCT:
712f08c3bdfSopenharmony_ci			/* allow definition of incomplete structs and unions */
713f08c3bdfSopenharmony_ci			if (t1->ident == t2->ident)
714f08c3bdfSopenharmony_ci			  return NULL;
715f08c3bdfSopenharmony_ci			return "different base types";
716f08c3bdfSopenharmony_ci		case SYM_ARRAY:
717f08c3bdfSopenharmony_ci			/* XXX: we ought to compare sizes */
718f08c3bdfSopenharmony_ci			break;
719f08c3bdfSopenharmony_ci		case SYM_PTR:
720f08c3bdfSopenharmony_ci			if (as1 != as2)
721f08c3bdfSopenharmony_ci				return "different address spaces";
722f08c3bdfSopenharmony_ci			/* MOD_SPECIFIER is due to idiocy in parse.c */
723f08c3bdfSopenharmony_ci			if ((mod1 ^ mod2) & ~MOD_IGNORE & ~MOD_SPECIFIER)
724f08c3bdfSopenharmony_ci				return "different modifiers";
725f08c3bdfSopenharmony_ci			/* we could be lazier here */
726f08c3bdfSopenharmony_ci			base1 = examine_pointer_target(t1);
727f08c3bdfSopenharmony_ci			base2 = examine_pointer_target(t2);
728f08c3bdfSopenharmony_ci			mod1 = t1->ctype.modifiers;
729f08c3bdfSopenharmony_ci			as1 = t1->ctype.as;
730f08c3bdfSopenharmony_ci			mod2 = t2->ctype.modifiers;
731f08c3bdfSopenharmony_ci			as2 = t2->ctype.as;
732f08c3bdfSopenharmony_ci			break;
733f08c3bdfSopenharmony_ci		case SYM_FN: {
734f08c3bdfSopenharmony_ci			struct symbol *arg1, *arg2;
735f08c3bdfSopenharmony_ci			int i;
736f08c3bdfSopenharmony_ci
737f08c3bdfSopenharmony_ci			if (as1 != as2)
738f08c3bdfSopenharmony_ci				return "different address spaces";
739f08c3bdfSopenharmony_ci			if ((mod1 ^ mod2) & ~MOD_IGNORE & ~MOD_SIGNEDNESS)
740f08c3bdfSopenharmony_ci				return "different modifiers";
741f08c3bdfSopenharmony_ci			mod1 = t1->ctype.modifiers;
742f08c3bdfSopenharmony_ci			as1 = t1->ctype.as;
743f08c3bdfSopenharmony_ci			mod2 = t2->ctype.modifiers;
744f08c3bdfSopenharmony_ci			as2 = t2->ctype.as;
745f08c3bdfSopenharmony_ci
746f08c3bdfSopenharmony_ci			if (t1->variadic != t2->variadic)
747f08c3bdfSopenharmony_ci				return "incompatible variadic arguments";
748f08c3bdfSopenharmony_ci			examine_fn_arguments(t1);
749f08c3bdfSopenharmony_ci			examine_fn_arguments(t2);
750f08c3bdfSopenharmony_ci			PREPARE_PTR_LIST(t1->arguments, arg1);
751f08c3bdfSopenharmony_ci			PREPARE_PTR_LIST(t2->arguments, arg2);
752f08c3bdfSopenharmony_ci			i = 1;
753f08c3bdfSopenharmony_ci			for (;;) {
754f08c3bdfSopenharmony_ci				const char *diffstr;
755f08c3bdfSopenharmony_ci				if (!arg1 && !arg2)
756f08c3bdfSopenharmony_ci					break;
757f08c3bdfSopenharmony_ci				if (!arg1 || !arg2)
758f08c3bdfSopenharmony_ci					return "different argument counts";
759f08c3bdfSopenharmony_ci				diffstr = type_difference(&arg1->ctype,
760f08c3bdfSopenharmony_ci							  &arg2->ctype,
761f08c3bdfSopenharmony_ci							  MOD_IGN, MOD_IGN);
762f08c3bdfSopenharmony_ci				if (diffstr) {
763f08c3bdfSopenharmony_ci					static char argdiff[80];
764f08c3bdfSopenharmony_ci					sprintf(argdiff, "incompatible argument %d (%s)", i, diffstr);
765f08c3bdfSopenharmony_ci					return argdiff;
766f08c3bdfSopenharmony_ci				}
767f08c3bdfSopenharmony_ci				NEXT_PTR_LIST(arg1);
768f08c3bdfSopenharmony_ci				NEXT_PTR_LIST(arg2);
769f08c3bdfSopenharmony_ci				i++;
770f08c3bdfSopenharmony_ci			}
771f08c3bdfSopenharmony_ci			FINISH_PTR_LIST(arg2);
772f08c3bdfSopenharmony_ci			FINISH_PTR_LIST(arg1);
773f08c3bdfSopenharmony_ci			break;
774f08c3bdfSopenharmony_ci		}
775f08c3bdfSopenharmony_ci		case SYM_BASETYPE:
776f08c3bdfSopenharmony_ci			if (as1 != as2)
777f08c3bdfSopenharmony_ci				return "different address spaces";
778f08c3bdfSopenharmony_ci			if (base1 != base2)
779f08c3bdfSopenharmony_ci				return "different base types";
780f08c3bdfSopenharmony_ci			if (t1->rank != t2->rank)
781f08c3bdfSopenharmony_ci				return "different type sizes";
782f08c3bdfSopenharmony_ci			diff = (mod1 ^ mod2) & ~MOD_IGNORE;
783f08c3bdfSopenharmony_ci			if (!diff)
784f08c3bdfSopenharmony_ci				return NULL;
785f08c3bdfSopenharmony_ci			else if (diff & ~MOD_SIGNEDNESS)
786f08c3bdfSopenharmony_ci				return "different modifiers";
787f08c3bdfSopenharmony_ci			else
788f08c3bdfSopenharmony_ci				return "different signedness";
789f08c3bdfSopenharmony_ci		}
790f08c3bdfSopenharmony_ci		t1 = base1;
791f08c3bdfSopenharmony_ci		t2 = base2;
792f08c3bdfSopenharmony_ci	}
793f08c3bdfSopenharmony_ci	if (as1 != as2)
794f08c3bdfSopenharmony_ci		return "different address spaces";
795f08c3bdfSopenharmony_ci	if ((mod1 ^ mod2) & ~MOD_IGNORE & ~MOD_SIGNEDNESS)
796f08c3bdfSopenharmony_ci		return "different modifiers";
797f08c3bdfSopenharmony_ci	return NULL;
798f08c3bdfSopenharmony_ci}
799f08c3bdfSopenharmony_ci
800f08c3bdfSopenharmony_cistatic void bad_null(struct expression *expr)
801f08c3bdfSopenharmony_ci{
802f08c3bdfSopenharmony_ci	if (Wnon_pointer_null)
803f08c3bdfSopenharmony_ci		warning(expr->pos, "Using plain integer as NULL pointer");
804f08c3bdfSopenharmony_ci}
805f08c3bdfSopenharmony_ci
806f08c3bdfSopenharmony_cistatic unsigned long target_qualifiers(struct symbol *type)
807f08c3bdfSopenharmony_ci{
808f08c3bdfSopenharmony_ci	unsigned long mod = type->ctype.modifiers & MOD_IGN;
809f08c3bdfSopenharmony_ci	if (type->ctype.base_type && type->ctype.base_type->type == SYM_ARRAY)
810f08c3bdfSopenharmony_ci		mod = 0;
811f08c3bdfSopenharmony_ci	return mod;
812f08c3bdfSopenharmony_ci}
813f08c3bdfSopenharmony_ci
814f08c3bdfSopenharmony_cistatic struct symbol *evaluate_ptr_sub(struct expression *expr)
815f08c3bdfSopenharmony_ci{
816f08c3bdfSopenharmony_ci	const char *typediff;
817f08c3bdfSopenharmony_ci	struct symbol *ltype, *rtype;
818f08c3bdfSopenharmony_ci	struct expression *l = expr->left;
819f08c3bdfSopenharmony_ci	struct expression *r = expr->right;
820f08c3bdfSopenharmony_ci	struct symbol *lbase;
821f08c3bdfSopenharmony_ci
822f08c3bdfSopenharmony_ci	classify_type(degenerate(l), &ltype);
823f08c3bdfSopenharmony_ci	classify_type(degenerate(r), &rtype);
824f08c3bdfSopenharmony_ci
825f08c3bdfSopenharmony_ci	lbase = examine_pointer_target(ltype);
826f08c3bdfSopenharmony_ci	examine_pointer_target(rtype);
827f08c3bdfSopenharmony_ci	typediff = type_difference(&ltype->ctype, &rtype->ctype,
828f08c3bdfSopenharmony_ci				   target_qualifiers(rtype),
829f08c3bdfSopenharmony_ci				   target_qualifiers(ltype));
830f08c3bdfSopenharmony_ci	if (typediff)
831f08c3bdfSopenharmony_ci		expression_error(expr, "subtraction of different types can't work (%s)", typediff);
832f08c3bdfSopenharmony_ci
833f08c3bdfSopenharmony_ci	if (is_function(lbase)) {
834f08c3bdfSopenharmony_ci		expression_error(expr, "subtraction of functions? Share your drugs");
835f08c3bdfSopenharmony_ci		return NULL;
836f08c3bdfSopenharmony_ci	}
837f08c3bdfSopenharmony_ci
838f08c3bdfSopenharmony_ci	expr->ctype = ssize_t_ctype;
839f08c3bdfSopenharmony_ci	if (lbase->bit_size > bits_in_char) {
840f08c3bdfSopenharmony_ci		struct expression *sub = alloc_expression(expr->pos, EXPR_BINOP);
841f08c3bdfSopenharmony_ci		struct expression *div = expr;
842f08c3bdfSopenharmony_ci		struct expression *val = alloc_expression(expr->pos, EXPR_VALUE);
843f08c3bdfSopenharmony_ci		unsigned long value = bits_to_bytes(lbase->bit_size);
844f08c3bdfSopenharmony_ci
845f08c3bdfSopenharmony_ci		val->ctype = size_t_ctype;
846f08c3bdfSopenharmony_ci		val->value = value;
847f08c3bdfSopenharmony_ci
848f08c3bdfSopenharmony_ci		if (value & (value-1)) {
849f08c3bdfSopenharmony_ci			if (Wptr_subtraction_blows) {
850f08c3bdfSopenharmony_ci				warning(expr->pos, "potentially expensive pointer subtraction");
851f08c3bdfSopenharmony_ci				info(expr->pos, "    '%s' has a non-power-of-2 size: %lu", show_typename(lbase), value);
852f08c3bdfSopenharmony_ci			}
853f08c3bdfSopenharmony_ci		}
854f08c3bdfSopenharmony_ci
855f08c3bdfSopenharmony_ci		sub->op = '-';
856f08c3bdfSopenharmony_ci		sub->ctype = ssize_t_ctype;
857f08c3bdfSopenharmony_ci		sub->left = l;
858f08c3bdfSopenharmony_ci		sub->right = r;
859f08c3bdfSopenharmony_ci
860f08c3bdfSopenharmony_ci		div->op = '/';
861f08c3bdfSopenharmony_ci		div->left = sub;
862f08c3bdfSopenharmony_ci		div->right = val;
863f08c3bdfSopenharmony_ci	}
864f08c3bdfSopenharmony_ci
865f08c3bdfSopenharmony_ci	return ssize_t_ctype;
866f08c3bdfSopenharmony_ci}
867f08c3bdfSopenharmony_ci
868f08c3bdfSopenharmony_ci#define is_safe_type(type) ((type)->ctype.modifiers & MOD_SAFE)
869f08c3bdfSopenharmony_ci
870f08c3bdfSopenharmony_cistatic struct symbol *evaluate_conditional(struct expression *expr, int iterator)
871f08c3bdfSopenharmony_ci{
872f08c3bdfSopenharmony_ci	struct symbol *ctype;
873f08c3bdfSopenharmony_ci
874f08c3bdfSopenharmony_ci	if (!expr)
875f08c3bdfSopenharmony_ci		return NULL;
876f08c3bdfSopenharmony_ci
877f08c3bdfSopenharmony_ci	if (!iterator && expr->type == EXPR_ASSIGNMENT && expr->op == '=')
878f08c3bdfSopenharmony_ci		warning(expr->pos, "assignment expression in conditional");
879f08c3bdfSopenharmony_ci
880f08c3bdfSopenharmony_ci	ctype = evaluate_expression(expr);
881f08c3bdfSopenharmony_ci	if (!valid_type(ctype))
882f08c3bdfSopenharmony_ci		return NULL;
883f08c3bdfSopenharmony_ci	if (is_safe_type(ctype))
884f08c3bdfSopenharmony_ci		warning(expr->pos, "testing a 'safe expression'");
885f08c3bdfSopenharmony_ci	if (is_func_type(ctype)) {
886f08c3bdfSopenharmony_ci		if (Waddress)
887f08c3bdfSopenharmony_ci			warning(expr->pos, "the address of %s will always evaluate as true", "a function");
888f08c3bdfSopenharmony_ci	} else if (is_array_type(ctype)) {
889f08c3bdfSopenharmony_ci		if (Waddress)
890f08c3bdfSopenharmony_ci			warning(expr->pos, "the address of %s will always evaluate as true", "an array");
891f08c3bdfSopenharmony_ci	} else if (!is_scalar_type(ctype)) {
892f08c3bdfSopenharmony_ci		sparse_error(expr->pos, "non-scalar type in conditional:");
893f08c3bdfSopenharmony_ci		info(expr->pos, "   %s", show_typename(ctype));
894f08c3bdfSopenharmony_ci		return NULL;
895f08c3bdfSopenharmony_ci	}
896f08c3bdfSopenharmony_ci
897f08c3bdfSopenharmony_ci	ctype = degenerate(expr);
898f08c3bdfSopenharmony_ci	return ctype;
899f08c3bdfSopenharmony_ci}
900f08c3bdfSopenharmony_ci
901f08c3bdfSopenharmony_cistatic struct symbol *evaluate_logical(struct expression *expr)
902f08c3bdfSopenharmony_ci{
903f08c3bdfSopenharmony_ci	if (!evaluate_conditional(expr->left, 0))
904f08c3bdfSopenharmony_ci		return NULL;
905f08c3bdfSopenharmony_ci	if (!evaluate_conditional(expr->right, 0))
906f08c3bdfSopenharmony_ci		return NULL;
907f08c3bdfSopenharmony_ci
908f08c3bdfSopenharmony_ci	/* the result is int [6.5.13(3), 6.5.14(3)] */
909f08c3bdfSopenharmony_ci	expr->ctype = &int_ctype;
910f08c3bdfSopenharmony_ci	expr->flags = expr->left->flags & expr->right->flags;
911f08c3bdfSopenharmony_ci	expr->flags &= ~(CEF_CONST_MASK | CEF_ADDR);
912f08c3bdfSopenharmony_ci	return &int_ctype;
913f08c3bdfSopenharmony_ci}
914f08c3bdfSopenharmony_ci
915f08c3bdfSopenharmony_cistatic struct symbol *evaluate_binop(struct expression *expr)
916f08c3bdfSopenharmony_ci{
917f08c3bdfSopenharmony_ci	struct symbol *ltype, *rtype, *ctype;
918f08c3bdfSopenharmony_ci	int lclass = classify_type(expr->left->ctype, &ltype);
919f08c3bdfSopenharmony_ci	int rclass = classify_type(expr->right->ctype, &rtype);
920f08c3bdfSopenharmony_ci	int op = expr->op;
921f08c3bdfSopenharmony_ci
922f08c3bdfSopenharmony_ci	/* number op number */
923f08c3bdfSopenharmony_ci	if (lclass & rclass & TYPE_NUM) {
924f08c3bdfSopenharmony_ci		expr->flags = expr->left->flags & expr->right->flags;
925f08c3bdfSopenharmony_ci		expr->flags &= ~CEF_CONST_MASK;
926f08c3bdfSopenharmony_ci
927f08c3bdfSopenharmony_ci		if ((lclass | rclass) & TYPE_FLOAT) {
928f08c3bdfSopenharmony_ci			switch (op) {
929f08c3bdfSopenharmony_ci			case '+': case '-': case '*': case '/':
930f08c3bdfSopenharmony_ci				break;
931f08c3bdfSopenharmony_ci			default:
932f08c3bdfSopenharmony_ci				return bad_expr_type(expr);
933f08c3bdfSopenharmony_ci			}
934f08c3bdfSopenharmony_ci		}
935f08c3bdfSopenharmony_ci
936f08c3bdfSopenharmony_ci		if (op == SPECIAL_LEFTSHIFT || op == SPECIAL_RIGHTSHIFT) {
937f08c3bdfSopenharmony_ci			// shifts do integer promotions, but that's it.
938f08c3bdfSopenharmony_ci			unrestrict(expr->left, lclass, &ltype);
939f08c3bdfSopenharmony_ci			unrestrict(expr->right, rclass, &rtype);
940f08c3bdfSopenharmony_ci			ctype = ltype = integer_promotion(ltype);
941f08c3bdfSopenharmony_ci			rtype = integer_promotion(rtype);
942f08c3bdfSopenharmony_ci		} else {
943f08c3bdfSopenharmony_ci			// The rest do usual conversions
944f08c3bdfSopenharmony_ci			const unsigned left_not  = expr->left->type == EXPR_PREOP
945f08c3bdfSopenharmony_ci			                           && expr->left->op == '!';
946f08c3bdfSopenharmony_ci			const unsigned right_not = expr->right->type == EXPR_PREOP
947f08c3bdfSopenharmony_ci			                           && expr->right->op == '!';
948f08c3bdfSopenharmony_ci			if ((op == '&' || op == '|') && (left_not || right_not))
949f08c3bdfSopenharmony_ci				warning(expr->pos, "dubious: %sx %c %sy",
950f08c3bdfSopenharmony_ci				        left_not ? "!" : "",
951f08c3bdfSopenharmony_ci					op,
952f08c3bdfSopenharmony_ci					right_not ? "!" : "");
953f08c3bdfSopenharmony_ci
954f08c3bdfSopenharmony_ci			ltype = usual_conversions(op, expr->left, expr->right,
955f08c3bdfSopenharmony_ci						  lclass, rclass, ltype, rtype);
956f08c3bdfSopenharmony_ci			ctype = rtype = ltype;
957f08c3bdfSopenharmony_ci		}
958f08c3bdfSopenharmony_ci
959f08c3bdfSopenharmony_ci		expr->left = cast_to(expr->left, ltype);
960f08c3bdfSopenharmony_ci		expr->right = cast_to(expr->right, rtype);
961f08c3bdfSopenharmony_ci		expr->ctype = ctype;
962f08c3bdfSopenharmony_ci		return ctype;
963f08c3bdfSopenharmony_ci	}
964f08c3bdfSopenharmony_ci
965f08c3bdfSopenharmony_ci	/* pointer (+|-) integer */
966f08c3bdfSopenharmony_ci	if (lclass & TYPE_PTR && is_int(rclass) && (op == '+' || op == '-')) {
967f08c3bdfSopenharmony_ci		unrestrict(expr->right, rclass, &rtype);
968f08c3bdfSopenharmony_ci		return evaluate_ptr_add(expr, rtype);
969f08c3bdfSopenharmony_ci	}
970f08c3bdfSopenharmony_ci
971f08c3bdfSopenharmony_ci	/* integer + pointer */
972f08c3bdfSopenharmony_ci	if (rclass & TYPE_PTR && is_int(lclass) && op == '+') {
973f08c3bdfSopenharmony_ci		struct expression *index = expr->left;
974f08c3bdfSopenharmony_ci		unrestrict(index, lclass, &ltype);
975f08c3bdfSopenharmony_ci		expr->left = expr->right;
976f08c3bdfSopenharmony_ci		expr->right = index;
977f08c3bdfSopenharmony_ci		return evaluate_ptr_add(expr, ltype);
978f08c3bdfSopenharmony_ci	}
979f08c3bdfSopenharmony_ci
980f08c3bdfSopenharmony_ci	/* pointer - pointer */
981f08c3bdfSopenharmony_ci	if (lclass & rclass & TYPE_PTR && expr->op == '-')
982f08c3bdfSopenharmony_ci		return evaluate_ptr_sub(expr);
983f08c3bdfSopenharmony_ci
984f08c3bdfSopenharmony_ci	return bad_expr_type(expr);
985f08c3bdfSopenharmony_ci}
986f08c3bdfSopenharmony_ci
987f08c3bdfSopenharmony_cistatic struct symbol *evaluate_comma(struct expression *expr)
988f08c3bdfSopenharmony_ci{
989f08c3bdfSopenharmony_ci	expr->ctype = unqualify_type(degenerate(expr->right));
990f08c3bdfSopenharmony_ci	if (expr->ctype == &null_ctype)
991f08c3bdfSopenharmony_ci		expr->ctype = &ptr_ctype;
992f08c3bdfSopenharmony_ci	expr->flags &= expr->left->flags & expr->right->flags;
993f08c3bdfSopenharmony_ci	return expr->ctype;
994f08c3bdfSopenharmony_ci}
995f08c3bdfSopenharmony_ci
996f08c3bdfSopenharmony_cistatic int modify_for_unsigned(int op)
997f08c3bdfSopenharmony_ci{
998f08c3bdfSopenharmony_ci	if (op == '<')
999f08c3bdfSopenharmony_ci		op = SPECIAL_UNSIGNED_LT;
1000f08c3bdfSopenharmony_ci	else if (op == '>')
1001f08c3bdfSopenharmony_ci		op = SPECIAL_UNSIGNED_GT;
1002f08c3bdfSopenharmony_ci	else if (op == SPECIAL_LTE)
1003f08c3bdfSopenharmony_ci		op = SPECIAL_UNSIGNED_LTE;
1004f08c3bdfSopenharmony_ci	else if (op == SPECIAL_GTE)
1005f08c3bdfSopenharmony_ci		op = SPECIAL_UNSIGNED_GTE;
1006f08c3bdfSopenharmony_ci	return op;
1007f08c3bdfSopenharmony_ci}
1008f08c3bdfSopenharmony_ci
1009f08c3bdfSopenharmony_cienum null_constant_type {
1010f08c3bdfSopenharmony_ci	NON_NULL,
1011f08c3bdfSopenharmony_ci	NULL_PTR,
1012f08c3bdfSopenharmony_ci	NULL_ZERO,
1013f08c3bdfSopenharmony_ci};
1014f08c3bdfSopenharmony_ci
1015f08c3bdfSopenharmony_cistatic inline int is_null_pointer_constant(struct expression *e)
1016f08c3bdfSopenharmony_ci{
1017f08c3bdfSopenharmony_ci	if (e->ctype == &null_ctype)
1018f08c3bdfSopenharmony_ci		return NULL_PTR;
1019f08c3bdfSopenharmony_ci	if (!(e->flags & CEF_ICE))
1020f08c3bdfSopenharmony_ci		return NON_NULL;
1021f08c3bdfSopenharmony_ci	return is_zero_constant(e) ? NULL_ZERO : NON_NULL;
1022f08c3bdfSopenharmony_ci}
1023f08c3bdfSopenharmony_ci
1024f08c3bdfSopenharmony_cistatic struct symbol *evaluate_compare(struct expression *expr)
1025f08c3bdfSopenharmony_ci{
1026f08c3bdfSopenharmony_ci	struct expression *left = expr->left, *right = expr->right;
1027f08c3bdfSopenharmony_ci	struct symbol *ltype, *rtype, *lbase, *rbase;
1028f08c3bdfSopenharmony_ci	int lclass = classify_type(degenerate(left), &ltype);
1029f08c3bdfSopenharmony_ci	int rclass = classify_type(degenerate(right), &rtype);
1030f08c3bdfSopenharmony_ci	struct symbol *ctype;
1031f08c3bdfSopenharmony_ci	const char *typediff;
1032f08c3bdfSopenharmony_ci
1033f08c3bdfSopenharmony_ci	/* Type types? */
1034f08c3bdfSopenharmony_ci	if (is_type_type(ltype) && is_type_type(rtype)) {
1035f08c3bdfSopenharmony_ci		/*
1036f08c3bdfSopenharmony_ci		 * __builtin_types_compatible_p() yields an integer
1037f08c3bdfSopenharmony_ci		 * constant expression
1038f08c3bdfSopenharmony_ci		 */
1039f08c3bdfSopenharmony_ci		expr->flags = CEF_SET_ICE;
1040f08c3bdfSopenharmony_ci		goto OK;
1041f08c3bdfSopenharmony_ci	}
1042f08c3bdfSopenharmony_ci
1043f08c3bdfSopenharmony_ci	if (is_safe_type(left->ctype) || is_safe_type(right->ctype))
1044f08c3bdfSopenharmony_ci		warning(expr->pos, "testing a 'safe expression'");
1045f08c3bdfSopenharmony_ci
1046f08c3bdfSopenharmony_ci	expr->flags = left->flags & right->flags & ~CEF_CONST_MASK & ~CEF_ADDR;
1047f08c3bdfSopenharmony_ci
1048f08c3bdfSopenharmony_ci	/* number on number */
1049f08c3bdfSopenharmony_ci	if (lclass & rclass & TYPE_NUM) {
1050f08c3bdfSopenharmony_ci		ctype = usual_conversions(expr->op, expr->left, expr->right,
1051f08c3bdfSopenharmony_ci					  lclass, rclass, ltype, rtype);
1052f08c3bdfSopenharmony_ci		expr->left = cast_to(expr->left, ctype);
1053f08c3bdfSopenharmony_ci		expr->right = cast_to(expr->right, ctype);
1054f08c3bdfSopenharmony_ci		if (ctype->ctype.modifiers & MOD_UNSIGNED)
1055f08c3bdfSopenharmony_ci			expr->op = modify_for_unsigned(expr->op);
1056f08c3bdfSopenharmony_ci		goto OK;
1057f08c3bdfSopenharmony_ci	}
1058f08c3bdfSopenharmony_ci
1059f08c3bdfSopenharmony_ci	/* at least one must be a pointer */
1060f08c3bdfSopenharmony_ci	if (!((lclass | rclass) & TYPE_PTR))
1061f08c3bdfSopenharmony_ci		return bad_expr_type(expr);
1062f08c3bdfSopenharmony_ci
1063f08c3bdfSopenharmony_ci	/* equality comparisons can be with null pointer constants */
1064f08c3bdfSopenharmony_ci	if (expr->op == SPECIAL_EQUAL || expr->op == SPECIAL_NOTEQUAL) {
1065f08c3bdfSopenharmony_ci		int is_null1 = is_null_pointer_constant(left);
1066f08c3bdfSopenharmony_ci		int is_null2 = is_null_pointer_constant(right);
1067f08c3bdfSopenharmony_ci		if (is_null1 == NULL_ZERO)
1068f08c3bdfSopenharmony_ci			bad_null(left);
1069f08c3bdfSopenharmony_ci		if (is_null2 == NULL_ZERO)
1070f08c3bdfSopenharmony_ci			bad_null(right);
1071f08c3bdfSopenharmony_ci		if (is_null1 && is_null2) {
1072f08c3bdfSopenharmony_ci			int positive = expr->op == SPECIAL_EQUAL;
1073f08c3bdfSopenharmony_ci			expr->type = EXPR_VALUE;
1074f08c3bdfSopenharmony_ci			expr->value = positive;
1075f08c3bdfSopenharmony_ci			goto OK;
1076f08c3bdfSopenharmony_ci		}
1077f08c3bdfSopenharmony_ci		if (is_null1 && (rclass & TYPE_PTR)) {
1078f08c3bdfSopenharmony_ci			expr->left = cast_to(left, rtype);
1079f08c3bdfSopenharmony_ci			goto OK;
1080f08c3bdfSopenharmony_ci		}
1081f08c3bdfSopenharmony_ci		if (is_null2 && (lclass & TYPE_PTR)) {
1082f08c3bdfSopenharmony_ci			expr->right = cast_to(right, ltype);
1083f08c3bdfSopenharmony_ci			goto OK;
1084f08c3bdfSopenharmony_ci		}
1085f08c3bdfSopenharmony_ci	}
1086f08c3bdfSopenharmony_ci	/* both should be pointers */
1087f08c3bdfSopenharmony_ci	if (!(lclass & rclass & TYPE_PTR))
1088f08c3bdfSopenharmony_ci		return bad_expr_type(expr);
1089f08c3bdfSopenharmony_ci	expr->op = modify_for_unsigned(expr->op);
1090f08c3bdfSopenharmony_ci
1091f08c3bdfSopenharmony_ci	lbase = examine_pointer_target(ltype);
1092f08c3bdfSopenharmony_ci	rbase = examine_pointer_target(rtype);
1093f08c3bdfSopenharmony_ci
1094f08c3bdfSopenharmony_ci	/* they also have special treatment for pointers to void */
1095f08c3bdfSopenharmony_ci	if (expr->op == SPECIAL_EQUAL || expr->op == SPECIAL_NOTEQUAL) {
1096f08c3bdfSopenharmony_ci		if (ltype->ctype.as == rtype->ctype.as) {
1097f08c3bdfSopenharmony_ci			if (lbase == &void_ctype) {
1098f08c3bdfSopenharmony_ci				expr->right = cast_to(right, ltype);
1099f08c3bdfSopenharmony_ci				goto OK;
1100f08c3bdfSopenharmony_ci			}
1101f08c3bdfSopenharmony_ci			if (rbase == &void_ctype) {
1102f08c3bdfSopenharmony_ci				expr->left = cast_to(left, rtype);
1103f08c3bdfSopenharmony_ci				goto OK;
1104f08c3bdfSopenharmony_ci			}
1105f08c3bdfSopenharmony_ci		}
1106f08c3bdfSopenharmony_ci	}
1107f08c3bdfSopenharmony_ci
1108f08c3bdfSopenharmony_ci	typediff = type_difference(&ltype->ctype, &rtype->ctype,
1109f08c3bdfSopenharmony_ci				   target_qualifiers(rtype),
1110f08c3bdfSopenharmony_ci				   target_qualifiers(ltype));
1111f08c3bdfSopenharmony_ci	if (!typediff)
1112f08c3bdfSopenharmony_ci		goto OK;
1113f08c3bdfSopenharmony_ci
1114f08c3bdfSopenharmony_ci	expression_error(expr, "incompatible types in comparison expression (%s):", typediff);
1115f08c3bdfSopenharmony_ci	info(expr->pos, "   %s", show_typename(ltype));
1116f08c3bdfSopenharmony_ci	info(expr->pos, "   %s", show_typename(rtype));
1117f08c3bdfSopenharmony_ci	return NULL;
1118f08c3bdfSopenharmony_ci
1119f08c3bdfSopenharmony_ciOK:
1120f08c3bdfSopenharmony_ci	/* the result is int [6.5.8(6), 6.5.9(3)]*/
1121f08c3bdfSopenharmony_ci	expr->ctype = &int_ctype;
1122f08c3bdfSopenharmony_ci	return &int_ctype;
1123f08c3bdfSopenharmony_ci}
1124f08c3bdfSopenharmony_ci
1125f08c3bdfSopenharmony_ci/*
1126f08c3bdfSopenharmony_ci * NOTE! The degenerate case of "x ? : y", where we don't
1127f08c3bdfSopenharmony_ci * have a true case, this will possibly promote "x" to the
1128f08c3bdfSopenharmony_ci * same type as "y", and thus _change_ the conditional
1129f08c3bdfSopenharmony_ci * test in the expression. But since promotion is "safe"
1130f08c3bdfSopenharmony_ci * for testing, that's OK.
1131f08c3bdfSopenharmony_ci */
1132f08c3bdfSopenharmony_cistatic struct symbol *evaluate_conditional_expression(struct expression *expr)
1133f08c3bdfSopenharmony_ci{
1134f08c3bdfSopenharmony_ci	struct expression **cond;
1135f08c3bdfSopenharmony_ci	struct symbol *ctype, *ltype, *rtype, *lbase, *rbase;
1136f08c3bdfSopenharmony_ci	int lclass, rclass;
1137f08c3bdfSopenharmony_ci	const char * typediff;
1138f08c3bdfSopenharmony_ci	int qual;
1139f08c3bdfSopenharmony_ci
1140f08c3bdfSopenharmony_ci	if (!evaluate_conditional(expr->conditional, 0))
1141f08c3bdfSopenharmony_ci		return NULL;
1142f08c3bdfSopenharmony_ci	if (!evaluate_expression(expr->cond_false))
1143f08c3bdfSopenharmony_ci		return NULL;
1144f08c3bdfSopenharmony_ci
1145f08c3bdfSopenharmony_ci	ctype = degenerate(expr->conditional);
1146f08c3bdfSopenharmony_ci	rtype = degenerate(expr->cond_false);
1147f08c3bdfSopenharmony_ci
1148f08c3bdfSopenharmony_ci	cond = &expr->conditional;
1149f08c3bdfSopenharmony_ci	ltype = ctype;
1150f08c3bdfSopenharmony_ci	if (expr->cond_true) {
1151f08c3bdfSopenharmony_ci		if (!evaluate_expression(expr->cond_true))
1152f08c3bdfSopenharmony_ci			return NULL;
1153f08c3bdfSopenharmony_ci		ltype = degenerate(expr->cond_true);
1154f08c3bdfSopenharmony_ci		cond = &expr->cond_true;
1155f08c3bdfSopenharmony_ci	}
1156f08c3bdfSopenharmony_ci
1157f08c3bdfSopenharmony_ci	expr->flags = (expr->conditional->flags & (*cond)->flags &
1158f08c3bdfSopenharmony_ci			expr->cond_false->flags & ~CEF_CONST_MASK);
1159f08c3bdfSopenharmony_ci	/*
1160f08c3bdfSopenharmony_ci	 * In the standard, it is defined that an integer constant expression
1161f08c3bdfSopenharmony_ci	 * shall only have operands that are themselves constant [6.6(6)].
1162f08c3bdfSopenharmony_ci	 * While this definition is very clear for expressions that need all
1163f08c3bdfSopenharmony_ci	 * their operands to be evaluated, for conditional expressions with a
1164f08c3bdfSopenharmony_ci	 * constant condition things are much less obvious.
1165f08c3bdfSopenharmony_ci	 * So, as an extension, do the same as GCC seems to do:
1166f08c3bdfSopenharmony_ci	 *	Consider a conditional expression with a constant condition
1167f08c3bdfSopenharmony_ci	 *	as having the same constantness as the argument corresponding
1168f08c3bdfSopenharmony_ci	 *	to the truth value (including in the case of address constants
1169f08c3bdfSopenharmony_ci	 *	which are defined more stricly [6.6(9)]).
1170f08c3bdfSopenharmony_ci	 */
1171f08c3bdfSopenharmony_ci	if (expr->conditional->flags & (CEF_ACE | CEF_ADDR)) {
1172f08c3bdfSopenharmony_ci		int is_true = expr_truth_value(expr->conditional);
1173f08c3bdfSopenharmony_ci		struct expression *arg = is_true ? *cond : expr->cond_false;
1174f08c3bdfSopenharmony_ci		expr->flags = arg->flags & ~CEF_CONST_MASK;
1175f08c3bdfSopenharmony_ci	}
1176f08c3bdfSopenharmony_ci
1177f08c3bdfSopenharmony_ci	lclass = classify_type(ltype, &ltype);
1178f08c3bdfSopenharmony_ci	rclass = classify_type(rtype, &rtype);
1179f08c3bdfSopenharmony_ci	if (lclass & rclass & TYPE_NUM) {
1180f08c3bdfSopenharmony_ci		ctype = usual_conversions('?', *cond, expr->cond_false,
1181f08c3bdfSopenharmony_ci					  lclass, rclass, ltype, rtype);
1182f08c3bdfSopenharmony_ci		*cond = cast_to(*cond, ctype);
1183f08c3bdfSopenharmony_ci		expr->cond_false = cast_to(expr->cond_false, ctype);
1184f08c3bdfSopenharmony_ci		goto out;
1185f08c3bdfSopenharmony_ci	}
1186f08c3bdfSopenharmony_ci
1187f08c3bdfSopenharmony_ci	if ((lclass | rclass) & TYPE_PTR) {
1188f08c3bdfSopenharmony_ci		int is_null1 = is_null_pointer_constant(*cond);
1189f08c3bdfSopenharmony_ci		int is_null2 = is_null_pointer_constant(expr->cond_false);
1190f08c3bdfSopenharmony_ci
1191f08c3bdfSopenharmony_ci		if (is_null1 && is_null2) {
1192f08c3bdfSopenharmony_ci			*cond = cast_to(*cond, &ptr_ctype);
1193f08c3bdfSopenharmony_ci			expr->cond_false = cast_to(expr->cond_false, &ptr_ctype);
1194f08c3bdfSopenharmony_ci			ctype = &ptr_ctype;
1195f08c3bdfSopenharmony_ci			goto out;
1196f08c3bdfSopenharmony_ci		}
1197f08c3bdfSopenharmony_ci		if (is_null1 && (rclass & TYPE_PTR)) {
1198f08c3bdfSopenharmony_ci			if (is_null1 == NULL_ZERO)
1199f08c3bdfSopenharmony_ci				bad_null(*cond);
1200f08c3bdfSopenharmony_ci			*cond = cast_to(*cond, rtype);
1201f08c3bdfSopenharmony_ci			ctype = rtype;
1202f08c3bdfSopenharmony_ci			goto out;
1203f08c3bdfSopenharmony_ci		}
1204f08c3bdfSopenharmony_ci		if (is_null2 && (lclass & TYPE_PTR)) {
1205f08c3bdfSopenharmony_ci			if (is_null2 == NULL_ZERO)
1206f08c3bdfSopenharmony_ci				bad_null(expr->cond_false);
1207f08c3bdfSopenharmony_ci			expr->cond_false = cast_to(expr->cond_false, ltype);
1208f08c3bdfSopenharmony_ci			ctype = ltype;
1209f08c3bdfSopenharmony_ci			goto out;
1210f08c3bdfSopenharmony_ci		}
1211f08c3bdfSopenharmony_ci		if (!(lclass & rclass & TYPE_PTR)) {
1212f08c3bdfSopenharmony_ci			typediff = "different types";
1213f08c3bdfSopenharmony_ci			goto Err;
1214f08c3bdfSopenharmony_ci		}
1215f08c3bdfSopenharmony_ci		/* OK, it's pointer on pointer */
1216f08c3bdfSopenharmony_ci		if (ltype->ctype.as != rtype->ctype.as) {
1217f08c3bdfSopenharmony_ci			typediff = "different address spaces";
1218f08c3bdfSopenharmony_ci			goto Err;
1219f08c3bdfSopenharmony_ci		}
1220f08c3bdfSopenharmony_ci
1221f08c3bdfSopenharmony_ci		/* need to be lazier here */
1222f08c3bdfSopenharmony_ci		lbase = examine_pointer_target(ltype);
1223f08c3bdfSopenharmony_ci		rbase = examine_pointer_target(rtype);
1224f08c3bdfSopenharmony_ci		qual = target_qualifiers(ltype) | target_qualifiers(rtype);
1225f08c3bdfSopenharmony_ci
1226f08c3bdfSopenharmony_ci		if (lbase == &void_ctype) {
1227f08c3bdfSopenharmony_ci			/* XXX: pointers to function should warn here */
1228f08c3bdfSopenharmony_ci			ctype = ltype;
1229f08c3bdfSopenharmony_ci			goto Qual;
1230f08c3bdfSopenharmony_ci
1231f08c3bdfSopenharmony_ci		}
1232f08c3bdfSopenharmony_ci		if (rbase == &void_ctype) {
1233f08c3bdfSopenharmony_ci			/* XXX: pointers to function should warn here */
1234f08c3bdfSopenharmony_ci			ctype = rtype;
1235f08c3bdfSopenharmony_ci			goto Qual;
1236f08c3bdfSopenharmony_ci		}
1237f08c3bdfSopenharmony_ci		/* XXX: that should be pointer to composite */
1238f08c3bdfSopenharmony_ci		ctype = ltype;
1239f08c3bdfSopenharmony_ci		typediff = type_difference(&ltype->ctype, &rtype->ctype,
1240f08c3bdfSopenharmony_ci					   qual, qual);
1241f08c3bdfSopenharmony_ci		if (!typediff)
1242f08c3bdfSopenharmony_ci			goto Qual;
1243f08c3bdfSopenharmony_ci		goto Err;
1244f08c3bdfSopenharmony_ci	}
1245f08c3bdfSopenharmony_ci
1246f08c3bdfSopenharmony_ci	/* void on void, struct on same struct, union on same union */
1247f08c3bdfSopenharmony_ci	if (ltype == rtype) {
1248f08c3bdfSopenharmony_ci		ctype = ltype;
1249f08c3bdfSopenharmony_ci		goto out;
1250f08c3bdfSopenharmony_ci	}
1251f08c3bdfSopenharmony_ci	typediff = "different base types";
1252f08c3bdfSopenharmony_ci
1253f08c3bdfSopenharmony_ciErr:
1254f08c3bdfSopenharmony_ci	expression_error(expr, "incompatible types in conditional expression (%s):", typediff);
1255f08c3bdfSopenharmony_ci	info(expr->pos, "   %s", show_typename(ltype));
1256f08c3bdfSopenharmony_ci	info(expr->pos, "   %s", show_typename(rtype));
1257f08c3bdfSopenharmony_ci	/*
1258f08c3bdfSopenharmony_ci	 * if the condition is constant, the type is in fact known
1259f08c3bdfSopenharmony_ci	 * so use it, as gcc & clang do.
1260f08c3bdfSopenharmony_ci	 */
1261f08c3bdfSopenharmony_ci	switch (expr_truth_value(expr->conditional)) {
1262f08c3bdfSopenharmony_ci	case 1:	expr->ctype = ltype;
1263f08c3bdfSopenharmony_ci		break;
1264f08c3bdfSopenharmony_ci	case 0: expr->ctype = rtype;
1265f08c3bdfSopenharmony_ci		break;
1266f08c3bdfSopenharmony_ci	default:
1267f08c3bdfSopenharmony_ci		break;
1268f08c3bdfSopenharmony_ci	}
1269f08c3bdfSopenharmony_ci	return NULL;
1270f08c3bdfSopenharmony_ci
1271f08c3bdfSopenharmony_ciout:
1272f08c3bdfSopenharmony_ci	expr->ctype = ctype;
1273f08c3bdfSopenharmony_ci	return ctype;
1274f08c3bdfSopenharmony_ci
1275f08c3bdfSopenharmony_ciQual:
1276f08c3bdfSopenharmony_ci	if (qual & ~ctype->ctype.modifiers) {
1277f08c3bdfSopenharmony_ci		struct symbol *sym = alloc_symbol(ctype->pos, SYM_PTR);
1278f08c3bdfSopenharmony_ci		*sym = *ctype;
1279f08c3bdfSopenharmony_ci		sym->ctype.modifiers |= qual;
1280f08c3bdfSopenharmony_ci		ctype = sym;
1281f08c3bdfSopenharmony_ci	}
1282f08c3bdfSopenharmony_ci	*cond = cast_to(*cond, ctype);
1283f08c3bdfSopenharmony_ci	expr->cond_false = cast_to(expr->cond_false, ctype);
1284f08c3bdfSopenharmony_ci	goto out;
1285f08c3bdfSopenharmony_ci}
1286f08c3bdfSopenharmony_ci
1287f08c3bdfSopenharmony_ci/* FP assignments can not do modulo or bit operations */
1288f08c3bdfSopenharmony_cistatic int compatible_float_op(int op)
1289f08c3bdfSopenharmony_ci{
1290f08c3bdfSopenharmony_ci	return	op == SPECIAL_ADD_ASSIGN ||
1291f08c3bdfSopenharmony_ci		op == SPECIAL_SUB_ASSIGN ||
1292f08c3bdfSopenharmony_ci		op == SPECIAL_MUL_ASSIGN ||
1293f08c3bdfSopenharmony_ci		op == SPECIAL_DIV_ASSIGN;
1294f08c3bdfSopenharmony_ci}
1295f08c3bdfSopenharmony_ci
1296f08c3bdfSopenharmony_cistatic int evaluate_assign_op(struct expression *expr)
1297f08c3bdfSopenharmony_ci{
1298f08c3bdfSopenharmony_ci	struct symbol *target = expr->left->ctype;
1299f08c3bdfSopenharmony_ci	struct symbol *source = expr->right->ctype;
1300f08c3bdfSopenharmony_ci	struct symbol *t, *s;
1301f08c3bdfSopenharmony_ci	int tclass = classify_type(target, &t);
1302f08c3bdfSopenharmony_ci	int sclass = classify_type(source, &s);
1303f08c3bdfSopenharmony_ci	int op = expr->op;
1304f08c3bdfSopenharmony_ci
1305f08c3bdfSopenharmony_ci	if (tclass & sclass & TYPE_NUM) {
1306f08c3bdfSopenharmony_ci		if (tclass & TYPE_FLOAT && !compatible_float_op(op)) {
1307f08c3bdfSopenharmony_ci			expression_error(expr, "invalid assignment");
1308f08c3bdfSopenharmony_ci			return 0;
1309f08c3bdfSopenharmony_ci		}
1310f08c3bdfSopenharmony_ci		if (tclass & TYPE_RESTRICT) {
1311f08c3bdfSopenharmony_ci			if (!restricted_binop(op, t)) {
1312f08c3bdfSopenharmony_ci				warning(expr->pos, "bad assignment (%s) to %s",
1313f08c3bdfSopenharmony_ci					show_special(op), show_typename(t));
1314f08c3bdfSopenharmony_ci				expr->right = cast_to(expr->right, target);
1315f08c3bdfSopenharmony_ci				return 0;
1316f08c3bdfSopenharmony_ci			}
1317f08c3bdfSopenharmony_ci			/* allowed assignments unfoul */
1318f08c3bdfSopenharmony_ci			if (sclass & TYPE_FOULED && unfoul(s) == t)
1319f08c3bdfSopenharmony_ci				goto Cast;
1320f08c3bdfSopenharmony_ci			if (!restricted_value(expr->right, t))
1321f08c3bdfSopenharmony_ci				return 1;
1322f08c3bdfSopenharmony_ci		} else if (op == SPECIAL_SHR_ASSIGN || op == SPECIAL_SHL_ASSIGN) {
1323f08c3bdfSopenharmony_ci			// shifts do integer promotions, but that's it.
1324f08c3bdfSopenharmony_ci			unrestrict(expr->left, tclass, &t);
1325f08c3bdfSopenharmony_ci			target = integer_promotion(t);
1326f08c3bdfSopenharmony_ci
1327f08c3bdfSopenharmony_ci			unrestrict(expr->right, sclass, &s);
1328f08c3bdfSopenharmony_ci			source = integer_promotion(s);
1329f08c3bdfSopenharmony_ci			expr->right = cast_to(expr->right, source);
1330f08c3bdfSopenharmony_ci
1331f08c3bdfSopenharmony_ci			// both gcc & clang seems to do this, so ...
1332f08c3bdfSopenharmony_ci			if (target->bit_size > source->bit_size)
1333f08c3bdfSopenharmony_ci				expr->right = cast_to(expr->right, &uint_ctype);
1334f08c3bdfSopenharmony_ci
1335f08c3bdfSopenharmony_ci			goto Cast;
1336f08c3bdfSopenharmony_ci		} else if (!(sclass & TYPE_RESTRICT))
1337f08c3bdfSopenharmony_ci			goto usual;
1338f08c3bdfSopenharmony_ci		/* source and target would better be identical restricted */
1339f08c3bdfSopenharmony_ci		if (t == s)
1340f08c3bdfSopenharmony_ci			return 1;
1341f08c3bdfSopenharmony_ci		warning(expr->pos, "invalid assignment: %s", show_special(op));
1342f08c3bdfSopenharmony_ci		info(expr->pos, "   left side has type %s", show_typename(t));
1343f08c3bdfSopenharmony_ci		info(expr->pos, "   right side has type %s", show_typename(s));
1344f08c3bdfSopenharmony_ci		expr->right = cast_to(expr->right, target);
1345f08c3bdfSopenharmony_ci		return 0;
1346f08c3bdfSopenharmony_ci	}
1347f08c3bdfSopenharmony_ci	if (tclass == TYPE_PTR && is_int(sclass)) {
1348f08c3bdfSopenharmony_ci		if (op == SPECIAL_ADD_ASSIGN || op == SPECIAL_SUB_ASSIGN) {
1349f08c3bdfSopenharmony_ci			unrestrict(expr->right, sclass, &s);
1350f08c3bdfSopenharmony_ci			evaluate_ptr_add(expr, s);
1351f08c3bdfSopenharmony_ci			return 1;
1352f08c3bdfSopenharmony_ci		}
1353f08c3bdfSopenharmony_ci		expression_error(expr, "invalid pointer assignment");
1354f08c3bdfSopenharmony_ci		return 0;
1355f08c3bdfSopenharmony_ci	}
1356f08c3bdfSopenharmony_ci
1357f08c3bdfSopenharmony_ci	expression_error(expr, "invalid assignment");
1358f08c3bdfSopenharmony_ci	return 0;
1359f08c3bdfSopenharmony_ci
1360f08c3bdfSopenharmony_ciusual:
1361f08c3bdfSopenharmony_ci	target = usual_conversions(op, expr->left, expr->right,
1362f08c3bdfSopenharmony_ci				tclass, sclass, target, source);
1363f08c3bdfSopenharmony_ciCast:
1364f08c3bdfSopenharmony_ci	expr->right = cast_to(expr->right, target);
1365f08c3bdfSopenharmony_ci	return 1;
1366f08c3bdfSopenharmony_ci}
1367f08c3bdfSopenharmony_ci
1368f08c3bdfSopenharmony_cistatic int whitelist_pointers(struct symbol *t1, struct symbol *t2)
1369f08c3bdfSopenharmony_ci{
1370f08c3bdfSopenharmony_ci	if (t1 == t2)
1371f08c3bdfSopenharmony_ci		return 0;	/* yes, 0 - we don't want a cast_to here */
1372f08c3bdfSopenharmony_ci	if (t1 == &void_ctype)
1373f08c3bdfSopenharmony_ci		return 1;
1374f08c3bdfSopenharmony_ci	if (t2 == &void_ctype)
1375f08c3bdfSopenharmony_ci		return 1;
1376f08c3bdfSopenharmony_ci	if (classify_type(t1, &t1) != TYPE_NUM)
1377f08c3bdfSopenharmony_ci		return 0;
1378f08c3bdfSopenharmony_ci	if (classify_type(t2, &t2) != TYPE_NUM)
1379f08c3bdfSopenharmony_ci		return 0;
1380f08c3bdfSopenharmony_ci	if (t1 == t2)
1381f08c3bdfSopenharmony_ci		return 1;
1382f08c3bdfSopenharmony_ci	if (t1->rank == -2 && t2->rank == -2)
1383f08c3bdfSopenharmony_ci		return 1;
1384f08c3bdfSopenharmony_ci	if (t1->rank != t2->rank)
1385f08c3bdfSopenharmony_ci		return 0;
1386f08c3bdfSopenharmony_ci	return !Wtypesign;
1387f08c3bdfSopenharmony_ci}
1388f08c3bdfSopenharmony_ci
1389f08c3bdfSopenharmony_cistatic int check_assignment_types(struct symbol *target, struct expression **rp,
1390f08c3bdfSopenharmony_ci	const char **typediff)
1391f08c3bdfSopenharmony_ci{
1392f08c3bdfSopenharmony_ci	struct symbol *source = degenerate(*rp);
1393f08c3bdfSopenharmony_ci	struct symbol *t, *s;
1394f08c3bdfSopenharmony_ci	int tclass = classify_type(target, &t);
1395f08c3bdfSopenharmony_ci	int sclass = classify_type(source, &s);
1396f08c3bdfSopenharmony_ci
1397f08c3bdfSopenharmony_ci	if (tclass & sclass & TYPE_NUM) {
1398f08c3bdfSopenharmony_ci		if (tclass & TYPE_RESTRICT) {
1399f08c3bdfSopenharmony_ci			/* allowed assignments unfoul */
1400f08c3bdfSopenharmony_ci			if (sclass & TYPE_FOULED && unfoul(s) == t)
1401f08c3bdfSopenharmony_ci				goto Cast;
1402f08c3bdfSopenharmony_ci			if (!restricted_value(*rp, target))
1403f08c3bdfSopenharmony_ci				goto Cast;
1404f08c3bdfSopenharmony_ci			if (s == t)
1405f08c3bdfSopenharmony_ci				return 1;
1406f08c3bdfSopenharmony_ci		} else if (!(sclass & TYPE_RESTRICT))
1407f08c3bdfSopenharmony_ci			goto Cast;
1408f08c3bdfSopenharmony_ci                if (t == &bool_ctype) {
1409f08c3bdfSopenharmony_ci                        if (is_fouled_type(s))
1410f08c3bdfSopenharmony_ci                                warning((*rp)->pos, "%s degrades to integer",
1411f08c3bdfSopenharmony_ci                                        show_typename(s->ctype.base_type));
1412f08c3bdfSopenharmony_ci                        goto Cast;
1413f08c3bdfSopenharmony_ci                }
1414f08c3bdfSopenharmony_ci		*typediff = "different base types";
1415f08c3bdfSopenharmony_ci		return 0;
1416f08c3bdfSopenharmony_ci	}
1417f08c3bdfSopenharmony_ci
1418f08c3bdfSopenharmony_ci	if (tclass == TYPE_PTR) {
1419f08c3bdfSopenharmony_ci		unsigned long mod1, mod2;
1420f08c3bdfSopenharmony_ci		unsigned long modl, modr;
1421f08c3bdfSopenharmony_ci		struct symbol *b1, *b2;
1422f08c3bdfSopenharmony_ci		// NULL pointer is always OK
1423f08c3bdfSopenharmony_ci		int is_null = is_null_pointer_constant(*rp);
1424f08c3bdfSopenharmony_ci		if (is_null) {
1425f08c3bdfSopenharmony_ci			if (is_null == NULL_ZERO)
1426f08c3bdfSopenharmony_ci				bad_null(*rp);
1427f08c3bdfSopenharmony_ci			goto Cast;
1428f08c3bdfSopenharmony_ci		}
1429f08c3bdfSopenharmony_ci		if (!(sclass & TYPE_PTR)) {
1430f08c3bdfSopenharmony_ci			*typediff = "different base types";
1431f08c3bdfSopenharmony_ci			return 0;
1432f08c3bdfSopenharmony_ci		}
1433f08c3bdfSopenharmony_ci		b1 = examine_pointer_target(t);
1434f08c3bdfSopenharmony_ci		b2 = examine_pointer_target(s);
1435f08c3bdfSopenharmony_ci		mod1 = t->ctype.modifiers & MOD_IGN;
1436f08c3bdfSopenharmony_ci		mod2 = s->ctype.modifiers & MOD_IGN;
1437f08c3bdfSopenharmony_ci		if (whitelist_pointers(b1, b2)) {
1438f08c3bdfSopenharmony_ci			/*
1439f08c3bdfSopenharmony_ci			 * assignments to/from void * are OK, provided that
1440f08c3bdfSopenharmony_ci			 * we do not remove qualifiers from pointed to [C]
1441f08c3bdfSopenharmony_ci			 * or mix address spaces [sparse].
1442f08c3bdfSopenharmony_ci			 */
1443f08c3bdfSopenharmony_ci			if (t->ctype.as != s->ctype.as) {
1444f08c3bdfSopenharmony_ci				*typediff = "different address spaces";
1445f08c3bdfSopenharmony_ci				return 0;
1446f08c3bdfSopenharmony_ci			}
1447f08c3bdfSopenharmony_ci			/*
1448f08c3bdfSopenharmony_ci			 * If this is a function pointer assignment, it is
1449f08c3bdfSopenharmony_ci			 * actually fine to assign a pointer to const data to
1450f08c3bdfSopenharmony_ci			 * it, as a function pointer points to const data
1451f08c3bdfSopenharmony_ci			 * implicitly, i.e., dereferencing it does not produce
1452f08c3bdfSopenharmony_ci			 * an lvalue.
1453f08c3bdfSopenharmony_ci			 */
1454f08c3bdfSopenharmony_ci			if (b1->type == SYM_FN)
1455f08c3bdfSopenharmony_ci				mod1 |= MOD_CONST;
1456f08c3bdfSopenharmony_ci			if (mod2 & ~mod1 & ~MOD_FUN_ATTR) {
1457f08c3bdfSopenharmony_ci				*typediff = "different modifiers";
1458f08c3bdfSopenharmony_ci				return 0;
1459f08c3bdfSopenharmony_ci			}
1460f08c3bdfSopenharmony_ci			goto Cast;
1461f08c3bdfSopenharmony_ci		}
1462f08c3bdfSopenharmony_ci		/* It's OK if the target is more volatile or const than the source */
1463f08c3bdfSopenharmony_ci		/* It's OK if the source is more pure/noreturn than the target */
1464f08c3bdfSopenharmony_ci		modr = mod1 & ~MOD_REV_QUAL;
1465f08c3bdfSopenharmony_ci		modl = mod2 &  MOD_REV_QUAL;
1466f08c3bdfSopenharmony_ci		*typediff = type_difference(&t->ctype, &s->ctype, modl, modr);
1467f08c3bdfSopenharmony_ci		if (*typediff)
1468f08c3bdfSopenharmony_ci			return 0;
1469f08c3bdfSopenharmony_ci		return 1;
1470f08c3bdfSopenharmony_ci	}
1471f08c3bdfSopenharmony_ci
1472f08c3bdfSopenharmony_ci	if ((tclass & TYPE_COMPOUND) && s == t)
1473f08c3bdfSopenharmony_ci		return 1;
1474f08c3bdfSopenharmony_ci
1475f08c3bdfSopenharmony_ci	if (tclass & TYPE_NUM) {
1476f08c3bdfSopenharmony_ci		/* XXX: need to turn into comparison with NULL */
1477f08c3bdfSopenharmony_ci		if (t == &bool_ctype && (sclass & TYPE_PTR))
1478f08c3bdfSopenharmony_ci			goto Cast;
1479f08c3bdfSopenharmony_ci		*typediff = "different base types";
1480f08c3bdfSopenharmony_ci		return 0;
1481f08c3bdfSopenharmony_ci	}
1482f08c3bdfSopenharmony_ci	*typediff = "invalid types";
1483f08c3bdfSopenharmony_ci	return 0;
1484f08c3bdfSopenharmony_ci
1485f08c3bdfSopenharmony_ciCast:
1486f08c3bdfSopenharmony_ci	*rp = cast_to(*rp, target);
1487f08c3bdfSopenharmony_ci	return 1;
1488f08c3bdfSopenharmony_ci}
1489f08c3bdfSopenharmony_ci
1490f08c3bdfSopenharmony_cistatic int compatible_assignment_types(struct expression *expr, struct symbol *target,
1491f08c3bdfSopenharmony_ci	struct expression **rp, const char *where)
1492f08c3bdfSopenharmony_ci{
1493f08c3bdfSopenharmony_ci	const char *typediff;
1494f08c3bdfSopenharmony_ci
1495f08c3bdfSopenharmony_ci	if (!check_assignment_types(target, rp, &typediff)) {
1496f08c3bdfSopenharmony_ci		struct symbol *source = *rp ? (*rp)->ctype : NULL;
1497f08c3bdfSopenharmony_ci		warning(expr->pos, "incorrect type in %s (%s)", where, typediff);
1498f08c3bdfSopenharmony_ci		info(expr->pos, "   expected %s", show_typename(target));
1499f08c3bdfSopenharmony_ci		info(expr->pos, "   got %s", show_typename(source));
1500f08c3bdfSopenharmony_ci		*rp = cast_to(*rp, target);
1501f08c3bdfSopenharmony_ci		return 0;
1502f08c3bdfSopenharmony_ci	}
1503f08c3bdfSopenharmony_ci
1504f08c3bdfSopenharmony_ci	return 1;
1505f08c3bdfSopenharmony_ci}
1506f08c3bdfSopenharmony_ci
1507f08c3bdfSopenharmony_cistatic int compatible_transparent_union(struct symbol *target,
1508f08c3bdfSopenharmony_ci	struct expression **rp)
1509f08c3bdfSopenharmony_ci{
1510f08c3bdfSopenharmony_ci	struct symbol *t, *member;
1511f08c3bdfSopenharmony_ci	classify_type(target, &t);
1512f08c3bdfSopenharmony_ci	if (t->type != SYM_UNION || !t->transparent_union)
1513f08c3bdfSopenharmony_ci		return 0;
1514f08c3bdfSopenharmony_ci
1515f08c3bdfSopenharmony_ci	FOR_EACH_PTR(t->symbol_list, member) {
1516f08c3bdfSopenharmony_ci		const char *typediff;
1517f08c3bdfSopenharmony_ci		if (check_assignment_types(member, rp, &typediff))
1518f08c3bdfSopenharmony_ci			return 1;
1519f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(member);
1520f08c3bdfSopenharmony_ci
1521f08c3bdfSopenharmony_ci	return 0;
1522f08c3bdfSopenharmony_ci}
1523f08c3bdfSopenharmony_ci
1524f08c3bdfSopenharmony_cistatic int compatible_argument_type(struct expression *expr, struct symbol *target,
1525f08c3bdfSopenharmony_ci	struct expression **rp, const char *where)
1526f08c3bdfSopenharmony_ci{
1527f08c3bdfSopenharmony_ci	if (compatible_transparent_union(target, rp))
1528f08c3bdfSopenharmony_ci		return 1;
1529f08c3bdfSopenharmony_ci
1530f08c3bdfSopenharmony_ci	return compatible_assignment_types(expr, target, rp, where);
1531f08c3bdfSopenharmony_ci}
1532f08c3bdfSopenharmony_ci
1533f08c3bdfSopenharmony_cistatic void mark_addressable(struct expression *expr)
1534f08c3bdfSopenharmony_ci{
1535f08c3bdfSopenharmony_ci	while (expr->type == EXPR_BINOP && expr->op == '+')
1536f08c3bdfSopenharmony_ci		expr = expr->left;
1537f08c3bdfSopenharmony_ci	if (expr->type == EXPR_SYMBOL) {
1538f08c3bdfSopenharmony_ci		struct symbol *sym = expr->symbol;
1539f08c3bdfSopenharmony_ci		sym->ctype.modifiers |= MOD_ADDRESSABLE;
1540f08c3bdfSopenharmony_ci	}
1541f08c3bdfSopenharmony_ci}
1542f08c3bdfSopenharmony_ci
1543f08c3bdfSopenharmony_cistatic void mark_assigned(struct expression *expr)
1544f08c3bdfSopenharmony_ci{
1545f08c3bdfSopenharmony_ci	struct symbol *sym;
1546f08c3bdfSopenharmony_ci
1547f08c3bdfSopenharmony_ci	if (!expr)
1548f08c3bdfSopenharmony_ci		return;
1549f08c3bdfSopenharmony_ci	switch (expr->type) {
1550f08c3bdfSopenharmony_ci	case EXPR_SYMBOL:
1551f08c3bdfSopenharmony_ci		sym = expr->symbol;
1552f08c3bdfSopenharmony_ci		if (!sym)
1553f08c3bdfSopenharmony_ci			return;
1554f08c3bdfSopenharmony_ci		if (sym->type != SYM_NODE)
1555f08c3bdfSopenharmony_ci			return;
1556f08c3bdfSopenharmony_ci		sym->ctype.modifiers |= MOD_ASSIGNED;
1557f08c3bdfSopenharmony_ci		return;
1558f08c3bdfSopenharmony_ci
1559f08c3bdfSopenharmony_ci	case EXPR_BINOP:
1560f08c3bdfSopenharmony_ci		mark_assigned(expr->left);
1561f08c3bdfSopenharmony_ci		mark_assigned(expr->right);
1562f08c3bdfSopenharmony_ci		return;
1563f08c3bdfSopenharmony_ci	case EXPR_CAST:
1564f08c3bdfSopenharmony_ci	case EXPR_FORCE_CAST:
1565f08c3bdfSopenharmony_ci		mark_assigned(expr->cast_expression);
1566f08c3bdfSopenharmony_ci		return;
1567f08c3bdfSopenharmony_ci	case EXPR_SLICE:
1568f08c3bdfSopenharmony_ci		mark_assigned(expr->base);
1569f08c3bdfSopenharmony_ci		return;
1570f08c3bdfSopenharmony_ci	default:
1571f08c3bdfSopenharmony_ci		/* Hmm? */
1572f08c3bdfSopenharmony_ci		return;
1573f08c3bdfSopenharmony_ci	}
1574f08c3bdfSopenharmony_ci}
1575f08c3bdfSopenharmony_ci
1576f08c3bdfSopenharmony_cistatic void evaluate_assign_to(struct expression *left, struct symbol *type)
1577f08c3bdfSopenharmony_ci{
1578f08c3bdfSopenharmony_ci	if (type->ctype.modifiers & MOD_CONST)
1579f08c3bdfSopenharmony_ci		expression_error(left, "assignment to const expression");
1580f08c3bdfSopenharmony_ci
1581f08c3bdfSopenharmony_ci	/* We know left is an lvalue, so it's a "preop-*" */
1582f08c3bdfSopenharmony_ci	mark_assigned(left->unop);
1583f08c3bdfSopenharmony_ci}
1584f08c3bdfSopenharmony_ci
1585f08c3bdfSopenharmony_cistatic struct symbol *evaluate_assignment(struct expression *expr)
1586f08c3bdfSopenharmony_ci{
1587f08c3bdfSopenharmony_ci	struct expression *left = expr->left;
1588f08c3bdfSopenharmony_ci	struct symbol *ltype;
1589f08c3bdfSopenharmony_ci
1590f08c3bdfSopenharmony_ci	if (!lvalue_expression(left)) {
1591f08c3bdfSopenharmony_ci		expression_error(expr, "not an lvalue");
1592f08c3bdfSopenharmony_ci		return NULL;
1593f08c3bdfSopenharmony_ci	}
1594f08c3bdfSopenharmony_ci
1595f08c3bdfSopenharmony_ci	ltype = left->ctype;
1596f08c3bdfSopenharmony_ci
1597f08c3bdfSopenharmony_ci	if (expr->op != '=') {
1598f08c3bdfSopenharmony_ci		if (!evaluate_assign_op(expr))
1599f08c3bdfSopenharmony_ci			return NULL;
1600f08c3bdfSopenharmony_ci	} else {
1601f08c3bdfSopenharmony_ci		if (!compatible_assignment_types(expr, ltype, &expr->right, "assignment"))
1602f08c3bdfSopenharmony_ci			return NULL;
1603f08c3bdfSopenharmony_ci	}
1604f08c3bdfSopenharmony_ci
1605f08c3bdfSopenharmony_ci	evaluate_assign_to(left, ltype);
1606f08c3bdfSopenharmony_ci
1607f08c3bdfSopenharmony_ci	expr->ctype = ltype;
1608f08c3bdfSopenharmony_ci	return ltype;
1609f08c3bdfSopenharmony_ci}
1610f08c3bdfSopenharmony_ci
1611f08c3bdfSopenharmony_cistatic void examine_fn_arguments(struct symbol *fn)
1612f08c3bdfSopenharmony_ci{
1613f08c3bdfSopenharmony_ci	struct symbol *s;
1614f08c3bdfSopenharmony_ci
1615f08c3bdfSopenharmony_ci	FOR_EACH_PTR(fn->arguments, s) {
1616f08c3bdfSopenharmony_ci		struct symbol *arg = evaluate_symbol(s);
1617f08c3bdfSopenharmony_ci		/* Array/function arguments silently degenerate into pointers */
1618f08c3bdfSopenharmony_ci		if (arg) {
1619f08c3bdfSopenharmony_ci			struct symbol *ptr;
1620f08c3bdfSopenharmony_ci			switch(arg->type) {
1621f08c3bdfSopenharmony_ci			case SYM_ARRAY:
1622f08c3bdfSopenharmony_ci			case SYM_FN:
1623f08c3bdfSopenharmony_ci				ptr = alloc_symbol(s->pos, SYM_PTR);
1624f08c3bdfSopenharmony_ci				if (arg->type == SYM_ARRAY)
1625f08c3bdfSopenharmony_ci					ptr->ctype = arg->ctype;
1626f08c3bdfSopenharmony_ci				else
1627f08c3bdfSopenharmony_ci					ptr->ctype.base_type = arg;
1628f08c3bdfSopenharmony_ci				combine_address_space(s->pos, &ptr->ctype.as, s->ctype.as);
1629f08c3bdfSopenharmony_ci				ptr->ctype.modifiers |= s->ctype.modifiers & MOD_PTRINHERIT;
1630f08c3bdfSopenharmony_ci
1631f08c3bdfSopenharmony_ci				s->ctype.base_type = ptr;
1632f08c3bdfSopenharmony_ci				s->ctype.as = NULL;
1633f08c3bdfSopenharmony_ci				s->ctype.modifiers &= ~MOD_PTRINHERIT;
1634f08c3bdfSopenharmony_ci				s->bit_size = 0;
1635f08c3bdfSopenharmony_ci				s->examined = 0;
1636f08c3bdfSopenharmony_ci				examine_symbol_type(s);
1637f08c3bdfSopenharmony_ci				break;
1638f08c3bdfSopenharmony_ci			default:
1639f08c3bdfSopenharmony_ci				/* nothing */
1640f08c3bdfSopenharmony_ci				break;
1641f08c3bdfSopenharmony_ci			}
1642f08c3bdfSopenharmony_ci		}
1643f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(s);
1644f08c3bdfSopenharmony_ci}
1645f08c3bdfSopenharmony_ci
1646f08c3bdfSopenharmony_cistatic struct symbol *convert_to_as_mod(struct symbol *sym, struct ident *as, int mod)
1647f08c3bdfSopenharmony_ci{
1648f08c3bdfSopenharmony_ci	/* Take the modifiers of the pointer, and apply them to the member */
1649f08c3bdfSopenharmony_ci	mod |= sym->ctype.modifiers;
1650f08c3bdfSopenharmony_ci	if (sym->ctype.as != as || sym->ctype.modifiers != mod) {
1651f08c3bdfSopenharmony_ci		struct symbol *newsym = alloc_symbol(sym->pos, SYM_NODE);
1652f08c3bdfSopenharmony_ci		*newsym = *sym;
1653f08c3bdfSopenharmony_ci		newsym->ctype.as = as;
1654f08c3bdfSopenharmony_ci		newsym->ctype.modifiers = mod;
1655f08c3bdfSopenharmony_ci		sym = newsym;
1656f08c3bdfSopenharmony_ci	}
1657f08c3bdfSopenharmony_ci	return sym;
1658f08c3bdfSopenharmony_ci}
1659f08c3bdfSopenharmony_ci
1660f08c3bdfSopenharmony_cistatic struct symbol *create_pointer(struct expression *expr, struct symbol *sym, int degenerate)
1661f08c3bdfSopenharmony_ci{
1662f08c3bdfSopenharmony_ci	struct symbol *node = alloc_symbol(expr->pos, SYM_NODE);
1663f08c3bdfSopenharmony_ci	struct symbol *ptr = alloc_symbol(expr->pos, SYM_PTR);
1664f08c3bdfSopenharmony_ci
1665f08c3bdfSopenharmony_ci	node->ctype.base_type = ptr;
1666f08c3bdfSopenharmony_ci	ptr->bit_size = bits_in_pointer;
1667f08c3bdfSopenharmony_ci	ptr->ctype.alignment = pointer_alignment;
1668f08c3bdfSopenharmony_ci
1669f08c3bdfSopenharmony_ci	node->bit_size = bits_in_pointer;
1670f08c3bdfSopenharmony_ci	node->ctype.alignment = pointer_alignment;
1671f08c3bdfSopenharmony_ci
1672f08c3bdfSopenharmony_ci	access_symbol(sym);
1673f08c3bdfSopenharmony_ci	if (sym->ctype.modifiers & MOD_REGISTER) {
1674f08c3bdfSopenharmony_ci		warning(expr->pos, "taking address of 'register' variable '%s'", show_ident(sym->ident));
1675f08c3bdfSopenharmony_ci		sym->ctype.modifiers &= ~MOD_REGISTER;
1676f08c3bdfSopenharmony_ci	}
1677f08c3bdfSopenharmony_ci	if (sym->type == SYM_NODE) {
1678f08c3bdfSopenharmony_ci		combine_address_space(sym->pos, &ptr->ctype.as, sym->ctype.as);
1679f08c3bdfSopenharmony_ci		ptr->ctype.modifiers |= sym->ctype.modifiers & MOD_PTRINHERIT;
1680f08c3bdfSopenharmony_ci		sym = sym->ctype.base_type;
1681f08c3bdfSopenharmony_ci	}
1682f08c3bdfSopenharmony_ci	if (degenerate && sym->type == SYM_ARRAY) {
1683f08c3bdfSopenharmony_ci		combine_address_space(sym->pos, &ptr->ctype.as, sym->ctype.as);
1684f08c3bdfSopenharmony_ci		ptr->ctype.modifiers |= sym->ctype.modifiers & MOD_PTRINHERIT;
1685f08c3bdfSopenharmony_ci		sym = sym->ctype.base_type;
1686f08c3bdfSopenharmony_ci	}
1687f08c3bdfSopenharmony_ci	ptr->ctype.base_type = sym;
1688f08c3bdfSopenharmony_ci
1689f08c3bdfSopenharmony_ci	return node;
1690f08c3bdfSopenharmony_ci}
1691f08c3bdfSopenharmony_ci
1692f08c3bdfSopenharmony_ci/* Arrays degenerate into pointers on pointer arithmetic */
1693f08c3bdfSopenharmony_cistatic struct symbol *degenerate(struct expression *expr)
1694f08c3bdfSopenharmony_ci{
1695f08c3bdfSopenharmony_ci	struct symbol *ctype, *base;
1696f08c3bdfSopenharmony_ci
1697f08c3bdfSopenharmony_ci	if (!expr)
1698f08c3bdfSopenharmony_ci		return NULL;
1699f08c3bdfSopenharmony_ci	ctype = expr->ctype;
1700f08c3bdfSopenharmony_ci	if (!ctype)
1701f08c3bdfSopenharmony_ci		return NULL;
1702f08c3bdfSopenharmony_ci	base = examine_symbol_type(ctype);
1703f08c3bdfSopenharmony_ci	if (ctype->type == SYM_NODE)
1704f08c3bdfSopenharmony_ci		base = ctype->ctype.base_type;
1705f08c3bdfSopenharmony_ci	/*
1706f08c3bdfSopenharmony_ci	 * Arrays degenerate into pointers to the entries, while
1707f08c3bdfSopenharmony_ci	 * functions degenerate into pointers to themselves.
1708f08c3bdfSopenharmony_ci	 * If array was part of non-lvalue compound, we create a copy
1709f08c3bdfSopenharmony_ci	 * of that compound first and then act as if we were dealing with
1710f08c3bdfSopenharmony_ci	 * the corresponding field in there.
1711f08c3bdfSopenharmony_ci	 */
1712f08c3bdfSopenharmony_ci	switch (base->type) {
1713f08c3bdfSopenharmony_ci	case SYM_ARRAY:
1714f08c3bdfSopenharmony_ci		if (expr->type == EXPR_SLICE) {
1715f08c3bdfSopenharmony_ci			struct symbol *a = alloc_symbol(expr->pos, SYM_NODE);
1716f08c3bdfSopenharmony_ci			struct expression *e0, *e1, *e2, *e3, *e4;
1717f08c3bdfSopenharmony_ci
1718f08c3bdfSopenharmony_ci			a->ctype.base_type = expr->base->ctype;
1719f08c3bdfSopenharmony_ci			a->bit_size = expr->base->ctype->bit_size;
1720f08c3bdfSopenharmony_ci			a->array_size = expr->base->ctype->array_size;
1721f08c3bdfSopenharmony_ci
1722f08c3bdfSopenharmony_ci			e0 = alloc_expression(expr->pos, EXPR_SYMBOL);
1723f08c3bdfSopenharmony_ci			e0->symbol = a;
1724f08c3bdfSopenharmony_ci			e0->ctype = &lazy_ptr_ctype;
1725f08c3bdfSopenharmony_ci
1726f08c3bdfSopenharmony_ci			e1 = alloc_expression(expr->pos, EXPR_PREOP);
1727f08c3bdfSopenharmony_ci			e1->unop = e0;
1728f08c3bdfSopenharmony_ci			e1->op = '*';
1729f08c3bdfSopenharmony_ci			e1->ctype = expr->base->ctype;	/* XXX */
1730f08c3bdfSopenharmony_ci
1731f08c3bdfSopenharmony_ci			e2 = alloc_expression(expr->pos, EXPR_ASSIGNMENT);
1732f08c3bdfSopenharmony_ci			e2->left = e1;
1733f08c3bdfSopenharmony_ci			e2->right = expr->base;
1734f08c3bdfSopenharmony_ci			e2->op = '=';
1735f08c3bdfSopenharmony_ci			e2->ctype = expr->base->ctype;
1736f08c3bdfSopenharmony_ci
1737f08c3bdfSopenharmony_ci			if (expr->r_bitpos) {
1738f08c3bdfSopenharmony_ci				e3 = alloc_expression(expr->pos, EXPR_BINOP);
1739f08c3bdfSopenharmony_ci				e3->op = '+';
1740f08c3bdfSopenharmony_ci				e3->left = e0;
1741f08c3bdfSopenharmony_ci				e3->right = alloc_const_expression(expr->pos,
1742f08c3bdfSopenharmony_ci							bits_to_bytes(expr->r_bitpos));
1743f08c3bdfSopenharmony_ci				e3->ctype = &lazy_ptr_ctype;
1744f08c3bdfSopenharmony_ci			} else {
1745f08c3bdfSopenharmony_ci				e3 = e0;
1746f08c3bdfSopenharmony_ci			}
1747f08c3bdfSopenharmony_ci
1748f08c3bdfSopenharmony_ci			e4 = alloc_expression(expr->pos, EXPR_COMMA);
1749f08c3bdfSopenharmony_ci			e4->left = e2;
1750f08c3bdfSopenharmony_ci			e4->right = e3;
1751f08c3bdfSopenharmony_ci			e4->ctype = &lazy_ptr_ctype;
1752f08c3bdfSopenharmony_ci
1753f08c3bdfSopenharmony_ci			expr->unop = e4;
1754f08c3bdfSopenharmony_ci			expr->type = EXPR_PREOP;
1755f08c3bdfSopenharmony_ci			expr->op = '*';
1756f08c3bdfSopenharmony_ci		}
1757f08c3bdfSopenharmony_ci	case SYM_FN:
1758f08c3bdfSopenharmony_ci		if (expr->op != '*' || expr->type != EXPR_PREOP) {
1759f08c3bdfSopenharmony_ci			expression_error(expr, "strange non-value function or array");
1760f08c3bdfSopenharmony_ci			return &bad_ctype;
1761f08c3bdfSopenharmony_ci		}
1762f08c3bdfSopenharmony_ci		if (ctype->builtin)
1763f08c3bdfSopenharmony_ci			sparse_error(expr->pos, "taking the address of built-in function '%s'", show_ident(ctype->ident));
1764f08c3bdfSopenharmony_ci		*expr = *expr->unop;
1765f08c3bdfSopenharmony_ci		ctype = create_pointer(expr, ctype, 1);
1766f08c3bdfSopenharmony_ci		expr->ctype = ctype;
1767f08c3bdfSopenharmony_ci		mark_addressable(expr);
1768f08c3bdfSopenharmony_ci	default:
1769f08c3bdfSopenharmony_ci		/* nothing */;
1770f08c3bdfSopenharmony_ci	}
1771f08c3bdfSopenharmony_ci	return ctype;
1772f08c3bdfSopenharmony_ci}
1773f08c3bdfSopenharmony_ci
1774f08c3bdfSopenharmony_cistatic struct symbol *evaluate_addressof(struct expression *expr)
1775f08c3bdfSopenharmony_ci{
1776f08c3bdfSopenharmony_ci	struct expression *op = expr->unop;
1777f08c3bdfSopenharmony_ci	struct symbol *ctype;
1778f08c3bdfSopenharmony_ci
1779f08c3bdfSopenharmony_ci	if (op->op != '*' || op->type != EXPR_PREOP) {
1780f08c3bdfSopenharmony_ci		expression_error(expr, "not addressable");
1781f08c3bdfSopenharmony_ci		return NULL;
1782f08c3bdfSopenharmony_ci	}
1783f08c3bdfSopenharmony_ci	ctype = op->ctype;
1784f08c3bdfSopenharmony_ci	if (ctype->builtin)
1785f08c3bdfSopenharmony_ci		sparse_error(expr->pos, "taking the address of built-in function '%s'", show_ident(ctype->ident));
1786f08c3bdfSopenharmony_ci	*expr = *op->unop;
1787f08c3bdfSopenharmony_ci
1788f08c3bdfSopenharmony_ci	mark_addressable(expr);
1789f08c3bdfSopenharmony_ci
1790f08c3bdfSopenharmony_ci	/*
1791f08c3bdfSopenharmony_ci	 * symbol expression evaluation is lazy about the type
1792f08c3bdfSopenharmony_ci	 * of the sub-expression, so we may have to generate
1793f08c3bdfSopenharmony_ci	 * the type here if so..
1794f08c3bdfSopenharmony_ci	 */
1795f08c3bdfSopenharmony_ci	if (expr->ctype == &lazy_ptr_ctype) {
1796f08c3bdfSopenharmony_ci		ctype = create_pointer(expr, ctype, 0);
1797f08c3bdfSopenharmony_ci		expr->ctype = ctype;
1798f08c3bdfSopenharmony_ci	}
1799f08c3bdfSopenharmony_ci	return expr->ctype;
1800f08c3bdfSopenharmony_ci}
1801f08c3bdfSopenharmony_ci
1802f08c3bdfSopenharmony_ci
1803f08c3bdfSopenharmony_cistatic struct symbol *evaluate_dereference(struct expression *expr)
1804f08c3bdfSopenharmony_ci{
1805f08c3bdfSopenharmony_ci	struct expression *op = expr->unop;
1806f08c3bdfSopenharmony_ci	struct symbol *ctype = op->ctype, *node, *target;
1807f08c3bdfSopenharmony_ci
1808f08c3bdfSopenharmony_ci	/* Simplify: *&(expr) => (expr) */
1809f08c3bdfSopenharmony_ci	if (op->type == EXPR_PREOP && op->op == '&') {
1810f08c3bdfSopenharmony_ci		*expr = *op->unop;
1811f08c3bdfSopenharmony_ci		expr->flags = CEF_NONE;
1812f08c3bdfSopenharmony_ci		return expr->ctype;
1813f08c3bdfSopenharmony_ci	}
1814f08c3bdfSopenharmony_ci
1815f08c3bdfSopenharmony_ci	examine_symbol_type(ctype);
1816f08c3bdfSopenharmony_ci
1817f08c3bdfSopenharmony_ci	/* Dereferencing a node drops all the node information. */
1818f08c3bdfSopenharmony_ci	if (ctype->type == SYM_NODE)
1819f08c3bdfSopenharmony_ci		ctype = ctype->ctype.base_type;
1820f08c3bdfSopenharmony_ci
1821f08c3bdfSopenharmony_ci	target = ctype->ctype.base_type;
1822f08c3bdfSopenharmony_ci
1823f08c3bdfSopenharmony_ci	switch (ctype->type) {
1824f08c3bdfSopenharmony_ci	default:
1825f08c3bdfSopenharmony_ci		expression_error(expr, "cannot dereference this type");
1826f08c3bdfSopenharmony_ci		return NULL;
1827f08c3bdfSopenharmony_ci	case SYM_FN:
1828f08c3bdfSopenharmony_ci		*expr = *op;
1829f08c3bdfSopenharmony_ci		return expr->ctype;
1830f08c3bdfSopenharmony_ci	case SYM_PTR:
1831f08c3bdfSopenharmony_ci		examine_symbol_type(target);
1832f08c3bdfSopenharmony_ci		node = alloc_symbol(expr->pos, SYM_NODE);
1833f08c3bdfSopenharmony_ci		node->ctype.modifiers = target->ctype.modifiers & MOD_SPECIFIER;
1834f08c3bdfSopenharmony_ci		merge_type(node, ctype);
1835f08c3bdfSopenharmony_ci		break;
1836f08c3bdfSopenharmony_ci
1837f08c3bdfSopenharmony_ci	case SYM_ARRAY:
1838f08c3bdfSopenharmony_ci		if (!lvalue_expression(op)) {
1839f08c3bdfSopenharmony_ci			expression_error(op, "non-lvalue array??");
1840f08c3bdfSopenharmony_ci			return NULL;
1841f08c3bdfSopenharmony_ci		}
1842f08c3bdfSopenharmony_ci
1843f08c3bdfSopenharmony_ci		/* Do the implied "addressof" on the array */
1844f08c3bdfSopenharmony_ci		*op = *op->unop;
1845f08c3bdfSopenharmony_ci
1846f08c3bdfSopenharmony_ci		/*
1847f08c3bdfSopenharmony_ci		 * When an array is dereferenced, we need to pick
1848f08c3bdfSopenharmony_ci		 * up the attributes of the original node too..
1849f08c3bdfSopenharmony_ci		 */
1850f08c3bdfSopenharmony_ci		node = alloc_symbol(expr->pos, SYM_NODE);
1851f08c3bdfSopenharmony_ci		merge_type(node, op->ctype);
1852f08c3bdfSopenharmony_ci		merge_type(node, ctype);
1853f08c3bdfSopenharmony_ci		break;
1854f08c3bdfSopenharmony_ci	}
1855f08c3bdfSopenharmony_ci
1856f08c3bdfSopenharmony_ci	node->bit_size = target->bit_size;
1857f08c3bdfSopenharmony_ci	node->array_size = target->array_size;
1858f08c3bdfSopenharmony_ci
1859f08c3bdfSopenharmony_ci	expr->ctype = node;
1860f08c3bdfSopenharmony_ci	return node;
1861f08c3bdfSopenharmony_ci}
1862f08c3bdfSopenharmony_ci
1863f08c3bdfSopenharmony_ci/*
1864f08c3bdfSopenharmony_ci * Unary post-ops: x++ and x--
1865f08c3bdfSopenharmony_ci */
1866f08c3bdfSopenharmony_cistatic struct symbol *evaluate_postop(struct expression *expr)
1867f08c3bdfSopenharmony_ci{
1868f08c3bdfSopenharmony_ci	struct expression *op = expr->unop;
1869f08c3bdfSopenharmony_ci	struct symbol *ctype = op->ctype;
1870f08c3bdfSopenharmony_ci	int class = classify_type(ctype, &ctype);
1871f08c3bdfSopenharmony_ci	int multiply = 0;
1872f08c3bdfSopenharmony_ci
1873f08c3bdfSopenharmony_ci	if (!class || class & TYPE_COMPOUND) {
1874f08c3bdfSopenharmony_ci		expression_error(expr, "need scalar for ++/--");
1875f08c3bdfSopenharmony_ci		return NULL;
1876f08c3bdfSopenharmony_ci	}
1877f08c3bdfSopenharmony_ci	if (!lvalue_expression(expr->unop)) {
1878f08c3bdfSopenharmony_ci		expression_error(expr, "need lvalue expression for ++/--");
1879f08c3bdfSopenharmony_ci		return NULL;
1880f08c3bdfSopenharmony_ci	}
1881f08c3bdfSopenharmony_ci
1882f08c3bdfSopenharmony_ci	unrestrict(expr, class, &ctype);
1883f08c3bdfSopenharmony_ci
1884f08c3bdfSopenharmony_ci	if (class & TYPE_NUM) {
1885f08c3bdfSopenharmony_ci		multiply = 1;
1886f08c3bdfSopenharmony_ci	} else if (class == TYPE_PTR) {
1887f08c3bdfSopenharmony_ci		struct symbol *target = examine_pointer_target(ctype);
1888f08c3bdfSopenharmony_ci		if (!is_function(target))
1889f08c3bdfSopenharmony_ci			multiply = bits_to_bytes(target->bit_size);
1890f08c3bdfSopenharmony_ci	}
1891f08c3bdfSopenharmony_ci
1892f08c3bdfSopenharmony_ci	if (multiply) {
1893f08c3bdfSopenharmony_ci		evaluate_assign_to(op, op->ctype);
1894f08c3bdfSopenharmony_ci		expr->op_value = multiply;
1895f08c3bdfSopenharmony_ci		expr->ctype = ctype;
1896f08c3bdfSopenharmony_ci		return ctype;
1897f08c3bdfSopenharmony_ci	}
1898f08c3bdfSopenharmony_ci
1899f08c3bdfSopenharmony_ci	expression_error(expr, "bad argument type for ++/--");
1900f08c3bdfSopenharmony_ci	return NULL;
1901f08c3bdfSopenharmony_ci}
1902f08c3bdfSopenharmony_ci
1903f08c3bdfSopenharmony_cistatic struct symbol *evaluate_sign(struct expression *expr)
1904f08c3bdfSopenharmony_ci{
1905f08c3bdfSopenharmony_ci	struct symbol *ctype = expr->unop->ctype;
1906f08c3bdfSopenharmony_ci	int class = classify_type(ctype, &ctype);
1907f08c3bdfSopenharmony_ci	unsigned char flags = expr->unop->flags & ~CEF_CONST_MASK;
1908f08c3bdfSopenharmony_ci
1909f08c3bdfSopenharmony_ci	/* should be an arithmetic type */
1910f08c3bdfSopenharmony_ci	if (!(class & TYPE_NUM))
1911f08c3bdfSopenharmony_ci		return bad_expr_type(expr);
1912f08c3bdfSopenharmony_ci	if (class & TYPE_RESTRICT)
1913f08c3bdfSopenharmony_ci		goto Restr;
1914f08c3bdfSopenharmony_ciNormal:
1915f08c3bdfSopenharmony_ci	if (!(class & TYPE_FLOAT)) {
1916f08c3bdfSopenharmony_ci		ctype = integer_promotion(ctype);
1917f08c3bdfSopenharmony_ci		expr->unop = cast_to(expr->unop, ctype);
1918f08c3bdfSopenharmony_ci	} else if (expr->op != '~') {
1919f08c3bdfSopenharmony_ci		/* no conversions needed */
1920f08c3bdfSopenharmony_ci	} else {
1921f08c3bdfSopenharmony_ci		return bad_expr_type(expr);
1922f08c3bdfSopenharmony_ci	}
1923f08c3bdfSopenharmony_ci	if (expr->op == '+')
1924f08c3bdfSopenharmony_ci		*expr = *expr->unop;
1925f08c3bdfSopenharmony_ci	expr->flags = flags;
1926f08c3bdfSopenharmony_ci	expr->ctype = ctype;
1927f08c3bdfSopenharmony_ci	return ctype;
1928f08c3bdfSopenharmony_ciRestr:
1929f08c3bdfSopenharmony_ci	if (restricted_unop(expr->op, &ctype))
1930f08c3bdfSopenharmony_ci		unrestrict(expr, class, &ctype);
1931f08c3bdfSopenharmony_ci	goto Normal;
1932f08c3bdfSopenharmony_ci}
1933f08c3bdfSopenharmony_ci
1934f08c3bdfSopenharmony_cistatic struct symbol *evaluate_preop(struct expression *expr)
1935f08c3bdfSopenharmony_ci{
1936f08c3bdfSopenharmony_ci	struct symbol *ctype = expr->unop->ctype;
1937f08c3bdfSopenharmony_ci
1938f08c3bdfSopenharmony_ci	switch (expr->op) {
1939f08c3bdfSopenharmony_ci	case '(':
1940f08c3bdfSopenharmony_ci		*expr = *expr->unop;
1941f08c3bdfSopenharmony_ci		return ctype;
1942f08c3bdfSopenharmony_ci
1943f08c3bdfSopenharmony_ci	case '+':
1944f08c3bdfSopenharmony_ci	case '-':
1945f08c3bdfSopenharmony_ci	case '~':
1946f08c3bdfSopenharmony_ci		return evaluate_sign(expr);
1947f08c3bdfSopenharmony_ci
1948f08c3bdfSopenharmony_ci	case '*':
1949f08c3bdfSopenharmony_ci		return evaluate_dereference(expr);
1950f08c3bdfSopenharmony_ci
1951f08c3bdfSopenharmony_ci	case '&':
1952f08c3bdfSopenharmony_ci		return evaluate_addressof(expr);
1953f08c3bdfSopenharmony_ci
1954f08c3bdfSopenharmony_ci	case SPECIAL_INCREMENT:
1955f08c3bdfSopenharmony_ci	case SPECIAL_DECREMENT:
1956f08c3bdfSopenharmony_ci		/*
1957f08c3bdfSopenharmony_ci		 * From a type evaluation standpoint the preops are
1958f08c3bdfSopenharmony_ci		 * the same as the postops
1959f08c3bdfSopenharmony_ci		 */
1960f08c3bdfSopenharmony_ci		return evaluate_postop(expr);
1961f08c3bdfSopenharmony_ci
1962f08c3bdfSopenharmony_ci	case '!':
1963f08c3bdfSopenharmony_ci		ctype = degenerate(expr->unop);
1964f08c3bdfSopenharmony_ci		expr->flags = expr->unop->flags & ~CEF_CONST_MASK;
1965f08c3bdfSopenharmony_ci		/*
1966f08c3bdfSopenharmony_ci		 * A logical negation never yields an address constant
1967f08c3bdfSopenharmony_ci		 * [6.6(9)].
1968f08c3bdfSopenharmony_ci		 */
1969f08c3bdfSopenharmony_ci		expr->flags &= ~CEF_ADDR;
1970f08c3bdfSopenharmony_ci
1971f08c3bdfSopenharmony_ci		if (is_safe_type(ctype))
1972f08c3bdfSopenharmony_ci			warning(expr->pos, "testing a 'safe expression'");
1973f08c3bdfSopenharmony_ci		if (is_float_type(ctype)) {
1974f08c3bdfSopenharmony_ci			struct expression *arg = expr->unop;
1975f08c3bdfSopenharmony_ci			expr->type = EXPR_COMPARE;
1976f08c3bdfSopenharmony_ci			expr->op = SPECIAL_EQUAL;
1977f08c3bdfSopenharmony_ci			expr->left = arg;
1978f08c3bdfSopenharmony_ci			expr->right = alloc_expression(expr->pos, EXPR_FVALUE);
1979f08c3bdfSopenharmony_ci			expr->right->ctype = ctype;
1980f08c3bdfSopenharmony_ci			expr->right->fvalue = 0;
1981f08c3bdfSopenharmony_ci		} else if (is_fouled_type(ctype)) {
1982f08c3bdfSopenharmony_ci			warning(expr->pos, "%s degrades to integer",
1983f08c3bdfSopenharmony_ci				show_typename(ctype->ctype.base_type));
1984f08c3bdfSopenharmony_ci		}
1985f08c3bdfSopenharmony_ci		/* the result is int [6.5.3.3(5)]*/
1986f08c3bdfSopenharmony_ci		ctype = &int_ctype;
1987f08c3bdfSopenharmony_ci		break;
1988f08c3bdfSopenharmony_ci
1989f08c3bdfSopenharmony_ci	default:
1990f08c3bdfSopenharmony_ci		break;
1991f08c3bdfSopenharmony_ci	}
1992f08c3bdfSopenharmony_ci	expr->ctype = ctype;
1993f08c3bdfSopenharmony_ci	return ctype;
1994f08c3bdfSopenharmony_ci}
1995f08c3bdfSopenharmony_ci
1996f08c3bdfSopenharmony_cistatic struct symbol *find_identifier(struct ident *ident, struct symbol_list *_list, int *offset)
1997f08c3bdfSopenharmony_ci{
1998f08c3bdfSopenharmony_ci	struct ptr_list *head = (struct ptr_list *)_list;
1999f08c3bdfSopenharmony_ci	struct ptr_list *list = head;
2000f08c3bdfSopenharmony_ci
2001f08c3bdfSopenharmony_ci	if (!head)
2002f08c3bdfSopenharmony_ci		return NULL;
2003f08c3bdfSopenharmony_ci	do {
2004f08c3bdfSopenharmony_ci		int i;
2005f08c3bdfSopenharmony_ci		for (i = 0; i < list->nr; i++) {
2006f08c3bdfSopenharmony_ci			struct symbol *sym = (struct symbol *) list->list[i];
2007f08c3bdfSopenharmony_ci			if (sym->ident) {
2008f08c3bdfSopenharmony_ci				if (sym->ident != ident)
2009f08c3bdfSopenharmony_ci					continue;
2010f08c3bdfSopenharmony_ci				*offset = sym->offset;
2011f08c3bdfSopenharmony_ci				return sym;
2012f08c3bdfSopenharmony_ci			} else {
2013f08c3bdfSopenharmony_ci				struct symbol *ctype = sym->ctype.base_type;
2014f08c3bdfSopenharmony_ci				struct symbol *sub;
2015f08c3bdfSopenharmony_ci				if (!ctype)
2016f08c3bdfSopenharmony_ci					continue;
2017f08c3bdfSopenharmony_ci				if (ctype->type != SYM_UNION && ctype->type != SYM_STRUCT)
2018f08c3bdfSopenharmony_ci					continue;
2019f08c3bdfSopenharmony_ci				sub = find_identifier(ident, ctype->symbol_list, offset);
2020f08c3bdfSopenharmony_ci				if (!sub)
2021f08c3bdfSopenharmony_ci					continue;
2022f08c3bdfSopenharmony_ci				*offset += sym->offset;
2023f08c3bdfSopenharmony_ci				return sub;
2024f08c3bdfSopenharmony_ci			}
2025f08c3bdfSopenharmony_ci		}
2026f08c3bdfSopenharmony_ci	} while ((list = list->next) != head);
2027f08c3bdfSopenharmony_ci	return NULL;
2028f08c3bdfSopenharmony_ci}
2029f08c3bdfSopenharmony_ci
2030f08c3bdfSopenharmony_cistatic struct expression *evaluate_offset(struct expression *expr, unsigned long offset)
2031f08c3bdfSopenharmony_ci{
2032f08c3bdfSopenharmony_ci	struct expression *add;
2033f08c3bdfSopenharmony_ci
2034f08c3bdfSopenharmony_ci	/*
2035f08c3bdfSopenharmony_ci	 * Create a new add-expression
2036f08c3bdfSopenharmony_ci	 *
2037f08c3bdfSopenharmony_ci	 * NOTE! Even if we just add zero, we need a new node
2038f08c3bdfSopenharmony_ci	 * for the member pointer, since it has a different
2039f08c3bdfSopenharmony_ci	 * type than the original pointer. We could make that
2040f08c3bdfSopenharmony_ci	 * be just a cast, but the fact is, a node is a node,
2041f08c3bdfSopenharmony_ci	 * so we might as well just do the "add zero" here.
2042f08c3bdfSopenharmony_ci	 */
2043f08c3bdfSopenharmony_ci	add = alloc_expression(expr->pos, EXPR_BINOP);
2044f08c3bdfSopenharmony_ci	add->op = '+';
2045f08c3bdfSopenharmony_ci	add->left = expr;
2046f08c3bdfSopenharmony_ci	add->right = alloc_expression(expr->pos, EXPR_VALUE);
2047f08c3bdfSopenharmony_ci	add->right->ctype = &int_ctype;
2048f08c3bdfSopenharmony_ci	add->right->value = offset;
2049f08c3bdfSopenharmony_ci
2050f08c3bdfSopenharmony_ci	/*
2051f08c3bdfSopenharmony_ci	 * The ctype of the pointer will be lazily evaluated if
2052f08c3bdfSopenharmony_ci	 * we ever take the address of this member dereference..
2053f08c3bdfSopenharmony_ci	 */
2054f08c3bdfSopenharmony_ci	add->ctype = &lazy_ptr_ctype;
2055f08c3bdfSopenharmony_ci	/*
2056f08c3bdfSopenharmony_ci	 * The resulting address of a member access through an address
2057f08c3bdfSopenharmony_ci	 * constant is an address constant again [6.6(9)].
2058f08c3bdfSopenharmony_ci	 */
2059f08c3bdfSopenharmony_ci	add->flags = expr->flags;
2060f08c3bdfSopenharmony_ci
2061f08c3bdfSopenharmony_ci	return add;
2062f08c3bdfSopenharmony_ci}
2063f08c3bdfSopenharmony_ci
2064f08c3bdfSopenharmony_ci/* structure/union dereference */
2065f08c3bdfSopenharmony_cistatic struct symbol *evaluate_member_dereference(struct expression *expr)
2066f08c3bdfSopenharmony_ci{
2067f08c3bdfSopenharmony_ci	int offset;
2068f08c3bdfSopenharmony_ci	struct symbol *ctype, *member;
2069f08c3bdfSopenharmony_ci	struct expression *deref = expr->deref, *add;
2070f08c3bdfSopenharmony_ci	struct ident *ident = expr->member;
2071f08c3bdfSopenharmony_ci	struct ident *address_space;
2072f08c3bdfSopenharmony_ci	unsigned int mod;
2073f08c3bdfSopenharmony_ci
2074f08c3bdfSopenharmony_ci	if (!evaluate_expression(deref))
2075f08c3bdfSopenharmony_ci		return NULL;
2076f08c3bdfSopenharmony_ci	if (!ident) {
2077f08c3bdfSopenharmony_ci		expression_error(expr, "bad member name");
2078f08c3bdfSopenharmony_ci		return NULL;
2079f08c3bdfSopenharmony_ci	}
2080f08c3bdfSopenharmony_ci
2081f08c3bdfSopenharmony_ci	ctype = deref->ctype;
2082f08c3bdfSopenharmony_ci	examine_symbol_type(ctype);
2083f08c3bdfSopenharmony_ci	address_space = ctype->ctype.as;
2084f08c3bdfSopenharmony_ci	mod = ctype->ctype.modifiers;
2085f08c3bdfSopenharmony_ci	if (ctype->type == SYM_NODE) {
2086f08c3bdfSopenharmony_ci		ctype = ctype->ctype.base_type;
2087f08c3bdfSopenharmony_ci		combine_address_space(deref->pos, &address_space, ctype->ctype.as);
2088f08c3bdfSopenharmony_ci		mod |= ctype->ctype.modifiers;
2089f08c3bdfSopenharmony_ci	}
2090f08c3bdfSopenharmony_ci	if (!ctype || (ctype->type != SYM_STRUCT && ctype->type != SYM_UNION)) {
2091f08c3bdfSopenharmony_ci		expression_error(expr, "expected structure or union");
2092f08c3bdfSopenharmony_ci		return NULL;
2093f08c3bdfSopenharmony_ci	}
2094f08c3bdfSopenharmony_ci	offset = 0;
2095f08c3bdfSopenharmony_ci	member = find_identifier(ident, ctype->symbol_list, &offset);
2096f08c3bdfSopenharmony_ci	if (!member) {
2097f08c3bdfSopenharmony_ci		const char *type = ctype->type == SYM_STRUCT ? "struct" : "union";
2098f08c3bdfSopenharmony_ci		const char *name = "<unnamed>";
2099f08c3bdfSopenharmony_ci		int namelen = 9;
2100f08c3bdfSopenharmony_ci		if (ctype->ident) {
2101f08c3bdfSopenharmony_ci			name = ctype->ident->name;
2102f08c3bdfSopenharmony_ci			namelen = ctype->ident->len;
2103f08c3bdfSopenharmony_ci		}
2104f08c3bdfSopenharmony_ci		if (ctype->symbol_list)
2105f08c3bdfSopenharmony_ci			expression_error(expr, "no member '%s' in %s %.*s",
2106f08c3bdfSopenharmony_ci				show_ident(ident), type, namelen, name);
2107f08c3bdfSopenharmony_ci		else
2108f08c3bdfSopenharmony_ci			expression_error(expr, "using member '%s' in "
2109f08c3bdfSopenharmony_ci				"incomplete %s %.*s", show_ident(ident),
2110f08c3bdfSopenharmony_ci				type, namelen, name);
2111f08c3bdfSopenharmony_ci		return NULL;
2112f08c3bdfSopenharmony_ci	}
2113f08c3bdfSopenharmony_ci
2114f08c3bdfSopenharmony_ci	/*
2115f08c3bdfSopenharmony_ci	 * The member needs to take on the address space and modifiers of
2116f08c3bdfSopenharmony_ci	 * the "parent" type.
2117f08c3bdfSopenharmony_ci	 */
2118f08c3bdfSopenharmony_ci	member = convert_to_as_mod(member, address_space, mod);
2119f08c3bdfSopenharmony_ci	ctype = get_base_type(member);
2120f08c3bdfSopenharmony_ci
2121f08c3bdfSopenharmony_ci	if (!lvalue_expression(deref)) {
2122f08c3bdfSopenharmony_ci		if (deref->type != EXPR_SLICE) {
2123f08c3bdfSopenharmony_ci			expr->base = deref;
2124f08c3bdfSopenharmony_ci			expr->r_bitpos = 0;
2125f08c3bdfSopenharmony_ci		} else {
2126f08c3bdfSopenharmony_ci			expr->base = deref->base;
2127f08c3bdfSopenharmony_ci			expr->r_bitpos = deref->r_bitpos;
2128f08c3bdfSopenharmony_ci		}
2129f08c3bdfSopenharmony_ci		expr->r_bitpos += bytes_to_bits(offset);
2130f08c3bdfSopenharmony_ci		expr->type = EXPR_SLICE;
2131f08c3bdfSopenharmony_ci		expr->r_bitpos += member->bit_offset;
2132f08c3bdfSopenharmony_ci		expr->ctype = member;
2133f08c3bdfSopenharmony_ci		return member;
2134f08c3bdfSopenharmony_ci	}
2135f08c3bdfSopenharmony_ci
2136f08c3bdfSopenharmony_ci	deref = deref->unop;
2137f08c3bdfSopenharmony_ci	expr->deref = deref;
2138f08c3bdfSopenharmony_ci
2139f08c3bdfSopenharmony_ci	add = evaluate_offset(deref, offset);
2140f08c3bdfSopenharmony_ci	expr->type = EXPR_PREOP;
2141f08c3bdfSopenharmony_ci	expr->op = '*';
2142f08c3bdfSopenharmony_ci	expr->unop = add;
2143f08c3bdfSopenharmony_ci
2144f08c3bdfSopenharmony_ci	expr->ctype = member;
2145f08c3bdfSopenharmony_ci	return member;
2146f08c3bdfSopenharmony_ci}
2147f08c3bdfSopenharmony_ci
2148f08c3bdfSopenharmony_cistatic int is_promoted(struct expression *expr)
2149f08c3bdfSopenharmony_ci{
2150f08c3bdfSopenharmony_ci	while (1) {
2151f08c3bdfSopenharmony_ci		switch (expr->type) {
2152f08c3bdfSopenharmony_ci		case EXPR_BINOP:
2153f08c3bdfSopenharmony_ci		case EXPR_SELECT:
2154f08c3bdfSopenharmony_ci		case EXPR_CONDITIONAL:
2155f08c3bdfSopenharmony_ci			return 1;
2156f08c3bdfSopenharmony_ci		case EXPR_COMMA:
2157f08c3bdfSopenharmony_ci			expr = expr->right;
2158f08c3bdfSopenharmony_ci			continue;
2159f08c3bdfSopenharmony_ci		case EXPR_PREOP:
2160f08c3bdfSopenharmony_ci			switch (expr->op) {
2161f08c3bdfSopenharmony_ci			case '(':
2162f08c3bdfSopenharmony_ci				expr = expr->unop;
2163f08c3bdfSopenharmony_ci				continue;
2164f08c3bdfSopenharmony_ci			case '+':
2165f08c3bdfSopenharmony_ci			case '-':
2166f08c3bdfSopenharmony_ci			case '~':
2167f08c3bdfSopenharmony_ci				return 1;
2168f08c3bdfSopenharmony_ci			default:
2169f08c3bdfSopenharmony_ci				return 0;
2170f08c3bdfSopenharmony_ci			}
2171f08c3bdfSopenharmony_ci		default:
2172f08c3bdfSopenharmony_ci			return 0;
2173f08c3bdfSopenharmony_ci		}
2174f08c3bdfSopenharmony_ci	}
2175f08c3bdfSopenharmony_ci}
2176f08c3bdfSopenharmony_ci
2177f08c3bdfSopenharmony_ci
2178f08c3bdfSopenharmony_cistatic struct symbol *evaluate_type_information(struct expression *expr)
2179f08c3bdfSopenharmony_ci{
2180f08c3bdfSopenharmony_ci	struct symbol *sym = expr->cast_type;
2181f08c3bdfSopenharmony_ci	if (!sym) {
2182f08c3bdfSopenharmony_ci		sym = evaluate_expression(expr->cast_expression);
2183f08c3bdfSopenharmony_ci		if (!sym)
2184f08c3bdfSopenharmony_ci			return NULL;
2185f08c3bdfSopenharmony_ci		/*
2186f08c3bdfSopenharmony_ci		 * Expressions of restricted types will possibly get
2187f08c3bdfSopenharmony_ci		 * promoted - check that here
2188f08c3bdfSopenharmony_ci		 */
2189f08c3bdfSopenharmony_ci		if (is_restricted_type(sym)) {
2190f08c3bdfSopenharmony_ci			if (sym->bit_size < bits_in_int && is_promoted(expr))
2191f08c3bdfSopenharmony_ci				sym = &int_ctype;
2192f08c3bdfSopenharmony_ci		} else if (is_fouled_type(sym)) {
2193f08c3bdfSopenharmony_ci			sym = &int_ctype;
2194f08c3bdfSopenharmony_ci		}
2195f08c3bdfSopenharmony_ci	}
2196f08c3bdfSopenharmony_ci	examine_symbol_type(sym);
2197f08c3bdfSopenharmony_ci	if (is_bitfield_type(sym)) {
2198f08c3bdfSopenharmony_ci		expression_error(expr, "trying to examine bitfield type");
2199f08c3bdfSopenharmony_ci		return NULL;
2200f08c3bdfSopenharmony_ci	}
2201f08c3bdfSopenharmony_ci	return sym;
2202f08c3bdfSopenharmony_ci}
2203f08c3bdfSopenharmony_ci
2204f08c3bdfSopenharmony_cistatic struct symbol *evaluate_sizeof(struct expression *expr)
2205f08c3bdfSopenharmony_ci{
2206f08c3bdfSopenharmony_ci	struct symbol *type;
2207f08c3bdfSopenharmony_ci	int size;
2208f08c3bdfSopenharmony_ci
2209f08c3bdfSopenharmony_ci	type = evaluate_type_information(expr);
2210f08c3bdfSopenharmony_ci	if (!type)
2211f08c3bdfSopenharmony_ci		return NULL;
2212f08c3bdfSopenharmony_ci
2213f08c3bdfSopenharmony_ci	size = type->bit_size;
2214f08c3bdfSopenharmony_ci
2215f08c3bdfSopenharmony_ci	if (size < 0 && is_void_type(type)) {
2216f08c3bdfSopenharmony_ci		if (Wpointer_arith)
2217f08c3bdfSopenharmony_ci			warning(expr->pos, "expression using sizeof(void)");
2218f08c3bdfSopenharmony_ci		size = bits_in_char;
2219f08c3bdfSopenharmony_ci	}
2220f08c3bdfSopenharmony_ci
2221f08c3bdfSopenharmony_ci	if (is_bool_type(type)) {
2222f08c3bdfSopenharmony_ci		if (Wsizeof_bool)
2223f08c3bdfSopenharmony_ci			warning(expr->pos, "expression using sizeof _Bool");
2224f08c3bdfSopenharmony_ci		size = bits_to_bytes(bits_in_bool) * bits_in_char;
2225f08c3bdfSopenharmony_ci	}
2226f08c3bdfSopenharmony_ci
2227f08c3bdfSopenharmony_ci	if (is_function(type->ctype.base_type)) {
2228f08c3bdfSopenharmony_ci		if (Wpointer_arith)
2229f08c3bdfSopenharmony_ci			warning(expr->pos, "expression using sizeof on a function");
2230f08c3bdfSopenharmony_ci		size = bits_in_char;
2231f08c3bdfSopenharmony_ci	}
2232f08c3bdfSopenharmony_ci
2233f08c3bdfSopenharmony_ci	if (has_flexible_array(type) && Wflexible_array_sizeof)
2234f08c3bdfSopenharmony_ci		warning(expr->pos, "using sizeof on a flexible structure");
2235f08c3bdfSopenharmony_ci
2236f08c3bdfSopenharmony_ci	if (is_array_type(type) && size < 0) {	// VLA, 1-dimension only
2237f08c3bdfSopenharmony_ci		struct expression *base, *size;
2238f08c3bdfSopenharmony_ci		struct symbol *base_type;
2239f08c3bdfSopenharmony_ci
2240f08c3bdfSopenharmony_ci		if (type->type == SYM_NODE)
2241f08c3bdfSopenharmony_ci			type = type->ctype.base_type;	// strip the SYM_NODE
2242f08c3bdfSopenharmony_ci		base_type = get_base_type(type);
2243f08c3bdfSopenharmony_ci		if (!base_type)
2244f08c3bdfSopenharmony_ci			goto error;
2245f08c3bdfSopenharmony_ci		if (base_type->bit_size <= 0) {
2246f08c3bdfSopenharmony_ci			base = alloc_expression(expr->pos, EXPR_SIZEOF);
2247f08c3bdfSopenharmony_ci			base->cast_type = base_type;
2248f08c3bdfSopenharmony_ci			if (!evaluate_sizeof(base))
2249f08c3bdfSopenharmony_ci				goto error;
2250f08c3bdfSopenharmony_ci		} else {
2251f08c3bdfSopenharmony_ci			base = alloc_expression(expr->pos, EXPR_VALUE);
2252f08c3bdfSopenharmony_ci			base->value = bits_to_bytes(base_type->bit_size);
2253f08c3bdfSopenharmony_ci			base->ctype = size_t_ctype;
2254f08c3bdfSopenharmony_ci		}
2255f08c3bdfSopenharmony_ci		size = alloc_expression(expr->pos, EXPR_CAST);
2256f08c3bdfSopenharmony_ci		size->cast_type = size_t_ctype;
2257f08c3bdfSopenharmony_ci		size->cast_expression = type->array_size;
2258f08c3bdfSopenharmony_ci		if (!evaluate_expression(size))
2259f08c3bdfSopenharmony_ci			goto error;
2260f08c3bdfSopenharmony_ci		expr->left = size;
2261f08c3bdfSopenharmony_ci		expr->right = base;
2262f08c3bdfSopenharmony_ci		expr->type = EXPR_BINOP;
2263f08c3bdfSopenharmony_ci		expr->op = '*';
2264f08c3bdfSopenharmony_ci		return expr->ctype = size_t_ctype;
2265f08c3bdfSopenharmony_ci	}
2266f08c3bdfSopenharmony_ci
2267f08c3bdfSopenharmony_cierror:
2268f08c3bdfSopenharmony_ci	if ((size < 0) || (size & (bits_in_char - 1)))
2269f08c3bdfSopenharmony_ci		expression_error(expr, "cannot size expression");
2270f08c3bdfSopenharmony_ci
2271f08c3bdfSopenharmony_ci	expr->type = EXPR_VALUE;
2272f08c3bdfSopenharmony_ci	expr->value = bits_to_bytes(size);
2273f08c3bdfSopenharmony_ci	expr->taint = 0;
2274f08c3bdfSopenharmony_ci	expr->ctype = size_t_ctype;
2275f08c3bdfSopenharmony_ci	return size_t_ctype;
2276f08c3bdfSopenharmony_ci}
2277f08c3bdfSopenharmony_ci
2278f08c3bdfSopenharmony_cistatic struct symbol *evaluate_ptrsizeof(struct expression *expr)
2279f08c3bdfSopenharmony_ci{
2280f08c3bdfSopenharmony_ci	struct symbol *type;
2281f08c3bdfSopenharmony_ci	int size;
2282f08c3bdfSopenharmony_ci
2283f08c3bdfSopenharmony_ci	type = evaluate_type_information(expr);
2284f08c3bdfSopenharmony_ci	if (!type)
2285f08c3bdfSopenharmony_ci		return NULL;
2286f08c3bdfSopenharmony_ci
2287f08c3bdfSopenharmony_ci	if (type->type == SYM_NODE)
2288f08c3bdfSopenharmony_ci		type = type->ctype.base_type;
2289f08c3bdfSopenharmony_ci	if (!type)
2290f08c3bdfSopenharmony_ci		return NULL;
2291f08c3bdfSopenharmony_ci	switch (type->type) {
2292f08c3bdfSopenharmony_ci	case SYM_ARRAY:
2293f08c3bdfSopenharmony_ci		break;
2294f08c3bdfSopenharmony_ci	case SYM_PTR:
2295f08c3bdfSopenharmony_ci		type = get_base_type(type);
2296f08c3bdfSopenharmony_ci		if (type)
2297f08c3bdfSopenharmony_ci			break;
2298f08c3bdfSopenharmony_ci	default:
2299f08c3bdfSopenharmony_ci		expression_error(expr, "expected pointer expression");
2300f08c3bdfSopenharmony_ci		return NULL;
2301f08c3bdfSopenharmony_ci	}
2302f08c3bdfSopenharmony_ci	size = type->bit_size;
2303f08c3bdfSopenharmony_ci	if (size & (bits_in_char-1))
2304f08c3bdfSopenharmony_ci		size = 0;
2305f08c3bdfSopenharmony_ci	expr->type = EXPR_VALUE;
2306f08c3bdfSopenharmony_ci	expr->value = bits_to_bytes(size);
2307f08c3bdfSopenharmony_ci	expr->taint = 0;
2308f08c3bdfSopenharmony_ci	expr->ctype = size_t_ctype;
2309f08c3bdfSopenharmony_ci	return size_t_ctype;
2310f08c3bdfSopenharmony_ci}
2311f08c3bdfSopenharmony_ci
2312f08c3bdfSopenharmony_cistatic struct symbol *evaluate_alignof(struct expression *expr)
2313f08c3bdfSopenharmony_ci{
2314f08c3bdfSopenharmony_ci	struct symbol *type;
2315f08c3bdfSopenharmony_ci
2316f08c3bdfSopenharmony_ci	type = evaluate_type_information(expr);
2317f08c3bdfSopenharmony_ci	if (!type)
2318f08c3bdfSopenharmony_ci		return NULL;
2319f08c3bdfSopenharmony_ci
2320f08c3bdfSopenharmony_ci	expr->type = EXPR_VALUE;
2321f08c3bdfSopenharmony_ci	expr->value = type->ctype.alignment;
2322f08c3bdfSopenharmony_ci	expr->taint = 0;
2323f08c3bdfSopenharmony_ci	expr->ctype = size_t_ctype;
2324f08c3bdfSopenharmony_ci	return size_t_ctype;
2325f08c3bdfSopenharmony_ci}
2326f08c3bdfSopenharmony_ci
2327f08c3bdfSopenharmony_ciint evaluate_arguments(struct symbol_list *argtypes, struct expression_list *head)
2328f08c3bdfSopenharmony_ci{
2329f08c3bdfSopenharmony_ci	struct expression *expr;
2330f08c3bdfSopenharmony_ci	struct symbol *argtype;
2331f08c3bdfSopenharmony_ci	int i = 1;
2332f08c3bdfSopenharmony_ci
2333f08c3bdfSopenharmony_ci	PREPARE_PTR_LIST(argtypes, argtype);
2334f08c3bdfSopenharmony_ci	FOR_EACH_PTR (head, expr) {
2335f08c3bdfSopenharmony_ci		struct expression **p = THIS_ADDRESS(expr);
2336f08c3bdfSopenharmony_ci		struct symbol *ctype, *target;
2337f08c3bdfSopenharmony_ci		ctype = evaluate_expression(expr);
2338f08c3bdfSopenharmony_ci
2339f08c3bdfSopenharmony_ci		if (!ctype)
2340f08c3bdfSopenharmony_ci			return 0;
2341f08c3bdfSopenharmony_ci
2342f08c3bdfSopenharmony_ci		target = argtype;
2343f08c3bdfSopenharmony_ci		if (!target) {
2344f08c3bdfSopenharmony_ci			struct symbol *type;
2345f08c3bdfSopenharmony_ci			int class = classify_type(ctype, &type);
2346f08c3bdfSopenharmony_ci			if (is_int(class)) {
2347f08c3bdfSopenharmony_ci				*p = cast_to(expr, integer_promotion(type));
2348f08c3bdfSopenharmony_ci			} else if (class & TYPE_FLOAT) {
2349f08c3bdfSopenharmony_ci				if (type->rank < 0)
2350f08c3bdfSopenharmony_ci					*p = cast_to(expr, &double_ctype);
2351f08c3bdfSopenharmony_ci			} else if (class & TYPE_PTR) {
2352f08c3bdfSopenharmony_ci				if (expr->ctype == &null_ctype)
2353f08c3bdfSopenharmony_ci					*p = cast_to(expr, &ptr_ctype);
2354f08c3bdfSopenharmony_ci				else
2355f08c3bdfSopenharmony_ci					degenerate(expr);
2356f08c3bdfSopenharmony_ci			}
2357f08c3bdfSopenharmony_ci		} else if (!target->forced_arg){
2358f08c3bdfSopenharmony_ci			static char where[30];
2359f08c3bdfSopenharmony_ci			examine_symbol_type(target);
2360f08c3bdfSopenharmony_ci			sprintf(where, "argument %d", i);
2361f08c3bdfSopenharmony_ci			compatible_argument_type(expr, target, p, where);
2362f08c3bdfSopenharmony_ci		}
2363f08c3bdfSopenharmony_ci
2364f08c3bdfSopenharmony_ci		i++;
2365f08c3bdfSopenharmony_ci		NEXT_PTR_LIST(argtype);
2366f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(expr);
2367f08c3bdfSopenharmony_ci	FINISH_PTR_LIST(argtype);
2368f08c3bdfSopenharmony_ci	return 1;
2369f08c3bdfSopenharmony_ci}
2370f08c3bdfSopenharmony_ci
2371f08c3bdfSopenharmony_cistatic void convert_index(struct expression *e)
2372f08c3bdfSopenharmony_ci{
2373f08c3bdfSopenharmony_ci	struct expression *child = e->idx_expression;
2374f08c3bdfSopenharmony_ci	unsigned from = e->idx_from;
2375f08c3bdfSopenharmony_ci	unsigned to = e->idx_to + 1;
2376f08c3bdfSopenharmony_ci	e->type = EXPR_POS;
2377f08c3bdfSopenharmony_ci	e->init_offset = from * bits_to_bytes(e->ctype->bit_size);
2378f08c3bdfSopenharmony_ci	e->init_nr = to - from;
2379f08c3bdfSopenharmony_ci	e->init_expr = child;
2380f08c3bdfSopenharmony_ci}
2381f08c3bdfSopenharmony_ci
2382f08c3bdfSopenharmony_cistatic void convert_ident(struct expression *e)
2383f08c3bdfSopenharmony_ci{
2384f08c3bdfSopenharmony_ci	struct expression *child = e->ident_expression;
2385f08c3bdfSopenharmony_ci	int offset = e->offset;
2386f08c3bdfSopenharmony_ci
2387f08c3bdfSopenharmony_ci	e->type = EXPR_POS;
2388f08c3bdfSopenharmony_ci	e->init_offset = offset;
2389f08c3bdfSopenharmony_ci	e->init_nr = 1;
2390f08c3bdfSopenharmony_ci	e->init_expr = child;
2391f08c3bdfSopenharmony_ci}
2392f08c3bdfSopenharmony_ci
2393f08c3bdfSopenharmony_cistatic void convert_designators(struct expression *e)
2394f08c3bdfSopenharmony_ci{
2395f08c3bdfSopenharmony_ci	while (e) {
2396f08c3bdfSopenharmony_ci		if (e->type == EXPR_INDEX)
2397f08c3bdfSopenharmony_ci			convert_index(e);
2398f08c3bdfSopenharmony_ci		else if (e->type == EXPR_IDENTIFIER)
2399f08c3bdfSopenharmony_ci			convert_ident(e);
2400f08c3bdfSopenharmony_ci		else
2401f08c3bdfSopenharmony_ci			break;
2402f08c3bdfSopenharmony_ci		e = e->init_expr;
2403f08c3bdfSopenharmony_ci	}
2404f08c3bdfSopenharmony_ci}
2405f08c3bdfSopenharmony_ci
2406f08c3bdfSopenharmony_cistatic void excess(struct expression *e, const char *s)
2407f08c3bdfSopenharmony_ci{
2408f08c3bdfSopenharmony_ci	warning(e->pos, "excessive elements in %s initializer", s);
2409f08c3bdfSopenharmony_ci}
2410f08c3bdfSopenharmony_ci
2411f08c3bdfSopenharmony_ci/*
2412f08c3bdfSopenharmony_ci * implicit designator for the first element
2413f08c3bdfSopenharmony_ci */
2414f08c3bdfSopenharmony_cistatic struct expression *first_subobject(struct symbol *ctype, int class,
2415f08c3bdfSopenharmony_ci					  struct expression **v)
2416f08c3bdfSopenharmony_ci{
2417f08c3bdfSopenharmony_ci	struct expression *e = *v, *new;
2418f08c3bdfSopenharmony_ci
2419f08c3bdfSopenharmony_ci	if (ctype->type == SYM_NODE)
2420f08c3bdfSopenharmony_ci		ctype = ctype->ctype.base_type;
2421f08c3bdfSopenharmony_ci
2422f08c3bdfSopenharmony_ci	if (class & TYPE_PTR) { /* array */
2423f08c3bdfSopenharmony_ci		if (!ctype->bit_size)
2424f08c3bdfSopenharmony_ci			return NULL;
2425f08c3bdfSopenharmony_ci		new = alloc_expression(e->pos, EXPR_INDEX);
2426f08c3bdfSopenharmony_ci		new->idx_expression = e;
2427f08c3bdfSopenharmony_ci		new->ctype = ctype->ctype.base_type;
2428f08c3bdfSopenharmony_ci	} else  {
2429f08c3bdfSopenharmony_ci		struct symbol *field, *p;
2430f08c3bdfSopenharmony_ci		PREPARE_PTR_LIST(ctype->symbol_list, p);
2431f08c3bdfSopenharmony_ci		while (p && !p->ident && is_bitfield_type(p))
2432f08c3bdfSopenharmony_ci			NEXT_PTR_LIST(p);
2433f08c3bdfSopenharmony_ci		field = p;
2434f08c3bdfSopenharmony_ci		FINISH_PTR_LIST(p);
2435f08c3bdfSopenharmony_ci		if (!field)
2436f08c3bdfSopenharmony_ci			return NULL;
2437f08c3bdfSopenharmony_ci		new = alloc_expression(e->pos, EXPR_IDENTIFIER);
2438f08c3bdfSopenharmony_ci		new->ident_expression = e;
2439f08c3bdfSopenharmony_ci		new->field = new->ctype = field;
2440f08c3bdfSopenharmony_ci		new->offset = field->offset;
2441f08c3bdfSopenharmony_ci	}
2442f08c3bdfSopenharmony_ci	*v = new;
2443f08c3bdfSopenharmony_ci	return new;
2444f08c3bdfSopenharmony_ci}
2445f08c3bdfSopenharmony_ci
2446f08c3bdfSopenharmony_ci/*
2447f08c3bdfSopenharmony_ci * sanity-check explicit designators; return the innermost one or NULL
2448f08c3bdfSopenharmony_ci * in case of error.  Assign types.
2449f08c3bdfSopenharmony_ci */
2450f08c3bdfSopenharmony_cistatic struct expression *check_designators(struct expression *e,
2451f08c3bdfSopenharmony_ci					    struct symbol *ctype)
2452f08c3bdfSopenharmony_ci{
2453f08c3bdfSopenharmony_ci	struct expression *last = NULL;
2454f08c3bdfSopenharmony_ci	const char *err;
2455f08c3bdfSopenharmony_ci	while (1) {
2456f08c3bdfSopenharmony_ci		if (ctype->type == SYM_NODE)
2457f08c3bdfSopenharmony_ci			ctype = ctype->ctype.base_type;
2458f08c3bdfSopenharmony_ci		if (e->type == EXPR_INDEX) {
2459f08c3bdfSopenharmony_ci			struct symbol *type;
2460f08c3bdfSopenharmony_ci			if (ctype->type != SYM_ARRAY) {
2461f08c3bdfSopenharmony_ci				err = "array index in non-array";
2462f08c3bdfSopenharmony_ci				break;
2463f08c3bdfSopenharmony_ci			}
2464f08c3bdfSopenharmony_ci			type = ctype->ctype.base_type;
2465f08c3bdfSopenharmony_ci			if (ctype->bit_size >= 0 && type->bit_size >= 0) {
2466f08c3bdfSopenharmony_ci				unsigned offset = array_element_offset(type->bit_size, e->idx_to);
2467f08c3bdfSopenharmony_ci				if (offset >= ctype->bit_size) {
2468f08c3bdfSopenharmony_ci					err = "index out of bounds in";
2469f08c3bdfSopenharmony_ci					break;
2470f08c3bdfSopenharmony_ci				}
2471f08c3bdfSopenharmony_ci			}
2472f08c3bdfSopenharmony_ci			e->ctype = ctype = type;
2473f08c3bdfSopenharmony_ci			ctype = type;
2474f08c3bdfSopenharmony_ci			last = e;
2475f08c3bdfSopenharmony_ci			if (!e->idx_expression) {
2476f08c3bdfSopenharmony_ci				err = "invalid";
2477f08c3bdfSopenharmony_ci				break;
2478f08c3bdfSopenharmony_ci			}
2479f08c3bdfSopenharmony_ci			e = e->idx_expression;
2480f08c3bdfSopenharmony_ci		} else if (e->type == EXPR_IDENTIFIER) {
2481f08c3bdfSopenharmony_ci			int offset = 0;
2482f08c3bdfSopenharmony_ci			if (ctype->type != SYM_STRUCT && ctype->type != SYM_UNION) {
2483f08c3bdfSopenharmony_ci				err = "field name not in struct or union";
2484f08c3bdfSopenharmony_ci				break;
2485f08c3bdfSopenharmony_ci			}
2486f08c3bdfSopenharmony_ci			ctype = find_identifier(e->expr_ident, ctype->symbol_list, &offset);
2487f08c3bdfSopenharmony_ci			if (!ctype) {
2488f08c3bdfSopenharmony_ci				err = "unknown field name in";
2489f08c3bdfSopenharmony_ci				break;
2490f08c3bdfSopenharmony_ci			}
2491f08c3bdfSopenharmony_ci			e->offset = offset;
2492f08c3bdfSopenharmony_ci			e->field = e->ctype = ctype;
2493f08c3bdfSopenharmony_ci			last = e;
2494f08c3bdfSopenharmony_ci			if (!e->ident_expression) {
2495f08c3bdfSopenharmony_ci				err = "invalid";
2496f08c3bdfSopenharmony_ci				break;
2497f08c3bdfSopenharmony_ci			}
2498f08c3bdfSopenharmony_ci			e = e->ident_expression;
2499f08c3bdfSopenharmony_ci		} else if (e->type == EXPR_POS) {
2500f08c3bdfSopenharmony_ci			err = "internal front-end error: EXPR_POS in";
2501f08c3bdfSopenharmony_ci			break;
2502f08c3bdfSopenharmony_ci		} else
2503f08c3bdfSopenharmony_ci			return last;
2504f08c3bdfSopenharmony_ci	}
2505f08c3bdfSopenharmony_ci	expression_error(e, "%s initializer", err);
2506f08c3bdfSopenharmony_ci	return NULL;
2507f08c3bdfSopenharmony_ci}
2508f08c3bdfSopenharmony_ci
2509f08c3bdfSopenharmony_ci/*
2510f08c3bdfSopenharmony_ci * choose the next subobject to initialize.
2511f08c3bdfSopenharmony_ci *
2512f08c3bdfSopenharmony_ci * Get designators for next element, switch old ones to EXPR_POS.
2513f08c3bdfSopenharmony_ci * Return the resulting expression or NULL if we'd run out of subobjects.
2514f08c3bdfSopenharmony_ci * The innermost designator is returned in *v.  Designators in old
2515f08c3bdfSopenharmony_ci * are assumed to be already sanity-checked.
2516f08c3bdfSopenharmony_ci */
2517f08c3bdfSopenharmony_cistatic struct expression *next_designators(struct expression *old,
2518f08c3bdfSopenharmony_ci			     struct symbol *ctype,
2519f08c3bdfSopenharmony_ci			     struct expression *e, struct expression **v)
2520f08c3bdfSopenharmony_ci{
2521f08c3bdfSopenharmony_ci	struct expression *new = NULL;
2522f08c3bdfSopenharmony_ci
2523f08c3bdfSopenharmony_ci	if (!old)
2524f08c3bdfSopenharmony_ci		return NULL;
2525f08c3bdfSopenharmony_ci	if (old->type == EXPR_INDEX) {
2526f08c3bdfSopenharmony_ci		struct expression *copy;
2527f08c3bdfSopenharmony_ci		unsigned n;
2528f08c3bdfSopenharmony_ci
2529f08c3bdfSopenharmony_ci		copy = next_designators(old->idx_expression,
2530f08c3bdfSopenharmony_ci					old->ctype, e, v);
2531f08c3bdfSopenharmony_ci		if (!copy) {
2532f08c3bdfSopenharmony_ci			n = old->idx_to + 1;
2533f08c3bdfSopenharmony_ci			if (array_element_offset(old->ctype->bit_size, n) == ctype->bit_size) {
2534f08c3bdfSopenharmony_ci				convert_index(old);
2535f08c3bdfSopenharmony_ci				return NULL;
2536f08c3bdfSopenharmony_ci			}
2537f08c3bdfSopenharmony_ci			copy = e;
2538f08c3bdfSopenharmony_ci			*v = new = alloc_expression(e->pos, EXPR_INDEX);
2539f08c3bdfSopenharmony_ci		} else {
2540f08c3bdfSopenharmony_ci			n = old->idx_to;
2541f08c3bdfSopenharmony_ci			new = alloc_expression(e->pos, EXPR_INDEX);
2542f08c3bdfSopenharmony_ci		}
2543f08c3bdfSopenharmony_ci
2544f08c3bdfSopenharmony_ci		new->idx_from = new->idx_to = n;
2545f08c3bdfSopenharmony_ci		new->idx_expression = copy;
2546f08c3bdfSopenharmony_ci		new->ctype = old->ctype;
2547f08c3bdfSopenharmony_ci		convert_index(old);
2548f08c3bdfSopenharmony_ci	} else if (old->type == EXPR_IDENTIFIER) {
2549f08c3bdfSopenharmony_ci		struct expression *copy;
2550f08c3bdfSopenharmony_ci		struct symbol *field;
2551f08c3bdfSopenharmony_ci		int offset = 0;
2552f08c3bdfSopenharmony_ci
2553f08c3bdfSopenharmony_ci		copy = next_designators(old->ident_expression,
2554f08c3bdfSopenharmony_ci					old->ctype, e, v);
2555f08c3bdfSopenharmony_ci		if (!copy) {
2556f08c3bdfSopenharmony_ci			field = old->field->next_subobject;
2557f08c3bdfSopenharmony_ci			if (!field) {
2558f08c3bdfSopenharmony_ci				convert_ident(old);
2559f08c3bdfSopenharmony_ci				return NULL;
2560f08c3bdfSopenharmony_ci			}
2561f08c3bdfSopenharmony_ci			copy = e;
2562f08c3bdfSopenharmony_ci			*v = new = alloc_expression(e->pos, EXPR_IDENTIFIER);
2563f08c3bdfSopenharmony_ci			/*
2564f08c3bdfSopenharmony_ci			 * We can't necessarily trust "field->offset",
2565f08c3bdfSopenharmony_ci			 * because the field might be in an anonymous
2566f08c3bdfSopenharmony_ci			 * union, and the field offset is then the offset
2567f08c3bdfSopenharmony_ci			 * within that union.
2568f08c3bdfSopenharmony_ci			 *
2569f08c3bdfSopenharmony_ci			 * The "old->offset - old->field->offset"
2570f08c3bdfSopenharmony_ci			 * would be the offset of such an anonymous
2571f08c3bdfSopenharmony_ci			 * union.
2572f08c3bdfSopenharmony_ci			 */
2573f08c3bdfSopenharmony_ci			offset = old->offset - old->field->offset;
2574f08c3bdfSopenharmony_ci		} else {
2575f08c3bdfSopenharmony_ci			field = old->field;
2576f08c3bdfSopenharmony_ci			new = alloc_expression(e->pos, EXPR_IDENTIFIER);
2577f08c3bdfSopenharmony_ci		}
2578f08c3bdfSopenharmony_ci
2579f08c3bdfSopenharmony_ci		new->field = field;
2580f08c3bdfSopenharmony_ci		new->expr_ident = field->ident;
2581f08c3bdfSopenharmony_ci		new->ident_expression = copy;
2582f08c3bdfSopenharmony_ci		new->ctype = field;
2583f08c3bdfSopenharmony_ci		new->offset = field->offset + offset;
2584f08c3bdfSopenharmony_ci		convert_ident(old);
2585f08c3bdfSopenharmony_ci	}
2586f08c3bdfSopenharmony_ci	return new;
2587f08c3bdfSopenharmony_ci}
2588f08c3bdfSopenharmony_ci
2589f08c3bdfSopenharmony_cistatic int handle_initializer(struct expression **ep, int nested,
2590f08c3bdfSopenharmony_ci		int class, struct symbol *ctype, unsigned long mods);
2591f08c3bdfSopenharmony_ci
2592f08c3bdfSopenharmony_ci/*
2593f08c3bdfSopenharmony_ci * deal with traversing subobjects [6.7.8(17,18,20)]
2594f08c3bdfSopenharmony_ci */
2595f08c3bdfSopenharmony_cistatic void handle_list_initializer(struct expression *expr,
2596f08c3bdfSopenharmony_ci		int class, struct symbol *ctype, unsigned long mods)
2597f08c3bdfSopenharmony_ci{
2598f08c3bdfSopenharmony_ci	struct expression *e, *last = NULL, *top = NULL, *next;
2599f08c3bdfSopenharmony_ci	int jumped = 0;	// has the last designator multiple levels?
2600f08c3bdfSopenharmony_ci
2601f08c3bdfSopenharmony_ci	if (expr->zero_init)
2602f08c3bdfSopenharmony_ci		free_ptr_list(&expr->expr_list);
2603f08c3bdfSopenharmony_ci
2604f08c3bdfSopenharmony_ci	FOR_EACH_PTR(expr->expr_list, e) {
2605f08c3bdfSopenharmony_ci		struct expression **v;
2606f08c3bdfSopenharmony_ci		struct symbol *type;
2607f08c3bdfSopenharmony_ci		int lclass;
2608f08c3bdfSopenharmony_ci
2609f08c3bdfSopenharmony_ci		if (e->type != EXPR_INDEX && e->type != EXPR_IDENTIFIER) {
2610f08c3bdfSopenharmony_ci			struct symbol *struct_sym;
2611f08c3bdfSopenharmony_ci			if (!top) {
2612f08c3bdfSopenharmony_ci				top = e;
2613f08c3bdfSopenharmony_ci				last = first_subobject(ctype, class, &top);
2614f08c3bdfSopenharmony_ci			} else {
2615f08c3bdfSopenharmony_ci				last = next_designators(last, ctype, e, &top);
2616f08c3bdfSopenharmony_ci			}
2617f08c3bdfSopenharmony_ci			if (!last) {
2618f08c3bdfSopenharmony_ci				excess(e, class & TYPE_PTR ? "array" :
2619f08c3bdfSopenharmony_ci							"struct or union");
2620f08c3bdfSopenharmony_ci				DELETE_CURRENT_PTR(e);
2621f08c3bdfSopenharmony_ci				continue;
2622f08c3bdfSopenharmony_ci			}
2623f08c3bdfSopenharmony_ci			struct_sym = ctype->type == SYM_NODE ? ctype->ctype.base_type : ctype;
2624f08c3bdfSopenharmony_ci			if (Wdesignated_init && struct_sym->designated_init)
2625f08c3bdfSopenharmony_ci				warning(e->pos, "%s%.*s%spositional init of field in %s %s, declared with attribute designated_init",
2626f08c3bdfSopenharmony_ci					ctype->ident ? "in initializer for " : "",
2627f08c3bdfSopenharmony_ci					ctype->ident ? ctype->ident->len : 0,
2628f08c3bdfSopenharmony_ci					ctype->ident ? ctype->ident->name : "",
2629f08c3bdfSopenharmony_ci					ctype->ident ? ": " : "",
2630f08c3bdfSopenharmony_ci					get_type_name(struct_sym->type),
2631f08c3bdfSopenharmony_ci					show_ident(struct_sym->ident));
2632f08c3bdfSopenharmony_ci			if (jumped && Wpast_deep_designator) {
2633f08c3bdfSopenharmony_ci				warning(e->pos, "advancing past deep designator");
2634f08c3bdfSopenharmony_ci				jumped = 0;
2635f08c3bdfSopenharmony_ci			}
2636f08c3bdfSopenharmony_ci			REPLACE_CURRENT_PTR(e, last);
2637f08c3bdfSopenharmony_ci		} else {
2638f08c3bdfSopenharmony_ci			next = check_designators(e, ctype);
2639f08c3bdfSopenharmony_ci			if (!next) {
2640f08c3bdfSopenharmony_ci				DELETE_CURRENT_PTR(e);
2641f08c3bdfSopenharmony_ci				continue;
2642f08c3bdfSopenharmony_ci			}
2643f08c3bdfSopenharmony_ci			top = next;
2644f08c3bdfSopenharmony_ci			/* deeper than one designator? */
2645f08c3bdfSopenharmony_ci			jumped = top != e;
2646f08c3bdfSopenharmony_ci			convert_designators(last);
2647f08c3bdfSopenharmony_ci			last = e;
2648f08c3bdfSopenharmony_ci		}
2649f08c3bdfSopenharmony_ci
2650f08c3bdfSopenharmony_cifound:
2651f08c3bdfSopenharmony_ci		lclass = classify_type(top->ctype, &type);
2652f08c3bdfSopenharmony_ci		if (top->type == EXPR_INDEX)
2653f08c3bdfSopenharmony_ci			v = &top->idx_expression;
2654f08c3bdfSopenharmony_ci		else
2655f08c3bdfSopenharmony_ci			v = &top->ident_expression;
2656f08c3bdfSopenharmony_ci
2657f08c3bdfSopenharmony_ci		mods |= ctype->ctype.modifiers & MOD_STORAGE;
2658f08c3bdfSopenharmony_ci		if (handle_initializer(v, 1, lclass, top->ctype, mods))
2659f08c3bdfSopenharmony_ci			continue;
2660f08c3bdfSopenharmony_ci
2661f08c3bdfSopenharmony_ci		if (!(lclass & TYPE_COMPOUND)) {
2662f08c3bdfSopenharmony_ci			warning(e->pos, "bogus scalar initializer");
2663f08c3bdfSopenharmony_ci			DELETE_CURRENT_PTR(e);
2664f08c3bdfSopenharmony_ci			continue;
2665f08c3bdfSopenharmony_ci		}
2666f08c3bdfSopenharmony_ci
2667f08c3bdfSopenharmony_ci		next = first_subobject(type, lclass, v);
2668f08c3bdfSopenharmony_ci		if (next) {
2669f08c3bdfSopenharmony_ci			warning(e->pos, "missing braces around initializer");
2670f08c3bdfSopenharmony_ci			top = next;
2671f08c3bdfSopenharmony_ci			goto found;
2672f08c3bdfSopenharmony_ci		}
2673f08c3bdfSopenharmony_ci
2674f08c3bdfSopenharmony_ci		DELETE_CURRENT_PTR(e);
2675f08c3bdfSopenharmony_ci		excess(e, lclass & TYPE_PTR ? "array" : "struct or union");
2676f08c3bdfSopenharmony_ci
2677f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(e);
2678f08c3bdfSopenharmony_ci
2679f08c3bdfSopenharmony_ci	convert_designators(last);
2680f08c3bdfSopenharmony_ci	expr->ctype = ctype;
2681f08c3bdfSopenharmony_ci}
2682f08c3bdfSopenharmony_ci
2683f08c3bdfSopenharmony_cistatic int is_string_literal(struct expression **v)
2684f08c3bdfSopenharmony_ci{
2685f08c3bdfSopenharmony_ci	struct expression *e = *v;
2686f08c3bdfSopenharmony_ci	while (e && e->type == EXPR_PREOP && e->op == '(')
2687f08c3bdfSopenharmony_ci		e = e->unop;
2688f08c3bdfSopenharmony_ci	if (!e || e->type != EXPR_STRING)
2689f08c3bdfSopenharmony_ci		return 0;
2690f08c3bdfSopenharmony_ci	if (e != *v && Wparen_string)
2691f08c3bdfSopenharmony_ci		warning(e->pos,
2692f08c3bdfSopenharmony_ci			"array initialized from parenthesized string constant");
2693f08c3bdfSopenharmony_ci	*v = e;
2694f08c3bdfSopenharmony_ci	return 1;
2695f08c3bdfSopenharmony_ci}
2696f08c3bdfSopenharmony_ci
2697f08c3bdfSopenharmony_ci/*
2698f08c3bdfSopenharmony_ci * We want a normal expression, possibly in one layer of braces.  Warn
2699f08c3bdfSopenharmony_ci * if the latter happens inside a list (it's legal, but likely to be
2700f08c3bdfSopenharmony_ci * an effect of screwup).  In case of anything not legal, we are definitely
2701f08c3bdfSopenharmony_ci * having an effect of screwup, so just fail and let the caller warn.
2702f08c3bdfSopenharmony_ci */
2703f08c3bdfSopenharmony_cistatic struct expression *handle_scalar(struct expression *e, int nested)
2704f08c3bdfSopenharmony_ci{
2705f08c3bdfSopenharmony_ci	struct expression *v = NULL, *p;
2706f08c3bdfSopenharmony_ci	int count = 0;
2707f08c3bdfSopenharmony_ci
2708f08c3bdfSopenharmony_ci	/* normal case */
2709f08c3bdfSopenharmony_ci	if (e->type != EXPR_INITIALIZER)
2710f08c3bdfSopenharmony_ci		return e;
2711f08c3bdfSopenharmony_ci
2712f08c3bdfSopenharmony_ci	FOR_EACH_PTR(e->expr_list, p) {
2713f08c3bdfSopenharmony_ci		if (!v)
2714f08c3bdfSopenharmony_ci			v = p;
2715f08c3bdfSopenharmony_ci		count++;
2716f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(p);
2717f08c3bdfSopenharmony_ci	if (count != 1)
2718f08c3bdfSopenharmony_ci		return NULL;
2719f08c3bdfSopenharmony_ci	switch(v->type) {
2720f08c3bdfSopenharmony_ci	case EXPR_INITIALIZER:
2721f08c3bdfSopenharmony_ci	case EXPR_INDEX:
2722f08c3bdfSopenharmony_ci	case EXPR_IDENTIFIER:
2723f08c3bdfSopenharmony_ci		return NULL;
2724f08c3bdfSopenharmony_ci	default:
2725f08c3bdfSopenharmony_ci		break;
2726f08c3bdfSopenharmony_ci	}
2727f08c3bdfSopenharmony_ci	if (nested)
2728f08c3bdfSopenharmony_ci		warning(e->pos, "braces around scalar initializer");
2729f08c3bdfSopenharmony_ci	return v;
2730f08c3bdfSopenharmony_ci}
2731f08c3bdfSopenharmony_ci
2732f08c3bdfSopenharmony_ci/*
2733f08c3bdfSopenharmony_ci * deal with the cases that don't care about subobjects:
2734f08c3bdfSopenharmony_ci * scalar <- assignment expression, possibly in braces [6.7.8(11)]
2735f08c3bdfSopenharmony_ci * character array <- string literal, possibly in braces [6.7.8(14)]
2736f08c3bdfSopenharmony_ci * struct or union <- assignment expression of compatible type [6.7.8(13)]
2737f08c3bdfSopenharmony_ci * compound type <- initializer list in braces [6.7.8(16)]
2738f08c3bdfSopenharmony_ci * The last one punts to handle_list_initializer() which, in turn will call
2739f08c3bdfSopenharmony_ci * us for individual elements of the list.
2740f08c3bdfSopenharmony_ci *
2741f08c3bdfSopenharmony_ci * We do not handle 6.7.8(15) (wide char array <- wide string literal) for
2742f08c3bdfSopenharmony_ci * the lack of support of wide char stuff in general.
2743f08c3bdfSopenharmony_ci *
2744f08c3bdfSopenharmony_ci * One note: we need to take care not to evaluate a string literal until
2745f08c3bdfSopenharmony_ci * we know that we *will* handle it right here.  Otherwise we would screw
2746f08c3bdfSopenharmony_ci * the cases like struct { struct {char s[10]; ...} ...} initialized with
2747f08c3bdfSopenharmony_ci * { "string", ...} - we need to preserve that string literal recognizable
2748f08c3bdfSopenharmony_ci * until we dig into the inner struct.
2749f08c3bdfSopenharmony_ci */
2750f08c3bdfSopenharmony_cistatic int handle_initializer(struct expression **ep, int nested,
2751f08c3bdfSopenharmony_ci		int class, struct symbol *ctype, unsigned long mods)
2752f08c3bdfSopenharmony_ci{
2753f08c3bdfSopenharmony_ci	struct expression *e = *ep, *p;
2754f08c3bdfSopenharmony_ci	struct symbol *type;
2755f08c3bdfSopenharmony_ci
2756f08c3bdfSopenharmony_ci	if (!e)
2757f08c3bdfSopenharmony_ci		return 0;
2758f08c3bdfSopenharmony_ci
2759f08c3bdfSopenharmony_ci	/* scalar */
2760f08c3bdfSopenharmony_ci	if (!(class & TYPE_COMPOUND)) {
2761f08c3bdfSopenharmony_ci		e = handle_scalar(e, nested);
2762f08c3bdfSopenharmony_ci		if (!e)
2763f08c3bdfSopenharmony_ci			return 0;
2764f08c3bdfSopenharmony_ci		*ep = e;
2765f08c3bdfSopenharmony_ci		if (!evaluate_expression(e))
2766f08c3bdfSopenharmony_ci			return 1;
2767f08c3bdfSopenharmony_ci		compatible_assignment_types(e, ctype, ep, "initializer");
2768f08c3bdfSopenharmony_ci		/*
2769f08c3bdfSopenharmony_ci		 * Initializers for static storage duration objects
2770f08c3bdfSopenharmony_ci		 * shall be constant expressions or a string literal [6.7.8(4)].
2771f08c3bdfSopenharmony_ci		 */
2772f08c3bdfSopenharmony_ci		mods |= ctype->ctype.modifiers;
2773f08c3bdfSopenharmony_ci		mods &= (MOD_TOPLEVEL | MOD_STATIC);
2774f08c3bdfSopenharmony_ci		if (mods && !(e->flags & (CEF_ACE | CEF_ADDR)))
2775f08c3bdfSopenharmony_ci			if (Wconstexpr_not_const)
2776f08c3bdfSopenharmony_ci				warning(e->pos, "non-constant initializer for static object");
2777f08c3bdfSopenharmony_ci
2778f08c3bdfSopenharmony_ci		return 1;
2779f08c3bdfSopenharmony_ci	}
2780f08c3bdfSopenharmony_ci
2781f08c3bdfSopenharmony_ci	/*
2782f08c3bdfSopenharmony_ci	 * sublist; either a string, or we dig in; the latter will deal with
2783f08c3bdfSopenharmony_ci	 * pathologies, so we don't need anything fancy here.
2784f08c3bdfSopenharmony_ci	 */
2785f08c3bdfSopenharmony_ci	if (e->type == EXPR_INITIALIZER) {
2786f08c3bdfSopenharmony_ci		if (is_string_type(ctype)) {
2787f08c3bdfSopenharmony_ci			struct expression *v = NULL;
2788f08c3bdfSopenharmony_ci			int count = 0;
2789f08c3bdfSopenharmony_ci
2790f08c3bdfSopenharmony_ci			FOR_EACH_PTR(e->expr_list, p) {
2791f08c3bdfSopenharmony_ci				if (!v)
2792f08c3bdfSopenharmony_ci					v = p;
2793f08c3bdfSopenharmony_ci				count++;
2794f08c3bdfSopenharmony_ci			} END_FOR_EACH_PTR(p);
2795f08c3bdfSopenharmony_ci			if (count == 1 && is_string_literal(&v)) {
2796f08c3bdfSopenharmony_ci				*ep = e = v;
2797f08c3bdfSopenharmony_ci				goto String;
2798f08c3bdfSopenharmony_ci			}
2799f08c3bdfSopenharmony_ci		}
2800f08c3bdfSopenharmony_ci		handle_list_initializer(e, class, ctype, mods);
2801f08c3bdfSopenharmony_ci		return 1;
2802f08c3bdfSopenharmony_ci	}
2803f08c3bdfSopenharmony_ci
2804f08c3bdfSopenharmony_ci	/* string */
2805f08c3bdfSopenharmony_ci	if (is_string_literal(&e)) {
2806f08c3bdfSopenharmony_ci		/* either we are doing array of char, or we'll have to dig in */
2807f08c3bdfSopenharmony_ci		if (is_string_type(ctype)) {
2808f08c3bdfSopenharmony_ci			*ep = e;
2809f08c3bdfSopenharmony_ci			goto String;
2810f08c3bdfSopenharmony_ci		}
2811f08c3bdfSopenharmony_ci		return 0;
2812f08c3bdfSopenharmony_ci	}
2813f08c3bdfSopenharmony_ci	/* struct or union can be initialized by compatible */
2814f08c3bdfSopenharmony_ci	if (class != TYPE_COMPOUND)
2815f08c3bdfSopenharmony_ci		return 0;
2816f08c3bdfSopenharmony_ci	type = evaluate_expression(e);
2817f08c3bdfSopenharmony_ci	if (!type)
2818f08c3bdfSopenharmony_ci		return 0;
2819f08c3bdfSopenharmony_ci	if (ctype->type == SYM_NODE)
2820f08c3bdfSopenharmony_ci		ctype = ctype->ctype.base_type;
2821f08c3bdfSopenharmony_ci	if (type->type == SYM_NODE)
2822f08c3bdfSopenharmony_ci		type = type->ctype.base_type;
2823f08c3bdfSopenharmony_ci	if (ctype == type)
2824f08c3bdfSopenharmony_ci		return 1;
2825f08c3bdfSopenharmony_ci	return 0;
2826f08c3bdfSopenharmony_ci
2827f08c3bdfSopenharmony_ciString:
2828f08c3bdfSopenharmony_ci	p = alloc_expression(e->pos, EXPR_STRING);
2829f08c3bdfSopenharmony_ci	*p = *e;
2830f08c3bdfSopenharmony_ci	type = evaluate_expression(p);
2831f08c3bdfSopenharmony_ci	if (ctype->bit_size != -1) {
2832f08c3bdfSopenharmony_ci		struct symbol *char_type = e->wide ? wchar_ctype : &char_ctype;
2833f08c3bdfSopenharmony_ci		unsigned int size_with_null = ctype->bit_size + char_type->bit_size;
2834f08c3bdfSopenharmony_ci		if (size_with_null < type->bit_size)
2835f08c3bdfSopenharmony_ci			warning(e->pos,
2836f08c3bdfSopenharmony_ci				"too long initializer-string for array of char");
2837f08c3bdfSopenharmony_ci		else if (Winit_cstring && size_with_null == type->bit_size) {
2838f08c3bdfSopenharmony_ci			warning(e->pos,
2839f08c3bdfSopenharmony_ci				"too long initializer-string for array of char(no space for nul char)");
2840f08c3bdfSopenharmony_ci		}
2841f08c3bdfSopenharmony_ci	}
2842f08c3bdfSopenharmony_ci	*ep = p;
2843f08c3bdfSopenharmony_ci	return 1;
2844f08c3bdfSopenharmony_ci}
2845f08c3bdfSopenharmony_ci
2846f08c3bdfSopenharmony_cistatic void evaluate_initializer(struct symbol *ctype, struct expression **ep)
2847f08c3bdfSopenharmony_ci{
2848f08c3bdfSopenharmony_ci	struct symbol *type;
2849f08c3bdfSopenharmony_ci	int class = classify_type(ctype, &type);
2850f08c3bdfSopenharmony_ci	if (!handle_initializer(ep, 0, class, ctype, 0))
2851f08c3bdfSopenharmony_ci		expression_error(*ep, "invalid initializer");
2852f08c3bdfSopenharmony_ci}
2853f08c3bdfSopenharmony_ci
2854f08c3bdfSopenharmony_cistatic struct symbol *cast_to_bool(struct expression *expr)
2855f08c3bdfSopenharmony_ci{
2856f08c3bdfSopenharmony_ci	struct expression *old = expr->cast_expression;
2857f08c3bdfSopenharmony_ci	struct expression *zero;
2858f08c3bdfSopenharmony_ci	struct symbol *otype;
2859f08c3bdfSopenharmony_ci	int oclass = classify_type(degenerate(old), &otype);
2860f08c3bdfSopenharmony_ci	struct symbol *ctype;
2861f08c3bdfSopenharmony_ci
2862f08c3bdfSopenharmony_ci	if (oclass & TYPE_COMPOUND)
2863f08c3bdfSopenharmony_ci		return NULL;
2864f08c3bdfSopenharmony_ci
2865f08c3bdfSopenharmony_ci	zero = alloc_const_expression(expr->pos, 0);
2866f08c3bdfSopenharmony_ci	if (oclass & TYPE_PTR)
2867f08c3bdfSopenharmony_ci		zero->ctype = otype;
2868f08c3bdfSopenharmony_ci	expr->op = SPECIAL_NOTEQUAL;
2869f08c3bdfSopenharmony_ci	ctype = usual_conversions(expr->op, old, zero,
2870f08c3bdfSopenharmony_ci			oclass, TYPE_NUM, otype, zero->ctype);
2871f08c3bdfSopenharmony_ci	expr->type = EXPR_COMPARE;
2872f08c3bdfSopenharmony_ci	expr->left = cast_to(old, ctype);
2873f08c3bdfSopenharmony_ci	expr->right = cast_to(zero, ctype);
2874f08c3bdfSopenharmony_ci
2875f08c3bdfSopenharmony_ci	return expr->ctype;
2876f08c3bdfSopenharmony_ci}
2877f08c3bdfSopenharmony_ci
2878f08c3bdfSopenharmony_cistatic int cast_flags(struct expression *expr, struct expression *old)
2879f08c3bdfSopenharmony_ci{
2880f08c3bdfSopenharmony_ci	struct symbol *t;
2881f08c3bdfSopenharmony_ci	int class;
2882f08c3bdfSopenharmony_ci	int flags = CEF_NONE;
2883f08c3bdfSopenharmony_ci
2884f08c3bdfSopenharmony_ci	class = classify_type(expr->ctype, &t);
2885f08c3bdfSopenharmony_ci	if (class & TYPE_NUM) {
2886f08c3bdfSopenharmony_ci		flags = old->flags & ~CEF_CONST_MASK;
2887f08c3bdfSopenharmony_ci		/*
2888f08c3bdfSopenharmony_ci		 * Casts to numeric types never result in address
2889f08c3bdfSopenharmony_ci		 * constants [6.6(9)].
2890f08c3bdfSopenharmony_ci		 */
2891f08c3bdfSopenharmony_ci		flags &= ~CEF_ADDR;
2892f08c3bdfSopenharmony_ci
2893f08c3bdfSopenharmony_ci		/*
2894f08c3bdfSopenharmony_ci		 * As an extension, treat address constants cast to
2895f08c3bdfSopenharmony_ci		 * integer type as an arithmetic constant.
2896f08c3bdfSopenharmony_ci		 */
2897f08c3bdfSopenharmony_ci		if (old->flags & CEF_ADDR)
2898f08c3bdfSopenharmony_ci			flags = CEF_ACE;
2899f08c3bdfSopenharmony_ci
2900f08c3bdfSopenharmony_ci		/*
2901f08c3bdfSopenharmony_ci		 * Cast to float type -> not an integer constant
2902f08c3bdfSopenharmony_ci		 * expression [6.6(6)].
2903f08c3bdfSopenharmony_ci		 */
2904f08c3bdfSopenharmony_ci		if (class & TYPE_FLOAT)
2905f08c3bdfSopenharmony_ci			flags &= ~CEF_CLR_ICE;
2906f08c3bdfSopenharmony_ci		/*
2907f08c3bdfSopenharmony_ci		 * Casts of float literals to integer type results in
2908f08c3bdfSopenharmony_ci		 * a constant integer expression [6.6(6)].
2909f08c3bdfSopenharmony_ci		 */
2910f08c3bdfSopenharmony_ci		else if (old->flags & CEF_FLOAT)
2911f08c3bdfSopenharmony_ci			flags = CEF_SET_ICE;
2912f08c3bdfSopenharmony_ci	} else if (class & TYPE_PTR) {
2913f08c3bdfSopenharmony_ci		/*
2914f08c3bdfSopenharmony_ci		 * Casts of integer literals to pointer type yield
2915f08c3bdfSopenharmony_ci		 * address constants [6.6(9)].
2916f08c3bdfSopenharmony_ci		 *
2917f08c3bdfSopenharmony_ci		 * As an extension, treat address constants cast to a
2918f08c3bdfSopenharmony_ci		 * different pointer type as address constants again.
2919f08c3bdfSopenharmony_ci		 *
2920f08c3bdfSopenharmony_ci		 * As another extension, treat integer constant
2921f08c3bdfSopenharmony_ci		 * expressions (in contrast to literals) cast to
2922f08c3bdfSopenharmony_ci		 * pointer type as address constants.
2923f08c3bdfSopenharmony_ci		 */
2924f08c3bdfSopenharmony_ci		if (old->flags & (CEF_ICE | CEF_ADDR))
2925f08c3bdfSopenharmony_ci			flags = CEF_ADDR;
2926f08c3bdfSopenharmony_ci	}
2927f08c3bdfSopenharmony_ci
2928f08c3bdfSopenharmony_ci	return flags;
2929f08c3bdfSopenharmony_ci}
2930f08c3bdfSopenharmony_ci
2931f08c3bdfSopenharmony_ci///
2932f08c3bdfSopenharmony_ci// check if a type matches one of the members of a union type
2933f08c3bdfSopenharmony_ci// @utype: the union type
2934f08c3bdfSopenharmony_ci// @type: to type to check
2935f08c3bdfSopenharmony_ci// @return: to identifier of the matching type in the union.
2936f08c3bdfSopenharmony_cistatic struct symbol *find_member_type(struct symbol *utype, struct symbol *type)
2937f08c3bdfSopenharmony_ci{
2938f08c3bdfSopenharmony_ci	struct symbol *t, *member;
2939f08c3bdfSopenharmony_ci
2940f08c3bdfSopenharmony_ci	if (utype->type != SYM_UNION)
2941f08c3bdfSopenharmony_ci		return NULL;
2942f08c3bdfSopenharmony_ci
2943f08c3bdfSopenharmony_ci	FOR_EACH_PTR(utype->symbol_list, member) {
2944f08c3bdfSopenharmony_ci		classify_type(member, &t);
2945f08c3bdfSopenharmony_ci		if (type == t)
2946f08c3bdfSopenharmony_ci			return member;
2947f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(member);
2948f08c3bdfSopenharmony_ci	return NULL;
2949f08c3bdfSopenharmony_ci}
2950f08c3bdfSopenharmony_ci
2951f08c3bdfSopenharmony_cistatic struct symbol *evaluate_compound_literal(struct expression *expr, struct expression *source)
2952f08c3bdfSopenharmony_ci{
2953f08c3bdfSopenharmony_ci	struct expression *addr = alloc_expression(expr->pos, EXPR_SYMBOL);
2954f08c3bdfSopenharmony_ci	struct symbol *sym = expr->cast_type;
2955f08c3bdfSopenharmony_ci
2956f08c3bdfSopenharmony_ci	sym->initializer = source;
2957f08c3bdfSopenharmony_ci	evaluate_symbol(sym);
2958f08c3bdfSopenharmony_ci
2959f08c3bdfSopenharmony_ci	addr->ctype = &lazy_ptr_ctype;	/* Lazy eval */
2960f08c3bdfSopenharmony_ci	addr->symbol = sym;
2961f08c3bdfSopenharmony_ci	if (sym->ctype.modifiers & MOD_TOPLEVEL)
2962f08c3bdfSopenharmony_ci		addr->flags |= CEF_ADDR;
2963f08c3bdfSopenharmony_ci
2964f08c3bdfSopenharmony_ci	expr->type = EXPR_PREOP;
2965f08c3bdfSopenharmony_ci	expr->op = '*';
2966f08c3bdfSopenharmony_ci	expr->deref = addr;
2967f08c3bdfSopenharmony_ci	expr->ctype = sym;
2968f08c3bdfSopenharmony_ci	return sym;
2969f08c3bdfSopenharmony_ci}
2970f08c3bdfSopenharmony_ci
2971f08c3bdfSopenharmony_cistatic struct symbol *evaluate_cast(struct expression *expr)
2972f08c3bdfSopenharmony_ci{
2973f08c3bdfSopenharmony_ci	struct expression *source = expr->cast_expression;
2974f08c3bdfSopenharmony_ci	struct symbol *ctype;
2975f08c3bdfSopenharmony_ci	struct symbol *ttype, *stype;
2976f08c3bdfSopenharmony_ci	struct symbol *member;
2977f08c3bdfSopenharmony_ci	int tclass, sclass;
2978f08c3bdfSopenharmony_ci	struct ident *tas = NULL, *sas = NULL;
2979f08c3bdfSopenharmony_ci
2980f08c3bdfSopenharmony_ci	if (!source)
2981f08c3bdfSopenharmony_ci		return NULL;
2982f08c3bdfSopenharmony_ci
2983f08c3bdfSopenharmony_ci	/*
2984f08c3bdfSopenharmony_ci	 * Special case: a cast can be followed by an
2985f08c3bdfSopenharmony_ci	 * initializer, in which case we need to pass
2986f08c3bdfSopenharmony_ci	 * the type value down to that initializer rather
2987f08c3bdfSopenharmony_ci	 * than trying to evaluate it as an expression
2988f08c3bdfSopenharmony_ci	 * (cfr. compound literals: C99 & C11 6.5.2.5).
2989f08c3bdfSopenharmony_ci	 *
2990f08c3bdfSopenharmony_ci	 * A more complex case is when the initializer is
2991f08c3bdfSopenharmony_ci	 * dereferenced as part of a post-fix expression.
2992f08c3bdfSopenharmony_ci	 * We need to produce an expression that can be dereferenced.
2993f08c3bdfSopenharmony_ci	 */
2994f08c3bdfSopenharmony_ci	if (source->type == EXPR_INITIALIZER)
2995f08c3bdfSopenharmony_ci		return evaluate_compound_literal(expr, source);
2996f08c3bdfSopenharmony_ci
2997f08c3bdfSopenharmony_ci	ctype = examine_symbol_type(expr->cast_type);
2998f08c3bdfSopenharmony_ci	ctype = unqualify_type(ctype);
2999f08c3bdfSopenharmony_ci	expr->ctype = ctype;
3000f08c3bdfSopenharmony_ci	expr->cast_type = ctype;
3001f08c3bdfSopenharmony_ci
3002f08c3bdfSopenharmony_ci	evaluate_expression(source);
3003f08c3bdfSopenharmony_ci	degenerate(source);
3004f08c3bdfSopenharmony_ci
3005f08c3bdfSopenharmony_ci	tclass = classify_type(ctype, &ttype);
3006f08c3bdfSopenharmony_ci
3007f08c3bdfSopenharmony_ci	expr->flags = cast_flags(expr, source);
3008f08c3bdfSopenharmony_ci
3009f08c3bdfSopenharmony_ci	/*
3010f08c3bdfSopenharmony_ci	 * You can always throw a value away by casting to
3011f08c3bdfSopenharmony_ci	 * "void" - that's an implicit "force". Note that
3012f08c3bdfSopenharmony_ci	 * the same is _not_ true of "void *".
3013f08c3bdfSopenharmony_ci	 */
3014f08c3bdfSopenharmony_ci	if (ttype == &void_ctype)
3015f08c3bdfSopenharmony_ci		goto out;
3016f08c3bdfSopenharmony_ci
3017f08c3bdfSopenharmony_ci	stype = source->ctype;
3018f08c3bdfSopenharmony_ci	if (!stype) {
3019f08c3bdfSopenharmony_ci		expression_error(expr, "cast from unknown type");
3020f08c3bdfSopenharmony_ci		goto out;
3021f08c3bdfSopenharmony_ci	}
3022f08c3bdfSopenharmony_ci	sclass = classify_type(stype, &stype);
3023f08c3bdfSopenharmony_ci
3024f08c3bdfSopenharmony_ci	if (expr->type == EXPR_FORCE_CAST)
3025f08c3bdfSopenharmony_ci		goto out;
3026f08c3bdfSopenharmony_ci
3027f08c3bdfSopenharmony_ci	if (tclass & (TYPE_COMPOUND | TYPE_FN)) {
3028f08c3bdfSopenharmony_ci		/*
3029f08c3bdfSopenharmony_ci		 * Special case: cast to union type (GCC extension)
3030f08c3bdfSopenharmony_ci		 * The effect is similar to a compound literal except
3031f08c3bdfSopenharmony_ci		 * that the result is a rvalue.
3032f08c3bdfSopenharmony_ci		 */
3033f08c3bdfSopenharmony_ci		if ((member = find_member_type(ttype, stype))) {
3034f08c3bdfSopenharmony_ci			struct expression *item, *init;
3035f08c3bdfSopenharmony_ci
3036f08c3bdfSopenharmony_ci			if (Wunion_cast)
3037f08c3bdfSopenharmony_ci				warning(expr->pos, "cast to union type");
3038f08c3bdfSopenharmony_ci
3039f08c3bdfSopenharmony_ci			item = alloc_expression(source->pos, EXPR_IDENTIFIER);
3040f08c3bdfSopenharmony_ci			item->expr_ident = member->ident;
3041f08c3bdfSopenharmony_ci			item->ident_expression = source;
3042f08c3bdfSopenharmony_ci
3043f08c3bdfSopenharmony_ci			init = alloc_expression(source->pos, EXPR_INITIALIZER);
3044f08c3bdfSopenharmony_ci			add_expression(&init->expr_list, item);
3045f08c3bdfSopenharmony_ci
3046f08c3bdfSopenharmony_ci			// FIXME: this should be a rvalue
3047f08c3bdfSopenharmony_ci			evaluate_compound_literal(expr, init);
3048f08c3bdfSopenharmony_ci			return ctype;
3049f08c3bdfSopenharmony_ci		}
3050f08c3bdfSopenharmony_ci
3051f08c3bdfSopenharmony_ci		warning(expr->pos, "cast to non-scalar");
3052f08c3bdfSopenharmony_ci	}
3053f08c3bdfSopenharmony_ci
3054f08c3bdfSopenharmony_ci	if (sclass & TYPE_COMPOUND)
3055f08c3bdfSopenharmony_ci		warning(expr->pos, "cast from non-scalar");
3056f08c3bdfSopenharmony_ci
3057f08c3bdfSopenharmony_ci	/* allowed cast unfouls */
3058f08c3bdfSopenharmony_ci	if (sclass & TYPE_FOULED)
3059f08c3bdfSopenharmony_ci		stype = unfoul(stype);
3060f08c3bdfSopenharmony_ci
3061f08c3bdfSopenharmony_ci	if (ttype != stype) {
3062f08c3bdfSopenharmony_ci		if ((tclass & TYPE_RESTRICT) && restricted_value(source, ttype))
3063f08c3bdfSopenharmony_ci			warning(expr->pos, "cast to %s",
3064f08c3bdfSopenharmony_ci				show_typename(ttype));
3065f08c3bdfSopenharmony_ci		if (sclass & TYPE_RESTRICT) {
3066f08c3bdfSopenharmony_ci			if (ttype == &bool_ctype) {
3067f08c3bdfSopenharmony_ci				if (sclass & TYPE_FOULED)
3068f08c3bdfSopenharmony_ci					warning(expr->pos, "%s degrades to integer",
3069f08c3bdfSopenharmony_ci						show_typename(stype));
3070f08c3bdfSopenharmony_ci			} else {
3071f08c3bdfSopenharmony_ci				warning(expr->pos, "cast from %s",
3072f08c3bdfSopenharmony_ci					show_typename(stype));
3073f08c3bdfSopenharmony_ci			}
3074f08c3bdfSopenharmony_ci		}
3075f08c3bdfSopenharmony_ci	}
3076f08c3bdfSopenharmony_ci
3077f08c3bdfSopenharmony_ci	if ((ttype == &ulong_ctype || ttype == uintptr_ctype) && !Wcast_from_as)
3078f08c3bdfSopenharmony_ci		tas = &bad_address_space;
3079f08c3bdfSopenharmony_ci	else if (tclass == TYPE_PTR) {
3080f08c3bdfSopenharmony_ci		examine_pointer_target(ttype);
3081f08c3bdfSopenharmony_ci		tas = ttype->ctype.as;
3082f08c3bdfSopenharmony_ci	}
3083f08c3bdfSopenharmony_ci
3084f08c3bdfSopenharmony_ci	if ((stype == &ulong_ctype || stype == uintptr_ctype))
3085f08c3bdfSopenharmony_ci		sas = &bad_address_space;
3086f08c3bdfSopenharmony_ci	else if (sclass == TYPE_PTR) {
3087f08c3bdfSopenharmony_ci		examine_pointer_target(stype);
3088f08c3bdfSopenharmony_ci		sas = stype->ctype.as;
3089f08c3bdfSopenharmony_ci	}
3090f08c3bdfSopenharmony_ci
3091f08c3bdfSopenharmony_ci	if (!tas && valid_as(sas))
3092f08c3bdfSopenharmony_ci		warning(expr->pos, "cast removes address space '%s' of expression", show_as(sas));
3093f08c3bdfSopenharmony_ci	if (valid_as(tas) && valid_as(sas) && tas != sas)
3094f08c3bdfSopenharmony_ci		warning(expr->pos, "cast between address spaces (%s -> %s)", show_as(sas), show_as(tas));
3095f08c3bdfSopenharmony_ci	if (valid_as(tas) && !sas &&
3096f08c3bdfSopenharmony_ci	    !is_null_pointer_constant(source) && Wcast_to_as)
3097f08c3bdfSopenharmony_ci		warning(expr->pos,
3098f08c3bdfSopenharmony_ci			"cast adds address space '%s' to expression", show_as(tas));
3099f08c3bdfSopenharmony_ci
3100f08c3bdfSopenharmony_ci	if (!(ttype->ctype.modifiers & MOD_PTRINHERIT) && tclass == TYPE_PTR &&
3101f08c3bdfSopenharmony_ci	    !tas && (source->flags & CEF_ICE)) {
3102f08c3bdfSopenharmony_ci		if (ttype->ctype.base_type == &void_ctype) {
3103f08c3bdfSopenharmony_ci			if (is_zero_constant(source)) {
3104f08c3bdfSopenharmony_ci				/* NULL */
3105f08c3bdfSopenharmony_ci				expr->type = EXPR_VALUE;
3106f08c3bdfSopenharmony_ci				expr->ctype = &null_ctype;
3107f08c3bdfSopenharmony_ci				expr->value = 0;
3108f08c3bdfSopenharmony_ci				return expr->ctype;
3109f08c3bdfSopenharmony_ci			}
3110f08c3bdfSopenharmony_ci		}
3111f08c3bdfSopenharmony_ci	}
3112f08c3bdfSopenharmony_ci
3113f08c3bdfSopenharmony_ci	if (ttype == &bool_ctype)
3114f08c3bdfSopenharmony_ci		cast_to_bool(expr);
3115f08c3bdfSopenharmony_ci
3116f08c3bdfSopenharmony_ci	// checks pointers to restricted
3117f08c3bdfSopenharmony_ci	while (Wbitwise_pointer && tclass == TYPE_PTR && sclass == TYPE_PTR) {
3118f08c3bdfSopenharmony_ci		tclass = classify_type(ttype->ctype.base_type, &ttype);
3119f08c3bdfSopenharmony_ci		sclass = classify_type(stype->ctype.base_type, &stype);
3120f08c3bdfSopenharmony_ci		if (ttype == stype)
3121f08c3bdfSopenharmony_ci			break;
3122f08c3bdfSopenharmony_ci		if (!ttype || !stype)
3123f08c3bdfSopenharmony_ci			break;
3124f08c3bdfSopenharmony_ci		if (ttype == &void_ctype || stype == &void_ctype)
3125f08c3bdfSopenharmony_ci			break;
3126f08c3bdfSopenharmony_ci		if (tclass & TYPE_RESTRICT) {
3127f08c3bdfSopenharmony_ci			warning(expr->pos, "cast to %s", show_typename(ctype));
3128f08c3bdfSopenharmony_ci			break;
3129f08c3bdfSopenharmony_ci		}
3130f08c3bdfSopenharmony_ci		if (sclass & TYPE_RESTRICT) {
3131f08c3bdfSopenharmony_ci			warning(expr->pos, "cast from %s", show_typename(source->ctype));
3132f08c3bdfSopenharmony_ci			break;
3133f08c3bdfSopenharmony_ci		}
3134f08c3bdfSopenharmony_ci	}
3135f08c3bdfSopenharmony_ciout:
3136f08c3bdfSopenharmony_ci	return ctype;
3137f08c3bdfSopenharmony_ci}
3138f08c3bdfSopenharmony_ci
3139f08c3bdfSopenharmony_ci/*
3140f08c3bdfSopenharmony_ci * Evaluate a call expression with a symbol. This
3141f08c3bdfSopenharmony_ci * should expand inline functions, and evaluate
3142f08c3bdfSopenharmony_ci * builtins.
3143f08c3bdfSopenharmony_ci */
3144f08c3bdfSopenharmony_cistatic int evaluate_symbol_call(struct expression *expr)
3145f08c3bdfSopenharmony_ci{
3146f08c3bdfSopenharmony_ci	struct expression *fn = expr->fn;
3147f08c3bdfSopenharmony_ci	struct symbol *ctype = fn->ctype;
3148f08c3bdfSopenharmony_ci
3149f08c3bdfSopenharmony_ci	if (fn->type != EXPR_PREOP)
3150f08c3bdfSopenharmony_ci		return 0;
3151f08c3bdfSopenharmony_ci
3152f08c3bdfSopenharmony_ci	if (ctype->op && ctype->op->evaluate)
3153f08c3bdfSopenharmony_ci		return ctype->op->evaluate(expr);
3154f08c3bdfSopenharmony_ci
3155f08c3bdfSopenharmony_ci	return 0;
3156f08c3bdfSopenharmony_ci}
3157f08c3bdfSopenharmony_ci
3158f08c3bdfSopenharmony_cistatic struct symbol *evaluate_call(struct expression *expr)
3159f08c3bdfSopenharmony_ci{
3160f08c3bdfSopenharmony_ci	int args, fnargs;
3161f08c3bdfSopenharmony_ci	struct symbol *ctype, *sym;
3162f08c3bdfSopenharmony_ci	struct expression *fn = expr->fn;
3163f08c3bdfSopenharmony_ci	struct expression_list *arglist = expr->args;
3164f08c3bdfSopenharmony_ci
3165f08c3bdfSopenharmony_ci	if (!evaluate_expression(fn))
3166f08c3bdfSopenharmony_ci		return NULL;
3167f08c3bdfSopenharmony_ci	sym = ctype = fn->ctype;
3168f08c3bdfSopenharmony_ci	if (ctype->type == SYM_NODE)
3169f08c3bdfSopenharmony_ci		ctype = ctype->ctype.base_type;
3170f08c3bdfSopenharmony_ci	if (ctype->type == SYM_PTR)
3171f08c3bdfSopenharmony_ci		ctype = get_base_type(ctype);
3172f08c3bdfSopenharmony_ci
3173f08c3bdfSopenharmony_ci	if (ctype->type != SYM_FN) {
3174f08c3bdfSopenharmony_ci		struct expression *arg;
3175f08c3bdfSopenharmony_ci
3176f08c3bdfSopenharmony_ci		if (fn->ctype == &bad_ctype)
3177f08c3bdfSopenharmony_ci			return NULL;
3178f08c3bdfSopenharmony_ci
3179f08c3bdfSopenharmony_ci		expression_error(expr, "not a function %s",
3180f08c3bdfSopenharmony_ci			     show_ident(sym->ident));
3181f08c3bdfSopenharmony_ci		/* do typechecking in arguments */
3182f08c3bdfSopenharmony_ci		FOR_EACH_PTR (arglist, arg) {
3183f08c3bdfSopenharmony_ci			evaluate_expression(arg);
3184f08c3bdfSopenharmony_ci		} END_FOR_EACH_PTR(arg);
3185f08c3bdfSopenharmony_ci		return NULL;
3186f08c3bdfSopenharmony_ci	}
3187f08c3bdfSopenharmony_ci
3188f08c3bdfSopenharmony_ci	examine_fn_arguments(ctype);
3189f08c3bdfSopenharmony_ci        if (sym->type == SYM_NODE && fn->type == EXPR_PREOP &&
3190f08c3bdfSopenharmony_ci	    sym->op && sym->op->args) {
3191f08c3bdfSopenharmony_ci		if (!sym->op->args(expr))
3192f08c3bdfSopenharmony_ci			return NULL;
3193f08c3bdfSopenharmony_ci	} else {
3194f08c3bdfSopenharmony_ci		if (!evaluate_arguments(ctype->arguments, arglist))
3195f08c3bdfSopenharmony_ci			return NULL;
3196f08c3bdfSopenharmony_ci		args = expression_list_size(expr->args);
3197f08c3bdfSopenharmony_ci		fnargs = symbol_list_size(ctype->arguments);
3198f08c3bdfSopenharmony_ci		if (args < fnargs) {
3199f08c3bdfSopenharmony_ci			expression_error(expr,
3200f08c3bdfSopenharmony_ci				     "not enough arguments for function %s",
3201f08c3bdfSopenharmony_ci				     show_ident(sym->ident));
3202f08c3bdfSopenharmony_ci			return NULL;
3203f08c3bdfSopenharmony_ci		}
3204f08c3bdfSopenharmony_ci		if (args > fnargs && !ctype->variadic)
3205f08c3bdfSopenharmony_ci			expression_error(expr,
3206f08c3bdfSopenharmony_ci				     "too many arguments for function %s",
3207f08c3bdfSopenharmony_ci				     show_ident(sym->ident));
3208f08c3bdfSopenharmony_ci	}
3209f08c3bdfSopenharmony_ci	expr->ctype = ctype->ctype.base_type;
3210f08c3bdfSopenharmony_ci	if (sym->type == SYM_NODE) {
3211f08c3bdfSopenharmony_ci		if (evaluate_symbol_call(expr))
3212f08c3bdfSopenharmony_ci			return expr->ctype;
3213f08c3bdfSopenharmony_ci	}
3214f08c3bdfSopenharmony_ci	return expr->ctype;
3215f08c3bdfSopenharmony_ci}
3216f08c3bdfSopenharmony_ci
3217f08c3bdfSopenharmony_cistatic struct symbol *evaluate_offsetof(struct expression *expr)
3218f08c3bdfSopenharmony_ci{
3219f08c3bdfSopenharmony_ci	struct expression *e = expr->down;
3220f08c3bdfSopenharmony_ci	struct symbol *ctype = expr->in;
3221f08c3bdfSopenharmony_ci	int class;
3222f08c3bdfSopenharmony_ci
3223f08c3bdfSopenharmony_ci	if (expr->op == '.') {
3224f08c3bdfSopenharmony_ci		struct symbol *field;
3225f08c3bdfSopenharmony_ci		int offset = 0;
3226f08c3bdfSopenharmony_ci		if (!ctype) {
3227f08c3bdfSopenharmony_ci			expression_error(expr, "expected structure or union");
3228f08c3bdfSopenharmony_ci			return NULL;
3229f08c3bdfSopenharmony_ci		}
3230f08c3bdfSopenharmony_ci		examine_symbol_type(ctype);
3231f08c3bdfSopenharmony_ci		class = classify_type(ctype, &ctype);
3232f08c3bdfSopenharmony_ci		if (class != TYPE_COMPOUND) {
3233f08c3bdfSopenharmony_ci			expression_error(expr, "expected structure or union");
3234f08c3bdfSopenharmony_ci			return NULL;
3235f08c3bdfSopenharmony_ci		}
3236f08c3bdfSopenharmony_ci
3237f08c3bdfSopenharmony_ci		field = find_identifier(expr->ident, ctype->symbol_list, &offset);
3238f08c3bdfSopenharmony_ci		if (!field) {
3239f08c3bdfSopenharmony_ci			expression_error(expr, "unknown member");
3240f08c3bdfSopenharmony_ci			return NULL;
3241f08c3bdfSopenharmony_ci		}
3242f08c3bdfSopenharmony_ci		ctype = field;
3243f08c3bdfSopenharmony_ci		expr->type = EXPR_VALUE;
3244f08c3bdfSopenharmony_ci		expr->flags = CEF_SET_ICE;
3245f08c3bdfSopenharmony_ci		expr->value = offset;
3246f08c3bdfSopenharmony_ci		expr->taint = 0;
3247f08c3bdfSopenharmony_ci		expr->ctype = size_t_ctype;
3248f08c3bdfSopenharmony_ci	} else {
3249f08c3bdfSopenharmony_ci		if (!ctype) {
3250f08c3bdfSopenharmony_ci			expression_error(expr, "expected structure or union");
3251f08c3bdfSopenharmony_ci			return NULL;
3252f08c3bdfSopenharmony_ci		}
3253f08c3bdfSopenharmony_ci		examine_symbol_type(ctype);
3254f08c3bdfSopenharmony_ci		class = classify_type(ctype, &ctype);
3255f08c3bdfSopenharmony_ci		if (class != (TYPE_COMPOUND | TYPE_PTR)) {
3256f08c3bdfSopenharmony_ci			expression_error(expr, "expected array");
3257f08c3bdfSopenharmony_ci			return NULL;
3258f08c3bdfSopenharmony_ci		}
3259f08c3bdfSopenharmony_ci		ctype = ctype->ctype.base_type;
3260f08c3bdfSopenharmony_ci		if (!expr->index) {
3261f08c3bdfSopenharmony_ci			expr->type = EXPR_VALUE;
3262f08c3bdfSopenharmony_ci			expr->flags = CEF_SET_ICE;
3263f08c3bdfSopenharmony_ci			expr->value = 0;
3264f08c3bdfSopenharmony_ci			expr->taint = 0;
3265f08c3bdfSopenharmony_ci			expr->ctype = size_t_ctype;
3266f08c3bdfSopenharmony_ci		} else {
3267f08c3bdfSopenharmony_ci			struct expression *idx = expr->index, *m;
3268f08c3bdfSopenharmony_ci			struct symbol *i_type = evaluate_expression(idx);
3269f08c3bdfSopenharmony_ci			unsigned old_idx_flags;
3270f08c3bdfSopenharmony_ci			int i_class = classify_type(i_type, &i_type);
3271f08c3bdfSopenharmony_ci
3272f08c3bdfSopenharmony_ci			if (!is_int(i_class)) {
3273f08c3bdfSopenharmony_ci				expression_error(expr, "non-integer index");
3274f08c3bdfSopenharmony_ci				return NULL;
3275f08c3bdfSopenharmony_ci			}
3276f08c3bdfSopenharmony_ci			unrestrict(idx, i_class, &i_type);
3277f08c3bdfSopenharmony_ci			old_idx_flags = idx->flags;
3278f08c3bdfSopenharmony_ci			idx = cast_to(idx, size_t_ctype);
3279f08c3bdfSopenharmony_ci			idx->flags = old_idx_flags;
3280f08c3bdfSopenharmony_ci			m = alloc_const_expression(expr->pos,
3281f08c3bdfSopenharmony_ci						   bits_to_bytes(ctype->bit_size));
3282f08c3bdfSopenharmony_ci			m->ctype = size_t_ctype;
3283f08c3bdfSopenharmony_ci			m->flags = CEF_SET_INT;
3284f08c3bdfSopenharmony_ci			expr->type = EXPR_BINOP;
3285f08c3bdfSopenharmony_ci			expr->left = idx;
3286f08c3bdfSopenharmony_ci			expr->right = m;
3287f08c3bdfSopenharmony_ci			expr->op = '*';
3288f08c3bdfSopenharmony_ci			expr->ctype = size_t_ctype;
3289f08c3bdfSopenharmony_ci			expr->flags = m->flags & idx->flags & ~CEF_CONST_MASK;
3290f08c3bdfSopenharmony_ci		}
3291f08c3bdfSopenharmony_ci	}
3292f08c3bdfSopenharmony_ci	if (e) {
3293f08c3bdfSopenharmony_ci		struct expression *copy = __alloc_expression(0);
3294f08c3bdfSopenharmony_ci		*copy = *expr;
3295f08c3bdfSopenharmony_ci		if (e->type == EXPR_OFFSETOF)
3296f08c3bdfSopenharmony_ci			e->in = ctype;
3297f08c3bdfSopenharmony_ci		if (!evaluate_expression(e))
3298f08c3bdfSopenharmony_ci			return NULL;
3299f08c3bdfSopenharmony_ci		expr->type = EXPR_BINOP;
3300f08c3bdfSopenharmony_ci		expr->flags = e->flags & copy->flags & ~CEF_CONST_MASK;
3301f08c3bdfSopenharmony_ci		expr->op = '+';
3302f08c3bdfSopenharmony_ci		expr->ctype = size_t_ctype;
3303f08c3bdfSopenharmony_ci		expr->left = copy;
3304f08c3bdfSopenharmony_ci		expr->right = e;
3305f08c3bdfSopenharmony_ci	}
3306f08c3bdfSopenharmony_ci	return size_t_ctype;
3307f08c3bdfSopenharmony_ci}
3308f08c3bdfSopenharmony_ci
3309f08c3bdfSopenharmony_cistatic void check_label_declaration(struct position pos, struct symbol *label)
3310f08c3bdfSopenharmony_ci{
3311f08c3bdfSopenharmony_ci	switch (label->namespace) {
3312f08c3bdfSopenharmony_ci	case NS_LABEL:
3313f08c3bdfSopenharmony_ci		if (label->stmt)
3314f08c3bdfSopenharmony_ci			break;
3315f08c3bdfSopenharmony_ci		sparse_error(pos, "label '%s' was not declared", show_ident(label->ident));
3316f08c3bdfSopenharmony_ci		/* fallthrough */
3317f08c3bdfSopenharmony_ci	case NS_NONE:
3318f08c3bdfSopenharmony_ci		current_fn->bogus_linear = 1;
3319f08c3bdfSopenharmony_ci	default:
3320f08c3bdfSopenharmony_ci		break;
3321f08c3bdfSopenharmony_ci	}
3322f08c3bdfSopenharmony_ci}
3323f08c3bdfSopenharmony_ci
3324f08c3bdfSopenharmony_cistatic int type_selection(struct symbol *ctrl, struct symbol *type)
3325f08c3bdfSopenharmony_ci{
3326f08c3bdfSopenharmony_ci	struct ctype c = { .base_type = ctrl };
3327f08c3bdfSopenharmony_ci	struct ctype t = { .base_type = type };
3328f08c3bdfSopenharmony_ci
3329f08c3bdfSopenharmony_ci	return !type_difference(&c, &t, 0, 0);
3330f08c3bdfSopenharmony_ci}
3331f08c3bdfSopenharmony_ci
3332f08c3bdfSopenharmony_cistatic struct symbol *evaluate_generic_selection(struct expression *expr)
3333f08c3bdfSopenharmony_ci{
3334f08c3bdfSopenharmony_ci	struct type_expression *map;
3335f08c3bdfSopenharmony_ci	struct expression *res;
3336f08c3bdfSopenharmony_ci	struct symbol source;
3337f08c3bdfSopenharmony_ci	struct symbol *ctrl;
3338f08c3bdfSopenharmony_ci
3339f08c3bdfSopenharmony_ci	if (!evaluate_expression(expr->control))
3340f08c3bdfSopenharmony_ci		return NULL;
3341f08c3bdfSopenharmony_ci	if (!(ctrl = degenerate(expr->control)))
3342f08c3bdfSopenharmony_ci		return NULL;
3343f08c3bdfSopenharmony_ci
3344f08c3bdfSopenharmony_ci	source = *ctrl;
3345f08c3bdfSopenharmony_ci	source.ctype.modifiers &= ~(MOD_QUALIFIER|MOD_ATOMIC);
3346f08c3bdfSopenharmony_ci	for (map = expr->map; map; map = map->next) {
3347f08c3bdfSopenharmony_ci		struct symbol *stype = map->type;
3348f08c3bdfSopenharmony_ci		struct symbol *base;
3349f08c3bdfSopenharmony_ci
3350f08c3bdfSopenharmony_ci		if (!evaluate_symbol(stype))
3351f08c3bdfSopenharmony_ci			continue;
3352f08c3bdfSopenharmony_ci
3353f08c3bdfSopenharmony_ci		base = stype->ctype.base_type;
3354f08c3bdfSopenharmony_ci		if (base->type == SYM_ARRAY && base->array_size) {
3355f08c3bdfSopenharmony_ci			get_expression_value_silent(base->array_size);
3356f08c3bdfSopenharmony_ci			if (base->array_size->type == EXPR_VALUE)
3357f08c3bdfSopenharmony_ci				continue;
3358f08c3bdfSopenharmony_ci			sparse_error(stype->pos, "variable length array type in generic selection");
3359f08c3bdfSopenharmony_ci			continue;
3360f08c3bdfSopenharmony_ci		}
3361f08c3bdfSopenharmony_ci		if (is_func_type(stype)) {
3362f08c3bdfSopenharmony_ci			sparse_error(stype->pos, "function type in generic selection");
3363f08c3bdfSopenharmony_ci			continue;
3364f08c3bdfSopenharmony_ci		}
3365f08c3bdfSopenharmony_ci		if (stype->bit_size <= 0 || is_void_type(stype)) {
3366f08c3bdfSopenharmony_ci			sparse_error(stype->pos, "incomplete type in generic selection");
3367f08c3bdfSopenharmony_ci			continue;
3368f08c3bdfSopenharmony_ci		}
3369f08c3bdfSopenharmony_ci		if (!type_selection(&source, stype))
3370f08c3bdfSopenharmony_ci			continue;
3371f08c3bdfSopenharmony_ci
3372f08c3bdfSopenharmony_ci		res = map->expr;
3373f08c3bdfSopenharmony_ci		goto found;
3374f08c3bdfSopenharmony_ci	}
3375f08c3bdfSopenharmony_ci	res = expr->def;
3376f08c3bdfSopenharmony_ci	if (!res) {
3377f08c3bdfSopenharmony_ci		sparse_error(expr->pos, "no generic selection for '%s'", show_typename(ctrl));
3378f08c3bdfSopenharmony_ci		return NULL;
3379f08c3bdfSopenharmony_ci	}
3380f08c3bdfSopenharmony_ci
3381f08c3bdfSopenharmony_cifound:
3382f08c3bdfSopenharmony_ci	*expr = *res;
3383f08c3bdfSopenharmony_ci	return evaluate_expression(expr);
3384f08c3bdfSopenharmony_ci}
3385f08c3bdfSopenharmony_ci
3386f08c3bdfSopenharmony_cistruct symbol *evaluate_expression(struct expression *expr)
3387f08c3bdfSopenharmony_ci{
3388f08c3bdfSopenharmony_ci	if (!expr)
3389f08c3bdfSopenharmony_ci		return NULL;
3390f08c3bdfSopenharmony_ci	if (expr->ctype)
3391f08c3bdfSopenharmony_ci		return expr->ctype;
3392f08c3bdfSopenharmony_ci
3393f08c3bdfSopenharmony_ci	switch (expr->type) {
3394f08c3bdfSopenharmony_ci	case EXPR_VALUE:
3395f08c3bdfSopenharmony_ci	case EXPR_FVALUE:
3396f08c3bdfSopenharmony_ci		expression_error(expr, "value expression without a type");
3397f08c3bdfSopenharmony_ci		return NULL;
3398f08c3bdfSopenharmony_ci	case EXPR_STRING:
3399f08c3bdfSopenharmony_ci		return evaluate_string(expr);
3400f08c3bdfSopenharmony_ci	case EXPR_SYMBOL:
3401f08c3bdfSopenharmony_ci		return evaluate_symbol_expression(expr);
3402f08c3bdfSopenharmony_ci	case EXPR_BINOP:
3403f08c3bdfSopenharmony_ci		evaluate_expression(expr->left);
3404f08c3bdfSopenharmony_ci		evaluate_expression(expr->right);
3405f08c3bdfSopenharmony_ci		if (!valid_subexpr_type(expr))
3406f08c3bdfSopenharmony_ci			return NULL;
3407f08c3bdfSopenharmony_ci		return evaluate_binop(expr);
3408f08c3bdfSopenharmony_ci	case EXPR_LOGICAL:
3409f08c3bdfSopenharmony_ci		return evaluate_logical(expr);
3410f08c3bdfSopenharmony_ci	case EXPR_COMMA:
3411f08c3bdfSopenharmony_ci		evaluate_expression(expr->left);
3412f08c3bdfSopenharmony_ci		if (!evaluate_expression(expr->right))
3413f08c3bdfSopenharmony_ci			return NULL;
3414f08c3bdfSopenharmony_ci		return evaluate_comma(expr);
3415f08c3bdfSopenharmony_ci	case EXPR_COMPARE:
3416f08c3bdfSopenharmony_ci		evaluate_expression(expr->left);
3417f08c3bdfSopenharmony_ci		evaluate_expression(expr->right);
3418f08c3bdfSopenharmony_ci		if (!valid_subexpr_type(expr))
3419f08c3bdfSopenharmony_ci			return NULL;
3420f08c3bdfSopenharmony_ci		return evaluate_compare(expr);
3421f08c3bdfSopenharmony_ci	case EXPR_ASSIGNMENT:
3422f08c3bdfSopenharmony_ci		evaluate_expression(expr->left);
3423f08c3bdfSopenharmony_ci		evaluate_expression(expr->right);
3424f08c3bdfSopenharmony_ci		if (!valid_subexpr_type(expr))
3425f08c3bdfSopenharmony_ci			return NULL;
3426f08c3bdfSopenharmony_ci		return evaluate_assignment(expr);
3427f08c3bdfSopenharmony_ci	case EXPR_PREOP:
3428f08c3bdfSopenharmony_ci		if (!evaluate_expression(expr->unop))
3429f08c3bdfSopenharmony_ci			return NULL;
3430f08c3bdfSopenharmony_ci		return evaluate_preop(expr);
3431f08c3bdfSopenharmony_ci	case EXPR_POSTOP:
3432f08c3bdfSopenharmony_ci		if (!evaluate_expression(expr->unop))
3433f08c3bdfSopenharmony_ci			return NULL;
3434f08c3bdfSopenharmony_ci		return evaluate_postop(expr);
3435f08c3bdfSopenharmony_ci	case EXPR_CAST:
3436f08c3bdfSopenharmony_ci	case EXPR_FORCE_CAST:
3437f08c3bdfSopenharmony_ci	case EXPR_IMPLIED_CAST:
3438f08c3bdfSopenharmony_ci		return evaluate_cast(expr);
3439f08c3bdfSopenharmony_ci	case EXPR_SIZEOF:
3440f08c3bdfSopenharmony_ci		return evaluate_sizeof(expr);
3441f08c3bdfSopenharmony_ci	case EXPR_PTRSIZEOF:
3442f08c3bdfSopenharmony_ci		return evaluate_ptrsizeof(expr);
3443f08c3bdfSopenharmony_ci	case EXPR_ALIGNOF:
3444f08c3bdfSopenharmony_ci		return evaluate_alignof(expr);
3445f08c3bdfSopenharmony_ci	case EXPR_DEREF:
3446f08c3bdfSopenharmony_ci		return evaluate_member_dereference(expr);
3447f08c3bdfSopenharmony_ci	case EXPR_CALL:
3448f08c3bdfSopenharmony_ci		return evaluate_call(expr);
3449f08c3bdfSopenharmony_ci	case EXPR_SELECT:
3450f08c3bdfSopenharmony_ci	case EXPR_CONDITIONAL:
3451f08c3bdfSopenharmony_ci		return evaluate_conditional_expression(expr);
3452f08c3bdfSopenharmony_ci	case EXPR_STATEMENT:
3453f08c3bdfSopenharmony_ci		expr->ctype = evaluate_statement(expr->statement);
3454f08c3bdfSopenharmony_ci		return expr->ctype;
3455f08c3bdfSopenharmony_ci
3456f08c3bdfSopenharmony_ci	case EXPR_LABEL:
3457f08c3bdfSopenharmony_ci		expr->ctype = &ptr_ctype;
3458f08c3bdfSopenharmony_ci		check_label_declaration(expr->pos, expr->label_symbol);
3459f08c3bdfSopenharmony_ci		return &ptr_ctype;
3460f08c3bdfSopenharmony_ci
3461f08c3bdfSopenharmony_ci	case EXPR_TYPE:
3462f08c3bdfSopenharmony_ci		/* Evaluate the type of the symbol .. */
3463f08c3bdfSopenharmony_ci		evaluate_symbol(expr->symbol);
3464f08c3bdfSopenharmony_ci		/* .. but the type of the _expression_ is a "type" */
3465f08c3bdfSopenharmony_ci		expr->ctype = &type_ctype;
3466f08c3bdfSopenharmony_ci		return &type_ctype;
3467f08c3bdfSopenharmony_ci
3468f08c3bdfSopenharmony_ci	case EXPR_OFFSETOF:
3469f08c3bdfSopenharmony_ci		return evaluate_offsetof(expr);
3470f08c3bdfSopenharmony_ci
3471f08c3bdfSopenharmony_ci	case EXPR_GENERIC:
3472f08c3bdfSopenharmony_ci		return evaluate_generic_selection(expr);
3473f08c3bdfSopenharmony_ci
3474f08c3bdfSopenharmony_ci	/* These can not exist as stand-alone expressions */
3475f08c3bdfSopenharmony_ci	case EXPR_INITIALIZER:
3476f08c3bdfSopenharmony_ci	case EXPR_IDENTIFIER:
3477f08c3bdfSopenharmony_ci	case EXPR_INDEX:
3478f08c3bdfSopenharmony_ci	case EXPR_POS:
3479f08c3bdfSopenharmony_ci		expression_error(expr, "internal front-end error: initializer in expression");
3480f08c3bdfSopenharmony_ci		return NULL;
3481f08c3bdfSopenharmony_ci	case EXPR_SLICE:
3482f08c3bdfSopenharmony_ci		expression_error(expr, "internal front-end error: SLICE re-evaluated");
3483f08c3bdfSopenharmony_ci		return NULL;
3484f08c3bdfSopenharmony_ci	}
3485f08c3bdfSopenharmony_ci	return NULL;
3486f08c3bdfSopenharmony_ci}
3487f08c3bdfSopenharmony_ci
3488f08c3bdfSopenharmony_civoid check_duplicates(struct symbol *sym)
3489f08c3bdfSopenharmony_ci{
3490f08c3bdfSopenharmony_ci	int declared = 0;
3491f08c3bdfSopenharmony_ci	struct symbol *next = sym;
3492f08c3bdfSopenharmony_ci	int initialized = sym->initializer != NULL;
3493f08c3bdfSopenharmony_ci
3494f08c3bdfSopenharmony_ci	while ((next = next->same_symbol) != NULL) {
3495f08c3bdfSopenharmony_ci		const char *typediff;
3496f08c3bdfSopenharmony_ci		evaluate_symbol(next);
3497f08c3bdfSopenharmony_ci		if (initialized && next->initializer) {
3498f08c3bdfSopenharmony_ci			sparse_error(sym->pos, "symbol '%s' has multiple initializers (originally initialized at %s:%d)",
3499f08c3bdfSopenharmony_ci				show_ident(sym->ident),
3500f08c3bdfSopenharmony_ci				stream_name(next->pos.stream), next->pos.line);
3501f08c3bdfSopenharmony_ci			/* Only warn once */
3502f08c3bdfSopenharmony_ci			initialized = 0;
3503f08c3bdfSopenharmony_ci		}
3504f08c3bdfSopenharmony_ci		declared++;
3505f08c3bdfSopenharmony_ci		typediff = type_difference(&sym->ctype, &next->ctype, 0, 0);
3506f08c3bdfSopenharmony_ci		if (typediff) {
3507f08c3bdfSopenharmony_ci			sparse_error(sym->pos, "symbol '%s' redeclared with different type (%s):",
3508f08c3bdfSopenharmony_ci				show_ident(sym->ident), typediff);
3509f08c3bdfSopenharmony_ci			info(sym->pos, "   %s", show_typename(sym));
3510f08c3bdfSopenharmony_ci			info(next->pos, "note: previously declared as:");
3511f08c3bdfSopenharmony_ci			info(next->pos, "   %s", show_typename(next));
3512f08c3bdfSopenharmony_ci			return;
3513f08c3bdfSopenharmony_ci		}
3514f08c3bdfSopenharmony_ci	}
3515f08c3bdfSopenharmony_ci	if (!declared) {
3516f08c3bdfSopenharmony_ci		unsigned long mod = sym->ctype.modifiers;
3517f08c3bdfSopenharmony_ci		if (mod & (MOD_STATIC | MOD_REGISTER | MOD_EXT_VISIBLE))
3518f08c3bdfSopenharmony_ci			return;
3519f08c3bdfSopenharmony_ci		if (!(mod & MOD_TOPLEVEL))
3520f08c3bdfSopenharmony_ci			return;
3521f08c3bdfSopenharmony_ci		if (!Wdecl)
3522f08c3bdfSopenharmony_ci			return;
3523f08c3bdfSopenharmony_ci		if (sym->ident == &main_ident)
3524f08c3bdfSopenharmony_ci			return;
3525f08c3bdfSopenharmony_ci		warning(sym->pos, "symbol '%s' was not declared. Should it be static?", show_ident(sym->ident));
3526f08c3bdfSopenharmony_ci	}
3527f08c3bdfSopenharmony_ci}
3528f08c3bdfSopenharmony_ci
3529f08c3bdfSopenharmony_cistatic struct symbol *evaluate_symbol(struct symbol *sym)
3530f08c3bdfSopenharmony_ci{
3531f08c3bdfSopenharmony_ci	struct symbol *base_type;
3532f08c3bdfSopenharmony_ci
3533f08c3bdfSopenharmony_ci	if (!sym)
3534f08c3bdfSopenharmony_ci		return sym;
3535f08c3bdfSopenharmony_ci	if (sym->evaluated)
3536f08c3bdfSopenharmony_ci		return sym;
3537f08c3bdfSopenharmony_ci	sym->evaluated = 1;
3538f08c3bdfSopenharmony_ci
3539f08c3bdfSopenharmony_ci	sym = examine_symbol_type(sym);
3540f08c3bdfSopenharmony_ci	base_type = get_base_type(sym);
3541f08c3bdfSopenharmony_ci	if (!base_type)
3542f08c3bdfSopenharmony_ci		return NULL;
3543f08c3bdfSopenharmony_ci
3544f08c3bdfSopenharmony_ci	/* Evaluate the initializers */
3545f08c3bdfSopenharmony_ci	if (sym->initializer)
3546f08c3bdfSopenharmony_ci		evaluate_initializer(sym, &sym->initializer);
3547f08c3bdfSopenharmony_ci
3548f08c3bdfSopenharmony_ci	/* And finally, evaluate the body of the symbol too */
3549f08c3bdfSopenharmony_ci	if (base_type->type == SYM_FN) {
3550f08c3bdfSopenharmony_ci		struct symbol *curr = current_fn;
3551f08c3bdfSopenharmony_ci
3552f08c3bdfSopenharmony_ci		if (sym->definition && sym->definition != sym)
3553f08c3bdfSopenharmony_ci			return evaluate_symbol(sym->definition);
3554f08c3bdfSopenharmony_ci
3555f08c3bdfSopenharmony_ci		current_fn = sym;
3556f08c3bdfSopenharmony_ci
3557f08c3bdfSopenharmony_ci		examine_fn_arguments(base_type);
3558f08c3bdfSopenharmony_ci		if (!base_type->stmt && base_type->inline_stmt)
3559f08c3bdfSopenharmony_ci			uninline(sym);
3560f08c3bdfSopenharmony_ci		if (base_type->stmt)
3561f08c3bdfSopenharmony_ci			evaluate_statement(base_type->stmt);
3562f08c3bdfSopenharmony_ci
3563f08c3bdfSopenharmony_ci		current_fn = curr;
3564f08c3bdfSopenharmony_ci	}
3565f08c3bdfSopenharmony_ci
3566f08c3bdfSopenharmony_ci	return base_type;
3567f08c3bdfSopenharmony_ci}
3568f08c3bdfSopenharmony_ci
3569f08c3bdfSopenharmony_civoid evaluate_symbol_list(struct symbol_list *list)
3570f08c3bdfSopenharmony_ci{
3571f08c3bdfSopenharmony_ci	struct symbol *sym;
3572f08c3bdfSopenharmony_ci
3573f08c3bdfSopenharmony_ci	FOR_EACH_PTR(list, sym) {
3574f08c3bdfSopenharmony_ci		has_error &= ~ERROR_CURR_PHASE;
3575f08c3bdfSopenharmony_ci		evaluate_symbol(sym);
3576f08c3bdfSopenharmony_ci		check_duplicates(sym);
3577f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(sym);
3578f08c3bdfSopenharmony_ci}
3579f08c3bdfSopenharmony_ci
3580f08c3bdfSopenharmony_cistatic struct symbol *evaluate_return_expression(struct statement *stmt)
3581f08c3bdfSopenharmony_ci{
3582f08c3bdfSopenharmony_ci	struct expression *expr = stmt->expression;
3583f08c3bdfSopenharmony_ci	struct symbol *fntype, *rettype;
3584f08c3bdfSopenharmony_ci
3585f08c3bdfSopenharmony_ci	evaluate_expression(expr);
3586f08c3bdfSopenharmony_ci	fntype = current_fn->ctype.base_type;
3587f08c3bdfSopenharmony_ci	rettype = fntype->ctype.base_type;
3588f08c3bdfSopenharmony_ci	if (!rettype || rettype == &void_ctype) {
3589f08c3bdfSopenharmony_ci		if (expr && expr->ctype && !is_void_type(expr->ctype))
3590f08c3bdfSopenharmony_ci			expression_error(expr, "return expression in %s function", rettype?"void":"typeless");
3591f08c3bdfSopenharmony_ci		if (expr && Wreturn_void)
3592f08c3bdfSopenharmony_ci			warning(stmt->pos, "returning void-valued expression");
3593f08c3bdfSopenharmony_ci		return NULL;
3594f08c3bdfSopenharmony_ci	}
3595f08c3bdfSopenharmony_ci
3596f08c3bdfSopenharmony_ci	if (!expr) {
3597f08c3bdfSopenharmony_ci		sparse_error(stmt->pos, "return with no return value");
3598f08c3bdfSopenharmony_ci		return NULL;
3599f08c3bdfSopenharmony_ci	}
3600f08c3bdfSopenharmony_ci	if (!expr->ctype)
3601f08c3bdfSopenharmony_ci		return NULL;
3602f08c3bdfSopenharmony_ci	compatible_assignment_types(expr, rettype, &stmt->expression, "return expression");
3603f08c3bdfSopenharmony_ci	return NULL;
3604f08c3bdfSopenharmony_ci}
3605f08c3bdfSopenharmony_ci
3606f08c3bdfSopenharmony_cistatic void evaluate_if_statement(struct statement *stmt)
3607f08c3bdfSopenharmony_ci{
3608f08c3bdfSopenharmony_ci	if (!stmt->if_conditional)
3609f08c3bdfSopenharmony_ci		return;
3610f08c3bdfSopenharmony_ci
3611f08c3bdfSopenharmony_ci	evaluate_conditional(stmt->if_conditional, 0);
3612f08c3bdfSopenharmony_ci	evaluate_statement(stmt->if_true);
3613f08c3bdfSopenharmony_ci	evaluate_statement(stmt->if_false);
3614f08c3bdfSopenharmony_ci}
3615f08c3bdfSopenharmony_ci
3616f08c3bdfSopenharmony_cistatic void evaluate_iterator(struct statement *stmt)
3617f08c3bdfSopenharmony_ci{
3618f08c3bdfSopenharmony_ci	evaluate_symbol_list(stmt->iterator_syms);
3619f08c3bdfSopenharmony_ci	evaluate_conditional(stmt->iterator_pre_condition, 1);
3620f08c3bdfSopenharmony_ci	evaluate_conditional(stmt->iterator_post_condition,1);
3621f08c3bdfSopenharmony_ci	evaluate_statement(stmt->iterator_pre_statement);
3622f08c3bdfSopenharmony_ci	evaluate_statement(stmt->iterator_statement);
3623f08c3bdfSopenharmony_ci	evaluate_statement(stmt->iterator_post_statement);
3624f08c3bdfSopenharmony_ci}
3625f08c3bdfSopenharmony_ci
3626f08c3bdfSopenharmony_ci
3627f08c3bdfSopenharmony_cistatic void parse_asm_constraint(struct asm_operand *op)
3628f08c3bdfSopenharmony_ci{
3629f08c3bdfSopenharmony_ci	struct expression *constraint = op->constraint;
3630f08c3bdfSopenharmony_ci	const char *str = constraint->string->data;
3631f08c3bdfSopenharmony_ci	int c;
3632f08c3bdfSopenharmony_ci
3633f08c3bdfSopenharmony_ci	switch (str[0]) {
3634f08c3bdfSopenharmony_ci	case '\0':
3635f08c3bdfSopenharmony_ci		sparse_error(constraint->pos, "invalid ASM constraint (\"\")");
3636f08c3bdfSopenharmony_ci		break;
3637f08c3bdfSopenharmony_ci	case '+':
3638f08c3bdfSopenharmony_ci		op->is_modify = true;
3639f08c3bdfSopenharmony_ci		/* fall-through */
3640f08c3bdfSopenharmony_ci	case '=':
3641f08c3bdfSopenharmony_ci		op->is_assign = true;
3642f08c3bdfSopenharmony_ci		str++;
3643f08c3bdfSopenharmony_ci		break;
3644f08c3bdfSopenharmony_ci	}
3645f08c3bdfSopenharmony_ci
3646f08c3bdfSopenharmony_ci	while ((c = *str++)) {
3647f08c3bdfSopenharmony_ci		switch (c) {
3648f08c3bdfSopenharmony_ci		case '=':
3649f08c3bdfSopenharmony_ci		case '+':
3650f08c3bdfSopenharmony_ci			sparse_error(constraint->pos, "invalid ASM constraint '%c'", c);
3651f08c3bdfSopenharmony_ci			break;
3652f08c3bdfSopenharmony_ci
3653f08c3bdfSopenharmony_ci		case '&':
3654f08c3bdfSopenharmony_ci			op->is_earlyclobber = true;
3655f08c3bdfSopenharmony_ci			break;
3656f08c3bdfSopenharmony_ci		case '%':
3657f08c3bdfSopenharmony_ci			op->is_commutative = true;
3658f08c3bdfSopenharmony_ci			break;
3659f08c3bdfSopenharmony_ci		case 'r':
3660f08c3bdfSopenharmony_ci			op->is_register = true;
3661f08c3bdfSopenharmony_ci			break;
3662f08c3bdfSopenharmony_ci
3663f08c3bdfSopenharmony_ci		case 'm':
3664f08c3bdfSopenharmony_ci		case 'o':
3665f08c3bdfSopenharmony_ci		case 'V':
3666f08c3bdfSopenharmony_ci		case 'Q':
3667f08c3bdfSopenharmony_ci			op->is_memory = true;
3668f08c3bdfSopenharmony_ci			break;
3669f08c3bdfSopenharmony_ci
3670f08c3bdfSopenharmony_ci		case '<':
3671f08c3bdfSopenharmony_ci		case '>':
3672f08c3bdfSopenharmony_ci			// FIXME: ignored for now
3673f08c3bdfSopenharmony_ci			break;
3674f08c3bdfSopenharmony_ci
3675f08c3bdfSopenharmony_ci		case ',':
3676f08c3bdfSopenharmony_ci			// FIXME: multiple alternative constraints
3677f08c3bdfSopenharmony_ci			break;
3678f08c3bdfSopenharmony_ci
3679f08c3bdfSopenharmony_ci		case '0' ... '9':
3680f08c3bdfSopenharmony_ci			// FIXME: numeric  matching constraint?
3681f08c3bdfSopenharmony_ci			break;
3682f08c3bdfSopenharmony_ci		case '[':
3683f08c3bdfSopenharmony_ci			// FIXME: symbolic matching constraint
3684f08c3bdfSopenharmony_ci			return;
3685f08c3bdfSopenharmony_ci
3686f08c3bdfSopenharmony_ci		default:
3687f08c3bdfSopenharmony_ci			if (arch_target->asm_constraint)
3688f08c3bdfSopenharmony_ci				str = arch_target->asm_constraint(op, c, str);
3689f08c3bdfSopenharmony_ci
3690f08c3bdfSopenharmony_ci			// FIXME: multi-letter constraints
3691f08c3bdfSopenharmony_ci			break;
3692f08c3bdfSopenharmony_ci		}
3693f08c3bdfSopenharmony_ci	}
3694f08c3bdfSopenharmony_ci
3695f08c3bdfSopenharmony_ci	// FIXME: how to deal with multi-constraint?
3696f08c3bdfSopenharmony_ci	if (op->is_register)
3697f08c3bdfSopenharmony_ci		op->is_memory = 0;
3698f08c3bdfSopenharmony_ci}
3699f08c3bdfSopenharmony_ci
3700f08c3bdfSopenharmony_cistatic void verify_output_constraint(struct asm_operand *op)
3701f08c3bdfSopenharmony_ci{
3702f08c3bdfSopenharmony_ci	struct expression *expr = op->constraint;
3703f08c3bdfSopenharmony_ci	const char *constraint = expr->string->data;
3704f08c3bdfSopenharmony_ci
3705f08c3bdfSopenharmony_ci	if (!op->is_assign)
3706f08c3bdfSopenharmony_ci		expression_error(expr, "output constraint is not an assignment constraint (\"%s\")", constraint);
3707f08c3bdfSopenharmony_ci}
3708f08c3bdfSopenharmony_ci
3709f08c3bdfSopenharmony_cistatic void verify_input_constraint(struct asm_operand *op)
3710f08c3bdfSopenharmony_ci{
3711f08c3bdfSopenharmony_ci	struct expression *expr = op->constraint;
3712f08c3bdfSopenharmony_ci	const char *constraint = expr->string->data;
3713f08c3bdfSopenharmony_ci
3714f08c3bdfSopenharmony_ci	if (op->is_assign)
3715f08c3bdfSopenharmony_ci		expression_error(expr, "input constraint with assignment (\"%s\")", constraint);
3716f08c3bdfSopenharmony_ci}
3717f08c3bdfSopenharmony_ci
3718f08c3bdfSopenharmony_cistatic void evaluate_asm_memop(struct asm_operand *op)
3719f08c3bdfSopenharmony_ci{
3720f08c3bdfSopenharmony_ci	if (op->is_memory) {
3721f08c3bdfSopenharmony_ci		struct expression *expr = op->expr;
3722f08c3bdfSopenharmony_ci		struct expression *addr;
3723f08c3bdfSopenharmony_ci
3724f08c3bdfSopenharmony_ci		// implicit addressof
3725f08c3bdfSopenharmony_ci		addr = alloc_expression(expr->pos, EXPR_PREOP);
3726f08c3bdfSopenharmony_ci		addr->op = '&';
3727f08c3bdfSopenharmony_ci		addr->unop = expr;
3728f08c3bdfSopenharmony_ci
3729f08c3bdfSopenharmony_ci		evaluate_addressof(addr);
3730f08c3bdfSopenharmony_ci		op->expr = addr;
3731f08c3bdfSopenharmony_ci	} else {
3732f08c3bdfSopenharmony_ci		evaluate_expression(op->expr);
3733f08c3bdfSopenharmony_ci		degenerate(op->expr);
3734f08c3bdfSopenharmony_ci	}
3735f08c3bdfSopenharmony_ci}
3736f08c3bdfSopenharmony_ci
3737f08c3bdfSopenharmony_cistatic void evaluate_asm_statement(struct statement *stmt)
3738f08c3bdfSopenharmony_ci{
3739f08c3bdfSopenharmony_ci	struct expression *expr;
3740f08c3bdfSopenharmony_ci	struct asm_operand *op;
3741f08c3bdfSopenharmony_ci	struct symbol *sym;
3742f08c3bdfSopenharmony_ci
3743f08c3bdfSopenharmony_ci	if (!stmt->asm_string)
3744f08c3bdfSopenharmony_ci		return;
3745f08c3bdfSopenharmony_ci
3746f08c3bdfSopenharmony_ci	FOR_EACH_PTR(stmt->asm_outputs, op) {
3747f08c3bdfSopenharmony_ci		/* Identifier */
3748f08c3bdfSopenharmony_ci
3749f08c3bdfSopenharmony_ci		/* Constraint */
3750f08c3bdfSopenharmony_ci		if (op->constraint) {
3751f08c3bdfSopenharmony_ci			parse_asm_constraint(op);
3752f08c3bdfSopenharmony_ci			verify_output_constraint(op);
3753f08c3bdfSopenharmony_ci		}
3754f08c3bdfSopenharmony_ci
3755f08c3bdfSopenharmony_ci		/* Expression */
3756f08c3bdfSopenharmony_ci		expr = op->expr;
3757f08c3bdfSopenharmony_ci		if (!evaluate_expression(expr))
3758f08c3bdfSopenharmony_ci			return;
3759f08c3bdfSopenharmony_ci		if (!lvalue_expression(expr))
3760f08c3bdfSopenharmony_ci			warning(expr->pos, "asm output is not an lvalue");
3761f08c3bdfSopenharmony_ci		evaluate_assign_to(expr, expr->ctype);
3762f08c3bdfSopenharmony_ci		evaluate_asm_memop(op);
3763f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(op);
3764f08c3bdfSopenharmony_ci
3765f08c3bdfSopenharmony_ci	FOR_EACH_PTR(stmt->asm_inputs, op) {
3766f08c3bdfSopenharmony_ci		/* Identifier */
3767f08c3bdfSopenharmony_ci
3768f08c3bdfSopenharmony_ci		/* Constraint */
3769f08c3bdfSopenharmony_ci		if (op->constraint) {
3770f08c3bdfSopenharmony_ci			parse_asm_constraint(op);
3771f08c3bdfSopenharmony_ci			verify_input_constraint(op);
3772f08c3bdfSopenharmony_ci		}
3773f08c3bdfSopenharmony_ci
3774f08c3bdfSopenharmony_ci		/* Expression */
3775f08c3bdfSopenharmony_ci		if (!evaluate_expression(op->expr))
3776f08c3bdfSopenharmony_ci			return;
3777f08c3bdfSopenharmony_ci		evaluate_asm_memop(op);
3778f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(op);
3779f08c3bdfSopenharmony_ci
3780f08c3bdfSopenharmony_ci	FOR_EACH_PTR(stmt->asm_clobbers, expr) {
3781f08c3bdfSopenharmony_ci		if (!expr) {
3782f08c3bdfSopenharmony_ci			sparse_error(stmt->pos, "bad asm clobbers");
3783f08c3bdfSopenharmony_ci			return;
3784f08c3bdfSopenharmony_ci		}
3785f08c3bdfSopenharmony_ci		if (expr->type == EXPR_STRING)
3786f08c3bdfSopenharmony_ci			continue;
3787f08c3bdfSopenharmony_ci		expression_error(expr, "asm clobber is not a string");
3788f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(expr);
3789f08c3bdfSopenharmony_ci
3790f08c3bdfSopenharmony_ci	FOR_EACH_PTR(stmt->asm_labels, sym) {
3791f08c3bdfSopenharmony_ci		if (!sym || sym->type != SYM_LABEL) {
3792f08c3bdfSopenharmony_ci			sparse_error(stmt->pos, "bad asm label");
3793f08c3bdfSopenharmony_ci			return;
3794f08c3bdfSopenharmony_ci		}
3795f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(sym);
3796f08c3bdfSopenharmony_ci}
3797f08c3bdfSopenharmony_ci
3798f08c3bdfSopenharmony_cistatic void evaluate_case_statement(struct statement *stmt)
3799f08c3bdfSopenharmony_ci{
3800f08c3bdfSopenharmony_ci	evaluate_expression(stmt->case_expression);
3801f08c3bdfSopenharmony_ci	evaluate_expression(stmt->case_to);
3802f08c3bdfSopenharmony_ci	evaluate_statement(stmt->case_statement);
3803f08c3bdfSopenharmony_ci}
3804f08c3bdfSopenharmony_ci
3805f08c3bdfSopenharmony_cistatic void check_case_type(struct expression *switch_expr,
3806f08c3bdfSopenharmony_ci			    struct expression *case_expr,
3807f08c3bdfSopenharmony_ci			    struct expression **enumcase)
3808f08c3bdfSopenharmony_ci{
3809f08c3bdfSopenharmony_ci	struct symbol *switch_type, *case_type;
3810f08c3bdfSopenharmony_ci	int sclass, cclass;
3811f08c3bdfSopenharmony_ci
3812f08c3bdfSopenharmony_ci	if (!case_expr)
3813f08c3bdfSopenharmony_ci		return;
3814f08c3bdfSopenharmony_ci
3815f08c3bdfSopenharmony_ci	switch_type = switch_expr->ctype;
3816f08c3bdfSopenharmony_ci	case_type = evaluate_expression(case_expr);
3817f08c3bdfSopenharmony_ci
3818f08c3bdfSopenharmony_ci	if (!switch_type || !case_type)
3819f08c3bdfSopenharmony_ci		goto Bad;
3820f08c3bdfSopenharmony_ci	if (enumcase) {
3821f08c3bdfSopenharmony_ci		if (*enumcase)
3822f08c3bdfSopenharmony_ci			warn_for_different_enum_types(case_expr->pos, case_type, (*enumcase)->ctype);
3823f08c3bdfSopenharmony_ci		else if (is_enum_type(case_type))
3824f08c3bdfSopenharmony_ci			*enumcase = case_expr;
3825f08c3bdfSopenharmony_ci	}
3826f08c3bdfSopenharmony_ci
3827f08c3bdfSopenharmony_ci	sclass = classify_type(switch_type, &switch_type);
3828f08c3bdfSopenharmony_ci	cclass = classify_type(case_type, &case_type);
3829f08c3bdfSopenharmony_ci
3830f08c3bdfSopenharmony_ci	/* both should be arithmetic */
3831f08c3bdfSopenharmony_ci	if (!(sclass & cclass & TYPE_NUM))
3832f08c3bdfSopenharmony_ci		goto Bad;
3833f08c3bdfSopenharmony_ci
3834f08c3bdfSopenharmony_ci	/* neither should be floating */
3835f08c3bdfSopenharmony_ci	if ((sclass | cclass) & TYPE_FLOAT)
3836f08c3bdfSopenharmony_ci		goto Bad;
3837f08c3bdfSopenharmony_ci
3838f08c3bdfSopenharmony_ci	/* if neither is restricted, we are OK */
3839f08c3bdfSopenharmony_ci	if (!((sclass | cclass) & TYPE_RESTRICT))
3840f08c3bdfSopenharmony_ci		return;
3841f08c3bdfSopenharmony_ci
3842f08c3bdfSopenharmony_ci	if (!restricted_binop_type(SPECIAL_EQUAL, case_expr, switch_expr,
3843f08c3bdfSopenharmony_ci				   cclass, sclass, case_type, switch_type)) {
3844f08c3bdfSopenharmony_ci		unrestrict(case_expr, cclass, &case_type);
3845f08c3bdfSopenharmony_ci		unrestrict(switch_expr, sclass, &switch_type);
3846f08c3bdfSopenharmony_ci	}
3847f08c3bdfSopenharmony_ci	return;
3848f08c3bdfSopenharmony_ci
3849f08c3bdfSopenharmony_ciBad:
3850f08c3bdfSopenharmony_ci	expression_error(case_expr, "incompatible types for 'case' statement");
3851f08c3bdfSopenharmony_ci}
3852f08c3bdfSopenharmony_ci
3853f08c3bdfSopenharmony_cistatic void evaluate_switch_statement(struct statement *stmt)
3854f08c3bdfSopenharmony_ci{
3855f08c3bdfSopenharmony_ci	struct symbol *sym;
3856f08c3bdfSopenharmony_ci	struct expression *enumcase = NULL;
3857f08c3bdfSopenharmony_ci	struct expression **enumcase_holder = &enumcase;
3858f08c3bdfSopenharmony_ci	struct expression *sel = stmt->switch_expression;
3859f08c3bdfSopenharmony_ci
3860f08c3bdfSopenharmony_ci	evaluate_expression(sel);
3861f08c3bdfSopenharmony_ci	evaluate_statement(stmt->switch_statement);
3862f08c3bdfSopenharmony_ci	if (!sel)
3863f08c3bdfSopenharmony_ci		return;
3864f08c3bdfSopenharmony_ci	if (sel->ctype && is_enum_type(sel->ctype))
3865f08c3bdfSopenharmony_ci		enumcase_holder = NULL; /* Only check cases against switch */
3866f08c3bdfSopenharmony_ci
3867f08c3bdfSopenharmony_ci	FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
3868f08c3bdfSopenharmony_ci		struct statement *case_stmt = sym->stmt;
3869f08c3bdfSopenharmony_ci		check_case_type(sel, case_stmt->case_expression, enumcase_holder);
3870f08c3bdfSopenharmony_ci		check_case_type(sel, case_stmt->case_to, enumcase_holder);
3871f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(sym);
3872f08c3bdfSopenharmony_ci}
3873f08c3bdfSopenharmony_ci
3874f08c3bdfSopenharmony_cistatic void evaluate_goto_statement(struct statement *stmt)
3875f08c3bdfSopenharmony_ci{
3876f08c3bdfSopenharmony_ci	struct symbol *label = stmt->goto_label;
3877f08c3bdfSopenharmony_ci
3878f08c3bdfSopenharmony_ci	if (!label) {
3879f08c3bdfSopenharmony_ci		// no label associated, may be a computed goto
3880f08c3bdfSopenharmony_ci		evaluate_expression(stmt->goto_expression);
3881f08c3bdfSopenharmony_ci		return;
3882f08c3bdfSopenharmony_ci	}
3883f08c3bdfSopenharmony_ci
3884f08c3bdfSopenharmony_ci	check_label_declaration(stmt->pos, label);
3885f08c3bdfSopenharmony_ci}
3886f08c3bdfSopenharmony_ci
3887f08c3bdfSopenharmony_cistruct symbol *evaluate_statement(struct statement *stmt)
3888f08c3bdfSopenharmony_ci{
3889f08c3bdfSopenharmony_ci	if (!stmt)
3890f08c3bdfSopenharmony_ci		return NULL;
3891f08c3bdfSopenharmony_ci
3892f08c3bdfSopenharmony_ci	switch (stmt->type) {
3893f08c3bdfSopenharmony_ci	case STMT_DECLARATION: {
3894f08c3bdfSopenharmony_ci		struct symbol *s;
3895f08c3bdfSopenharmony_ci		FOR_EACH_PTR(stmt->declaration, s) {
3896f08c3bdfSopenharmony_ci			evaluate_symbol(s);
3897f08c3bdfSopenharmony_ci		} END_FOR_EACH_PTR(s);
3898f08c3bdfSopenharmony_ci		return NULL;
3899f08c3bdfSopenharmony_ci	}
3900f08c3bdfSopenharmony_ci
3901f08c3bdfSopenharmony_ci	case STMT_RETURN:
3902f08c3bdfSopenharmony_ci		return evaluate_return_expression(stmt);
3903f08c3bdfSopenharmony_ci
3904f08c3bdfSopenharmony_ci	case STMT_EXPRESSION:
3905f08c3bdfSopenharmony_ci		if (!evaluate_expression(stmt->expression))
3906f08c3bdfSopenharmony_ci			return NULL;
3907f08c3bdfSopenharmony_ci		if (stmt->expression->ctype == &null_ctype)
3908f08c3bdfSopenharmony_ci			stmt->expression = cast_to(stmt->expression, &ptr_ctype);
3909f08c3bdfSopenharmony_ci		return unqualify_type(degenerate(stmt->expression));
3910f08c3bdfSopenharmony_ci
3911f08c3bdfSopenharmony_ci	case STMT_COMPOUND: {
3912f08c3bdfSopenharmony_ci		struct statement *s;
3913f08c3bdfSopenharmony_ci		struct symbol *type = NULL;
3914f08c3bdfSopenharmony_ci
3915f08c3bdfSopenharmony_ci		/* Evaluate the return symbol in the compound statement */
3916f08c3bdfSopenharmony_ci		evaluate_symbol(stmt->ret);
3917f08c3bdfSopenharmony_ci
3918f08c3bdfSopenharmony_ci		/*
3919f08c3bdfSopenharmony_ci		 * Then, evaluate each statement, making the type of the
3920f08c3bdfSopenharmony_ci		 * compound statement be the type of the last statement
3921f08c3bdfSopenharmony_ci		 */
3922f08c3bdfSopenharmony_ci		type = evaluate_statement(stmt->args);
3923f08c3bdfSopenharmony_ci		FOR_EACH_PTR(stmt->stmts, s) {
3924f08c3bdfSopenharmony_ci			type = evaluate_statement(s);
3925f08c3bdfSopenharmony_ci		} END_FOR_EACH_PTR(s);
3926f08c3bdfSopenharmony_ci		if (!type)
3927f08c3bdfSopenharmony_ci			type = &void_ctype;
3928f08c3bdfSopenharmony_ci		return type;
3929f08c3bdfSopenharmony_ci	}
3930f08c3bdfSopenharmony_ci	case STMT_IF:
3931f08c3bdfSopenharmony_ci		evaluate_if_statement(stmt);
3932f08c3bdfSopenharmony_ci		return NULL;
3933f08c3bdfSopenharmony_ci	case STMT_ITERATOR:
3934f08c3bdfSopenharmony_ci		evaluate_iterator(stmt);
3935f08c3bdfSopenharmony_ci		return NULL;
3936f08c3bdfSopenharmony_ci	case STMT_SWITCH:
3937f08c3bdfSopenharmony_ci		evaluate_switch_statement(stmt);
3938f08c3bdfSopenharmony_ci		return NULL;
3939f08c3bdfSopenharmony_ci	case STMT_CASE:
3940f08c3bdfSopenharmony_ci		evaluate_case_statement(stmt);
3941f08c3bdfSopenharmony_ci		return NULL;
3942f08c3bdfSopenharmony_ci	case STMT_LABEL:
3943f08c3bdfSopenharmony_ci		return evaluate_statement(stmt->label_statement);
3944f08c3bdfSopenharmony_ci	case STMT_GOTO:
3945f08c3bdfSopenharmony_ci		evaluate_goto_statement(stmt);
3946f08c3bdfSopenharmony_ci		return NULL;
3947f08c3bdfSopenharmony_ci	case STMT_NONE:
3948f08c3bdfSopenharmony_ci		break;
3949f08c3bdfSopenharmony_ci	case STMT_ASM:
3950f08c3bdfSopenharmony_ci		evaluate_asm_statement(stmt);
3951f08c3bdfSopenharmony_ci		return NULL;
3952f08c3bdfSopenharmony_ci	case STMT_CONTEXT:
3953f08c3bdfSopenharmony_ci		evaluate_expression(stmt->expression);
3954f08c3bdfSopenharmony_ci		return NULL;
3955f08c3bdfSopenharmony_ci	case STMT_RANGE:
3956f08c3bdfSopenharmony_ci		evaluate_expression(stmt->range_expression);
3957f08c3bdfSopenharmony_ci		evaluate_expression(stmt->range_low);
3958f08c3bdfSopenharmony_ci		evaluate_expression(stmt->range_high);
3959f08c3bdfSopenharmony_ci		return NULL;
3960f08c3bdfSopenharmony_ci	}
3961f08c3bdfSopenharmony_ci	return NULL;
3962f08c3bdfSopenharmony_ci}
3963