11f5207b7SJohn Levon /*
21f5207b7SJohn Levon  * sparse/expression.c
31f5207b7SJohn Levon  *
41f5207b7SJohn Levon  * Copyright (C) 2003 Transmeta Corp.
51f5207b7SJohn Levon  *               2003-2004 Linus Torvalds
61f5207b7SJohn Levon  *
71f5207b7SJohn Levon  * Permission is hereby granted, free of charge, to any person obtaining a copy
81f5207b7SJohn Levon  * of this software and associated documentation files (the "Software"), to deal
91f5207b7SJohn Levon  * in the Software without restriction, including without limitation the rights
101f5207b7SJohn Levon  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
111f5207b7SJohn Levon  * copies of the Software, and to permit persons to whom the Software is
121f5207b7SJohn Levon  * furnished to do so, subject to the following conditions:
131f5207b7SJohn Levon  *
141f5207b7SJohn Levon  * The above copyright notice and this permission notice shall be included in
151f5207b7SJohn Levon  * all copies or substantial portions of the Software.
161f5207b7SJohn Levon  *
171f5207b7SJohn Levon  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
181f5207b7SJohn Levon  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
191f5207b7SJohn Levon  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
201f5207b7SJohn Levon  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
211f5207b7SJohn Levon  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
221f5207b7SJohn Levon  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
231f5207b7SJohn Levon  * THE SOFTWARE.
241f5207b7SJohn Levon  *
251f5207b7SJohn Levon  * This is the expression parsing part of parsing C.
261f5207b7SJohn Levon  */
271f5207b7SJohn Levon #include <stdarg.h>
281f5207b7SJohn Levon #include <stdlib.h>
291f5207b7SJohn Levon #include <stdio.h>
301f5207b7SJohn Levon #include <string.h>
311f5207b7SJohn Levon #include <ctype.h>
321f5207b7SJohn Levon #include <unistd.h>
331f5207b7SJohn Levon #include <fcntl.h>
341f5207b7SJohn Levon #include <errno.h>
351f5207b7SJohn Levon #include <limits.h>
361f5207b7SJohn Levon 
371f5207b7SJohn Levon #include "lib.h"
381f5207b7SJohn Levon #include "allocate.h"
391f5207b7SJohn Levon #include "token.h"
401f5207b7SJohn Levon #include "parse.h"
411f5207b7SJohn Levon #include "symbol.h"
421f5207b7SJohn Levon #include "scope.h"
431f5207b7SJohn Levon #include "expression.h"
441f5207b7SJohn Levon #include "target.h"
451f5207b7SJohn Levon #include "char.h"
461f5207b7SJohn Levon 
match_oplist(int op,...)471f5207b7SJohn Levon static int match_oplist(int op, ...)
481f5207b7SJohn Levon {
491f5207b7SJohn Levon 	va_list args;
501f5207b7SJohn Levon 	int nextop;
511f5207b7SJohn Levon 
521f5207b7SJohn Levon 	va_start(args, op);
531f5207b7SJohn Levon 	do {
541f5207b7SJohn Levon 		nextop = va_arg(args, int);
551f5207b7SJohn Levon 	} while (nextop != 0 && nextop != op);
561f5207b7SJohn Levon 	va_end(args);
571f5207b7SJohn Levon 
581f5207b7SJohn Levon 	return nextop != 0;
591f5207b7SJohn Levon }
601f5207b7SJohn Levon 
611f5207b7SJohn Levon static struct token *comma_expression(struct token *, struct expression **);
621f5207b7SJohn Levon 
parens_expression(struct token * token,struct expression ** expr,const char * where)631f5207b7SJohn Levon struct token *parens_expression(struct token *token, struct expression **expr, const char *where)
641f5207b7SJohn Levon {
65*c85f09ccSJohn Levon 	struct token *p;
66*c85f09ccSJohn Levon 
671f5207b7SJohn Levon 	token = expect(token, '(', where);
68*c85f09ccSJohn Levon 	p = token;
691f5207b7SJohn Levon 	if (match_op(token, '{')) {
701f5207b7SJohn Levon 		struct expression *e = alloc_expression(token->pos, EXPR_STATEMENT);
711f5207b7SJohn Levon 		struct statement *stmt = alloc_statement(token->pos, STMT_COMPOUND);
721f5207b7SJohn Levon 		*expr = e;
731f5207b7SJohn Levon 		e->statement = stmt;
741f5207b7SJohn Levon 		start_symbol_scope(e->pos);
751f5207b7SJohn Levon 		token = compound_statement(token->next, stmt);
761f5207b7SJohn Levon 		end_symbol_scope();
771f5207b7SJohn Levon 		token = expect(token, '}', "at end of statement expression");
781f5207b7SJohn Levon 	} else
791f5207b7SJohn Levon 		token = parse_expression(token, expr);
80*c85f09ccSJohn Levon 
81*c85f09ccSJohn Levon 	if (token == p)
82*c85f09ccSJohn Levon 		sparse_error(token->pos, "an expression is expected before ')'");
831f5207b7SJohn Levon 	return expect(token, ')', where);
841f5207b7SJohn Levon }
851f5207b7SJohn Levon 
861f5207b7SJohn Levon /*
871f5207b7SJohn Levon  * Handle __func__, __FUNCTION__ and __PRETTY_FUNCTION__ token
881f5207b7SJohn Levon  * conversion
891f5207b7SJohn Levon  */
handle_func(struct token * token)901f5207b7SJohn Levon static struct symbol *handle_func(struct token *token)
911f5207b7SJohn Levon {
921f5207b7SJohn Levon 	struct ident *ident = token->ident;
931f5207b7SJohn Levon 	struct symbol *decl, *array;
941f5207b7SJohn Levon 	struct string *string;
951f5207b7SJohn Levon 	int len;
961f5207b7SJohn Levon 
971f5207b7SJohn Levon 	if (ident != &__func___ident &&
981f5207b7SJohn Levon 	    ident != &__FUNCTION___ident &&
991f5207b7SJohn Levon 	    ident != &__PRETTY_FUNCTION___ident)
1001f5207b7SJohn Levon 		return NULL;
1011f5207b7SJohn Levon 
1021f5207b7SJohn Levon 	if (!current_fn || !current_fn->ident)
1031f5207b7SJohn Levon 		return NULL;
1041f5207b7SJohn Levon 
1051f5207b7SJohn Levon 	/* OK, it's one of ours */
1061f5207b7SJohn Levon 	array = alloc_symbol(token->pos, SYM_ARRAY);
1071f5207b7SJohn Levon 	array->ctype.base_type = &char_ctype;
1081f5207b7SJohn Levon 	array->ctype.alignment = 1;
1091f5207b7SJohn Levon 	array->endpos = token->pos;
1101f5207b7SJohn Levon 	decl = alloc_symbol(token->pos, SYM_NODE);
1111f5207b7SJohn Levon 	decl->ctype.base_type = array;
1121f5207b7SJohn Levon 	decl->ctype.alignment = 1;
1131f5207b7SJohn Levon 	decl->ctype.modifiers = MOD_STATIC;
1141f5207b7SJohn Levon 	decl->endpos = token->pos;
1151f5207b7SJohn Levon 
1161f5207b7SJohn Levon 	/* function-scope, but in NS_SYMBOL */
1171f5207b7SJohn Levon 	bind_symbol(decl, ident, NS_LABEL);
1181f5207b7SJohn Levon 	decl->namespace = NS_SYMBOL;
1191f5207b7SJohn Levon 
1201f5207b7SJohn Levon 	len = current_fn->ident->len;
1211f5207b7SJohn Levon 	string = __alloc_string(len + 1);
1221f5207b7SJohn Levon 	memcpy(string->data, current_fn->ident->name, len);
1231f5207b7SJohn Levon 	string->data[len] = 0;
1241f5207b7SJohn Levon 	string->length = len + 1;
1251f5207b7SJohn Levon 
1261f5207b7SJohn Levon 	decl->initializer = alloc_expression(token->pos, EXPR_STRING);
1271f5207b7SJohn Levon 	decl->initializer->string = string;
1281f5207b7SJohn Levon 	decl->initializer->ctype = decl;
1291f5207b7SJohn Levon 	decl->array_size = alloc_const_expression(token->pos, len + 1);
1301f5207b7SJohn Levon 	array->array_size = decl->array_size;
1311f5207b7SJohn Levon 	decl->bit_size = array->bit_size = bytes_to_bits(len + 1);
1321f5207b7SJohn Levon 
1331f5207b7SJohn Levon 	return decl;
1341f5207b7SJohn Levon }
1351f5207b7SJohn Levon 
parse_type(struct token * token,struct expression ** tree)1361f5207b7SJohn Levon static struct token *parse_type(struct token *token, struct expression **tree)
1371f5207b7SJohn Levon {
1381f5207b7SJohn Levon 	struct symbol *sym;
1391f5207b7SJohn Levon 	*tree = alloc_expression(token->pos, EXPR_TYPE);
1401f5207b7SJohn Levon 	token = typename(token, &sym, NULL);
1411f5207b7SJohn Levon 	if (sym->ident)
1421f5207b7SJohn Levon 		sparse_error(token->pos,
1431f5207b7SJohn Levon 			     "type expression should not include identifier "
1441f5207b7SJohn Levon 			     "\"%s\"", sym->ident->name);
1451f5207b7SJohn Levon 	(*tree)->symbol = sym;
1461f5207b7SJohn Levon 	return token;
1471f5207b7SJohn Levon }
1481f5207b7SJohn Levon 
builtin_types_compatible_p_expr(struct token * token,struct expression ** tree)1491f5207b7SJohn Levon static struct token *builtin_types_compatible_p_expr(struct token *token,
1501f5207b7SJohn Levon 						     struct expression **tree)
1511f5207b7SJohn Levon {
1521f5207b7SJohn Levon 	struct expression *expr = alloc_expression(
1531f5207b7SJohn Levon 		token->pos, EXPR_COMPARE);
1541f5207b7SJohn Levon 	expr->op = SPECIAL_EQUAL;
1551f5207b7SJohn Levon 	token = token->next;
1561f5207b7SJohn Levon 	if (!match_op(token, '('))
1571f5207b7SJohn Levon 		return expect(token, '(',
1581f5207b7SJohn Levon 			      "after __builtin_types_compatible_p");
1591f5207b7SJohn Levon 	token = token->next;
1601f5207b7SJohn Levon 	token = parse_type(token, &expr->left);
1611f5207b7SJohn Levon 	if (!match_op(token, ','))
1621f5207b7SJohn Levon 		return expect(token, ',',
1631f5207b7SJohn Levon 			      "in __builtin_types_compatible_p");
1641f5207b7SJohn Levon 	token = token->next;
1651f5207b7SJohn Levon 	token = parse_type(token, &expr->right);
1661f5207b7SJohn Levon 	if (!match_op(token, ')'))
1671f5207b7SJohn Levon 		return expect(token, ')',
1681f5207b7SJohn Levon 			      "at end of __builtin_types_compatible_p");
1691f5207b7SJohn Levon 	token = token->next;
1701f5207b7SJohn Levon 
1711f5207b7SJohn Levon 	*tree = expr;
1721f5207b7SJohn Levon 	return token;
1731f5207b7SJohn Levon }
1741f5207b7SJohn Levon 
builtin_offsetof_expr(struct token * token,struct expression ** tree)1751f5207b7SJohn Levon static struct token *builtin_offsetof_expr(struct token *token,
1761f5207b7SJohn Levon 					   struct expression **tree)
1771f5207b7SJohn Levon {
1781f5207b7SJohn Levon 	struct expression *expr = NULL;
1791f5207b7SJohn Levon 	struct expression **p = &expr;
1801f5207b7SJohn Levon 	struct symbol *sym;
1811f5207b7SJohn Levon 	int op = '.';
1821f5207b7SJohn Levon 
1831f5207b7SJohn Levon 	token = token->next;
1841f5207b7SJohn Levon 	if (!match_op(token, '('))
1851f5207b7SJohn Levon 		return expect(token, '(', "after __builtin_offset");
1861f5207b7SJohn Levon 
1871f5207b7SJohn Levon 	token = token->next;
1881f5207b7SJohn Levon 	token = typename(token, &sym, NULL);
1891f5207b7SJohn Levon 	if (sym->ident)
1901f5207b7SJohn Levon 		sparse_error(token->pos,
1911f5207b7SJohn Levon 			     "type expression should not include identifier "
1921f5207b7SJohn Levon 			     "\"%s\"", sym->ident->name);
1931f5207b7SJohn Levon 
1941f5207b7SJohn Levon 	if (!match_op(token, ','))
1951f5207b7SJohn Levon 		return expect(token, ',', "in __builtin_offset");
1961f5207b7SJohn Levon 
1971f5207b7SJohn Levon 	while (1) {
1981f5207b7SJohn Levon 		struct expression *e;
1991f5207b7SJohn Levon 		switch (op) {
2001f5207b7SJohn Levon 		case ')':
2011f5207b7SJohn Levon 			expr->in = sym;
2021f5207b7SJohn Levon 			*tree = expr;
2031f5207b7SJohn Levon 		default:
2041f5207b7SJohn Levon 			return expect(token, ')', "at end of __builtin_offset");
2051f5207b7SJohn Levon 		case SPECIAL_DEREFERENCE:
2061f5207b7SJohn Levon 			e = alloc_expression(token->pos, EXPR_OFFSETOF);
2071f5207b7SJohn Levon 			e->op = '[';
2081f5207b7SJohn Levon 			*p = e;
2091f5207b7SJohn Levon 			p = &e->down;
2101f5207b7SJohn Levon 			/* fall through */
2111f5207b7SJohn Levon 		case '.':
2121f5207b7SJohn Levon 			token = token->next;
2131f5207b7SJohn Levon 			e = alloc_expression(token->pos, EXPR_OFFSETOF);
2141f5207b7SJohn Levon 			e->op = '.';
2151f5207b7SJohn Levon 			if (token_type(token) != TOKEN_IDENT) {
2161f5207b7SJohn Levon 				sparse_error(token->pos, "Expected member name");
2171f5207b7SJohn Levon 				return token;
2181f5207b7SJohn Levon 			}
2191f5207b7SJohn Levon 			e->ident = token->ident;
2201f5207b7SJohn Levon 			token = token->next;
2211f5207b7SJohn Levon 			break;
2221f5207b7SJohn Levon 		case '[':
2231f5207b7SJohn Levon 			token = token->next;
2241f5207b7SJohn Levon 			e = alloc_expression(token->pos, EXPR_OFFSETOF);
2251f5207b7SJohn Levon 			e->op = '[';
2261f5207b7SJohn Levon 			token = parse_expression(token, &e->index);
2271f5207b7SJohn Levon 			token = expect(token, ']',
2281f5207b7SJohn Levon 					"at end of array dereference");
2291f5207b7SJohn Levon 			if (!e->index)
2301f5207b7SJohn Levon 				return token;
2311f5207b7SJohn Levon 		}
2321f5207b7SJohn Levon 		*p = e;
2331f5207b7SJohn Levon 		p = &e->down;
2341f5207b7SJohn Levon 		op = token_type(token) == TOKEN_SPECIAL ? token->special : 0;
2351f5207b7SJohn Levon 	}
2361f5207b7SJohn Levon }
2371f5207b7SJohn Levon 
2381f5207b7SJohn Levon #ifndef ULLONG_MAX
2391f5207b7SJohn Levon #define ULLONG_MAX (~0ULL)
2401f5207b7SJohn Levon #endif
2411f5207b7SJohn Levon 
parse_num(const char * nptr,char ** end)2421f5207b7SJohn Levon static unsigned long long parse_num(const char *nptr, char **end)
2431f5207b7SJohn Levon {
2441f5207b7SJohn Levon 	if (nptr[0] == '0' && tolower((unsigned char)nptr[1]) == 'b')
2451f5207b7SJohn Levon 		return strtoull(&nptr[2], end, 2);
2461f5207b7SJohn Levon 	return strtoull(nptr, end, 0);
2471f5207b7SJohn Levon }
2481f5207b7SJohn Levon 
get_number_value(struct expression * expr,struct token * token)2491f5207b7SJohn Levon static void get_number_value(struct expression *expr, struct token *token)
2501f5207b7SJohn Levon {
2511f5207b7SJohn Levon 	const char *str = token->number;
2521f5207b7SJohn Levon 	unsigned long long value;
2531f5207b7SJohn Levon 	char *end;
2541f5207b7SJohn Levon 	int size = 0, want_unsigned = 0;
2551f5207b7SJohn Levon 	int overflow = 0, do_warn = 0;
2561f5207b7SJohn Levon 	int try_unsigned = 1;
2571f5207b7SJohn Levon 	int bits;
2581f5207b7SJohn Levon 
2591f5207b7SJohn Levon 	errno = 0;
2601f5207b7SJohn Levon 	value = parse_num(str, &end);
2611f5207b7SJohn Levon 	if (end == str)
2621f5207b7SJohn Levon 		goto Float;
2631f5207b7SJohn Levon 	if (value == ULLONG_MAX && errno == ERANGE)
2641f5207b7SJohn Levon 		overflow = 1;
2651f5207b7SJohn Levon 	while (1) {
2661f5207b7SJohn Levon 		char c = *end++;
2671f5207b7SJohn Levon 		if (!c) {
2681f5207b7SJohn Levon 			break;
2691f5207b7SJohn Levon 		} else if (c == 'u' || c == 'U') {
2701f5207b7SJohn Levon 			if (want_unsigned)
2711f5207b7SJohn Levon 				goto Enoint;
2721f5207b7SJohn Levon 			want_unsigned = 1;
2731f5207b7SJohn Levon 		} else if (c == 'l' || c == 'L') {
2741f5207b7SJohn Levon 			if (size)
2751f5207b7SJohn Levon 				goto Enoint;
2761f5207b7SJohn Levon 			size = 1;
2771f5207b7SJohn Levon 			if (*end == c) {
2781f5207b7SJohn Levon 				size = 2;
2791f5207b7SJohn Levon 				end++;
2801f5207b7SJohn Levon 			}
2811f5207b7SJohn Levon 		} else
2821f5207b7SJohn Levon 			goto Float;
2831f5207b7SJohn Levon 	}
2841f5207b7SJohn Levon 	if (overflow)
2851f5207b7SJohn Levon 		goto Eoverflow;
2861f5207b7SJohn Levon 	/* OK, it's a valid integer */
2871f5207b7SJohn Levon 	/* decimals can be unsigned only if directly specified as such */
2881f5207b7SJohn Levon 	if (str[0] != '0' && !want_unsigned)
2891f5207b7SJohn Levon 		try_unsigned = 0;
2901f5207b7SJohn Levon 	if (!size) {
2911f5207b7SJohn Levon 		bits = bits_in_int - 1;
2921f5207b7SJohn Levon 		if (!(value & (~1ULL << bits))) {
2931f5207b7SJohn Levon 			if (!(value & (1ULL << bits))) {
2941f5207b7SJohn Levon 				goto got_it;
2951f5207b7SJohn Levon 			} else if (try_unsigned) {
2961f5207b7SJohn Levon 				want_unsigned = 1;
2971f5207b7SJohn Levon 				goto got_it;
2981f5207b7SJohn Levon 			}
2991f5207b7SJohn Levon 		}
3001f5207b7SJohn Levon 		size = 1;
3011f5207b7SJohn Levon 		do_warn = 1;
3021f5207b7SJohn Levon 	}
3031f5207b7SJohn Levon 	if (size < 2) {
3041f5207b7SJohn Levon 		bits = bits_in_long - 1;
3051f5207b7SJohn Levon 		if (!(value & (~1ULL << bits))) {
3061f5207b7SJohn Levon 			if (!(value & (1ULL << bits))) {
3071f5207b7SJohn Levon 				goto got_it;
3081f5207b7SJohn Levon 			} else if (try_unsigned) {
3091f5207b7SJohn Levon 				want_unsigned = 1;
3101f5207b7SJohn Levon 				goto got_it;
3111f5207b7SJohn Levon 			}
3121f5207b7SJohn Levon 			do_warn |= 2;
3131f5207b7SJohn Levon 		}
3141f5207b7SJohn Levon 		size = 2;
3151f5207b7SJohn Levon 		do_warn |= 1;
3161f5207b7SJohn Levon 	}
3171f5207b7SJohn Levon 	bits = bits_in_longlong - 1;
3181f5207b7SJohn Levon 	if (value & (~1ULL << bits))
3191f5207b7SJohn Levon 		goto Eoverflow;
3201f5207b7SJohn Levon 	if (!(value & (1ULL << bits)))
3211f5207b7SJohn Levon 		goto got_it;
3221f5207b7SJohn Levon 	if (!try_unsigned)
3231f5207b7SJohn Levon 		warning(expr->pos, "decimal constant %s is too big for long long",
3241f5207b7SJohn Levon 			show_token(token));
3251f5207b7SJohn Levon 	want_unsigned = 1;
3261f5207b7SJohn Levon got_it:
3271f5207b7SJohn Levon 	if (do_warn && Wconstant_suffix)
3281f5207b7SJohn Levon 		warning(expr->pos, "constant %s is so big it is%s%s%s",
3291f5207b7SJohn Levon 			show_token(token),
3301f5207b7SJohn Levon 			want_unsigned ? " unsigned":"",
3311f5207b7SJohn Levon 			size > 0 ? " long":"",
3321f5207b7SJohn Levon 			size > 1 ? " long":"");
3331f5207b7SJohn Levon 	if (do_warn & 2)
3341f5207b7SJohn Levon 		warning(expr->pos,
3351f5207b7SJohn Levon 			"decimal constant %s is between LONG_MAX and ULONG_MAX."
3361f5207b7SJohn Levon 			" For C99 that means long long, C90 compilers are very "
3371f5207b7SJohn Levon 			"likely to produce unsigned long (and a warning) here",
3381f5207b7SJohn Levon 			show_token(token));
3391f5207b7SJohn Levon         expr->type = EXPR_VALUE;
3401f5207b7SJohn Levon 	expr->flags = CEF_SET_INT;
3411f5207b7SJohn Levon         expr->ctype = ctype_integer(size, want_unsigned);
3421f5207b7SJohn Levon         expr->value = value;
3431f5207b7SJohn Levon 	return;
3441f5207b7SJohn Levon Eoverflow:
3451f5207b7SJohn Levon 	error_die(expr->pos, "constant %s is too big even for unsigned long long",
3461f5207b7SJohn Levon 			show_token(token));
3471f5207b7SJohn Levon 	return;
3481f5207b7SJohn Levon Float:
3491f5207b7SJohn Levon 	expr->fvalue = string_to_ld(str, &end);
3501f5207b7SJohn Levon 	if (str == end)
3511f5207b7SJohn Levon 		goto Enoint;
3521f5207b7SJohn Levon 
3531f5207b7SJohn Levon 	if (*end && end[1])
3541f5207b7SJohn Levon 		goto Enoint;
3551f5207b7SJohn Levon 
3561f5207b7SJohn Levon 	if (*end == 'f' || *end == 'F')
3571f5207b7SJohn Levon 		expr->ctype = &float_ctype;
3581f5207b7SJohn Levon 	else if (*end == 'l' || *end == 'L')
3591f5207b7SJohn Levon 		expr->ctype = &ldouble_ctype;
3601f5207b7SJohn Levon 	else if (!*end)
3611f5207b7SJohn Levon 		expr->ctype = &double_ctype;
3621f5207b7SJohn Levon 	else
3631f5207b7SJohn Levon 		goto Enoint;
3641f5207b7SJohn Levon 
3651f5207b7SJohn Levon 	expr->flags = CEF_SET_FLOAT;
3661f5207b7SJohn Levon 	expr->type = EXPR_FVALUE;
3671f5207b7SJohn Levon 	return;
3681f5207b7SJohn Levon 
3691f5207b7SJohn Levon Enoint:
3701f5207b7SJohn Levon 	error_die(expr->pos, "constant %s is not a valid number", show_token(token));
3711f5207b7SJohn Levon }
3721f5207b7SJohn Levon 
primary_expression(struct token * token,struct expression ** tree)3731f5207b7SJohn Levon struct token *primary_expression(struct token *token, struct expression **tree)
3741f5207b7SJohn Levon {
3751f5207b7SJohn Levon 	struct expression *expr = NULL;
3761f5207b7SJohn Levon 
3771f5207b7SJohn Levon 	switch (token_type(token)) {
3781f5207b7SJohn Levon 	case TOKEN_CHAR ... TOKEN_WIDE_CHAR_EMBEDDED_3:
3791f5207b7SJohn Levon 		expr = alloc_expression(token->pos, EXPR_VALUE);
3801f5207b7SJohn Levon 		expr->flags = CEF_SET_CHAR;
3811f5207b7SJohn Levon 		expr->ctype = token_type(token) < TOKEN_WIDE_CHAR ? &int_ctype : &long_ctype;
3821f5207b7SJohn Levon 		get_char_constant(token, &expr->value);
3831f5207b7SJohn Levon 		token = token->next;
3841f5207b7SJohn Levon 		break;
3851f5207b7SJohn Levon 
3861f5207b7SJohn Levon 	case TOKEN_NUMBER:
3871f5207b7SJohn Levon 		expr = alloc_expression(token->pos, EXPR_VALUE);
3881f5207b7SJohn Levon 		get_number_value(expr, token); /* will see if it's an integer */
3891f5207b7SJohn Levon 		token = token->next;
3901f5207b7SJohn Levon 		break;
3911f5207b7SJohn Levon 
3921f5207b7SJohn Levon 	case TOKEN_ZERO_IDENT: {
3931f5207b7SJohn Levon 		expr = alloc_expression(token->pos, EXPR_SYMBOL);
3941f5207b7SJohn Levon 		expr->flags = CEF_SET_INT;
3951f5207b7SJohn Levon 		expr->ctype = &int_ctype;
3961f5207b7SJohn Levon 		expr->symbol = &zero_int;
3971f5207b7SJohn Levon 		expr->symbol_name = token->ident;
3981f5207b7SJohn Levon 		token = token->next;
3991f5207b7SJohn Levon 		break;
4001f5207b7SJohn Levon 	}
4011f5207b7SJohn Levon 
4021f5207b7SJohn Levon 	case TOKEN_IDENT: {
4031f5207b7SJohn Levon 		struct symbol *sym = lookup_symbol(token->ident, NS_SYMBOL | NS_TYPEDEF);
4041f5207b7SJohn Levon 		struct token *next = token->next;
4051f5207b7SJohn Levon 
4061f5207b7SJohn Levon 		if (!sym) {
4071f5207b7SJohn Levon 			sym = handle_func(token);
4081f5207b7SJohn Levon 			if (token->ident == &__builtin_types_compatible_p_ident) {
4091f5207b7SJohn Levon 				token = builtin_types_compatible_p_expr(token, &expr);
4101f5207b7SJohn Levon 				break;
4111f5207b7SJohn Levon 			}
4121f5207b7SJohn Levon 			if (token->ident == &__builtin_offsetof_ident) {
4131f5207b7SJohn Levon 				token = builtin_offsetof_expr(token, &expr);
4141f5207b7SJohn Levon 				break;
4151f5207b7SJohn Levon 			}
4161f5207b7SJohn Levon 		} else if (sym->enum_member) {
4171f5207b7SJohn Levon 			expr = alloc_expression(token->pos, EXPR_VALUE);
4181f5207b7SJohn Levon 			*expr = *sym->initializer;
4191f5207b7SJohn Levon 			/* we want the right position reported, thus the copy */
4201f5207b7SJohn Levon 			expr->pos = token->pos;
4211f5207b7SJohn Levon 			expr->flags = CEF_SET_ENUM;
4221f5207b7SJohn Levon 			token = next;
4231f5207b7SJohn Levon 			break;
4241f5207b7SJohn Levon 		}
4251f5207b7SJohn Levon 
4261f5207b7SJohn Levon 		expr = alloc_expression(token->pos, EXPR_SYMBOL);
4271f5207b7SJohn Levon 
4281f5207b7SJohn Levon 		/*
4291f5207b7SJohn Levon 		 * We support types as real first-class citizens, with type
4301f5207b7SJohn Levon 		 * comparisons etc:
4311f5207b7SJohn Levon 		 *
4321f5207b7SJohn Levon 		 *	if (typeof(a) == int) ..
4331f5207b7SJohn Levon 		 */
4341f5207b7SJohn Levon 		if (sym && sym->namespace == NS_TYPEDEF) {
4351f5207b7SJohn Levon 			sparse_error(token->pos, "typename in expression");
4361f5207b7SJohn Levon 			sym = NULL;
4371f5207b7SJohn Levon 		}
4381f5207b7SJohn Levon 		expr->symbol_name = token->ident;
4391f5207b7SJohn Levon 		expr->symbol = sym;
4401f5207b7SJohn Levon 
4411f5207b7SJohn Levon 		/*
4421f5207b7SJohn Levon 		 * A pointer to an lvalue designating a static storage
4431f5207b7SJohn Levon 		 * duration object is an address constant [6.6(9)].
4441f5207b7SJohn Levon 		 */
4451f5207b7SJohn Levon 		if (sym && (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_STATIC)))
4461f5207b7SJohn Levon 			expr->flags = CEF_ADDR;
4471f5207b7SJohn Levon 
4481f5207b7SJohn Levon 		token = next;
4491f5207b7SJohn Levon 		break;
4501f5207b7SJohn Levon 	}
4511f5207b7SJohn Levon 
4521f5207b7SJohn Levon 	case TOKEN_STRING:
4531f5207b7SJohn Levon 	case TOKEN_WIDE_STRING:
4541f5207b7SJohn Levon 		expr = alloc_expression(token->pos, EXPR_STRING);
4551f5207b7SJohn Levon 		token = get_string_constant(token, expr);
4561f5207b7SJohn Levon 		break;
4571f5207b7SJohn Levon 
4581f5207b7SJohn Levon 	case TOKEN_SPECIAL:
4591f5207b7SJohn Levon 		if (token->special == '(') {
4601f5207b7SJohn Levon 			expr = alloc_expression(token->pos, EXPR_PREOP);
4611f5207b7SJohn Levon 			expr->op = '(';
4621f5207b7SJohn Levon 			token = parens_expression(token, &expr->unop, "in expression");
4631f5207b7SJohn Levon 			break;
4641f5207b7SJohn Levon 		}
4651f5207b7SJohn Levon 		if (token->special == '[' && lookup_type(token->next)) {
4661f5207b7SJohn Levon 			expr = alloc_expression(token->pos, EXPR_TYPE);
4671f5207b7SJohn Levon 			token = typename(token->next, &expr->symbol, NULL);
4681f5207b7SJohn Levon 			token = expect(token, ']', "in type expression");
4691f5207b7SJohn Levon 			break;
4701f5207b7SJohn Levon 		}
4711f5207b7SJohn Levon 
4721f5207b7SJohn Levon 	default:
4731f5207b7SJohn Levon 		;
4741f5207b7SJohn Levon 	}
4751f5207b7SJohn Levon 	*tree = expr;
4761f5207b7SJohn Levon 	return token;
4771f5207b7SJohn Levon }
4781f5207b7SJohn Levon 
expression_list(struct token * token,struct expression_list ** list)4791f5207b7SJohn Levon static struct token *expression_list(struct token *token, struct expression_list **list)
4801f5207b7SJohn Levon {
4811f5207b7SJohn Levon 	while (!match_op(token, ')')) {
4821f5207b7SJohn Levon 		struct expression *expr = NULL;
4831f5207b7SJohn Levon 		token = assignment_expression(token, &expr);
4841f5207b7SJohn Levon 		if (!expr)
4851f5207b7SJohn Levon 			break;
4861f5207b7SJohn Levon 		add_expression(list, expr);
4871f5207b7SJohn Levon 		if (!match_op(token, ','))
4881f5207b7SJohn Levon 			break;
4891f5207b7SJohn Levon 		token = token->next;
4901f5207b7SJohn Levon 	}
4911f5207b7SJohn Levon 	return token;
4921f5207b7SJohn Levon }
4931f5207b7SJohn Levon 
4941f5207b7SJohn Levon /*
4951f5207b7SJohn Levon  * extend to deal with the ambiguous C grammar for parsing
4961f5207b7SJohn Levon  * a cast expressions followed by an initializer.
4971f5207b7SJohn Levon  */
postfix_expression(struct token * token,struct expression ** tree,struct expression * cast_init_expr)4981f5207b7SJohn Levon static struct token *postfix_expression(struct token *token, struct expression **tree, struct expression *cast_init_expr)
4991f5207b7SJohn Levon {
5001f5207b7SJohn Levon 	struct expression *expr = cast_init_expr;
5011f5207b7SJohn Levon 
5021f5207b7SJohn Levon 	if (!expr)
5031f5207b7SJohn Levon 		token = primary_expression(token, &expr);
5041f5207b7SJohn Levon 
5051f5207b7SJohn Levon 	while (expr && token_type(token) == TOKEN_SPECIAL) {
5061f5207b7SJohn Levon 		switch (token->special) {
5071f5207b7SJohn Levon 		case '[': {			/* Array dereference */
5081f5207b7SJohn Levon 			struct expression *deref = alloc_expression(token->pos, EXPR_PREOP);
5091f5207b7SJohn Levon 			struct expression *add = alloc_expression(token->pos, EXPR_BINOP);
5101f5207b7SJohn Levon 
5111f5207b7SJohn Levon 			deref->op = '*';
5121f5207b7SJohn Levon 			deref->unop = add;
5131f5207b7SJohn Levon 
5141f5207b7SJohn Levon 			add->op = '+';
5151f5207b7SJohn Levon 			add->left = expr;
5161f5207b7SJohn Levon 			token = parse_expression(token->next, &add->right);
5171f5207b7SJohn Levon 			token = expect(token, ']', "at end of array dereference");
5181f5207b7SJohn Levon 			expr = deref;
5191f5207b7SJohn Levon 			continue;
5201f5207b7SJohn Levon 		}
5211f5207b7SJohn Levon 		case SPECIAL_INCREMENT:		/* Post-increment */
5221f5207b7SJohn Levon 		case SPECIAL_DECREMENT:	{	/* Post-decrement */
5231f5207b7SJohn Levon 			struct expression *post = alloc_expression(token->pos, EXPR_POSTOP);
5241f5207b7SJohn Levon 			post->op = token->special;
5251f5207b7SJohn Levon 			post->unop = expr;
5261f5207b7SJohn Levon 			expr = post;
5271f5207b7SJohn Levon 			token = token->next;
5281f5207b7SJohn Levon 			continue;
5291f5207b7SJohn Levon 		}
5301f5207b7SJohn Levon 		case SPECIAL_DEREFERENCE: {	/* Structure pointer member dereference */
5311f5207b7SJohn Levon 			/* "x->y" is just shorthand for "(*x).y" */
5321f5207b7SJohn Levon 			struct expression *inner = alloc_expression(token->pos, EXPR_PREOP);
5331f5207b7SJohn Levon 			inner->op = '*';
5341f5207b7SJohn Levon 			inner->unop = expr;
5351f5207b7SJohn Levon 			expr = inner;
5361f5207b7SJohn Levon 		}
5371f5207b7SJohn Levon 		/* Fall through!! */
5381f5207b7SJohn Levon 		case '.': {			/* Structure member dereference */
5391f5207b7SJohn Levon 			struct expression *deref = alloc_expression(token->pos, EXPR_DEREF);
5401f5207b7SJohn Levon 			deref->op = '.';
5411f5207b7SJohn Levon 			deref->deref = expr;
5421f5207b7SJohn Levon 			token = token->next;
5431f5207b7SJohn Levon 			if (token_type(token) != TOKEN_IDENT) {
5441f5207b7SJohn Levon 				sparse_error(token->pos, "Expected member name");
5451f5207b7SJohn Levon 				break;
5461f5207b7SJohn Levon 			}
5471f5207b7SJohn Levon 			deref->member = token->ident;
5481f5207b7SJohn Levon 			deref->member_offset = -1;
5491f5207b7SJohn Levon 			token = token->next;
5501f5207b7SJohn Levon 			expr = deref;
5511f5207b7SJohn Levon 			continue;
5521f5207b7SJohn Levon 		}
5531f5207b7SJohn Levon 
5541f5207b7SJohn Levon 		case '(': {			/* Function call */
5551f5207b7SJohn Levon 			struct expression *call = alloc_expression(token->pos, EXPR_CALL);
5561f5207b7SJohn Levon 			call->op = '(';
5571f5207b7SJohn Levon 			call->fn = expr;
5581f5207b7SJohn Levon 			token = expression_list(token->next, &call->args);
5591f5207b7SJohn Levon 			token = expect(token, ')', "in function call");
5601f5207b7SJohn Levon 			expr = call;
5611f5207b7SJohn Levon 			continue;
5621f5207b7SJohn Levon 		}
5631f5207b7SJohn Levon 
5641f5207b7SJohn Levon 		default:
5651f5207b7SJohn Levon 			break;
5661f5207b7SJohn Levon 		}
5671f5207b7SJohn Levon 		break;
5681f5207b7SJohn Levon 	}
5691f5207b7SJohn Levon 	*tree = expr;
5701f5207b7SJohn Levon 	return token;
5711f5207b7SJohn Levon }
5721f5207b7SJohn Levon 
5731f5207b7SJohn Levon static struct token *cast_expression(struct token *token, struct expression **tree);
5741f5207b7SJohn Levon static struct token *unary_expression(struct token *token, struct expression **tree);
5751f5207b7SJohn Levon 
type_info_expression(struct token * token,struct expression ** tree,int type)5761f5207b7SJohn Levon static struct token *type_info_expression(struct token *token,
5771f5207b7SJohn Levon 	struct expression **tree, int type)
5781f5207b7SJohn Levon {
5791f5207b7SJohn Levon 	struct expression *expr = alloc_expression(token->pos, type);
5801f5207b7SJohn Levon 	struct token *p;
5811f5207b7SJohn Levon 
5821f5207b7SJohn Levon 	*tree = expr;
5831f5207b7SJohn Levon 	expr->flags = CEF_SET_ICE; /* XXX: VLA support will need that changed */
5841f5207b7SJohn Levon 	token = token->next;
5851f5207b7SJohn Levon 	if (!match_op(token, '(') || !lookup_type(token->next))
5861f5207b7SJohn Levon 		return unary_expression(token, &expr->cast_expression);
5871f5207b7SJohn Levon 	p = token;
5881f5207b7SJohn Levon 	token = typename(token->next, &expr->cast_type, NULL);
5891f5207b7SJohn Levon 
5901f5207b7SJohn Levon 	if (!match_op(token, ')')) {
5911f5207b7SJohn Levon 		static const char * error[] = {
5921f5207b7SJohn Levon 			[EXPR_SIZEOF] = "at end of sizeof",
5931f5207b7SJohn Levon 			[EXPR_ALIGNOF] = "at end of __alignof__",
5941f5207b7SJohn Levon 			[EXPR_PTRSIZEOF] = "at end of __sizeof_ptr__"
5951f5207b7SJohn Levon 		};
5961f5207b7SJohn Levon 		return expect(token, ')', error[type]);
5971f5207b7SJohn Levon 	}
5981f5207b7SJohn Levon 
5991f5207b7SJohn Levon 	token = token->next;
6001f5207b7SJohn Levon 	/*
6011f5207b7SJohn Levon 	 * C99 ambiguity: the typename might have been the beginning
6021f5207b7SJohn Levon 	 * of a typed initializer expression..
6031f5207b7SJohn Levon 	 */
6041f5207b7SJohn Levon 	if (match_op(token, '{')) {
6051f5207b7SJohn Levon 		struct expression *cast = alloc_expression(p->pos, EXPR_CAST);
6061f5207b7SJohn Levon 		cast->cast_type = expr->cast_type;
6071f5207b7SJohn Levon 		expr->cast_type = NULL;
6081f5207b7SJohn Levon 		expr->cast_expression = cast;
6091f5207b7SJohn Levon 		token = initializer(&cast->cast_expression, token);
6101f5207b7SJohn Levon 		token = postfix_expression(token, &expr->cast_expression, cast);
6111f5207b7SJohn Levon 	}
6121f5207b7SJohn Levon 	return token;
6131f5207b7SJohn Levon }
6141f5207b7SJohn Levon 
unary_expression(struct token * token,struct expression ** tree)6151f5207b7SJohn Levon static struct token *unary_expression(struct token *token, struct expression **tree)
6161f5207b7SJohn Levon {
6171f5207b7SJohn Levon 	if (token_type(token) == TOKEN_IDENT) {
6181f5207b7SJohn Levon 		struct ident *ident = token->ident;
6191f5207b7SJohn Levon 		if (ident->reserved) {
6201f5207b7SJohn Levon 			static const struct {
6211f5207b7SJohn Levon 				struct ident *id;
6221f5207b7SJohn Levon 				int type;
6231f5207b7SJohn Levon 			} type_information[] = {
6241f5207b7SJohn Levon 				{ &sizeof_ident, EXPR_SIZEOF },
6251f5207b7SJohn Levon 				{ &__alignof___ident, EXPR_ALIGNOF },
6261f5207b7SJohn Levon 				{ &__alignof_ident, EXPR_ALIGNOF },
6271f5207b7SJohn Levon 				{ &_Alignof_ident, EXPR_ALIGNOF },
6281f5207b7SJohn Levon 				{ &__sizeof_ptr___ident, EXPR_PTRSIZEOF },
6291f5207b7SJohn Levon 			};
6301f5207b7SJohn Levon 			int i;
6311f5207b7SJohn Levon 			for (i = 0; i < ARRAY_SIZE(type_information); i++) {
6321f5207b7SJohn Levon 				if (ident == type_information[i].id)
6331f5207b7SJohn Levon 					return type_info_expression(token, tree, type_information[i].type);
6341f5207b7SJohn Levon 			}
6351f5207b7SJohn Levon 		}
6361f5207b7SJohn Levon 	}
6371f5207b7SJohn Levon 
6381f5207b7SJohn Levon 	if (token_type(token) == TOKEN_SPECIAL) {
6391f5207b7SJohn Levon 		if (match_oplist(token->special,
6401f5207b7SJohn Levon 		    SPECIAL_INCREMENT, SPECIAL_DECREMENT,
6411f5207b7SJohn Levon 		    '&', '*', 0)) {
6421f5207b7SJohn Levon 		    	struct expression *unop;
6431f5207b7SJohn Levon 			struct expression *unary;
6441f5207b7SJohn Levon 			struct token *next;
6451f5207b7SJohn Levon 
6461f5207b7SJohn Levon 			next = cast_expression(token->next, &unop);
6471f5207b7SJohn Levon 			if (!unop) {
6481f5207b7SJohn Levon 				sparse_error(token->pos, "Syntax error in unary expression");
6491f5207b7SJohn Levon 				*tree = NULL;
6501f5207b7SJohn Levon 				return next;
6511f5207b7SJohn Levon 			}
6521f5207b7SJohn Levon 			unary = alloc_expression(token->pos, EXPR_PREOP);
6531f5207b7SJohn Levon 			unary->op = token->special;
6541f5207b7SJohn Levon 			unary->unop = unop;
6551f5207b7SJohn Levon 			*tree = unary;
6561f5207b7SJohn Levon 			return next;
6571f5207b7SJohn Levon 		}
6581f5207b7SJohn Levon 		/* possibly constant ones */
6591f5207b7SJohn Levon 		if (match_oplist(token->special, '+', '-', '~', '!', 0)) {
6601f5207b7SJohn Levon 		    	struct expression *unop;
6611f5207b7SJohn Levon 			struct expression *unary;
6621f5207b7SJohn Levon 			struct token *next;
6631f5207b7SJohn Levon 
6641f5207b7SJohn Levon 			next = cast_expression(token->next, &unop);
6651f5207b7SJohn Levon 			if (!unop) {
6661f5207b7SJohn Levon 				sparse_error(token->pos, "Syntax error in unary expression");
6671f5207b7SJohn Levon 				*tree = NULL;
6681f5207b7SJohn Levon 				return next;
6691f5207b7SJohn Levon 			}
6701f5207b7SJohn Levon 			unary = alloc_expression(token->pos, EXPR_PREOP);
6711f5207b7SJohn Levon 			unary->op = token->special;
6721f5207b7SJohn Levon 			unary->unop = unop;
6731f5207b7SJohn Levon 			*tree = unary;
6741f5207b7SJohn Levon 			return next;
6751f5207b7SJohn Levon 		}
6761f5207b7SJohn Levon 		/* Gcc extension: &&label gives the address of a label */
6771f5207b7SJohn Levon 		if (match_op(token, SPECIAL_LOGICAL_AND) &&
6781f5207b7SJohn Levon 		    token_type(token->next) == TOKEN_IDENT) {
6791f5207b7SJohn Levon 			struct expression *label = alloc_expression(token->pos, EXPR_LABEL);
6801f5207b7SJohn Levon 			struct symbol *sym = label_symbol(token->next);
6811f5207b7SJohn Levon 			if (!(sym->ctype.modifiers & MOD_ADDRESSABLE)) {
6821f5207b7SJohn Levon 				sym->ctype.modifiers |= MOD_ADDRESSABLE;
6831f5207b7SJohn Levon 				add_symbol(&function_computed_target_list, sym);
6841f5207b7SJohn Levon 			}
6851f5207b7SJohn Levon 			label->flags = CEF_ADDR;
6861f5207b7SJohn Levon 			label->label_symbol = sym;
6871f5207b7SJohn Levon 			*tree = label;
6881f5207b7SJohn Levon 			return token->next->next;
6891f5207b7SJohn Levon 		}
6901f5207b7SJohn Levon 
6911f5207b7SJohn Levon 	}
6921f5207b7SJohn Levon 
6931f5207b7SJohn Levon 	return postfix_expression(token, tree, NULL);
6941f5207b7SJohn Levon }
6951f5207b7SJohn Levon 
6961f5207b7SJohn Levon /*
6971f5207b7SJohn Levon  * Ambiguity: a '(' can be either a cast-expression or
6981f5207b7SJohn Levon  * a primary-expression depending on whether it is followed
6991f5207b7SJohn Levon  * by a type or not.
7001f5207b7SJohn Levon  *
7011f5207b7SJohn Levon  * additional ambiguity: a "cast expression" followed by
7021f5207b7SJohn Levon  * an initializer is really a postfix-expression.
7031f5207b7SJohn Levon  */
cast_expression(struct token * token,struct expression ** tree)7041f5207b7SJohn Levon static struct token *cast_expression(struct token *token, struct expression **tree)
7051f5207b7SJohn Levon {
7061f5207b7SJohn Levon 	if (match_op(token, '(')) {
7071f5207b7SJohn Levon 		struct token *next = token->next;
7081f5207b7SJohn Levon 		if (lookup_type(next)) {
7091f5207b7SJohn Levon 			struct expression *cast = alloc_expression(next->pos, EXPR_CAST);
7101f5207b7SJohn Levon 			struct expression *v;
7111f5207b7SJohn Levon 			struct symbol *sym;
7121f5207b7SJohn Levon 			int is_force;
7131f5207b7SJohn Levon 
7141f5207b7SJohn Levon 			token = typename(next, &sym, &is_force);
7151f5207b7SJohn Levon 			cast->cast_type = sym;
7161f5207b7SJohn Levon 			token = expect(token, ')', "at end of cast operator");
7171f5207b7SJohn Levon 			if (match_op(token, '{')) {
7181f5207b7SJohn Levon 				if (toplevel(block_scope))
7191f5207b7SJohn Levon 					sym->ctype.modifiers |= MOD_TOPLEVEL;
7201f5207b7SJohn Levon 				if (is_force)
7211f5207b7SJohn Levon 					warning(sym->pos,
7221f5207b7SJohn Levon 						"[force] in compound literal");
7231f5207b7SJohn Levon 				token = initializer(&cast->cast_expression, token);
7241f5207b7SJohn Levon 				return postfix_expression(token, tree, cast);
7251f5207b7SJohn Levon 			}
7261f5207b7SJohn Levon 			*tree = cast;
7271f5207b7SJohn Levon 			if (is_force)
7281f5207b7SJohn Levon 				cast->type = EXPR_FORCE_CAST;
7291f5207b7SJohn Levon 			token = cast_expression(token, &v);
7301f5207b7SJohn Levon 			if (!v)
7311f5207b7SJohn Levon 				return token;
7321f5207b7SJohn Levon 			cast->cast_expression = v;
7331f5207b7SJohn Levon 			return token;
7341f5207b7SJohn Levon 		}
7351f5207b7SJohn Levon 	}
7361f5207b7SJohn Levon 	return unary_expression(token, tree);
7371f5207b7SJohn Levon }
7381f5207b7SJohn Levon 
7391f5207b7SJohn Levon /*
7401f5207b7SJohn Levon  * Generic left-to-right binop parsing
7411f5207b7SJohn Levon  *
7421f5207b7SJohn Levon  * This _really_ needs to be inlined, because that makes the inner
7431f5207b7SJohn Levon  * function call statically deterministic rather than a totally
7441f5207b7SJohn Levon  * unpredictable indirect call. But gcc-3 is so "clever" that it
7451f5207b7SJohn Levon  * doesn't do so by default even when you tell it to inline it.
7461f5207b7SJohn Levon  *
7471f5207b7SJohn Levon  * Making it a macro avoids the inlining problem, and also means
7481f5207b7SJohn Levon  * that we can pass in the op-comparison as an expression rather
7491f5207b7SJohn Levon  * than create a data structure for it.
7501f5207b7SJohn Levon  */
7511f5207b7SJohn Levon 
7521f5207b7SJohn Levon #define LR_BINOP_EXPRESSION(__token, tree, type, inner, compare)	\
7531f5207b7SJohn Levon 	struct expression *left = NULL;					\
7541f5207b7SJohn Levon 	struct token * next = inner(__token, &left);			\
7551f5207b7SJohn Levon 									\
7561f5207b7SJohn Levon 	if (left) {							\
7571f5207b7SJohn Levon 		while (token_type(next) == TOKEN_SPECIAL) {		\
7581f5207b7SJohn Levon 			struct expression *top, *right = NULL;		\
7591f5207b7SJohn Levon 			int op = next->special;				\
7601f5207b7SJohn Levon 									\
7611f5207b7SJohn Levon 			if (!(compare))					\
7621f5207b7SJohn Levon 				goto out;				\
7631f5207b7SJohn Levon 			top = alloc_expression(next->pos, type);	\
7641f5207b7SJohn Levon 			next = inner(next->next, &right);		\
7651f5207b7SJohn Levon 			if (!right) {					\
7661f5207b7SJohn Levon 				sparse_error(next->pos, "No right hand side of '%s'-expression", show_special(op));	\
7671f5207b7SJohn Levon 				break;					\
7681f5207b7SJohn Levon 			}						\
7691f5207b7SJohn Levon 			top->op = op;					\
7701f5207b7SJohn Levon 			top->left = left;				\
7711f5207b7SJohn Levon 			top->right = right;				\
7721f5207b7SJohn Levon 			left = top;					\
7731f5207b7SJohn Levon 		}							\
7741f5207b7SJohn Levon 	}								\
7751f5207b7SJohn Levon out:									\
7761f5207b7SJohn Levon 	*tree = left;							\
7771f5207b7SJohn Levon 	return next;							\
7781f5207b7SJohn Levon 
multiplicative_expression(struct token * token,struct expression ** tree)7791f5207b7SJohn Levon static struct token *multiplicative_expression(struct token *token, struct expression **tree)
7801f5207b7SJohn Levon {
7811f5207b7SJohn Levon 	LR_BINOP_EXPRESSION(
7821f5207b7SJohn Levon 		token, tree, EXPR_BINOP, cast_expression,
7831f5207b7SJohn Levon 		(op == '*') || (op == '/') || (op == '%')
7841f5207b7SJohn Levon 	);
7851f5207b7SJohn Levon }
7861f5207b7SJohn Levon 
additive_expression(struct token * token,struct expression ** tree)7871f5207b7SJohn Levon static struct token *additive_expression(struct token *token, struct expression **tree)
7881f5207b7SJohn Levon {
7891f5207b7SJohn Levon 	LR_BINOP_EXPRESSION(
7901f5207b7SJohn Levon 		token, tree, EXPR_BINOP, multiplicative_expression,
7911f5207b7SJohn Levon 		(op == '+') || (op == '-')
7921f5207b7SJohn Levon 	);
7931f5207b7SJohn Levon }
7941f5207b7SJohn Levon 
shift_expression(struct token * token,struct expression ** tree)7951f5207b7SJohn Levon static struct token *shift_expression(struct token *token, struct expression **tree)
7961f5207b7SJohn Levon {
7971f5207b7SJohn Levon 	LR_BINOP_EXPRESSION(
7981f5207b7SJohn Levon 		token, tree, EXPR_BINOP, additive_expression,
7991f5207b7SJohn Levon 		(op == SPECIAL_LEFTSHIFT) || (op == SPECIAL_RIGHTSHIFT)
8001f5207b7SJohn Levon 	);
8011f5207b7SJohn Levon }
8021f5207b7SJohn Levon 
relational_expression(struct token * token,struct expression ** tree)8031f5207b7SJohn Levon static struct token *relational_expression(struct token *token, struct expression **tree)
8041f5207b7SJohn Levon {
8051f5207b7SJohn Levon 	LR_BINOP_EXPRESSION(
8061f5207b7SJohn Levon 		token, tree, EXPR_COMPARE, shift_expression,
8071f5207b7SJohn Levon 		(op == '<') || (op == '>') ||
8081f5207b7SJohn Levon 		(op == SPECIAL_LTE) || (op == SPECIAL_GTE)
8091f5207b7SJohn Levon 	);
8101f5207b7SJohn Levon }
8111f5207b7SJohn Levon 
equality_expression(struct token * token,struct expression ** tree)8121f5207b7SJohn Levon static struct token *equality_expression(struct token *token, struct expression **tree)
8131f5207b7SJohn Levon {
8141f5207b7SJohn Levon 	LR_BINOP_EXPRESSION(
8151f5207b7SJohn Levon 		token, tree, EXPR_COMPARE, relational_expression,
8161f5207b7SJohn Levon 		(op == SPECIAL_EQUAL) || (op == SPECIAL_NOTEQUAL)
8171f5207b7SJohn Levon 	);
8181f5207b7SJohn Levon }
8191f5207b7SJohn Levon 
bitwise_and_expression(struct token * token,struct expression ** tree)8201f5207b7SJohn Levon static struct token *bitwise_and_expression(struct token *token, struct expression **tree)
8211f5207b7SJohn Levon {
8221f5207b7SJohn Levon 	LR_BINOP_EXPRESSION(
8231f5207b7SJohn Levon 		token, tree, EXPR_BINOP, equality_expression,
8241f5207b7SJohn Levon 		(op == '&')
8251f5207b7SJohn Levon 	);
8261f5207b7SJohn Levon }
8271f5207b7SJohn Levon 
bitwise_xor_expression(struct token * token,struct expression ** tree)8281f5207b7SJohn Levon static struct token *bitwise_xor_expression(struct token *token, struct expression **tree)
8291f5207b7SJohn Levon {
8301f5207b7SJohn Levon 	LR_BINOP_EXPRESSION(
8311f5207b7SJohn Levon 		token, tree, EXPR_BINOP, bitwise_and_expression,
8321f5207b7SJohn Levon 		(op == '^')
8331f5207b7SJohn Levon 	);
8341f5207b7SJohn Levon }
8351f5207b7SJohn Levon 
bitwise_or_expression(struct token * token,struct expression ** tree)8361f5207b7SJohn Levon static struct token *bitwise_or_expression(struct token *token, struct expression **tree)
8371f5207b7SJohn Levon {
8381f5207b7SJohn Levon 	LR_BINOP_EXPRESSION(
8391f5207b7SJohn Levon 		token, tree, EXPR_BINOP, bitwise_xor_expression,
8401f5207b7SJohn Levon 		(op == '|')
8411f5207b7SJohn Levon 	);
8421f5207b7SJohn Levon }
8431f5207b7SJohn Levon 
logical_and_expression(struct token * token,struct expression ** tree)8441f5207b7SJohn Levon static struct token *logical_and_expression(struct token *token, struct expression **tree)
8451f5207b7SJohn Levon {
8461f5207b7SJohn Levon 	LR_BINOP_EXPRESSION(
8471f5207b7SJohn Levon 		token, tree, EXPR_LOGICAL, bitwise_or_expression,
8481f5207b7SJohn Levon 		(op == SPECIAL_LOGICAL_AND)
8491f5207b7SJohn Levon 	);
8501f5207b7SJohn Levon }
8511f5207b7SJohn Levon 
logical_or_expression(struct token * token,struct expression ** tree)8521f5207b7SJohn Levon static struct token *logical_or_expression(struct token *token, struct expression **tree)
8531f5207b7SJohn Levon {
8541f5207b7SJohn Levon 	LR_BINOP_EXPRESSION(
8551f5207b7SJohn Levon 		token, tree, EXPR_LOGICAL, logical_and_expression,
8561f5207b7SJohn Levon 		(op == SPECIAL_LOGICAL_OR)
8571f5207b7SJohn Levon 	);
8581f5207b7SJohn Levon }
8591f5207b7SJohn Levon 
conditional_expression(struct token * token,struct expression ** tree)8601f5207b7SJohn Levon struct token *conditional_expression(struct token *token, struct expression **tree)
8611f5207b7SJohn Levon {
8621f5207b7SJohn Levon 	token = logical_or_expression(token, tree);
8631f5207b7SJohn Levon 	if (*tree && match_op(token, '?')) {
8641f5207b7SJohn Levon 		struct expression *expr = alloc_expression(token->pos, EXPR_CONDITIONAL);
8651f5207b7SJohn Levon 		expr->op = token->special;
8661f5207b7SJohn Levon 		expr->left = *tree;
8671f5207b7SJohn Levon 		*tree = expr;
8681f5207b7SJohn Levon 		token = parse_expression(token->next, &expr->cond_true);
8691f5207b7SJohn Levon 		token = expect(token, ':', "in conditional expression");
8701f5207b7SJohn Levon 		token = conditional_expression(token, &expr->cond_false);
8711f5207b7SJohn Levon 	}
8721f5207b7SJohn Levon 	return token;
8731f5207b7SJohn Levon }
8741f5207b7SJohn Levon 
assignment_expression(struct token * token,struct expression ** tree)8751f5207b7SJohn Levon struct token *assignment_expression(struct token *token, struct expression **tree)
8761f5207b7SJohn Levon {
8771f5207b7SJohn Levon 	token = conditional_expression(token, tree);
8781f5207b7SJohn Levon 	if (*tree && token_type(token) == TOKEN_SPECIAL) {
8791f5207b7SJohn Levon 		static const int assignments[] = {
8801f5207b7SJohn Levon 			'=',
8811f5207b7SJohn Levon 			SPECIAL_ADD_ASSIGN, SPECIAL_SUB_ASSIGN,
8821f5207b7SJohn Levon 			SPECIAL_MUL_ASSIGN, SPECIAL_DIV_ASSIGN,
8831f5207b7SJohn Levon 			SPECIAL_MOD_ASSIGN, SPECIAL_SHL_ASSIGN,
8841f5207b7SJohn Levon 			SPECIAL_SHR_ASSIGN, SPECIAL_AND_ASSIGN,
8851f5207b7SJohn Levon 			SPECIAL_OR_ASSIGN,  SPECIAL_XOR_ASSIGN };
8861f5207b7SJohn Levon 		int i, op = token->special;
8871f5207b7SJohn Levon 		for (i = 0; i < ARRAY_SIZE(assignments); i++)
8881f5207b7SJohn Levon 			if (assignments[i] == op) {
8891f5207b7SJohn Levon 				struct expression * expr = alloc_expression(token->pos, EXPR_ASSIGNMENT);
8901f5207b7SJohn Levon 				expr->left = *tree;
8911f5207b7SJohn Levon 				expr->op = op;
8921f5207b7SJohn Levon 				*tree = expr;
8931f5207b7SJohn Levon 				return assignment_expression(token->next, &expr->right);
8941f5207b7SJohn Levon 			}
8951f5207b7SJohn Levon 	}
8961f5207b7SJohn Levon 	return token;
8971f5207b7SJohn Levon }
8981f5207b7SJohn Levon 
comma_expression(struct token * token,struct expression ** tree)8991f5207b7SJohn Levon static struct token *comma_expression(struct token *token, struct expression **tree)
9001f5207b7SJohn Levon {
9011f5207b7SJohn Levon 	LR_BINOP_EXPRESSION(
9021f5207b7SJohn Levon 		token, tree, EXPR_COMMA, assignment_expression,
9031f5207b7SJohn Levon 		(op == ',')
9041f5207b7SJohn Levon 	);
9051f5207b7SJohn Levon }
9061f5207b7SJohn Levon 
parse_expression(struct token * token,struct expression ** tree)9071f5207b7SJohn Levon struct token *parse_expression(struct token *token, struct expression **tree)
9081f5207b7SJohn Levon {
9091f5207b7SJohn Levon 	return comma_expression(token,tree);
9101f5207b7SJohn Levon }
9111f5207b7SJohn Levon 
9121f5207b7SJohn Levon 
913