1404b540aSrobert /* Parse C expressions for cpplib.
2404b540aSrobert Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
3404b540aSrobert 2002, 2004 Free Software Foundation.
4404b540aSrobert Contributed by Per Bothner, 1994.
5404b540aSrobert
6404b540aSrobert This program is free software; you can redistribute it and/or modify it
7404b540aSrobert under the terms of the GNU General Public License as published by the
8404b540aSrobert Free Software Foundation; either version 2, or (at your option) any
9404b540aSrobert later version.
10404b540aSrobert
11404b540aSrobert This program is distributed in the hope that it will be useful,
12404b540aSrobert but WITHOUT ANY WARRANTY; without even the implied warranty of
13404b540aSrobert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14404b540aSrobert GNU General Public License for more details.
15404b540aSrobert
16404b540aSrobert You should have received a copy of the GNU General Public License
17404b540aSrobert along with this program; if not, write to the Free Software
18404b540aSrobert Foundation, 51 Franklin Street, Fifth Floor,
19404b540aSrobert Boston, MA 02110-1301, USA. */
20404b540aSrobert
21404b540aSrobert #include "config.h"
22404b540aSrobert #include "system.h"
23404b540aSrobert #include "cpplib.h"
24404b540aSrobert #include "internal.h"
25404b540aSrobert
26404b540aSrobert #define PART_PRECISION (sizeof (cpp_num_part) * CHAR_BIT)
27404b540aSrobert #define HALF_MASK (~(cpp_num_part) 0 >> (PART_PRECISION / 2))
28404b540aSrobert #define LOW_PART(num_part) (num_part & HALF_MASK)
29404b540aSrobert #define HIGH_PART(num_part) (num_part >> (PART_PRECISION / 2))
30404b540aSrobert
31404b540aSrobert struct op
32404b540aSrobert {
33404b540aSrobert const cpp_token *token; /* The token forming op (for diagnostics). */
34404b540aSrobert cpp_num value; /* The value logically "right" of op. */
35404b540aSrobert enum cpp_ttype op;
36404b540aSrobert };
37404b540aSrobert
38404b540aSrobert /* Some simple utility routines on double integers. */
39404b540aSrobert #define num_zerop(num) ((num.low | num.high) == 0)
40404b540aSrobert #define num_eq(num1, num2) (num1.low == num2.low && num1.high == num2.high)
41404b540aSrobert static bool num_positive (cpp_num, size_t);
42404b540aSrobert static bool num_greater_eq (cpp_num, cpp_num, size_t);
43404b540aSrobert static cpp_num num_trim (cpp_num, size_t);
44404b540aSrobert static cpp_num num_part_mul (cpp_num_part, cpp_num_part);
45404b540aSrobert
46404b540aSrobert static cpp_num num_unary_op (cpp_reader *, cpp_num, enum cpp_ttype);
47404b540aSrobert static cpp_num num_binary_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype);
48404b540aSrobert static cpp_num num_negate (cpp_num, size_t);
49404b540aSrobert static cpp_num num_bitwise_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype);
50404b540aSrobert static cpp_num num_inequality_op (cpp_reader *, cpp_num, cpp_num,
51404b540aSrobert enum cpp_ttype);
52404b540aSrobert static cpp_num num_equality_op (cpp_reader *, cpp_num, cpp_num,
53404b540aSrobert enum cpp_ttype);
54404b540aSrobert static cpp_num num_mul (cpp_reader *, cpp_num, cpp_num);
55404b540aSrobert static cpp_num num_div_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype);
56404b540aSrobert static cpp_num num_lshift (cpp_num, size_t, size_t);
57404b540aSrobert static cpp_num num_rshift (cpp_num, size_t, size_t);
58404b540aSrobert
59404b540aSrobert static cpp_num append_digit (cpp_num, int, int, size_t);
60404b540aSrobert static cpp_num parse_defined (cpp_reader *);
61404b540aSrobert static cpp_num eval_token (cpp_reader *, const cpp_token *);
62404b540aSrobert static struct op *reduce (cpp_reader *, struct op *, enum cpp_ttype);
63404b540aSrobert static unsigned int interpret_float_suffix (const uchar *, size_t);
64404b540aSrobert static unsigned int interpret_int_suffix (const uchar *, size_t);
65404b540aSrobert static void check_promotion (cpp_reader *, const struct op *);
66404b540aSrobert
67404b540aSrobert /* Token type abuse to create unary plus and minus operators. */
68404b540aSrobert #define CPP_UPLUS ((enum cpp_ttype) (CPP_LAST_CPP_OP + 1))
69404b540aSrobert #define CPP_UMINUS ((enum cpp_ttype) (CPP_LAST_CPP_OP + 2))
70404b540aSrobert
71404b540aSrobert /* With -O2, gcc appears to produce nice code, moving the error
72404b540aSrobert message load and subsequent jump completely out of the main path. */
73404b540aSrobert #define SYNTAX_ERROR(msgid) \
74404b540aSrobert do { cpp_error (pfile, CPP_DL_ERROR, msgid); goto syntax_error; } while(0)
75404b540aSrobert #define SYNTAX_ERROR2(msgid, arg) \
76404b540aSrobert do { cpp_error (pfile, CPP_DL_ERROR, msgid, arg); goto syntax_error; } \
77404b540aSrobert while(0)
78404b540aSrobert
79404b540aSrobert /* Subroutine of cpp_classify_number. S points to a float suffix of
80404b540aSrobert length LEN, possibly zero. Returns 0 for an invalid suffix, or a
81404b540aSrobert flag vector describing the suffix. */
82404b540aSrobert static unsigned int
interpret_float_suffix(const uchar * s,size_t len)83404b540aSrobert interpret_float_suffix (const uchar *s, size_t len)
84404b540aSrobert {
85341535f4Smartynas size_t f = 0, l = 0, i = 0, d = 0, d0 = 0;
86404b540aSrobert
87404b540aSrobert while (len--)
88404b540aSrobert switch (s[len])
89404b540aSrobert {
90404b540aSrobert case 'f': case 'F': f++; break;
91404b540aSrobert case 'l': case 'L': l++; break;
92404b540aSrobert case 'i': case 'I':
93404b540aSrobert case 'j': case 'J': i++; break;
94404b540aSrobert case 'd': case 'D':
95404b540aSrobert /* Disallow fd, ld suffixes. */
96404b540aSrobert if (d && (f || l))
97404b540aSrobert return 0;
98404b540aSrobert d++;
99404b540aSrobert break;
100404b540aSrobert default:
101404b540aSrobert return 0;
102404b540aSrobert }
103404b540aSrobert
104341535f4Smartynas if (d == 1 && !f && !l) {
105341535f4Smartynas d = 0;
106341535f4Smartynas d0 = 1;
107341535f4Smartynas }
108341535f4Smartynas
109341535f4Smartynas if (f + d0 + l > 1 || i > 1)
110404b540aSrobert return 0;
111404b540aSrobert
112404b540aSrobert /* Allow dd, df, dl suffixes for decimal float constants. */
113404b540aSrobert if (d && ((d + f + l != 2) || i))
114404b540aSrobert return 0;
115404b540aSrobert
116404b540aSrobert return ((i ? CPP_N_IMAGINARY : 0)
117404b540aSrobert | (f ? CPP_N_SMALL :
118341535f4Smartynas d0 ? CPP_N_MEDIUM :
119341535f4Smartynas l ? CPP_N_LARGE : CPP_N_DEFAULT)
120404b540aSrobert | (d ? CPP_N_DFLOAT : 0));
121404b540aSrobert }
122404b540aSrobert
123404b540aSrobert /* Subroutine of cpp_classify_number. S points to an integer suffix
124404b540aSrobert of length LEN, possibly zero. Returns 0 for an invalid suffix, or a
125404b540aSrobert flag vector describing the suffix. */
126404b540aSrobert static unsigned int
interpret_int_suffix(const uchar * s,size_t len)127404b540aSrobert interpret_int_suffix (const uchar *s, size_t len)
128404b540aSrobert {
129404b540aSrobert size_t u, l, i;
130404b540aSrobert
131404b540aSrobert u = l = i = 0;
132404b540aSrobert
133404b540aSrobert while (len--)
134404b540aSrobert switch (s[len])
135404b540aSrobert {
136404b540aSrobert case 'u': case 'U': u++; break;
137404b540aSrobert case 'i': case 'I':
138404b540aSrobert case 'j': case 'J': i++; break;
139404b540aSrobert case 'l': case 'L': l++;
140404b540aSrobert /* If there are two Ls, they must be adjacent and the same case. */
141404b540aSrobert if (l == 2 && s[len] != s[len + 1])
142404b540aSrobert return 0;
143404b540aSrobert break;
144404b540aSrobert default:
145404b540aSrobert return 0;
146404b540aSrobert }
147404b540aSrobert
148404b540aSrobert if (l > 2 || u > 1 || i > 1)
149404b540aSrobert return 0;
150404b540aSrobert
151404b540aSrobert return ((i ? CPP_N_IMAGINARY : 0)
152404b540aSrobert | (u ? CPP_N_UNSIGNED : 0)
153404b540aSrobert | ((l == 0) ? CPP_N_SMALL
154404b540aSrobert : (l == 1) ? CPP_N_MEDIUM : CPP_N_LARGE));
155404b540aSrobert }
156404b540aSrobert
157404b540aSrobert /* Categorize numeric constants according to their field (integer,
158404b540aSrobert floating point, or invalid), radix (decimal, octal, hexadecimal),
159404b540aSrobert and type suffixes. */
160404b540aSrobert unsigned int
cpp_classify_number(cpp_reader * pfile,const cpp_token * token)161404b540aSrobert cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
162404b540aSrobert {
163404b540aSrobert const uchar *str = token->val.str.text;
164404b540aSrobert const uchar *limit;
165404b540aSrobert unsigned int max_digit, result, radix;
166404b540aSrobert enum {NOT_FLOAT = 0, AFTER_POINT, AFTER_EXPON} float_flag;
167404b540aSrobert
168404b540aSrobert /* If the lexer has done its job, length one can only be a single
169404b540aSrobert digit. Fast-path this very common case. */
170404b540aSrobert if (token->val.str.len == 1)
171404b540aSrobert return CPP_N_INTEGER | CPP_N_SMALL | CPP_N_DECIMAL;
172404b540aSrobert
173404b540aSrobert limit = str + token->val.str.len;
174404b540aSrobert float_flag = NOT_FLOAT;
175404b540aSrobert max_digit = 0;
176404b540aSrobert radix = 10;
177404b540aSrobert
178404b540aSrobert /* First, interpret the radix. */
179404b540aSrobert if (*str == '0')
180404b540aSrobert {
181404b540aSrobert radix = 8;
182404b540aSrobert str++;
183404b540aSrobert
184404b540aSrobert /* Require at least one hex digit to classify it as hex. */
185404b540aSrobert if ((*str == 'x' || *str == 'X')
186404b540aSrobert && (str[1] == '.' || ISXDIGIT (str[1])))
187404b540aSrobert {
188404b540aSrobert radix = 16;
189404b540aSrobert str++;
190404b540aSrobert }
191*9506a00bSjsg else if ((*str == 'b' || *str == 'B') && (str[1] == '0' || str[1] == '1'))
192*9506a00bSjsg {
193*9506a00bSjsg radix = 2;
194*9506a00bSjsg str++;
195*9506a00bSjsg }
196404b540aSrobert }
197404b540aSrobert
198404b540aSrobert /* Now scan for a well-formed integer or float. */
199404b540aSrobert for (;;)
200404b540aSrobert {
201404b540aSrobert unsigned int c = *str++;
202404b540aSrobert
203404b540aSrobert if (ISDIGIT (c) || (ISXDIGIT (c) && radix == 16))
204404b540aSrobert {
205404b540aSrobert c = hex_value (c);
206404b540aSrobert if (c > max_digit)
207404b540aSrobert max_digit = c;
208404b540aSrobert }
209404b540aSrobert else if (c == '.')
210404b540aSrobert {
211404b540aSrobert if (float_flag == NOT_FLOAT)
212404b540aSrobert float_flag = AFTER_POINT;
213404b540aSrobert else
214404b540aSrobert SYNTAX_ERROR ("too many decimal points in number");
215404b540aSrobert }
216404b540aSrobert else if ((radix <= 10 && (c == 'e' || c == 'E'))
217404b540aSrobert || (radix == 16 && (c == 'p' || c == 'P')))
218404b540aSrobert {
219404b540aSrobert float_flag = AFTER_EXPON;
220404b540aSrobert break;
221404b540aSrobert }
222404b540aSrobert else
223404b540aSrobert {
224404b540aSrobert /* Start of suffix. */
225404b540aSrobert str--;
226404b540aSrobert break;
227404b540aSrobert }
228404b540aSrobert }
229404b540aSrobert
230404b540aSrobert if (float_flag != NOT_FLOAT && radix == 8)
231404b540aSrobert radix = 10;
232404b540aSrobert
233404b540aSrobert if (max_digit >= radix)
234*9506a00bSjsg {
235*9506a00bSjsg if (radix == 2)
236*9506a00bSjsg SYNTAX_ERROR2 ("invalid digit \"%c\" in binary constant", '0' + max_digit);
237*9506a00bSjsg else
238404b540aSrobert SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit);
239*9506a00bSjsg }
240404b540aSrobert
241404b540aSrobert if (float_flag != NOT_FLOAT)
242404b540aSrobert {
243*9506a00bSjsg if (radix == 2)
244*9506a00bSjsg {
245*9506a00bSjsg cpp_error (pfile, CPP_DL_ERROR,
246*9506a00bSjsg "invalid prefix \"0b\" for floating constant");
247*9506a00bSjsg return CPP_N_INVALID;
248*9506a00bSjsg }
249*9506a00bSjsg
250404b540aSrobert if (radix == 16 && CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, c99))
251404b540aSrobert cpp_error (pfile, CPP_DL_PEDWARN,
252404b540aSrobert "use of C99 hexadecimal floating constant");
253404b540aSrobert
254404b540aSrobert if (float_flag == AFTER_EXPON)
255404b540aSrobert {
256404b540aSrobert if (*str == '+' || *str == '-')
257404b540aSrobert str++;
258404b540aSrobert
259404b540aSrobert /* Exponent is decimal, even if string is a hex float. */
260404b540aSrobert if (!ISDIGIT (*str))
261404b540aSrobert SYNTAX_ERROR ("exponent has no digits");
262404b540aSrobert
263404b540aSrobert do
264404b540aSrobert str++;
265404b540aSrobert while (ISDIGIT (*str));
266404b540aSrobert }
267404b540aSrobert else if (radix == 16)
268404b540aSrobert SYNTAX_ERROR ("hexadecimal floating constants require an exponent");
269404b540aSrobert
270404b540aSrobert result = interpret_float_suffix (str, limit - str);
271404b540aSrobert if (result == 0)
272404b540aSrobert {
273404b540aSrobert cpp_error (pfile, CPP_DL_ERROR,
274404b540aSrobert "invalid suffix \"%.*s\" on floating constant",
275404b540aSrobert (int) (limit - str), str);
276404b540aSrobert return CPP_N_INVALID;
277404b540aSrobert }
278404b540aSrobert
279404b540aSrobert /* Traditional C didn't accept any floating suffixes. */
280404b540aSrobert if (limit != str
281404b540aSrobert && CPP_WTRADITIONAL (pfile)
282404b540aSrobert && ! cpp_sys_macro_p (pfile))
283404b540aSrobert cpp_error (pfile, CPP_DL_WARNING,
284404b540aSrobert "traditional C rejects the \"%.*s\" suffix",
285404b540aSrobert (int) (limit - str), str);
286404b540aSrobert
287341535f4Smartynas /* A suffix for double is a GCC extension via decimal float support.
288341535f4Smartynas If the suffix also specifies an imaginary value we'll catch that
289341535f4Smartynas later. */
290341535f4Smartynas if ((result == CPP_N_MEDIUM) && CPP_PEDANTIC (pfile))
291341535f4Smartynas cpp_error (pfile, CPP_DL_PEDWARN,
292341535f4Smartynas "suffix for double constant is a GCC extension");
293341535f4Smartynas
294404b540aSrobert /* Radix must be 10 for decimal floats. */
295404b540aSrobert if ((result & CPP_N_DFLOAT) && radix != 10)
296404b540aSrobert {
297404b540aSrobert cpp_error (pfile, CPP_DL_ERROR,
298404b540aSrobert "invalid suffix \"%.*s\" with hexadecimal floating constant",
299404b540aSrobert (int) (limit - str), str);
300404b540aSrobert return CPP_N_INVALID;
301404b540aSrobert }
302404b540aSrobert
303404b540aSrobert result |= CPP_N_FLOATING;
304404b540aSrobert }
305404b540aSrobert else
306404b540aSrobert {
307404b540aSrobert result = interpret_int_suffix (str, limit - str);
308404b540aSrobert if (result == 0)
309404b540aSrobert {
310404b540aSrobert cpp_error (pfile, CPP_DL_ERROR,
311404b540aSrobert "invalid suffix \"%.*s\" on integer constant",
312404b540aSrobert (int) (limit - str), str);
313404b540aSrobert return CPP_N_INVALID;
314404b540aSrobert }
315404b540aSrobert
316404b540aSrobert /* Traditional C only accepted the 'L' suffix.
317404b540aSrobert Suppress warning about 'LL' with -Wno-long-long. */
318404b540aSrobert if (CPP_WTRADITIONAL (pfile) && ! cpp_sys_macro_p (pfile))
319404b540aSrobert {
320404b540aSrobert int u_or_i = (result & (CPP_N_UNSIGNED|CPP_N_IMAGINARY));
321404b540aSrobert int large = (result & CPP_N_WIDTH) == CPP_N_LARGE;
322404b540aSrobert
323404b540aSrobert if (u_or_i || (large && CPP_OPTION (pfile, warn_long_long)))
324404b540aSrobert cpp_error (pfile, CPP_DL_WARNING,
325404b540aSrobert "traditional C rejects the \"%.*s\" suffix",
326404b540aSrobert (int) (limit - str), str);
327404b540aSrobert }
328404b540aSrobert
329404b540aSrobert if ((result & CPP_N_WIDTH) == CPP_N_LARGE
330404b540aSrobert && ! CPP_OPTION (pfile, c99)
331404b540aSrobert && CPP_OPTION (pfile, warn_long_long))
332404b540aSrobert cpp_error (pfile, CPP_DL_PEDWARN,
333404b540aSrobert "use of C99 long long integer constant");
334404b540aSrobert
335404b540aSrobert result |= CPP_N_INTEGER;
336404b540aSrobert }
337404b540aSrobert
338404b540aSrobert if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
339404b540aSrobert cpp_error (pfile, CPP_DL_PEDWARN,
340404b540aSrobert "imaginary constants are a GCC extension");
341*9506a00bSjsg if (radix == 2 && CPP_PEDANTIC (pfile))
342*9506a00bSjsg cpp_error (pfile, CPP_DL_PEDWARN,
343*9506a00bSjsg "binary constants are a GCC extension");
344404b540aSrobert
345404b540aSrobert if (radix == 10)
346404b540aSrobert result |= CPP_N_DECIMAL;
347404b540aSrobert else if (radix == 16)
348404b540aSrobert result |= CPP_N_HEX;
349*9506a00bSjsg else if (radix == 2)
350*9506a00bSjsg result |= CPP_N_BINARY;
351404b540aSrobert else
352404b540aSrobert result |= CPP_N_OCTAL;
353404b540aSrobert
354404b540aSrobert return result;
355404b540aSrobert
356404b540aSrobert syntax_error:
357404b540aSrobert return CPP_N_INVALID;
358404b540aSrobert }
359404b540aSrobert
360404b540aSrobert /* cpp_interpret_integer converts an integer constant into a cpp_num,
361404b540aSrobert of precision options->precision.
362404b540aSrobert
363404b540aSrobert We do not provide any interface for decimal->float conversion,
364404b540aSrobert because the preprocessor doesn't need it and we don't want to
365404b540aSrobert drag in GCC's floating point emulator. */
366404b540aSrobert cpp_num
cpp_interpret_integer(cpp_reader * pfile,const cpp_token * token,unsigned int type)367404b540aSrobert cpp_interpret_integer (cpp_reader *pfile, const cpp_token *token,
368404b540aSrobert unsigned int type)
369404b540aSrobert {
370404b540aSrobert const uchar *p, *end;
371404b540aSrobert cpp_num result;
372404b540aSrobert
373404b540aSrobert result.low = 0;
374404b540aSrobert result.high = 0;
375404b540aSrobert result.unsignedp = !!(type & CPP_N_UNSIGNED);
376404b540aSrobert result.overflow = false;
377404b540aSrobert
378404b540aSrobert p = token->val.str.text;
379404b540aSrobert end = p + token->val.str.len;
380404b540aSrobert
381404b540aSrobert /* Common case of a single digit. */
382404b540aSrobert if (token->val.str.len == 1)
383404b540aSrobert result.low = p[0] - '0';
384404b540aSrobert else
385404b540aSrobert {
386404b540aSrobert cpp_num_part max;
387404b540aSrobert size_t precision = CPP_OPTION (pfile, precision);
388404b540aSrobert unsigned int base = 10, c = 0;
389404b540aSrobert bool overflow = false;
390404b540aSrobert
391404b540aSrobert if ((type & CPP_N_RADIX) == CPP_N_OCTAL)
392404b540aSrobert {
393404b540aSrobert base = 8;
394404b540aSrobert p++;
395404b540aSrobert }
396404b540aSrobert else if ((type & CPP_N_RADIX) == CPP_N_HEX)
397404b540aSrobert {
398404b540aSrobert base = 16;
399404b540aSrobert p += 2;
400404b540aSrobert }
401*9506a00bSjsg else if ((type & CPP_N_RADIX) == CPP_N_BINARY)
402*9506a00bSjsg {
403*9506a00bSjsg base = 2;
404*9506a00bSjsg p += 2;
405*9506a00bSjsg }
406404b540aSrobert
407404b540aSrobert /* We can add a digit to numbers strictly less than this without
408404b540aSrobert needing the precision and slowness of double integers. */
409404b540aSrobert max = ~(cpp_num_part) 0;
410404b540aSrobert if (precision < PART_PRECISION)
411404b540aSrobert max >>= PART_PRECISION - precision;
412404b540aSrobert max = (max - base + 1) / base + 1;
413404b540aSrobert
414404b540aSrobert for (; p < end; p++)
415404b540aSrobert {
416404b540aSrobert c = *p;
417404b540aSrobert
418404b540aSrobert if (ISDIGIT (c) || (base == 16 && ISXDIGIT (c)))
419404b540aSrobert c = hex_value (c);
420404b540aSrobert else
421404b540aSrobert break;
422404b540aSrobert
423404b540aSrobert /* Strict inequality for when max is set to zero. */
424404b540aSrobert if (result.low < max)
425404b540aSrobert result.low = result.low * base + c;
426404b540aSrobert else
427404b540aSrobert {
428404b540aSrobert result = append_digit (result, c, base, precision);
429404b540aSrobert overflow |= result.overflow;
430404b540aSrobert max = 0;
431404b540aSrobert }
432404b540aSrobert }
433404b540aSrobert
434404b540aSrobert if (overflow)
435404b540aSrobert cpp_error (pfile, CPP_DL_PEDWARN,
436404b540aSrobert "integer constant is too large for its type");
437404b540aSrobert /* If too big to be signed, consider it unsigned. Only warn for
438404b540aSrobert decimal numbers. Traditional numbers were always signed (but
439404b540aSrobert we still honor an explicit U suffix); but we only have
440404b540aSrobert traditional semantics in directives. */
441404b540aSrobert else if (!result.unsignedp
442404b540aSrobert && !(CPP_OPTION (pfile, traditional)
443404b540aSrobert && pfile->state.in_directive)
444404b540aSrobert && !num_positive (result, precision))
445404b540aSrobert {
446404b540aSrobert if (base == 10)
447404b540aSrobert cpp_error (pfile, CPP_DL_WARNING,
448404b540aSrobert "integer constant is so large that it is unsigned");
449404b540aSrobert result.unsignedp = true;
450404b540aSrobert }
451404b540aSrobert }
452404b540aSrobert
453404b540aSrobert return result;
454404b540aSrobert }
455404b540aSrobert
456404b540aSrobert /* Append DIGIT to NUM, a number of PRECISION bits being read in base BASE. */
457404b540aSrobert static cpp_num
append_digit(cpp_num num,int digit,int base,size_t precision)458404b540aSrobert append_digit (cpp_num num, int digit, int base, size_t precision)
459404b540aSrobert {
460404b540aSrobert cpp_num result;
461*9506a00bSjsg unsigned int shift;
462404b540aSrobert bool overflow;
463404b540aSrobert cpp_num_part add_high, add_low;
464404b540aSrobert
465*9506a00bSjsg /* Multiply by 2, 8 or 16. Catching this overflow here means we don't
466404b540aSrobert need to worry about add_high overflowing. */
467*9506a00bSjsg switch (base)
468*9506a00bSjsg {
469*9506a00bSjsg case 2:
470*9506a00bSjsg shift = 1;
471*9506a00bSjsg break;
472*9506a00bSjsg
473*9506a00bSjsg case 16:
474*9506a00bSjsg shift = 4;
475*9506a00bSjsg break;
476*9506a00bSjsg
477*9506a00bSjsg default:
478*9506a00bSjsg shift = 3;
479*9506a00bSjsg }
480404b540aSrobert overflow = !!(num.high >> (PART_PRECISION - shift));
481404b540aSrobert result.high = num.high << shift;
482404b540aSrobert result.low = num.low << shift;
483404b540aSrobert result.high |= num.low >> (PART_PRECISION - shift);
484404b540aSrobert result.unsignedp = num.unsignedp;
485404b540aSrobert
486404b540aSrobert if (base == 10)
487404b540aSrobert {
488404b540aSrobert add_low = num.low << 1;
489404b540aSrobert add_high = (num.high << 1) + (num.low >> (PART_PRECISION - 1));
490404b540aSrobert }
491404b540aSrobert else
492404b540aSrobert add_high = add_low = 0;
493404b540aSrobert
494404b540aSrobert if (add_low + digit < add_low)
495404b540aSrobert add_high++;
496404b540aSrobert add_low += digit;
497404b540aSrobert
498404b540aSrobert if (result.low + add_low < result.low)
499404b540aSrobert add_high++;
500404b540aSrobert if (result.high + add_high < result.high)
501404b540aSrobert overflow = true;
502404b540aSrobert
503404b540aSrobert result.low += add_low;
504404b540aSrobert result.high += add_high;
505404b540aSrobert result.overflow = overflow;
506404b540aSrobert
507404b540aSrobert /* The above code catches overflow of a cpp_num type. This catches
508404b540aSrobert overflow of the (possibly shorter) target precision. */
509404b540aSrobert num.low = result.low;
510404b540aSrobert num.high = result.high;
511404b540aSrobert result = num_trim (result, precision);
512404b540aSrobert if (!num_eq (result, num))
513404b540aSrobert result.overflow = true;
514404b540aSrobert
515404b540aSrobert return result;
516404b540aSrobert }
517404b540aSrobert
518404b540aSrobert /* Handle meeting "defined" in a preprocessor expression. */
519404b540aSrobert static cpp_num
parse_defined(cpp_reader * pfile)520404b540aSrobert parse_defined (cpp_reader *pfile)
521404b540aSrobert {
522404b540aSrobert cpp_num result;
523404b540aSrobert int paren = 0;
524404b540aSrobert cpp_hashnode *node = 0;
525404b540aSrobert const cpp_token *token;
526404b540aSrobert cpp_context *initial_context = pfile->context;
527404b540aSrobert
528404b540aSrobert /* Don't expand macros. */
529404b540aSrobert pfile->state.prevent_expansion++;
530404b540aSrobert
531404b540aSrobert token = cpp_get_token (pfile);
532404b540aSrobert if (token->type == CPP_OPEN_PAREN)
533404b540aSrobert {
534404b540aSrobert paren = 1;
535404b540aSrobert token = cpp_get_token (pfile);
536404b540aSrobert }
537404b540aSrobert
538404b540aSrobert if (token->type == CPP_NAME)
539404b540aSrobert {
540404b540aSrobert node = token->val.node;
541404b540aSrobert if (paren && cpp_get_token (pfile)->type != CPP_CLOSE_PAREN)
542404b540aSrobert {
543404b540aSrobert cpp_error (pfile, CPP_DL_ERROR, "missing ')' after \"defined\"");
544404b540aSrobert node = 0;
545404b540aSrobert }
546404b540aSrobert }
547404b540aSrobert else
548404b540aSrobert {
549404b540aSrobert cpp_error (pfile, CPP_DL_ERROR,
550404b540aSrobert "operator \"defined\" requires an identifier");
551404b540aSrobert if (token->flags & NAMED_OP)
552404b540aSrobert {
553404b540aSrobert cpp_token op;
554404b540aSrobert
555404b540aSrobert op.flags = 0;
556404b540aSrobert op.type = token->type;
557404b540aSrobert cpp_error (pfile, CPP_DL_ERROR,
558404b540aSrobert "(\"%s\" is an alternative token for \"%s\" in C++)",
559404b540aSrobert cpp_token_as_text (pfile, token),
560404b540aSrobert cpp_token_as_text (pfile, &op));
561404b540aSrobert }
562404b540aSrobert }
563404b540aSrobert
564404b540aSrobert if (node)
565404b540aSrobert {
566404b540aSrobert if (pfile->context != initial_context && CPP_PEDANTIC (pfile))
567404b540aSrobert cpp_error (pfile, CPP_DL_WARNING,
568404b540aSrobert "this use of \"defined\" may not be portable");
569404b540aSrobert
570404b540aSrobert _cpp_mark_macro_used (node);
571404b540aSrobert
572404b540aSrobert /* A possible controlling macro of the form #if !defined ().
573404b540aSrobert _cpp_parse_expr checks there was no other junk on the line. */
574404b540aSrobert pfile->mi_ind_cmacro = node;
575404b540aSrobert }
576404b540aSrobert
577404b540aSrobert pfile->state.prevent_expansion--;
578404b540aSrobert
579404b540aSrobert result.unsignedp = false;
580404b540aSrobert result.high = 0;
581404b540aSrobert result.overflow = false;
582404b540aSrobert result.low = node && node->type == NT_MACRO;
583404b540aSrobert return result;
584404b540aSrobert }
585404b540aSrobert
586404b540aSrobert /* Convert a token into a CPP_NUMBER (an interpreted preprocessing
587404b540aSrobert number or character constant, or the result of the "defined" or "#"
588404b540aSrobert operators). */
589404b540aSrobert static cpp_num
eval_token(cpp_reader * pfile,const cpp_token * token)590404b540aSrobert eval_token (cpp_reader *pfile, const cpp_token *token)
591404b540aSrobert {
592404b540aSrobert cpp_num result;
593404b540aSrobert unsigned int temp;
594404b540aSrobert int unsignedp = 0;
595404b540aSrobert
596404b540aSrobert result.unsignedp = false;
597404b540aSrobert result.overflow = false;
598404b540aSrobert
599404b540aSrobert switch (token->type)
600404b540aSrobert {
601404b540aSrobert case CPP_NUMBER:
602404b540aSrobert temp = cpp_classify_number (pfile, token);
603404b540aSrobert switch (temp & CPP_N_CATEGORY)
604404b540aSrobert {
605404b540aSrobert case CPP_N_FLOATING:
606404b540aSrobert cpp_error (pfile, CPP_DL_ERROR,
607404b540aSrobert "floating constant in preprocessor expression");
608404b540aSrobert break;
609404b540aSrobert case CPP_N_INTEGER:
610404b540aSrobert if (!(temp & CPP_N_IMAGINARY))
611404b540aSrobert return cpp_interpret_integer (pfile, token, temp);
612404b540aSrobert cpp_error (pfile, CPP_DL_ERROR,
613404b540aSrobert "imaginary number in preprocessor expression");
614404b540aSrobert break;
615404b540aSrobert
616404b540aSrobert case CPP_N_INVALID:
617404b540aSrobert /* Error already issued. */
618404b540aSrobert break;
619404b540aSrobert }
620404b540aSrobert result.high = result.low = 0;
621404b540aSrobert break;
622404b540aSrobert
623404b540aSrobert case CPP_WCHAR:
624404b540aSrobert case CPP_CHAR:
625404b540aSrobert {
626404b540aSrobert cppchar_t cc = cpp_interpret_charconst (pfile, token,
627404b540aSrobert &temp, &unsignedp);
628404b540aSrobert
629404b540aSrobert result.high = 0;
630404b540aSrobert result.low = cc;
631404b540aSrobert /* Sign-extend the result if necessary. */
632404b540aSrobert if (!unsignedp && (cppchar_signed_t) cc < 0)
633404b540aSrobert {
634404b540aSrobert if (PART_PRECISION > BITS_PER_CPPCHAR_T)
635404b540aSrobert result.low |= ~(~(cpp_num_part) 0
636404b540aSrobert >> (PART_PRECISION - BITS_PER_CPPCHAR_T));
637404b540aSrobert result.high = ~(cpp_num_part) 0;
638404b540aSrobert result = num_trim (result, CPP_OPTION (pfile, precision));
639404b540aSrobert }
640404b540aSrobert }
641404b540aSrobert break;
642404b540aSrobert
643404b540aSrobert case CPP_NAME:
644404b540aSrobert if (token->val.node == pfile->spec_nodes.n_defined)
645404b540aSrobert return parse_defined (pfile);
646404b540aSrobert else if (CPP_OPTION (pfile, cplusplus)
647404b540aSrobert && (token->val.node == pfile->spec_nodes.n_true
648404b540aSrobert || token->val.node == pfile->spec_nodes.n_false))
649404b540aSrobert {
650404b540aSrobert result.high = 0;
651404b540aSrobert result.low = (token->val.node == pfile->spec_nodes.n_true);
652404b540aSrobert }
653404b540aSrobert else
654404b540aSrobert {
655404b540aSrobert result.high = 0;
656404b540aSrobert result.low = 0;
657404b540aSrobert if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval)
658404b540aSrobert cpp_error (pfile, CPP_DL_WARNING, "\"%s\" is not defined",
659404b540aSrobert NODE_NAME (token->val.node));
660404b540aSrobert }
661404b540aSrobert break;
662404b540aSrobert
663404b540aSrobert default: /* CPP_HASH */
664404b540aSrobert _cpp_test_assertion (pfile, &temp);
665404b540aSrobert result.high = 0;
666404b540aSrobert result.low = temp;
667404b540aSrobert }
668404b540aSrobert
669404b540aSrobert result.unsignedp = !!unsignedp;
670404b540aSrobert return result;
671404b540aSrobert }
672404b540aSrobert
673404b540aSrobert /* Operator precedence and flags table.
674404b540aSrobert
675404b540aSrobert After an operator is returned from the lexer, if it has priority less
676404b540aSrobert than the operator on the top of the stack, we reduce the stack by one
677404b540aSrobert operator and repeat the test. Since equal priorities do not reduce,
678404b540aSrobert this is naturally right-associative.
679404b540aSrobert
680404b540aSrobert We handle left-associative operators by decrementing the priority of
681404b540aSrobert just-lexed operators by one, but retaining the priority of operators
682404b540aSrobert already on the stack.
683404b540aSrobert
684404b540aSrobert The remaining cases are '(' and ')'. We handle '(' by skipping the
685404b540aSrobert reduction phase completely. ')' is given lower priority than
686404b540aSrobert everything else, including '(', effectively forcing a reduction of the
687404b540aSrobert parenthesized expression. If there is a matching '(', the routine
688404b540aSrobert reduce() exits immediately. If the normal exit route sees a ')', then
689404b540aSrobert there cannot have been a matching '(' and an error message is output.
690404b540aSrobert
691404b540aSrobert The parser assumes all shifted operators require a left operand unless
692404b540aSrobert the flag NO_L_OPERAND is set. These semantics are automatic; any
693404b540aSrobert extra semantics need to be handled with operator-specific code. */
694404b540aSrobert
695404b540aSrobert /* Flags. If CHECK_PROMOTION, we warn if the effective sign of an
696404b540aSrobert operand changes because of integer promotions. */
697404b540aSrobert #define NO_L_OPERAND (1 << 0)
698404b540aSrobert #define LEFT_ASSOC (1 << 1)
699404b540aSrobert #define CHECK_PROMOTION (1 << 2)
700404b540aSrobert
701404b540aSrobert /* Operator to priority map. Must be in the same order as the first
702404b540aSrobert N entries of enum cpp_ttype. */
703404b540aSrobert static const struct cpp_operator
704404b540aSrobert {
705404b540aSrobert uchar prio;
706404b540aSrobert uchar flags;
707404b540aSrobert } optab[] =
708404b540aSrobert {
709404b540aSrobert /* EQ */ {0, 0}, /* Shouldn't happen. */
710404b540aSrobert /* NOT */ {16, NO_L_OPERAND},
711404b540aSrobert /* GREATER */ {12, LEFT_ASSOC | CHECK_PROMOTION},
712404b540aSrobert /* LESS */ {12, LEFT_ASSOC | CHECK_PROMOTION},
713404b540aSrobert /* PLUS */ {14, LEFT_ASSOC | CHECK_PROMOTION},
714404b540aSrobert /* MINUS */ {14, LEFT_ASSOC | CHECK_PROMOTION},
715404b540aSrobert /* MULT */ {15, LEFT_ASSOC | CHECK_PROMOTION},
716404b540aSrobert /* DIV */ {15, LEFT_ASSOC | CHECK_PROMOTION},
717404b540aSrobert /* MOD */ {15, LEFT_ASSOC | CHECK_PROMOTION},
718404b540aSrobert /* AND */ {9, LEFT_ASSOC | CHECK_PROMOTION},
719404b540aSrobert /* OR */ {7, LEFT_ASSOC | CHECK_PROMOTION},
720404b540aSrobert /* XOR */ {8, LEFT_ASSOC | CHECK_PROMOTION},
721404b540aSrobert /* RSHIFT */ {13, LEFT_ASSOC},
722404b540aSrobert /* LSHIFT */ {13, LEFT_ASSOC},
723404b540aSrobert
724404b540aSrobert /* COMPL */ {16, NO_L_OPERAND},
725404b540aSrobert /* AND_AND */ {6, LEFT_ASSOC},
726404b540aSrobert /* OR_OR */ {5, LEFT_ASSOC},
727404b540aSrobert /* QUERY */ {3, 0},
728404b540aSrobert /* COLON */ {4, LEFT_ASSOC | CHECK_PROMOTION},
729404b540aSrobert /* COMMA */ {2, LEFT_ASSOC},
730404b540aSrobert /* OPEN_PAREN */ {1, NO_L_OPERAND},
731404b540aSrobert /* CLOSE_PAREN */ {0, 0},
732404b540aSrobert /* EOF */ {0, 0},
733404b540aSrobert /* EQ_EQ */ {11, LEFT_ASSOC},
734404b540aSrobert /* NOT_EQ */ {11, LEFT_ASSOC},
735404b540aSrobert /* GREATER_EQ */ {12, LEFT_ASSOC | CHECK_PROMOTION},
736404b540aSrobert /* LESS_EQ */ {12, LEFT_ASSOC | CHECK_PROMOTION},
737404b540aSrobert /* UPLUS */ {16, NO_L_OPERAND},
738404b540aSrobert /* UMINUS */ {16, NO_L_OPERAND}
739404b540aSrobert };
740404b540aSrobert
741404b540aSrobert /* Parse and evaluate a C expression, reading from PFILE.
742404b540aSrobert Returns the truth value of the expression.
743404b540aSrobert
744404b540aSrobert The implementation is an operator precedence parser, i.e. a
745404b540aSrobert bottom-up parser, using a stack for not-yet-reduced tokens.
746404b540aSrobert
747404b540aSrobert The stack base is op_stack, and the current stack pointer is 'top'.
748404b540aSrobert There is a stack element for each operator (only), and the most
749404b540aSrobert recently pushed operator is 'top->op'. An operand (value) is
750404b540aSrobert stored in the 'value' field of the stack element of the operator
751404b540aSrobert that precedes it. */
752404b540aSrobert bool
_cpp_parse_expr(cpp_reader * pfile)753404b540aSrobert _cpp_parse_expr (cpp_reader *pfile)
754404b540aSrobert {
755404b540aSrobert struct op *top = pfile->op_stack;
756404b540aSrobert unsigned int lex_count;
757404b540aSrobert bool saw_leading_not, want_value = true;
758404b540aSrobert
759404b540aSrobert pfile->state.skip_eval = 0;
760404b540aSrobert
761404b540aSrobert /* Set up detection of #if ! defined(). */
762404b540aSrobert pfile->mi_ind_cmacro = 0;
763404b540aSrobert saw_leading_not = false;
764404b540aSrobert lex_count = 0;
765404b540aSrobert
766404b540aSrobert /* Lowest priority operator prevents further reductions. */
767404b540aSrobert top->op = CPP_EOF;
768404b540aSrobert
769404b540aSrobert for (;;)
770404b540aSrobert {
771404b540aSrobert struct op op;
772404b540aSrobert
773404b540aSrobert lex_count++;
774404b540aSrobert op.token = cpp_get_token (pfile);
775404b540aSrobert op.op = op.token->type;
776404b540aSrobert
777404b540aSrobert switch (op.op)
778404b540aSrobert {
779404b540aSrobert /* These tokens convert into values. */
780404b540aSrobert case CPP_NUMBER:
781404b540aSrobert case CPP_CHAR:
782404b540aSrobert case CPP_WCHAR:
783404b540aSrobert case CPP_NAME:
784404b540aSrobert case CPP_HASH:
785404b540aSrobert if (!want_value)
786404b540aSrobert SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
787404b540aSrobert cpp_token_as_text (pfile, op.token));
788404b540aSrobert want_value = false;
789404b540aSrobert top->value = eval_token (pfile, op.token);
790404b540aSrobert continue;
791404b540aSrobert
792404b540aSrobert case CPP_NOT:
793404b540aSrobert saw_leading_not = lex_count == 1;
794404b540aSrobert break;
795404b540aSrobert case CPP_PLUS:
796404b540aSrobert if (want_value)
797404b540aSrobert op.op = CPP_UPLUS;
798404b540aSrobert break;
799404b540aSrobert case CPP_MINUS:
800404b540aSrobert if (want_value)
801404b540aSrobert op.op = CPP_UMINUS;
802404b540aSrobert break;
803404b540aSrobert
804404b540aSrobert default:
805404b540aSrobert if ((int) op.op <= (int) CPP_EQ || (int) op.op >= (int) CPP_PLUS_EQ)
806404b540aSrobert SYNTAX_ERROR2 ("token \"%s\" is not valid in preprocessor expressions",
807404b540aSrobert cpp_token_as_text (pfile, op.token));
808404b540aSrobert break;
809404b540aSrobert }
810404b540aSrobert
811404b540aSrobert /* Check we have a value or operator as appropriate. */
812404b540aSrobert if (optab[op.op].flags & NO_L_OPERAND)
813404b540aSrobert {
814404b540aSrobert if (!want_value)
815404b540aSrobert SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
816404b540aSrobert cpp_token_as_text (pfile, op.token));
817404b540aSrobert }
818404b540aSrobert else if (want_value)
819404b540aSrobert {
820404b540aSrobert /* We want a number (or expression) and haven't got one.
821404b540aSrobert Try to emit a specific diagnostic. */
822404b540aSrobert if (op.op == CPP_CLOSE_PAREN && top->op == CPP_OPEN_PAREN)
823404b540aSrobert SYNTAX_ERROR ("missing expression between '(' and ')'");
824404b540aSrobert
825404b540aSrobert if (op.op == CPP_EOF && top->op == CPP_EOF)
826404b540aSrobert SYNTAX_ERROR ("#if with no expression");
827404b540aSrobert
828404b540aSrobert if (top->op != CPP_EOF && top->op != CPP_OPEN_PAREN)
829404b540aSrobert SYNTAX_ERROR2 ("operator '%s' has no right operand",
830404b540aSrobert cpp_token_as_text (pfile, top->token));
831404b540aSrobert else if (op.op == CPP_CLOSE_PAREN || op.op == CPP_EOF)
832404b540aSrobert /* Complain about missing paren during reduction. */;
833404b540aSrobert else
834404b540aSrobert SYNTAX_ERROR2 ("operator '%s' has no left operand",
835404b540aSrobert cpp_token_as_text (pfile, op.token));
836404b540aSrobert }
837404b540aSrobert
838404b540aSrobert top = reduce (pfile, top, op.op);
839404b540aSrobert if (!top)
840404b540aSrobert goto syntax_error;
841404b540aSrobert
842404b540aSrobert if (op.op == CPP_EOF)
843404b540aSrobert break;
844404b540aSrobert
845404b540aSrobert switch (op.op)
846404b540aSrobert {
847404b540aSrobert case CPP_CLOSE_PAREN:
848404b540aSrobert continue;
849404b540aSrobert case CPP_OR_OR:
850404b540aSrobert if (!num_zerop (top->value))
851404b540aSrobert pfile->state.skip_eval++;
852404b540aSrobert break;
853404b540aSrobert case CPP_AND_AND:
854404b540aSrobert case CPP_QUERY:
855404b540aSrobert if (num_zerop (top->value))
856404b540aSrobert pfile->state.skip_eval++;
857404b540aSrobert break;
858404b540aSrobert case CPP_COLON:
859404b540aSrobert if (top->op != CPP_QUERY)
860404b540aSrobert SYNTAX_ERROR (" ':' without preceding '?'");
861404b540aSrobert if (!num_zerop (top[-1].value)) /* Was '?' condition true? */
862404b540aSrobert pfile->state.skip_eval++;
863404b540aSrobert else
864404b540aSrobert pfile->state.skip_eval--;
865404b540aSrobert default:
866404b540aSrobert break;
867404b540aSrobert }
868404b540aSrobert
869404b540aSrobert want_value = true;
870404b540aSrobert
871404b540aSrobert /* Check for and handle stack overflow. */
872404b540aSrobert if (++top == pfile->op_limit)
873404b540aSrobert top = _cpp_expand_op_stack (pfile);
874404b540aSrobert
875404b540aSrobert top->op = op.op;
876404b540aSrobert top->token = op.token;
877404b540aSrobert }
878404b540aSrobert
879404b540aSrobert /* The controlling macro expression is only valid if we called lex 3
880404b540aSrobert times: <!> <defined expression> and <EOF>. push_conditional ()
881404b540aSrobert checks that we are at top-of-file. */
882404b540aSrobert if (pfile->mi_ind_cmacro && !(saw_leading_not && lex_count == 3))
883404b540aSrobert pfile->mi_ind_cmacro = 0;
884404b540aSrobert
885404b540aSrobert if (top != pfile->op_stack)
886404b540aSrobert {
887404b540aSrobert cpp_error (pfile, CPP_DL_ICE, "unbalanced stack in #if");
888404b540aSrobert syntax_error:
889404b540aSrobert return false; /* Return false on syntax error. */
890404b540aSrobert }
891404b540aSrobert
892404b540aSrobert return !num_zerop (top->value);
893404b540aSrobert }
894404b540aSrobert
895404b540aSrobert /* Reduce the operator / value stack if possible, in preparation for
896404b540aSrobert pushing operator OP. Returns NULL on error, otherwise the top of
897404b540aSrobert the stack. */
898404b540aSrobert static struct op *
reduce(cpp_reader * pfile,struct op * top,enum cpp_ttype op)899404b540aSrobert reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op)
900404b540aSrobert {
901404b540aSrobert unsigned int prio;
902404b540aSrobert
903404b540aSrobert if (top->op <= CPP_EQ || top->op > CPP_LAST_CPP_OP + 2)
904404b540aSrobert {
905404b540aSrobert bad_op:
906404b540aSrobert cpp_error (pfile, CPP_DL_ICE, "impossible operator '%u'", top->op);
907404b540aSrobert return 0;
908404b540aSrobert }
909404b540aSrobert
910404b540aSrobert if (op == CPP_OPEN_PAREN)
911404b540aSrobert return top;
912404b540aSrobert
913404b540aSrobert /* Decrement the priority of left-associative operators to force a
914404b540aSrobert reduction with operators of otherwise equal priority. */
915404b540aSrobert prio = optab[op].prio - ((optab[op].flags & LEFT_ASSOC) != 0);
916404b540aSrobert while (prio < optab[top->op].prio)
917404b540aSrobert {
918404b540aSrobert if (CPP_OPTION (pfile, warn_num_sign_change)
919404b540aSrobert && optab[top->op].flags & CHECK_PROMOTION)
920404b540aSrobert check_promotion (pfile, top);
921404b540aSrobert
922404b540aSrobert switch (top->op)
923404b540aSrobert {
924404b540aSrobert case CPP_UPLUS:
925404b540aSrobert case CPP_UMINUS:
926404b540aSrobert case CPP_NOT:
927404b540aSrobert case CPP_COMPL:
928404b540aSrobert top[-1].value = num_unary_op (pfile, top->value, top->op);
929404b540aSrobert break;
930404b540aSrobert
931404b540aSrobert case CPP_PLUS:
932404b540aSrobert case CPP_MINUS:
933404b540aSrobert case CPP_RSHIFT:
934404b540aSrobert case CPP_LSHIFT:
935404b540aSrobert case CPP_COMMA:
936404b540aSrobert top[-1].value = num_binary_op (pfile, top[-1].value,
937404b540aSrobert top->value, top->op);
938404b540aSrobert break;
939404b540aSrobert
940404b540aSrobert case CPP_GREATER:
941404b540aSrobert case CPP_LESS:
942404b540aSrobert case CPP_GREATER_EQ:
943404b540aSrobert case CPP_LESS_EQ:
944404b540aSrobert top[-1].value
945404b540aSrobert = num_inequality_op (pfile, top[-1].value, top->value, top->op);
946404b540aSrobert break;
947404b540aSrobert
948404b540aSrobert case CPP_EQ_EQ:
949404b540aSrobert case CPP_NOT_EQ:
950404b540aSrobert top[-1].value
951404b540aSrobert = num_equality_op (pfile, top[-1].value, top->value, top->op);
952404b540aSrobert break;
953404b540aSrobert
954404b540aSrobert case CPP_AND:
955404b540aSrobert case CPP_OR:
956404b540aSrobert case CPP_XOR:
957404b540aSrobert top[-1].value
958404b540aSrobert = num_bitwise_op (pfile, top[-1].value, top->value, top->op);
959404b540aSrobert break;
960404b540aSrobert
961404b540aSrobert case CPP_MULT:
962404b540aSrobert top[-1].value = num_mul (pfile, top[-1].value, top->value);
963404b540aSrobert break;
964404b540aSrobert
965404b540aSrobert case CPP_DIV:
966404b540aSrobert case CPP_MOD:
967404b540aSrobert top[-1].value = num_div_op (pfile, top[-1].value,
968404b540aSrobert top->value, top->op);
969404b540aSrobert break;
970404b540aSrobert
971404b540aSrobert case CPP_OR_OR:
972404b540aSrobert top--;
973404b540aSrobert if (!num_zerop (top->value))
974404b540aSrobert pfile->state.skip_eval--;
975404b540aSrobert top->value.low = (!num_zerop (top->value)
976404b540aSrobert || !num_zerop (top[1].value));
977404b540aSrobert top->value.high = 0;
978404b540aSrobert top->value.unsignedp = false;
979404b540aSrobert top->value.overflow = false;
980404b540aSrobert continue;
981404b540aSrobert
982404b540aSrobert case CPP_AND_AND:
983404b540aSrobert top--;
984404b540aSrobert if (num_zerop (top->value))
985404b540aSrobert pfile->state.skip_eval--;
986404b540aSrobert top->value.low = (!num_zerop (top->value)
987404b540aSrobert && !num_zerop (top[1].value));
988404b540aSrobert top->value.high = 0;
989404b540aSrobert top->value.unsignedp = false;
990404b540aSrobert top->value.overflow = false;
991404b540aSrobert continue;
992404b540aSrobert
993404b540aSrobert case CPP_OPEN_PAREN:
994404b540aSrobert if (op != CPP_CLOSE_PAREN)
995404b540aSrobert {
996404b540aSrobert cpp_error (pfile, CPP_DL_ERROR, "missing ')' in expression");
997404b540aSrobert return 0;
998404b540aSrobert }
999404b540aSrobert top--;
1000404b540aSrobert top->value = top[1].value;
1001404b540aSrobert return top;
1002404b540aSrobert
1003404b540aSrobert case CPP_COLON:
1004404b540aSrobert top -= 2;
1005404b540aSrobert if (!num_zerop (top->value))
1006404b540aSrobert {
1007404b540aSrobert pfile->state.skip_eval--;
1008404b540aSrobert top->value = top[1].value;
1009404b540aSrobert }
1010404b540aSrobert else
1011404b540aSrobert top->value = top[2].value;
1012404b540aSrobert top->value.unsignedp = (top[1].value.unsignedp
1013404b540aSrobert || top[2].value.unsignedp);
1014404b540aSrobert continue;
1015404b540aSrobert
1016404b540aSrobert case CPP_QUERY:
1017404b540aSrobert cpp_error (pfile, CPP_DL_ERROR, "'?' without following ':'");
1018404b540aSrobert return 0;
1019404b540aSrobert
1020404b540aSrobert default:
1021404b540aSrobert goto bad_op;
1022404b540aSrobert }
1023404b540aSrobert
1024404b540aSrobert top--;
1025404b540aSrobert if (top->value.overflow && !pfile->state.skip_eval)
1026404b540aSrobert cpp_error (pfile, CPP_DL_PEDWARN,
1027404b540aSrobert "integer overflow in preprocessor expression");
1028404b540aSrobert }
1029404b540aSrobert
1030404b540aSrobert if (op == CPP_CLOSE_PAREN)
1031404b540aSrobert {
1032404b540aSrobert cpp_error (pfile, CPP_DL_ERROR, "missing '(' in expression");
1033404b540aSrobert return 0;
1034404b540aSrobert }
1035404b540aSrobert
1036404b540aSrobert return top;
1037404b540aSrobert }
1038404b540aSrobert
1039404b540aSrobert /* Returns the position of the old top of stack after expansion. */
1040404b540aSrobert struct op *
_cpp_expand_op_stack(cpp_reader * pfile)1041404b540aSrobert _cpp_expand_op_stack (cpp_reader *pfile)
1042404b540aSrobert {
1043404b540aSrobert size_t old_size = (size_t) (pfile->op_limit - pfile->op_stack);
1044404b540aSrobert size_t new_size = old_size * 2 + 20;
1045404b540aSrobert
1046404b540aSrobert pfile->op_stack = XRESIZEVEC (struct op, pfile->op_stack, new_size);
1047404b540aSrobert pfile->op_limit = pfile->op_stack + new_size;
1048404b540aSrobert
1049404b540aSrobert return pfile->op_stack + old_size;
1050404b540aSrobert }
1051404b540aSrobert
1052404b540aSrobert /* Emits a warning if the effective sign of either operand of OP
1053404b540aSrobert changes because of integer promotions. */
1054404b540aSrobert static void
check_promotion(cpp_reader * pfile,const struct op * op)1055404b540aSrobert check_promotion (cpp_reader *pfile, const struct op *op)
1056404b540aSrobert {
1057404b540aSrobert if (op->value.unsignedp == op[-1].value.unsignedp)
1058404b540aSrobert return;
1059404b540aSrobert
1060404b540aSrobert if (op->value.unsignedp)
1061404b540aSrobert {
1062404b540aSrobert if (!num_positive (op[-1].value, CPP_OPTION (pfile, precision)))
1063404b540aSrobert cpp_error (pfile, CPP_DL_WARNING,
1064404b540aSrobert "the left operand of \"%s\" changes sign when promoted",
1065404b540aSrobert cpp_token_as_text (pfile, op->token));
1066404b540aSrobert }
1067404b540aSrobert else if (!num_positive (op->value, CPP_OPTION (pfile, precision)))
1068404b540aSrobert cpp_error (pfile, CPP_DL_WARNING,
1069404b540aSrobert "the right operand of \"%s\" changes sign when promoted",
1070404b540aSrobert cpp_token_as_text (pfile, op->token));
1071404b540aSrobert }
1072404b540aSrobert
1073404b540aSrobert /* Clears the unused high order bits of the number pointed to by PNUM. */
1074404b540aSrobert static cpp_num
num_trim(cpp_num num,size_t precision)1075404b540aSrobert num_trim (cpp_num num, size_t precision)
1076404b540aSrobert {
1077404b540aSrobert if (precision > PART_PRECISION)
1078404b540aSrobert {
1079404b540aSrobert precision -= PART_PRECISION;
1080404b540aSrobert if (precision < PART_PRECISION)
1081404b540aSrobert num.high &= ((cpp_num_part) 1 << precision) - 1;
1082404b540aSrobert }
1083404b540aSrobert else
1084404b540aSrobert {
1085404b540aSrobert if (precision < PART_PRECISION)
1086404b540aSrobert num.low &= ((cpp_num_part) 1 << precision) - 1;
1087404b540aSrobert num.high = 0;
1088404b540aSrobert }
1089404b540aSrobert
1090404b540aSrobert return num;
1091404b540aSrobert }
1092404b540aSrobert
1093404b540aSrobert /* True iff A (presumed signed) >= 0. */
1094404b540aSrobert static bool
num_positive(cpp_num num,size_t precision)1095404b540aSrobert num_positive (cpp_num num, size_t precision)
1096404b540aSrobert {
1097404b540aSrobert if (precision > PART_PRECISION)
1098404b540aSrobert {
1099404b540aSrobert precision -= PART_PRECISION;
1100404b540aSrobert return (num.high & (cpp_num_part) 1 << (precision - 1)) == 0;
1101404b540aSrobert }
1102404b540aSrobert
1103404b540aSrobert return (num.low & (cpp_num_part) 1 << (precision - 1)) == 0;
1104404b540aSrobert }
1105404b540aSrobert
1106404b540aSrobert /* Sign extend a number, with PRECISION significant bits and all
1107404b540aSrobert others assumed clear, to fill out a cpp_num structure. */
1108404b540aSrobert cpp_num
cpp_num_sign_extend(cpp_num num,size_t precision)1109404b540aSrobert cpp_num_sign_extend (cpp_num num, size_t precision)
1110404b540aSrobert {
1111404b540aSrobert if (!num.unsignedp)
1112404b540aSrobert {
1113404b540aSrobert if (precision > PART_PRECISION)
1114404b540aSrobert {
1115404b540aSrobert precision -= PART_PRECISION;
1116404b540aSrobert if (precision < PART_PRECISION
1117404b540aSrobert && (num.high & (cpp_num_part) 1 << (precision - 1)))
1118404b540aSrobert num.high |= ~(~(cpp_num_part) 0 >> (PART_PRECISION - precision));
1119404b540aSrobert }
1120404b540aSrobert else if (num.low & (cpp_num_part) 1 << (precision - 1))
1121404b540aSrobert {
1122404b540aSrobert if (precision < PART_PRECISION)
1123404b540aSrobert num.low |= ~(~(cpp_num_part) 0 >> (PART_PRECISION - precision));
1124404b540aSrobert num.high = ~(cpp_num_part) 0;
1125404b540aSrobert }
1126404b540aSrobert }
1127404b540aSrobert
1128404b540aSrobert return num;
1129404b540aSrobert }
1130404b540aSrobert
1131404b540aSrobert /* Returns the negative of NUM. */
1132404b540aSrobert static cpp_num
num_negate(cpp_num num,size_t precision)1133404b540aSrobert num_negate (cpp_num num, size_t precision)
1134404b540aSrobert {
1135404b540aSrobert cpp_num copy;
1136404b540aSrobert
1137404b540aSrobert copy = num;
1138404b540aSrobert num.high = ~num.high;
1139404b540aSrobert num.low = ~num.low;
1140404b540aSrobert if (++num.low == 0)
1141404b540aSrobert num.high++;
1142404b540aSrobert num = num_trim (num, precision);
1143404b540aSrobert num.overflow = (!num.unsignedp && num_eq (num, copy) && !num_zerop (num));
1144404b540aSrobert
1145404b540aSrobert return num;
1146404b540aSrobert }
1147404b540aSrobert
1148404b540aSrobert /* Returns true if A >= B. */
1149404b540aSrobert static bool
num_greater_eq(cpp_num pa,cpp_num pb,size_t precision)1150404b540aSrobert num_greater_eq (cpp_num pa, cpp_num pb, size_t precision)
1151404b540aSrobert {
1152404b540aSrobert bool unsignedp;
1153404b540aSrobert
1154404b540aSrobert unsignedp = pa.unsignedp || pb.unsignedp;
1155404b540aSrobert
1156404b540aSrobert if (!unsignedp)
1157404b540aSrobert {
1158404b540aSrobert /* Both numbers have signed type. If they are of different
1159404b540aSrobert sign, the answer is the sign of A. */
1160404b540aSrobert unsignedp = num_positive (pa, precision);
1161404b540aSrobert
1162404b540aSrobert if (unsignedp != num_positive (pb, precision))
1163404b540aSrobert return unsignedp;
1164404b540aSrobert
1165404b540aSrobert /* Otherwise we can do an unsigned comparison. */
1166404b540aSrobert }
1167404b540aSrobert
1168404b540aSrobert return (pa.high > pb.high) || (pa.high == pb.high && pa.low >= pb.low);
1169404b540aSrobert }
1170404b540aSrobert
1171404b540aSrobert /* Returns LHS OP RHS, where OP is a bit-wise operation. */
1172404b540aSrobert static cpp_num
num_bitwise_op(cpp_reader * pfile ATTRIBUTE_UNUSED,cpp_num lhs,cpp_num rhs,enum cpp_ttype op)1173404b540aSrobert num_bitwise_op (cpp_reader *pfile ATTRIBUTE_UNUSED,
1174404b540aSrobert cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
1175404b540aSrobert {
1176404b540aSrobert lhs.overflow = false;
1177404b540aSrobert lhs.unsignedp = lhs.unsignedp || rhs.unsignedp;
1178404b540aSrobert
1179404b540aSrobert /* As excess precision is zeroed, there is no need to num_trim () as
1180404b540aSrobert these operations cannot introduce a set bit there. */
1181404b540aSrobert if (op == CPP_AND)
1182404b540aSrobert {
1183404b540aSrobert lhs.low &= rhs.low;
1184404b540aSrobert lhs.high &= rhs.high;
1185404b540aSrobert }
1186404b540aSrobert else if (op == CPP_OR)
1187404b540aSrobert {
1188404b540aSrobert lhs.low |= rhs.low;
1189404b540aSrobert lhs.high |= rhs.high;
1190404b540aSrobert }
1191404b540aSrobert else
1192404b540aSrobert {
1193404b540aSrobert lhs.low ^= rhs.low;
1194404b540aSrobert lhs.high ^= rhs.high;
1195404b540aSrobert }
1196404b540aSrobert
1197404b540aSrobert return lhs;
1198404b540aSrobert }
1199404b540aSrobert
1200404b540aSrobert /* Returns LHS OP RHS, where OP is an inequality. */
1201404b540aSrobert static cpp_num
num_inequality_op(cpp_reader * pfile,cpp_num lhs,cpp_num rhs,enum cpp_ttype op)1202404b540aSrobert num_inequality_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs,
1203404b540aSrobert enum cpp_ttype op)
1204404b540aSrobert {
1205404b540aSrobert bool gte = num_greater_eq (lhs, rhs, CPP_OPTION (pfile, precision));
1206404b540aSrobert
1207404b540aSrobert if (op == CPP_GREATER_EQ)
1208404b540aSrobert lhs.low = gte;
1209404b540aSrobert else if (op == CPP_LESS)
1210404b540aSrobert lhs.low = !gte;
1211404b540aSrobert else if (op == CPP_GREATER)
1212404b540aSrobert lhs.low = gte && !num_eq (lhs, rhs);
1213404b540aSrobert else /* CPP_LESS_EQ. */
1214404b540aSrobert lhs.low = !gte || num_eq (lhs, rhs);
1215404b540aSrobert
1216404b540aSrobert lhs.high = 0;
1217404b540aSrobert lhs.overflow = false;
1218404b540aSrobert lhs.unsignedp = false;
1219404b540aSrobert return lhs;
1220404b540aSrobert }
1221404b540aSrobert
1222404b540aSrobert /* Returns LHS OP RHS, where OP is == or !=. */
1223404b540aSrobert static cpp_num
num_equality_op(cpp_reader * pfile ATTRIBUTE_UNUSED,cpp_num lhs,cpp_num rhs,enum cpp_ttype op)1224404b540aSrobert num_equality_op (cpp_reader *pfile ATTRIBUTE_UNUSED,
1225404b540aSrobert cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
1226404b540aSrobert {
1227404b540aSrobert /* Work around a 3.0.4 bug; see PR 6950. */
1228404b540aSrobert bool eq = num_eq (lhs, rhs);
1229404b540aSrobert if (op == CPP_NOT_EQ)
1230404b540aSrobert eq = !eq;
1231404b540aSrobert lhs.low = eq;
1232404b540aSrobert lhs.high = 0;
1233404b540aSrobert lhs.overflow = false;
1234404b540aSrobert lhs.unsignedp = false;
1235404b540aSrobert return lhs;
1236404b540aSrobert }
1237404b540aSrobert
1238404b540aSrobert /* Shift NUM, of width PRECISION, right by N bits. */
1239404b540aSrobert static cpp_num
num_rshift(cpp_num num,size_t precision,size_t n)1240404b540aSrobert num_rshift (cpp_num num, size_t precision, size_t n)
1241404b540aSrobert {
1242404b540aSrobert cpp_num_part sign_mask;
1243404b540aSrobert bool x = num_positive (num, precision);
1244404b540aSrobert
1245404b540aSrobert if (num.unsignedp || x)
1246404b540aSrobert sign_mask = 0;
1247404b540aSrobert else
1248404b540aSrobert sign_mask = ~(cpp_num_part) 0;
1249404b540aSrobert
1250404b540aSrobert if (n >= precision)
1251404b540aSrobert num.high = num.low = sign_mask;
1252404b540aSrobert else
1253404b540aSrobert {
1254404b540aSrobert /* Sign-extend. */
1255404b540aSrobert if (precision < PART_PRECISION)
1256404b540aSrobert num.high = sign_mask, num.low |= sign_mask << precision;
1257404b540aSrobert else if (precision < 2 * PART_PRECISION)
1258404b540aSrobert num.high |= sign_mask << (precision - PART_PRECISION);
1259404b540aSrobert
1260404b540aSrobert if (n >= PART_PRECISION)
1261404b540aSrobert {
1262404b540aSrobert n -= PART_PRECISION;
1263404b540aSrobert num.low = num.high;
1264404b540aSrobert num.high = sign_mask;
1265404b540aSrobert }
1266404b540aSrobert
1267404b540aSrobert if (n)
1268404b540aSrobert {
1269404b540aSrobert num.low = (num.low >> n) | (num.high << (PART_PRECISION - n));
1270404b540aSrobert num.high = (num.high >> n) | (sign_mask << (PART_PRECISION - n));
1271404b540aSrobert }
1272404b540aSrobert }
1273404b540aSrobert
1274404b540aSrobert num = num_trim (num, precision);
1275404b540aSrobert num.overflow = false;
1276404b540aSrobert return num;
1277404b540aSrobert }
1278404b540aSrobert
1279404b540aSrobert /* Shift NUM, of width PRECISION, left by N bits. */
1280404b540aSrobert static cpp_num
num_lshift(cpp_num num,size_t precision,size_t n)1281404b540aSrobert num_lshift (cpp_num num, size_t precision, size_t n)
1282404b540aSrobert {
1283404b540aSrobert if (n >= precision)
1284404b540aSrobert {
1285404b540aSrobert num.overflow = !num.unsignedp && !num_zerop (num);
1286404b540aSrobert num.high = num.low = 0;
1287404b540aSrobert }
1288404b540aSrobert else
1289404b540aSrobert {
1290404b540aSrobert cpp_num orig, maybe_orig;
1291404b540aSrobert size_t m = n;
1292404b540aSrobert
1293404b540aSrobert orig = num;
1294404b540aSrobert if (m >= PART_PRECISION)
1295404b540aSrobert {
1296404b540aSrobert m -= PART_PRECISION;
1297404b540aSrobert num.high = num.low;
1298404b540aSrobert num.low = 0;
1299404b540aSrobert }
1300404b540aSrobert if (m)
1301404b540aSrobert {
1302404b540aSrobert num.high = (num.high << m) | (num.low >> (PART_PRECISION - m));
1303404b540aSrobert num.low <<= m;
1304404b540aSrobert }
1305404b540aSrobert num = num_trim (num, precision);
1306404b540aSrobert
1307404b540aSrobert if (num.unsignedp)
1308404b540aSrobert num.overflow = false;
1309404b540aSrobert else
1310404b540aSrobert {
1311404b540aSrobert maybe_orig = num_rshift (num, precision, n);
1312404b540aSrobert num.overflow = !num_eq (orig, maybe_orig);
1313404b540aSrobert }
1314404b540aSrobert }
1315404b540aSrobert
1316404b540aSrobert return num;
1317404b540aSrobert }
1318404b540aSrobert
1319404b540aSrobert /* The four unary operators: +, -, ! and ~. */
1320404b540aSrobert static cpp_num
num_unary_op(cpp_reader * pfile,cpp_num num,enum cpp_ttype op)1321404b540aSrobert num_unary_op (cpp_reader *pfile, cpp_num num, enum cpp_ttype op)
1322404b540aSrobert {
1323404b540aSrobert switch (op)
1324404b540aSrobert {
1325404b540aSrobert case CPP_UPLUS:
1326404b540aSrobert if (CPP_WTRADITIONAL (pfile) && !pfile->state.skip_eval)
1327404b540aSrobert cpp_error (pfile, CPP_DL_WARNING,
1328404b540aSrobert "traditional C rejects the unary plus operator");
1329404b540aSrobert num.overflow = false;
1330404b540aSrobert break;
1331404b540aSrobert
1332404b540aSrobert case CPP_UMINUS:
1333404b540aSrobert num = num_negate (num, CPP_OPTION (pfile, precision));
1334404b540aSrobert break;
1335404b540aSrobert
1336404b540aSrobert case CPP_COMPL:
1337404b540aSrobert num.high = ~num.high;
1338404b540aSrobert num.low = ~num.low;
1339404b540aSrobert num = num_trim (num, CPP_OPTION (pfile, precision));
1340404b540aSrobert num.overflow = false;
1341404b540aSrobert break;
1342404b540aSrobert
1343404b540aSrobert default: /* case CPP_NOT: */
1344404b540aSrobert num.low = num_zerop (num);
1345404b540aSrobert num.high = 0;
1346404b540aSrobert num.overflow = false;
1347404b540aSrobert num.unsignedp = false;
1348404b540aSrobert break;
1349404b540aSrobert }
1350404b540aSrobert
1351404b540aSrobert return num;
1352404b540aSrobert }
1353404b540aSrobert
1354404b540aSrobert /* The various binary operators. */
1355404b540aSrobert static cpp_num
num_binary_op(cpp_reader * pfile,cpp_num lhs,cpp_num rhs,enum cpp_ttype op)1356404b540aSrobert num_binary_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
1357404b540aSrobert {
1358404b540aSrobert cpp_num result;
1359404b540aSrobert size_t precision = CPP_OPTION (pfile, precision);
1360404b540aSrobert size_t n;
1361404b540aSrobert
1362404b540aSrobert switch (op)
1363404b540aSrobert {
1364404b540aSrobert /* Shifts. */
1365404b540aSrobert case CPP_LSHIFT:
1366404b540aSrobert case CPP_RSHIFT:
1367404b540aSrobert if (!rhs.unsignedp && !num_positive (rhs, precision))
1368404b540aSrobert {
1369404b540aSrobert /* A negative shift is a positive shift the other way. */
1370404b540aSrobert if (op == CPP_LSHIFT)
1371404b540aSrobert op = CPP_RSHIFT;
1372404b540aSrobert else
1373404b540aSrobert op = CPP_LSHIFT;
1374404b540aSrobert rhs = num_negate (rhs, precision);
1375404b540aSrobert }
1376404b540aSrobert if (rhs.high)
1377404b540aSrobert n = ~0; /* Maximal. */
1378404b540aSrobert else
1379404b540aSrobert n = rhs.low;
1380404b540aSrobert if (op == CPP_LSHIFT)
1381404b540aSrobert lhs = num_lshift (lhs, precision, n);
1382404b540aSrobert else
1383404b540aSrobert lhs = num_rshift (lhs, precision, n);
1384404b540aSrobert break;
1385404b540aSrobert
1386404b540aSrobert /* Arithmetic. */
1387404b540aSrobert case CPP_MINUS:
1388404b540aSrobert rhs = num_negate (rhs, precision);
1389404b540aSrobert case CPP_PLUS:
1390404b540aSrobert result.low = lhs.low + rhs.low;
1391404b540aSrobert result.high = lhs.high + rhs.high;
1392404b540aSrobert if (result.low < lhs.low)
1393404b540aSrobert result.high++;
1394404b540aSrobert result.unsignedp = lhs.unsignedp || rhs.unsignedp;
1395404b540aSrobert result.overflow = false;
1396404b540aSrobert
1397404b540aSrobert result = num_trim (result, precision);
1398404b540aSrobert if (!result.unsignedp)
1399404b540aSrobert {
1400404b540aSrobert bool lhsp = num_positive (lhs, precision);
1401404b540aSrobert result.overflow = (lhsp == num_positive (rhs, precision)
1402404b540aSrobert && lhsp != num_positive (result, precision));
1403404b540aSrobert }
1404404b540aSrobert return result;
1405404b540aSrobert
1406404b540aSrobert /* Comma. */
1407404b540aSrobert default: /* case CPP_COMMA: */
1408404b540aSrobert if (CPP_PEDANTIC (pfile) && (!CPP_OPTION (pfile, c99)
1409404b540aSrobert || !pfile->state.skip_eval))
1410404b540aSrobert cpp_error (pfile, CPP_DL_PEDWARN,
1411404b540aSrobert "comma operator in operand of #if");
1412404b540aSrobert lhs = rhs;
1413404b540aSrobert break;
1414404b540aSrobert }
1415404b540aSrobert
1416404b540aSrobert return lhs;
1417404b540aSrobert }
1418404b540aSrobert
1419404b540aSrobert /* Multiplies two unsigned cpp_num_parts to give a cpp_num. This
1420404b540aSrobert cannot overflow. */
1421404b540aSrobert static cpp_num
num_part_mul(cpp_num_part lhs,cpp_num_part rhs)1422404b540aSrobert num_part_mul (cpp_num_part lhs, cpp_num_part rhs)
1423404b540aSrobert {
1424404b540aSrobert cpp_num result;
1425404b540aSrobert cpp_num_part middle[2], temp;
1426404b540aSrobert
1427404b540aSrobert result.low = LOW_PART (lhs) * LOW_PART (rhs);
1428404b540aSrobert result.high = HIGH_PART (lhs) * HIGH_PART (rhs);
1429404b540aSrobert
1430404b540aSrobert middle[0] = LOW_PART (lhs) * HIGH_PART (rhs);
1431404b540aSrobert middle[1] = HIGH_PART (lhs) * LOW_PART (rhs);
1432404b540aSrobert
1433404b540aSrobert temp = result.low;
1434404b540aSrobert result.low += LOW_PART (middle[0]) << (PART_PRECISION / 2);
1435404b540aSrobert if (result.low < temp)
1436404b540aSrobert result.high++;
1437404b540aSrobert
1438404b540aSrobert temp = result.low;
1439404b540aSrobert result.low += LOW_PART (middle[1]) << (PART_PRECISION / 2);
1440404b540aSrobert if (result.low < temp)
1441404b540aSrobert result.high++;
1442404b540aSrobert
1443404b540aSrobert result.high += HIGH_PART (middle[0]);
1444404b540aSrobert result.high += HIGH_PART (middle[1]);
1445404b540aSrobert result.unsignedp = true;
1446404b540aSrobert result.overflow = false;
1447404b540aSrobert
1448404b540aSrobert return result;
1449404b540aSrobert }
1450404b540aSrobert
1451404b540aSrobert /* Multiply two preprocessing numbers. */
1452404b540aSrobert static cpp_num
num_mul(cpp_reader * pfile,cpp_num lhs,cpp_num rhs)1453404b540aSrobert num_mul (cpp_reader *pfile, cpp_num lhs, cpp_num rhs)
1454404b540aSrobert {
1455404b540aSrobert cpp_num result, temp;
1456404b540aSrobert bool unsignedp = lhs.unsignedp || rhs.unsignedp;
1457404b540aSrobert bool overflow, negate = false;
1458404b540aSrobert size_t precision = CPP_OPTION (pfile, precision);
1459404b540aSrobert
1460404b540aSrobert /* Prepare for unsigned multiplication. */
1461404b540aSrobert if (!unsignedp)
1462404b540aSrobert {
1463404b540aSrobert if (!num_positive (lhs, precision))
1464404b540aSrobert negate = !negate, lhs = num_negate (lhs, precision);
1465404b540aSrobert if (!num_positive (rhs, precision))
1466404b540aSrobert negate = !negate, rhs = num_negate (rhs, precision);
1467404b540aSrobert }
1468404b540aSrobert
1469404b540aSrobert overflow = lhs.high && rhs.high;
1470404b540aSrobert result = num_part_mul (lhs.low, rhs.low);
1471404b540aSrobert
1472404b540aSrobert temp = num_part_mul (lhs.high, rhs.low);
1473404b540aSrobert result.high += temp.low;
1474404b540aSrobert if (temp.high)
1475404b540aSrobert overflow = true;
1476404b540aSrobert
1477404b540aSrobert temp = num_part_mul (lhs.low, rhs.high);
1478404b540aSrobert result.high += temp.low;
1479404b540aSrobert if (temp.high)
1480404b540aSrobert overflow = true;
1481404b540aSrobert
1482404b540aSrobert temp.low = result.low, temp.high = result.high;
1483404b540aSrobert result = num_trim (result, precision);
1484404b540aSrobert if (!num_eq (result, temp))
1485404b540aSrobert overflow = true;
1486404b540aSrobert
1487404b540aSrobert if (negate)
1488404b540aSrobert result = num_negate (result, precision);
1489404b540aSrobert
1490404b540aSrobert if (unsignedp)
1491404b540aSrobert result.overflow = false;
1492404b540aSrobert else
1493404b540aSrobert result.overflow = overflow || (num_positive (result, precision) ^ !negate
1494404b540aSrobert && !num_zerop (result));
1495404b540aSrobert result.unsignedp = unsignedp;
1496404b540aSrobert
1497404b540aSrobert return result;
1498404b540aSrobert }
1499404b540aSrobert
1500404b540aSrobert /* Divide two preprocessing numbers, returning the answer or the
1501404b540aSrobert remainder depending upon OP. */
1502404b540aSrobert static cpp_num
num_div_op(cpp_reader * pfile,cpp_num lhs,cpp_num rhs,enum cpp_ttype op)1503404b540aSrobert num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
1504404b540aSrobert {
1505404b540aSrobert cpp_num result, sub;
1506404b540aSrobert cpp_num_part mask;
1507404b540aSrobert bool unsignedp = lhs.unsignedp || rhs.unsignedp;
1508404b540aSrobert bool negate = false, lhs_neg = false;
1509404b540aSrobert size_t i, precision = CPP_OPTION (pfile, precision);
1510404b540aSrobert
1511404b540aSrobert /* Prepare for unsigned division. */
1512404b540aSrobert if (!unsignedp)
1513404b540aSrobert {
1514404b540aSrobert if (!num_positive (lhs, precision))
1515404b540aSrobert negate = !negate, lhs_neg = true, lhs = num_negate (lhs, precision);
1516404b540aSrobert if (!num_positive (rhs, precision))
1517404b540aSrobert negate = !negate, rhs = num_negate (rhs, precision);
1518404b540aSrobert }
1519404b540aSrobert
1520404b540aSrobert /* Find the high bit. */
1521404b540aSrobert if (rhs.high)
1522404b540aSrobert {
1523404b540aSrobert i = precision - 1;
1524404b540aSrobert mask = (cpp_num_part) 1 << (i - PART_PRECISION);
1525404b540aSrobert for (; ; i--, mask >>= 1)
1526404b540aSrobert if (rhs.high & mask)
1527404b540aSrobert break;
1528404b540aSrobert }
1529404b540aSrobert else if (rhs.low)
1530404b540aSrobert {
1531404b540aSrobert if (precision > PART_PRECISION)
1532404b540aSrobert i = precision - PART_PRECISION - 1;
1533404b540aSrobert else
1534404b540aSrobert i = precision - 1;
1535404b540aSrobert mask = (cpp_num_part) 1 << i;
1536404b540aSrobert for (; ; i--, mask >>= 1)
1537404b540aSrobert if (rhs.low & mask)
1538404b540aSrobert break;
1539404b540aSrobert }
1540404b540aSrobert else
1541404b540aSrobert {
1542404b540aSrobert if (!pfile->state.skip_eval)
1543404b540aSrobert cpp_error (pfile, CPP_DL_ERROR, "division by zero in #if");
1544404b540aSrobert return lhs;
1545404b540aSrobert }
1546404b540aSrobert
1547404b540aSrobert /* First nonzero bit of RHS is bit I. Do naive division by
1548404b540aSrobert shifting the RHS fully left, and subtracting from LHS if LHS is
1549404b540aSrobert at least as big, and then repeating but with one less shift.
1550404b540aSrobert This is not very efficient, but is easy to understand. */
1551404b540aSrobert
1552404b540aSrobert rhs.unsignedp = true;
1553404b540aSrobert lhs.unsignedp = true;
1554404b540aSrobert i = precision - i - 1;
1555404b540aSrobert sub = num_lshift (rhs, precision, i);
1556404b540aSrobert
1557404b540aSrobert result.high = result.low = 0;
1558404b540aSrobert for (;;)
1559404b540aSrobert {
1560404b540aSrobert if (num_greater_eq (lhs, sub, precision))
1561404b540aSrobert {
1562404b540aSrobert lhs = num_binary_op (pfile, lhs, sub, CPP_MINUS);
1563404b540aSrobert if (i >= PART_PRECISION)
1564404b540aSrobert result.high |= (cpp_num_part) 1 << (i - PART_PRECISION);
1565404b540aSrobert else
1566404b540aSrobert result.low |= (cpp_num_part) 1 << i;
1567404b540aSrobert }
1568404b540aSrobert if (i-- == 0)
1569404b540aSrobert break;
1570404b540aSrobert sub.low = (sub.low >> 1) | (sub.high << (PART_PRECISION - 1));
1571404b540aSrobert sub.high >>= 1;
1572404b540aSrobert }
1573404b540aSrobert
1574404b540aSrobert /* We divide so that the remainder has the sign of the LHS. */
1575404b540aSrobert if (op == CPP_DIV)
1576404b540aSrobert {
1577404b540aSrobert result.unsignedp = unsignedp;
1578404b540aSrobert result.overflow = false;
1579404b540aSrobert if (!unsignedp)
1580404b540aSrobert {
1581404b540aSrobert if (negate)
1582404b540aSrobert result = num_negate (result, precision);
1583404b540aSrobert result.overflow = num_positive (result, precision) ^ !negate;
1584404b540aSrobert }
1585404b540aSrobert
1586404b540aSrobert return result;
1587404b540aSrobert }
1588404b540aSrobert
1589404b540aSrobert /* CPP_MOD. */
1590404b540aSrobert lhs.unsignedp = unsignedp;
1591404b540aSrobert lhs.overflow = false;
1592404b540aSrobert if (lhs_neg)
1593404b540aSrobert lhs = num_negate (lhs, precision);
1594404b540aSrobert
1595404b540aSrobert return lhs;
1596404b540aSrobert }
1597