1627f7eb2Smrg /* Compiler arithmetic
2*4c3eb207Smrg Copyright (C) 2000-2020 Free Software Foundation, Inc.
3627f7eb2Smrg Contributed by Andy Vaught
4627f7eb2Smrg
5627f7eb2Smrg This file is part of GCC.
6627f7eb2Smrg
7627f7eb2Smrg GCC is free software; you can redistribute it and/or modify it under
8627f7eb2Smrg the terms of the GNU General Public License as published by the Free
9627f7eb2Smrg Software Foundation; either version 3, or (at your option) any later
10627f7eb2Smrg version.
11627f7eb2Smrg
12627f7eb2Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13627f7eb2Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
14627f7eb2Smrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15627f7eb2Smrg for more details.
16627f7eb2Smrg
17627f7eb2Smrg You should have received a copy of the GNU General Public License
18627f7eb2Smrg along with GCC; see the file COPYING3. If not see
19627f7eb2Smrg <http://www.gnu.org/licenses/>. */
20627f7eb2Smrg
21627f7eb2Smrg /* Since target arithmetic must be done on the host, there has to
22627f7eb2Smrg be some way of evaluating arithmetic expressions as the host
23627f7eb2Smrg would evaluate them. We use the GNU MP library and the MPFR
24627f7eb2Smrg library to do arithmetic, and this file provides the interface. */
25627f7eb2Smrg
26627f7eb2Smrg #include "config.h"
27627f7eb2Smrg #include "system.h"
28627f7eb2Smrg #include "coretypes.h"
29627f7eb2Smrg #include "options.h"
30627f7eb2Smrg #include "gfortran.h"
31627f7eb2Smrg #include "arith.h"
32627f7eb2Smrg #include "target-memory.h"
33627f7eb2Smrg #include "constructor.h"
34627f7eb2Smrg
35627f7eb2Smrg bool gfc_seen_div0;
36627f7eb2Smrg
37627f7eb2Smrg /* MPFR does not have a direct replacement for mpz_set_f() from GMP.
38627f7eb2Smrg It's easily implemented with a few calls though. */
39627f7eb2Smrg
40627f7eb2Smrg void
gfc_mpfr_to_mpz(mpz_t z,mpfr_t x,locus * where)41627f7eb2Smrg gfc_mpfr_to_mpz (mpz_t z, mpfr_t x, locus *where)
42627f7eb2Smrg {
43*4c3eb207Smrg mpfr_exp_t e;
44627f7eb2Smrg
45627f7eb2Smrg if (mpfr_inf_p (x) || mpfr_nan_p (x))
46627f7eb2Smrg {
47627f7eb2Smrg gfc_error ("Conversion of an Infinity or Not-a-Number at %L "
48627f7eb2Smrg "to INTEGER", where);
49627f7eb2Smrg mpz_set_ui (z, 0);
50627f7eb2Smrg return;
51627f7eb2Smrg }
52627f7eb2Smrg
53627f7eb2Smrg e = mpfr_get_z_exp (z, x);
54627f7eb2Smrg
55627f7eb2Smrg if (e > 0)
56627f7eb2Smrg mpz_mul_2exp (z, z, e);
57627f7eb2Smrg else
58627f7eb2Smrg mpz_tdiv_q_2exp (z, z, -e);
59627f7eb2Smrg }
60627f7eb2Smrg
61627f7eb2Smrg
62627f7eb2Smrg /* Set the model number precision by the requested KIND. */
63627f7eb2Smrg
64627f7eb2Smrg void
gfc_set_model_kind(int kind)65627f7eb2Smrg gfc_set_model_kind (int kind)
66627f7eb2Smrg {
67627f7eb2Smrg int index = gfc_validate_kind (BT_REAL, kind, false);
68627f7eb2Smrg int base2prec;
69627f7eb2Smrg
70627f7eb2Smrg base2prec = gfc_real_kinds[index].digits;
71627f7eb2Smrg if (gfc_real_kinds[index].radix != 2)
72627f7eb2Smrg base2prec *= gfc_real_kinds[index].radix / 2;
73627f7eb2Smrg mpfr_set_default_prec (base2prec);
74627f7eb2Smrg }
75627f7eb2Smrg
76627f7eb2Smrg
77627f7eb2Smrg /* Set the model number precision from mpfr_t x. */
78627f7eb2Smrg
79627f7eb2Smrg void
gfc_set_model(mpfr_t x)80627f7eb2Smrg gfc_set_model (mpfr_t x)
81627f7eb2Smrg {
82627f7eb2Smrg mpfr_set_default_prec (mpfr_get_prec (x));
83627f7eb2Smrg }
84627f7eb2Smrg
85627f7eb2Smrg
86627f7eb2Smrg /* Given an arithmetic error code, return a pointer to a string that
87627f7eb2Smrg explains the error. */
88627f7eb2Smrg
89627f7eb2Smrg static const char *
gfc_arith_error(arith code)90627f7eb2Smrg gfc_arith_error (arith code)
91627f7eb2Smrg {
92627f7eb2Smrg const char *p;
93627f7eb2Smrg
94627f7eb2Smrg switch (code)
95627f7eb2Smrg {
96627f7eb2Smrg case ARITH_OK:
97627f7eb2Smrg p = _("Arithmetic OK at %L");
98627f7eb2Smrg break;
99627f7eb2Smrg case ARITH_OVERFLOW:
100627f7eb2Smrg p = _("Arithmetic overflow at %L");
101627f7eb2Smrg break;
102627f7eb2Smrg case ARITH_UNDERFLOW:
103627f7eb2Smrg p = _("Arithmetic underflow at %L");
104627f7eb2Smrg break;
105627f7eb2Smrg case ARITH_NAN:
106627f7eb2Smrg p = _("Arithmetic NaN at %L");
107627f7eb2Smrg break;
108627f7eb2Smrg case ARITH_DIV0:
109627f7eb2Smrg p = _("Division by zero at %L");
110627f7eb2Smrg break;
111627f7eb2Smrg case ARITH_INCOMMENSURATE:
112627f7eb2Smrg p = _("Array operands are incommensurate at %L");
113627f7eb2Smrg break;
114627f7eb2Smrg case ARITH_ASYMMETRIC:
115627f7eb2Smrg p =
116627f7eb2Smrg _("Integer outside symmetric range implied by Standard Fortran at %L");
117627f7eb2Smrg break;
118627f7eb2Smrg case ARITH_WRONGCONCAT:
119627f7eb2Smrg p =
120627f7eb2Smrg _("Illegal type in character concatenation at %L");
121627f7eb2Smrg break;
122627f7eb2Smrg
123627f7eb2Smrg default:
124627f7eb2Smrg gfc_internal_error ("gfc_arith_error(): Bad error code");
125627f7eb2Smrg }
126627f7eb2Smrg
127627f7eb2Smrg return p;
128627f7eb2Smrg }
129627f7eb2Smrg
130627f7eb2Smrg
131627f7eb2Smrg /* Get things ready to do math. */
132627f7eb2Smrg
133627f7eb2Smrg void
gfc_arith_init_1(void)134627f7eb2Smrg gfc_arith_init_1 (void)
135627f7eb2Smrg {
136627f7eb2Smrg gfc_integer_info *int_info;
137627f7eb2Smrg gfc_real_info *real_info;
138627f7eb2Smrg mpfr_t a, b;
139627f7eb2Smrg int i;
140627f7eb2Smrg
141627f7eb2Smrg mpfr_set_default_prec (128);
142627f7eb2Smrg mpfr_init (a);
143627f7eb2Smrg
144627f7eb2Smrg /* Convert the minimum and maximum values for each kind into their
145627f7eb2Smrg GNU MP representation. */
146627f7eb2Smrg for (int_info = gfc_integer_kinds; int_info->kind != 0; int_info++)
147627f7eb2Smrg {
148627f7eb2Smrg /* Huge */
149627f7eb2Smrg mpz_init (int_info->huge);
150627f7eb2Smrg mpz_set_ui (int_info->huge, int_info->radix);
151627f7eb2Smrg mpz_pow_ui (int_info->huge, int_info->huge, int_info->digits);
152627f7eb2Smrg mpz_sub_ui (int_info->huge, int_info->huge, 1);
153627f7eb2Smrg
154627f7eb2Smrg /* These are the numbers that are actually representable by the
155627f7eb2Smrg target. For bases other than two, this needs to be changed. */
156627f7eb2Smrg if (int_info->radix != 2)
157627f7eb2Smrg gfc_internal_error ("Fix min_int calculation");
158627f7eb2Smrg
159627f7eb2Smrg /* See PRs 13490 and 17912, related to integer ranges.
160627f7eb2Smrg The pedantic_min_int exists for range checking when a program
161627f7eb2Smrg is compiled with -pedantic, and reflects the belief that
162627f7eb2Smrg Standard Fortran requires integers to be symmetrical, i.e.
163627f7eb2Smrg every negative integer must have a representable positive
164627f7eb2Smrg absolute value, and vice versa. */
165627f7eb2Smrg
166627f7eb2Smrg mpz_init (int_info->pedantic_min_int);
167627f7eb2Smrg mpz_neg (int_info->pedantic_min_int, int_info->huge);
168627f7eb2Smrg
169627f7eb2Smrg mpz_init (int_info->min_int);
170627f7eb2Smrg mpz_sub_ui (int_info->min_int, int_info->pedantic_min_int, 1);
171627f7eb2Smrg
172627f7eb2Smrg /* Range */
173627f7eb2Smrg mpfr_set_z (a, int_info->huge, GFC_RND_MODE);
174627f7eb2Smrg mpfr_log10 (a, a, GFC_RND_MODE);
175627f7eb2Smrg mpfr_trunc (a, a);
176627f7eb2Smrg int_info->range = (int) mpfr_get_si (a, GFC_RND_MODE);
177627f7eb2Smrg }
178627f7eb2Smrg
179627f7eb2Smrg mpfr_clear (a);
180627f7eb2Smrg
181627f7eb2Smrg for (real_info = gfc_real_kinds; real_info->kind != 0; real_info++)
182627f7eb2Smrg {
183627f7eb2Smrg gfc_set_model_kind (real_info->kind);
184627f7eb2Smrg
185627f7eb2Smrg mpfr_init (a);
186627f7eb2Smrg mpfr_init (b);
187627f7eb2Smrg
188627f7eb2Smrg /* huge(x) = (1 - b**(-p)) * b**(emax-1) * b */
189627f7eb2Smrg /* 1 - b**(-p) */
190627f7eb2Smrg mpfr_init (real_info->huge);
191627f7eb2Smrg mpfr_set_ui (real_info->huge, 1, GFC_RND_MODE);
192627f7eb2Smrg mpfr_set_ui (a, real_info->radix, GFC_RND_MODE);
193627f7eb2Smrg mpfr_pow_si (a, a, -real_info->digits, GFC_RND_MODE);
194627f7eb2Smrg mpfr_sub (real_info->huge, real_info->huge, a, GFC_RND_MODE);
195627f7eb2Smrg
196627f7eb2Smrg /* b**(emax-1) */
197627f7eb2Smrg mpfr_set_ui (a, real_info->radix, GFC_RND_MODE);
198627f7eb2Smrg mpfr_pow_ui (a, a, real_info->max_exponent - 1, GFC_RND_MODE);
199627f7eb2Smrg
200627f7eb2Smrg /* (1 - b**(-p)) * b**(emax-1) */
201627f7eb2Smrg mpfr_mul (real_info->huge, real_info->huge, a, GFC_RND_MODE);
202627f7eb2Smrg
203627f7eb2Smrg /* (1 - b**(-p)) * b**(emax-1) * b */
204627f7eb2Smrg mpfr_mul_ui (real_info->huge, real_info->huge, real_info->radix,
205627f7eb2Smrg GFC_RND_MODE);
206627f7eb2Smrg
207627f7eb2Smrg /* tiny(x) = b**(emin-1) */
208627f7eb2Smrg mpfr_init (real_info->tiny);
209627f7eb2Smrg mpfr_set_ui (real_info->tiny, real_info->radix, GFC_RND_MODE);
210627f7eb2Smrg mpfr_pow_si (real_info->tiny, real_info->tiny,
211627f7eb2Smrg real_info->min_exponent - 1, GFC_RND_MODE);
212627f7eb2Smrg
213627f7eb2Smrg /* subnormal (x) = b**(emin - digit) */
214627f7eb2Smrg mpfr_init (real_info->subnormal);
215627f7eb2Smrg mpfr_set_ui (real_info->subnormal, real_info->radix, GFC_RND_MODE);
216627f7eb2Smrg mpfr_pow_si (real_info->subnormal, real_info->subnormal,
217627f7eb2Smrg real_info->min_exponent - real_info->digits, GFC_RND_MODE);
218627f7eb2Smrg
219627f7eb2Smrg /* epsilon(x) = b**(1-p) */
220627f7eb2Smrg mpfr_init (real_info->epsilon);
221627f7eb2Smrg mpfr_set_ui (real_info->epsilon, real_info->radix, GFC_RND_MODE);
222627f7eb2Smrg mpfr_pow_si (real_info->epsilon, real_info->epsilon,
223627f7eb2Smrg 1 - real_info->digits, GFC_RND_MODE);
224627f7eb2Smrg
225627f7eb2Smrg /* range(x) = int(min(log10(huge(x)), -log10(tiny)) */
226627f7eb2Smrg mpfr_log10 (a, real_info->huge, GFC_RND_MODE);
227627f7eb2Smrg mpfr_log10 (b, real_info->tiny, GFC_RND_MODE);
228627f7eb2Smrg mpfr_neg (b, b, GFC_RND_MODE);
229627f7eb2Smrg
230627f7eb2Smrg /* a = min(a, b) */
231627f7eb2Smrg mpfr_min (a, a, b, GFC_RND_MODE);
232627f7eb2Smrg mpfr_trunc (a, a);
233627f7eb2Smrg real_info->range = (int) mpfr_get_si (a, GFC_RND_MODE);
234627f7eb2Smrg
235627f7eb2Smrg /* precision(x) = int((p - 1) * log10(b)) + k */
236627f7eb2Smrg mpfr_set_ui (a, real_info->radix, GFC_RND_MODE);
237627f7eb2Smrg mpfr_log10 (a, a, GFC_RND_MODE);
238627f7eb2Smrg mpfr_mul_ui (a, a, real_info->digits - 1, GFC_RND_MODE);
239627f7eb2Smrg mpfr_trunc (a, a);
240627f7eb2Smrg real_info->precision = (int) mpfr_get_si (a, GFC_RND_MODE);
241627f7eb2Smrg
242627f7eb2Smrg /* If the radix is an integral power of 10, add one to the precision. */
243627f7eb2Smrg for (i = 10; i <= real_info->radix; i *= 10)
244627f7eb2Smrg if (i == real_info->radix)
245627f7eb2Smrg real_info->precision++;
246627f7eb2Smrg
247627f7eb2Smrg mpfr_clears (a, b, NULL);
248627f7eb2Smrg }
249627f7eb2Smrg }
250627f7eb2Smrg
251627f7eb2Smrg
252627f7eb2Smrg /* Clean up, get rid of numeric constants. */
253627f7eb2Smrg
254627f7eb2Smrg void
gfc_arith_done_1(void)255627f7eb2Smrg gfc_arith_done_1 (void)
256627f7eb2Smrg {
257627f7eb2Smrg gfc_integer_info *ip;
258627f7eb2Smrg gfc_real_info *rp;
259627f7eb2Smrg
260627f7eb2Smrg for (ip = gfc_integer_kinds; ip->kind; ip++)
261627f7eb2Smrg {
262627f7eb2Smrg mpz_clear (ip->min_int);
263627f7eb2Smrg mpz_clear (ip->pedantic_min_int);
264627f7eb2Smrg mpz_clear (ip->huge);
265627f7eb2Smrg }
266627f7eb2Smrg
267627f7eb2Smrg for (rp = gfc_real_kinds; rp->kind; rp++)
268627f7eb2Smrg mpfr_clears (rp->epsilon, rp->huge, rp->tiny, rp->subnormal, NULL);
269627f7eb2Smrg
270627f7eb2Smrg mpfr_free_cache ();
271627f7eb2Smrg }
272627f7eb2Smrg
273627f7eb2Smrg
274627f7eb2Smrg /* Given a wide character value and a character kind, determine whether
275627f7eb2Smrg the character is representable for that kind. */
276627f7eb2Smrg bool
gfc_check_character_range(gfc_char_t c,int kind)277627f7eb2Smrg gfc_check_character_range (gfc_char_t c, int kind)
278627f7eb2Smrg {
279627f7eb2Smrg /* As wide characters are stored as 32-bit values, they're all
280627f7eb2Smrg representable in UCS=4. */
281627f7eb2Smrg if (kind == 4)
282627f7eb2Smrg return true;
283627f7eb2Smrg
284627f7eb2Smrg if (kind == 1)
285627f7eb2Smrg return c <= 255 ? true : false;
286627f7eb2Smrg
287627f7eb2Smrg gcc_unreachable ();
288627f7eb2Smrg }
289627f7eb2Smrg
290627f7eb2Smrg
291627f7eb2Smrg /* Given an integer and a kind, make sure that the integer lies within
292627f7eb2Smrg the range of the kind. Returns ARITH_OK, ARITH_ASYMMETRIC or
293627f7eb2Smrg ARITH_OVERFLOW. */
294627f7eb2Smrg
295627f7eb2Smrg arith
gfc_check_integer_range(mpz_t p,int kind)296627f7eb2Smrg gfc_check_integer_range (mpz_t p, int kind)
297627f7eb2Smrg {
298627f7eb2Smrg arith result;
299627f7eb2Smrg int i;
300627f7eb2Smrg
301627f7eb2Smrg i = gfc_validate_kind (BT_INTEGER, kind, false);
302627f7eb2Smrg result = ARITH_OK;
303627f7eb2Smrg
304627f7eb2Smrg if (pedantic)
305627f7eb2Smrg {
306627f7eb2Smrg if (mpz_cmp (p, gfc_integer_kinds[i].pedantic_min_int) < 0)
307627f7eb2Smrg result = ARITH_ASYMMETRIC;
308627f7eb2Smrg }
309627f7eb2Smrg
310627f7eb2Smrg
311627f7eb2Smrg if (flag_range_check == 0)
312627f7eb2Smrg return result;
313627f7eb2Smrg
314627f7eb2Smrg if (mpz_cmp (p, gfc_integer_kinds[i].min_int) < 0
315627f7eb2Smrg || mpz_cmp (p, gfc_integer_kinds[i].huge) > 0)
316627f7eb2Smrg result = ARITH_OVERFLOW;
317627f7eb2Smrg
318627f7eb2Smrg return result;
319627f7eb2Smrg }
320627f7eb2Smrg
321627f7eb2Smrg
322627f7eb2Smrg /* Given a real and a kind, make sure that the real lies within the
323627f7eb2Smrg range of the kind. Returns ARITH_OK, ARITH_OVERFLOW or
324627f7eb2Smrg ARITH_UNDERFLOW. */
325627f7eb2Smrg
326627f7eb2Smrg static arith
gfc_check_real_range(mpfr_t p,int kind)327627f7eb2Smrg gfc_check_real_range (mpfr_t p, int kind)
328627f7eb2Smrg {
329627f7eb2Smrg arith retval;
330627f7eb2Smrg mpfr_t q;
331627f7eb2Smrg int i;
332627f7eb2Smrg
333627f7eb2Smrg i = gfc_validate_kind (BT_REAL, kind, false);
334627f7eb2Smrg
335627f7eb2Smrg gfc_set_model (p);
336627f7eb2Smrg mpfr_init (q);
337627f7eb2Smrg mpfr_abs (q, p, GFC_RND_MODE);
338627f7eb2Smrg
339627f7eb2Smrg retval = ARITH_OK;
340627f7eb2Smrg
341627f7eb2Smrg if (mpfr_inf_p (p))
342627f7eb2Smrg {
343627f7eb2Smrg if (flag_range_check != 0)
344627f7eb2Smrg retval = ARITH_OVERFLOW;
345627f7eb2Smrg }
346627f7eb2Smrg else if (mpfr_nan_p (p))
347627f7eb2Smrg {
348627f7eb2Smrg if (flag_range_check != 0)
349627f7eb2Smrg retval = ARITH_NAN;
350627f7eb2Smrg }
351627f7eb2Smrg else if (mpfr_sgn (q) == 0)
352627f7eb2Smrg {
353627f7eb2Smrg mpfr_clear (q);
354627f7eb2Smrg return retval;
355627f7eb2Smrg }
356627f7eb2Smrg else if (mpfr_cmp (q, gfc_real_kinds[i].huge) > 0)
357627f7eb2Smrg {
358627f7eb2Smrg if (flag_range_check == 0)
359627f7eb2Smrg mpfr_set_inf (p, mpfr_sgn (p));
360627f7eb2Smrg else
361627f7eb2Smrg retval = ARITH_OVERFLOW;
362627f7eb2Smrg }
363627f7eb2Smrg else if (mpfr_cmp (q, gfc_real_kinds[i].subnormal) < 0)
364627f7eb2Smrg {
365627f7eb2Smrg if (flag_range_check == 0)
366627f7eb2Smrg {
367627f7eb2Smrg if (mpfr_sgn (p) < 0)
368627f7eb2Smrg {
369627f7eb2Smrg mpfr_set_ui (p, 0, GFC_RND_MODE);
370627f7eb2Smrg mpfr_set_si (q, -1, GFC_RND_MODE);
371627f7eb2Smrg mpfr_copysign (p, p, q, GFC_RND_MODE);
372627f7eb2Smrg }
373627f7eb2Smrg else
374627f7eb2Smrg mpfr_set_ui (p, 0, GFC_RND_MODE);
375627f7eb2Smrg }
376627f7eb2Smrg else
377627f7eb2Smrg retval = ARITH_UNDERFLOW;
378627f7eb2Smrg }
379627f7eb2Smrg else if (mpfr_cmp (q, gfc_real_kinds[i].tiny) < 0)
380627f7eb2Smrg {
381*4c3eb207Smrg mpfr_exp_t emin, emax;
382627f7eb2Smrg int en;
383627f7eb2Smrg
384627f7eb2Smrg /* Save current values of emin and emax. */
385627f7eb2Smrg emin = mpfr_get_emin ();
386627f7eb2Smrg emax = mpfr_get_emax ();
387627f7eb2Smrg
388627f7eb2Smrg /* Set emin and emax for the current model number. */
389627f7eb2Smrg en = gfc_real_kinds[i].min_exponent - gfc_real_kinds[i].digits + 1;
390*4c3eb207Smrg mpfr_set_emin ((mpfr_exp_t) en);
391*4c3eb207Smrg mpfr_set_emax ((mpfr_exp_t) gfc_real_kinds[i].max_exponent);
392627f7eb2Smrg mpfr_check_range (q, 0, GFC_RND_MODE);
393627f7eb2Smrg mpfr_subnormalize (q, 0, GFC_RND_MODE);
394627f7eb2Smrg
395627f7eb2Smrg /* Reset emin and emax. */
396627f7eb2Smrg mpfr_set_emin (emin);
397627f7eb2Smrg mpfr_set_emax (emax);
398627f7eb2Smrg
399627f7eb2Smrg /* Copy sign if needed. */
400627f7eb2Smrg if (mpfr_sgn (p) < 0)
401*4c3eb207Smrg mpfr_neg (p, q, MPFR_RNDN);
402627f7eb2Smrg else
403*4c3eb207Smrg mpfr_set (p, q, MPFR_RNDN);
404627f7eb2Smrg }
405627f7eb2Smrg
406627f7eb2Smrg mpfr_clear (q);
407627f7eb2Smrg
408627f7eb2Smrg return retval;
409627f7eb2Smrg }
410627f7eb2Smrg
411627f7eb2Smrg
412627f7eb2Smrg /* Low-level arithmetic functions. All of these subroutines assume
413627f7eb2Smrg that all operands are of the same type and return an operand of the
414627f7eb2Smrg same type. The other thing about these subroutines is that they
415627f7eb2Smrg can fail in various ways -- overflow, underflow, division by zero,
416627f7eb2Smrg zero raised to the zero, etc. */
417627f7eb2Smrg
418627f7eb2Smrg static arith
gfc_arith_not(gfc_expr * op1,gfc_expr ** resultp)419627f7eb2Smrg gfc_arith_not (gfc_expr *op1, gfc_expr **resultp)
420627f7eb2Smrg {
421627f7eb2Smrg gfc_expr *result;
422627f7eb2Smrg
423627f7eb2Smrg result = gfc_get_constant_expr (BT_LOGICAL, op1->ts.kind, &op1->where);
424627f7eb2Smrg result->value.logical = !op1->value.logical;
425627f7eb2Smrg *resultp = result;
426627f7eb2Smrg
427627f7eb2Smrg return ARITH_OK;
428627f7eb2Smrg }
429627f7eb2Smrg
430627f7eb2Smrg
431627f7eb2Smrg static arith
gfc_arith_and(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)432627f7eb2Smrg gfc_arith_and (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
433627f7eb2Smrg {
434627f7eb2Smrg gfc_expr *result;
435627f7eb2Smrg
436627f7eb2Smrg result = gfc_get_constant_expr (BT_LOGICAL, gfc_kind_max (op1, op2),
437627f7eb2Smrg &op1->where);
438627f7eb2Smrg result->value.logical = op1->value.logical && op2->value.logical;
439627f7eb2Smrg *resultp = result;
440627f7eb2Smrg
441627f7eb2Smrg return ARITH_OK;
442627f7eb2Smrg }
443627f7eb2Smrg
444627f7eb2Smrg
445627f7eb2Smrg static arith
gfc_arith_or(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)446627f7eb2Smrg gfc_arith_or (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
447627f7eb2Smrg {
448627f7eb2Smrg gfc_expr *result;
449627f7eb2Smrg
450627f7eb2Smrg result = gfc_get_constant_expr (BT_LOGICAL, gfc_kind_max (op1, op2),
451627f7eb2Smrg &op1->where);
452627f7eb2Smrg result->value.logical = op1->value.logical || op2->value.logical;
453627f7eb2Smrg *resultp = result;
454627f7eb2Smrg
455627f7eb2Smrg return ARITH_OK;
456627f7eb2Smrg }
457627f7eb2Smrg
458627f7eb2Smrg
459627f7eb2Smrg static arith
gfc_arith_eqv(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)460627f7eb2Smrg gfc_arith_eqv (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
461627f7eb2Smrg {
462627f7eb2Smrg gfc_expr *result;
463627f7eb2Smrg
464627f7eb2Smrg result = gfc_get_constant_expr (BT_LOGICAL, gfc_kind_max (op1, op2),
465627f7eb2Smrg &op1->where);
466627f7eb2Smrg result->value.logical = op1->value.logical == op2->value.logical;
467627f7eb2Smrg *resultp = result;
468627f7eb2Smrg
469627f7eb2Smrg return ARITH_OK;
470627f7eb2Smrg }
471627f7eb2Smrg
472627f7eb2Smrg
473627f7eb2Smrg static arith
gfc_arith_neqv(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)474627f7eb2Smrg gfc_arith_neqv (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
475627f7eb2Smrg {
476627f7eb2Smrg gfc_expr *result;
477627f7eb2Smrg
478627f7eb2Smrg result = gfc_get_constant_expr (BT_LOGICAL, gfc_kind_max (op1, op2),
479627f7eb2Smrg &op1->where);
480627f7eb2Smrg result->value.logical = op1->value.logical != op2->value.logical;
481627f7eb2Smrg *resultp = result;
482627f7eb2Smrg
483627f7eb2Smrg return ARITH_OK;
484627f7eb2Smrg }
485627f7eb2Smrg
486627f7eb2Smrg
487627f7eb2Smrg /* Make sure a constant numeric expression is within the range for
488627f7eb2Smrg its type and kind. Note that there's also a gfc_check_range(),
489627f7eb2Smrg but that one deals with the intrinsic RANGE function. */
490627f7eb2Smrg
491627f7eb2Smrg arith
gfc_range_check(gfc_expr * e)492627f7eb2Smrg gfc_range_check (gfc_expr *e)
493627f7eb2Smrg {
494627f7eb2Smrg arith rc;
495627f7eb2Smrg arith rc2;
496627f7eb2Smrg
497627f7eb2Smrg switch (e->ts.type)
498627f7eb2Smrg {
499627f7eb2Smrg case BT_INTEGER:
500627f7eb2Smrg rc = gfc_check_integer_range (e->value.integer, e->ts.kind);
501627f7eb2Smrg break;
502627f7eb2Smrg
503627f7eb2Smrg case BT_REAL:
504627f7eb2Smrg rc = gfc_check_real_range (e->value.real, e->ts.kind);
505627f7eb2Smrg if (rc == ARITH_UNDERFLOW)
506627f7eb2Smrg mpfr_set_ui (e->value.real, 0, GFC_RND_MODE);
507627f7eb2Smrg if (rc == ARITH_OVERFLOW)
508627f7eb2Smrg mpfr_set_inf (e->value.real, mpfr_sgn (e->value.real));
509627f7eb2Smrg if (rc == ARITH_NAN)
510627f7eb2Smrg mpfr_set_nan (e->value.real);
511627f7eb2Smrg break;
512627f7eb2Smrg
513627f7eb2Smrg case BT_COMPLEX:
514627f7eb2Smrg rc = gfc_check_real_range (mpc_realref (e->value.complex), e->ts.kind);
515627f7eb2Smrg if (rc == ARITH_UNDERFLOW)
516627f7eb2Smrg mpfr_set_ui (mpc_realref (e->value.complex), 0, GFC_RND_MODE);
517627f7eb2Smrg if (rc == ARITH_OVERFLOW)
518627f7eb2Smrg mpfr_set_inf (mpc_realref (e->value.complex),
519627f7eb2Smrg mpfr_sgn (mpc_realref (e->value.complex)));
520627f7eb2Smrg if (rc == ARITH_NAN)
521627f7eb2Smrg mpfr_set_nan (mpc_realref (e->value.complex));
522627f7eb2Smrg
523627f7eb2Smrg rc2 = gfc_check_real_range (mpc_imagref (e->value.complex), e->ts.kind);
524627f7eb2Smrg if (rc == ARITH_UNDERFLOW)
525627f7eb2Smrg mpfr_set_ui (mpc_imagref (e->value.complex), 0, GFC_RND_MODE);
526627f7eb2Smrg if (rc == ARITH_OVERFLOW)
527627f7eb2Smrg mpfr_set_inf (mpc_imagref (e->value.complex),
528627f7eb2Smrg mpfr_sgn (mpc_imagref (e->value.complex)));
529627f7eb2Smrg if (rc == ARITH_NAN)
530627f7eb2Smrg mpfr_set_nan (mpc_imagref (e->value.complex));
531627f7eb2Smrg
532627f7eb2Smrg if (rc == ARITH_OK)
533627f7eb2Smrg rc = rc2;
534627f7eb2Smrg break;
535627f7eb2Smrg
536627f7eb2Smrg default:
537627f7eb2Smrg gfc_internal_error ("gfc_range_check(): Bad type");
538627f7eb2Smrg }
539627f7eb2Smrg
540627f7eb2Smrg return rc;
541627f7eb2Smrg }
542627f7eb2Smrg
543627f7eb2Smrg
544627f7eb2Smrg /* Several of the following routines use the same set of statements to
545627f7eb2Smrg check the validity of the result. Encapsulate the checking here. */
546627f7eb2Smrg
547627f7eb2Smrg static arith
check_result(arith rc,gfc_expr * x,gfc_expr * r,gfc_expr ** rp)548627f7eb2Smrg check_result (arith rc, gfc_expr *x, gfc_expr *r, gfc_expr **rp)
549627f7eb2Smrg {
550627f7eb2Smrg arith val = rc;
551627f7eb2Smrg
552627f7eb2Smrg if (val == ARITH_UNDERFLOW)
553627f7eb2Smrg {
554627f7eb2Smrg if (warn_underflow)
555627f7eb2Smrg gfc_warning (OPT_Wunderflow, gfc_arith_error (val), &x->where);
556627f7eb2Smrg val = ARITH_OK;
557627f7eb2Smrg }
558627f7eb2Smrg
559627f7eb2Smrg if (val == ARITH_ASYMMETRIC)
560627f7eb2Smrg {
561627f7eb2Smrg gfc_warning (0, gfc_arith_error (val), &x->where);
562627f7eb2Smrg val = ARITH_OK;
563627f7eb2Smrg }
564627f7eb2Smrg
565627f7eb2Smrg if (val == ARITH_OK || val == ARITH_OVERFLOW)
566627f7eb2Smrg *rp = r;
567627f7eb2Smrg else
568627f7eb2Smrg gfc_free_expr (r);
569627f7eb2Smrg
570627f7eb2Smrg return val;
571627f7eb2Smrg }
572627f7eb2Smrg
573627f7eb2Smrg
574627f7eb2Smrg /* It may seem silly to have a subroutine that actually computes the
575627f7eb2Smrg unary plus of a constant, but it prevents us from making exceptions
576627f7eb2Smrg in the code elsewhere. Used for unary plus and parenthesized
577627f7eb2Smrg expressions. */
578627f7eb2Smrg
579627f7eb2Smrg static arith
gfc_arith_identity(gfc_expr * op1,gfc_expr ** resultp)580627f7eb2Smrg gfc_arith_identity (gfc_expr *op1, gfc_expr **resultp)
581627f7eb2Smrg {
582627f7eb2Smrg *resultp = gfc_copy_expr (op1);
583627f7eb2Smrg return ARITH_OK;
584627f7eb2Smrg }
585627f7eb2Smrg
586627f7eb2Smrg
587627f7eb2Smrg static arith
gfc_arith_uminus(gfc_expr * op1,gfc_expr ** resultp)588627f7eb2Smrg gfc_arith_uminus (gfc_expr *op1, gfc_expr **resultp)
589627f7eb2Smrg {
590627f7eb2Smrg gfc_expr *result;
591627f7eb2Smrg arith rc;
592627f7eb2Smrg
593627f7eb2Smrg result = gfc_get_constant_expr (op1->ts.type, op1->ts.kind, &op1->where);
594627f7eb2Smrg
595627f7eb2Smrg switch (op1->ts.type)
596627f7eb2Smrg {
597627f7eb2Smrg case BT_INTEGER:
598627f7eb2Smrg mpz_neg (result->value.integer, op1->value.integer);
599627f7eb2Smrg break;
600627f7eb2Smrg
601627f7eb2Smrg case BT_REAL:
602627f7eb2Smrg mpfr_neg (result->value.real, op1->value.real, GFC_RND_MODE);
603627f7eb2Smrg break;
604627f7eb2Smrg
605627f7eb2Smrg case BT_COMPLEX:
606627f7eb2Smrg mpc_neg (result->value.complex, op1->value.complex, GFC_MPC_RND_MODE);
607627f7eb2Smrg break;
608627f7eb2Smrg
609627f7eb2Smrg default:
610627f7eb2Smrg gfc_internal_error ("gfc_arith_uminus(): Bad basic type");
611627f7eb2Smrg }
612627f7eb2Smrg
613627f7eb2Smrg rc = gfc_range_check (result);
614627f7eb2Smrg
615627f7eb2Smrg return check_result (rc, op1, result, resultp);
616627f7eb2Smrg }
617627f7eb2Smrg
618627f7eb2Smrg
619627f7eb2Smrg static arith
gfc_arith_plus(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)620627f7eb2Smrg gfc_arith_plus (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
621627f7eb2Smrg {
622627f7eb2Smrg gfc_expr *result;
623627f7eb2Smrg arith rc;
624627f7eb2Smrg
625627f7eb2Smrg result = gfc_get_constant_expr (op1->ts.type, op1->ts.kind, &op1->where);
626627f7eb2Smrg
627627f7eb2Smrg switch (op1->ts.type)
628627f7eb2Smrg {
629627f7eb2Smrg case BT_INTEGER:
630627f7eb2Smrg mpz_add (result->value.integer, op1->value.integer, op2->value.integer);
631627f7eb2Smrg break;
632627f7eb2Smrg
633627f7eb2Smrg case BT_REAL:
634627f7eb2Smrg mpfr_add (result->value.real, op1->value.real, op2->value.real,
635627f7eb2Smrg GFC_RND_MODE);
636627f7eb2Smrg break;
637627f7eb2Smrg
638627f7eb2Smrg case BT_COMPLEX:
639627f7eb2Smrg mpc_add (result->value.complex, op1->value.complex, op2->value.complex,
640627f7eb2Smrg GFC_MPC_RND_MODE);
641627f7eb2Smrg break;
642627f7eb2Smrg
643627f7eb2Smrg default:
644627f7eb2Smrg gfc_internal_error ("gfc_arith_plus(): Bad basic type");
645627f7eb2Smrg }
646627f7eb2Smrg
647627f7eb2Smrg rc = gfc_range_check (result);
648627f7eb2Smrg
649627f7eb2Smrg return check_result (rc, op1, result, resultp);
650627f7eb2Smrg }
651627f7eb2Smrg
652627f7eb2Smrg
653627f7eb2Smrg static arith
gfc_arith_minus(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)654627f7eb2Smrg gfc_arith_minus (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
655627f7eb2Smrg {
656627f7eb2Smrg gfc_expr *result;
657627f7eb2Smrg arith rc;
658627f7eb2Smrg
659627f7eb2Smrg result = gfc_get_constant_expr (op1->ts.type, op1->ts.kind, &op1->where);
660627f7eb2Smrg
661627f7eb2Smrg switch (op1->ts.type)
662627f7eb2Smrg {
663627f7eb2Smrg case BT_INTEGER:
664627f7eb2Smrg mpz_sub (result->value.integer, op1->value.integer, op2->value.integer);
665627f7eb2Smrg break;
666627f7eb2Smrg
667627f7eb2Smrg case BT_REAL:
668627f7eb2Smrg mpfr_sub (result->value.real, op1->value.real, op2->value.real,
669627f7eb2Smrg GFC_RND_MODE);
670627f7eb2Smrg break;
671627f7eb2Smrg
672627f7eb2Smrg case BT_COMPLEX:
673627f7eb2Smrg mpc_sub (result->value.complex, op1->value.complex,
674627f7eb2Smrg op2->value.complex, GFC_MPC_RND_MODE);
675627f7eb2Smrg break;
676627f7eb2Smrg
677627f7eb2Smrg default:
678627f7eb2Smrg gfc_internal_error ("gfc_arith_minus(): Bad basic type");
679627f7eb2Smrg }
680627f7eb2Smrg
681627f7eb2Smrg rc = gfc_range_check (result);
682627f7eb2Smrg
683627f7eb2Smrg return check_result (rc, op1, result, resultp);
684627f7eb2Smrg }
685627f7eb2Smrg
686627f7eb2Smrg
687627f7eb2Smrg static arith
gfc_arith_times(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)688627f7eb2Smrg gfc_arith_times (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
689627f7eb2Smrg {
690627f7eb2Smrg gfc_expr *result;
691627f7eb2Smrg arith rc;
692627f7eb2Smrg
693627f7eb2Smrg result = gfc_get_constant_expr (op1->ts.type, op1->ts.kind, &op1->where);
694627f7eb2Smrg
695627f7eb2Smrg switch (op1->ts.type)
696627f7eb2Smrg {
697627f7eb2Smrg case BT_INTEGER:
698627f7eb2Smrg mpz_mul (result->value.integer, op1->value.integer, op2->value.integer);
699627f7eb2Smrg break;
700627f7eb2Smrg
701627f7eb2Smrg case BT_REAL:
702627f7eb2Smrg mpfr_mul (result->value.real, op1->value.real, op2->value.real,
703627f7eb2Smrg GFC_RND_MODE);
704627f7eb2Smrg break;
705627f7eb2Smrg
706627f7eb2Smrg case BT_COMPLEX:
707627f7eb2Smrg gfc_set_model (mpc_realref (op1->value.complex));
708627f7eb2Smrg mpc_mul (result->value.complex, op1->value.complex, op2->value.complex,
709627f7eb2Smrg GFC_MPC_RND_MODE);
710627f7eb2Smrg break;
711627f7eb2Smrg
712627f7eb2Smrg default:
713627f7eb2Smrg gfc_internal_error ("gfc_arith_times(): Bad basic type");
714627f7eb2Smrg }
715627f7eb2Smrg
716627f7eb2Smrg rc = gfc_range_check (result);
717627f7eb2Smrg
718627f7eb2Smrg return check_result (rc, op1, result, resultp);
719627f7eb2Smrg }
720627f7eb2Smrg
721627f7eb2Smrg
722627f7eb2Smrg static arith
gfc_arith_divide(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)723627f7eb2Smrg gfc_arith_divide (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
724627f7eb2Smrg {
725627f7eb2Smrg gfc_expr *result;
726627f7eb2Smrg arith rc;
727627f7eb2Smrg
728627f7eb2Smrg rc = ARITH_OK;
729627f7eb2Smrg
730627f7eb2Smrg result = gfc_get_constant_expr (op1->ts.type, op1->ts.kind, &op1->where);
731627f7eb2Smrg
732627f7eb2Smrg switch (op1->ts.type)
733627f7eb2Smrg {
734627f7eb2Smrg case BT_INTEGER:
735627f7eb2Smrg if (mpz_sgn (op2->value.integer) == 0)
736627f7eb2Smrg {
737627f7eb2Smrg rc = ARITH_DIV0;
738627f7eb2Smrg break;
739627f7eb2Smrg }
740627f7eb2Smrg
741627f7eb2Smrg if (warn_integer_division)
742627f7eb2Smrg {
743627f7eb2Smrg mpz_t r;
744627f7eb2Smrg mpz_init (r);
745627f7eb2Smrg mpz_tdiv_qr (result->value.integer, r, op1->value.integer,
746627f7eb2Smrg op2->value.integer);
747627f7eb2Smrg
748627f7eb2Smrg if (mpz_cmp_si (r, 0) != 0)
749627f7eb2Smrg {
750627f7eb2Smrg char *p;
751627f7eb2Smrg p = mpz_get_str (NULL, 10, result->value.integer);
752627f7eb2Smrg gfc_warning_now (OPT_Winteger_division, "Integer division "
753627f7eb2Smrg "truncated to constant %qs at %L", p,
754627f7eb2Smrg &op1->where);
755627f7eb2Smrg free (p);
756627f7eb2Smrg }
757627f7eb2Smrg mpz_clear (r);
758627f7eb2Smrg }
759627f7eb2Smrg else
760627f7eb2Smrg mpz_tdiv_q (result->value.integer, op1->value.integer,
761627f7eb2Smrg op2->value.integer);
762627f7eb2Smrg
763627f7eb2Smrg break;
764627f7eb2Smrg
765627f7eb2Smrg case BT_REAL:
766627f7eb2Smrg if (mpfr_sgn (op2->value.real) == 0 && flag_range_check == 1)
767627f7eb2Smrg {
768627f7eb2Smrg rc = ARITH_DIV0;
769627f7eb2Smrg break;
770627f7eb2Smrg }
771627f7eb2Smrg
772627f7eb2Smrg mpfr_div (result->value.real, op1->value.real, op2->value.real,
773627f7eb2Smrg GFC_RND_MODE);
774627f7eb2Smrg break;
775627f7eb2Smrg
776627f7eb2Smrg case BT_COMPLEX:
777627f7eb2Smrg if (mpc_cmp_si_si (op2->value.complex, 0, 0) == 0
778627f7eb2Smrg && flag_range_check == 1)
779627f7eb2Smrg {
780627f7eb2Smrg rc = ARITH_DIV0;
781627f7eb2Smrg break;
782627f7eb2Smrg }
783627f7eb2Smrg
784627f7eb2Smrg gfc_set_model (mpc_realref (op1->value.complex));
785627f7eb2Smrg if (mpc_cmp_si_si (op2->value.complex, 0, 0) == 0)
786627f7eb2Smrg {
787627f7eb2Smrg /* In Fortran, return (NaN + NaN I) for any zero divisor. See
788627f7eb2Smrg PR 40318. */
789627f7eb2Smrg mpfr_set_nan (mpc_realref (result->value.complex));
790627f7eb2Smrg mpfr_set_nan (mpc_imagref (result->value.complex));
791627f7eb2Smrg }
792627f7eb2Smrg else
793627f7eb2Smrg mpc_div (result->value.complex, op1->value.complex, op2->value.complex,
794627f7eb2Smrg GFC_MPC_RND_MODE);
795627f7eb2Smrg break;
796627f7eb2Smrg
797627f7eb2Smrg default:
798627f7eb2Smrg gfc_internal_error ("gfc_arith_divide(): Bad basic type");
799627f7eb2Smrg }
800627f7eb2Smrg
801627f7eb2Smrg if (rc == ARITH_OK)
802627f7eb2Smrg rc = gfc_range_check (result);
803627f7eb2Smrg
804627f7eb2Smrg return check_result (rc, op1, result, resultp);
805627f7eb2Smrg }
806627f7eb2Smrg
807627f7eb2Smrg /* Raise a number to a power. */
808627f7eb2Smrg
809627f7eb2Smrg static arith
arith_power(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)810627f7eb2Smrg arith_power (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
811627f7eb2Smrg {
812627f7eb2Smrg int power_sign;
813627f7eb2Smrg gfc_expr *result;
814627f7eb2Smrg arith rc;
815627f7eb2Smrg
816627f7eb2Smrg rc = ARITH_OK;
817627f7eb2Smrg result = gfc_get_constant_expr (op1->ts.type, op1->ts.kind, &op1->where);
818627f7eb2Smrg
819627f7eb2Smrg switch (op2->ts.type)
820627f7eb2Smrg {
821627f7eb2Smrg case BT_INTEGER:
822627f7eb2Smrg power_sign = mpz_sgn (op2->value.integer);
823627f7eb2Smrg
824627f7eb2Smrg if (power_sign == 0)
825627f7eb2Smrg {
826627f7eb2Smrg /* Handle something to the zeroth power. Since we're dealing
827627f7eb2Smrg with integral exponents, there is no ambiguity in the
828627f7eb2Smrg limiting procedure used to determine the value of 0**0. */
829627f7eb2Smrg switch (op1->ts.type)
830627f7eb2Smrg {
831627f7eb2Smrg case BT_INTEGER:
832627f7eb2Smrg mpz_set_ui (result->value.integer, 1);
833627f7eb2Smrg break;
834627f7eb2Smrg
835627f7eb2Smrg case BT_REAL:
836627f7eb2Smrg mpfr_set_ui (result->value.real, 1, GFC_RND_MODE);
837627f7eb2Smrg break;
838627f7eb2Smrg
839627f7eb2Smrg case BT_COMPLEX:
840627f7eb2Smrg mpc_set_ui (result->value.complex, 1, GFC_MPC_RND_MODE);
841627f7eb2Smrg break;
842627f7eb2Smrg
843627f7eb2Smrg default:
844627f7eb2Smrg gfc_internal_error ("arith_power(): Bad base");
845627f7eb2Smrg }
846627f7eb2Smrg }
847627f7eb2Smrg else
848627f7eb2Smrg {
849627f7eb2Smrg switch (op1->ts.type)
850627f7eb2Smrg {
851627f7eb2Smrg case BT_INTEGER:
852627f7eb2Smrg {
853627f7eb2Smrg /* First, we simplify the cases of op1 == 1, 0 or -1. */
854627f7eb2Smrg if (mpz_cmp_si (op1->value.integer, 1) == 0)
855627f7eb2Smrg {
856627f7eb2Smrg /* 1**op2 == 1 */
857627f7eb2Smrg mpz_set_si (result->value.integer, 1);
858627f7eb2Smrg }
859627f7eb2Smrg else if (mpz_cmp_si (op1->value.integer, 0) == 0)
860627f7eb2Smrg {
861627f7eb2Smrg /* 0**op2 == 0, if op2 > 0
862627f7eb2Smrg 0**op2 overflow, if op2 < 0 ; in that case, we
863627f7eb2Smrg set the result to 0 and return ARITH_DIV0. */
864627f7eb2Smrg mpz_set_si (result->value.integer, 0);
865627f7eb2Smrg if (mpz_cmp_si (op2->value.integer, 0) < 0)
866627f7eb2Smrg rc = ARITH_DIV0;
867627f7eb2Smrg }
868627f7eb2Smrg else if (mpz_cmp_si (op1->value.integer, -1) == 0)
869627f7eb2Smrg {
870627f7eb2Smrg /* (-1)**op2 == (-1)**(mod(op2,2)) */
871627f7eb2Smrg unsigned int odd = mpz_fdiv_ui (op2->value.integer, 2);
872627f7eb2Smrg if (odd)
873627f7eb2Smrg mpz_set_si (result->value.integer, -1);
874627f7eb2Smrg else
875627f7eb2Smrg mpz_set_si (result->value.integer, 1);
876627f7eb2Smrg }
877627f7eb2Smrg /* Then, we take care of op2 < 0. */
878627f7eb2Smrg else if (mpz_cmp_si (op2->value.integer, 0) < 0)
879627f7eb2Smrg {
880627f7eb2Smrg /* if op2 < 0, op1**op2 == 0 because abs(op1) > 1. */
881627f7eb2Smrg mpz_set_si (result->value.integer, 0);
882627f7eb2Smrg if (warn_integer_division)
883627f7eb2Smrg gfc_warning_now (OPT_Winteger_division, "Negative "
884627f7eb2Smrg "exponent of integer has zero "
885627f7eb2Smrg "result at %L", &result->where);
886627f7eb2Smrg }
887627f7eb2Smrg else
888627f7eb2Smrg {
889627f7eb2Smrg /* We have abs(op1) > 1 and op2 > 1.
890627f7eb2Smrg If op2 > bit_size(op1), we'll have an out-of-range
891627f7eb2Smrg result. */
892627f7eb2Smrg int k, power;
893627f7eb2Smrg
894627f7eb2Smrg k = gfc_validate_kind (BT_INTEGER, op1->ts.kind, false);
895627f7eb2Smrg power = gfc_integer_kinds[k].bit_size;
896627f7eb2Smrg if (mpz_cmp_si (op2->value.integer, power) < 0)
897627f7eb2Smrg {
898627f7eb2Smrg gfc_extract_int (op2, &power);
899627f7eb2Smrg mpz_pow_ui (result->value.integer, op1->value.integer,
900627f7eb2Smrg power);
901627f7eb2Smrg rc = gfc_range_check (result);
902627f7eb2Smrg if (rc == ARITH_OVERFLOW)
903627f7eb2Smrg gfc_error_now ("Result of exponentiation at %L "
904627f7eb2Smrg "exceeds the range of %s", &op1->where,
905627f7eb2Smrg gfc_typename (&(op1->ts)));
906627f7eb2Smrg }
907627f7eb2Smrg else
908627f7eb2Smrg {
909627f7eb2Smrg /* Provide a nonsense value to propagate up. */
910627f7eb2Smrg mpz_set (result->value.integer,
911627f7eb2Smrg gfc_integer_kinds[k].huge);
912627f7eb2Smrg mpz_add_ui (result->value.integer,
913627f7eb2Smrg result->value.integer, 1);
914627f7eb2Smrg rc = ARITH_OVERFLOW;
915627f7eb2Smrg }
916627f7eb2Smrg }
917627f7eb2Smrg }
918627f7eb2Smrg break;
919627f7eb2Smrg
920627f7eb2Smrg case BT_REAL:
921627f7eb2Smrg mpfr_pow_z (result->value.real, op1->value.real,
922627f7eb2Smrg op2->value.integer, GFC_RND_MODE);
923627f7eb2Smrg break;
924627f7eb2Smrg
925627f7eb2Smrg case BT_COMPLEX:
926627f7eb2Smrg mpc_pow_z (result->value.complex, op1->value.complex,
927627f7eb2Smrg op2->value.integer, GFC_MPC_RND_MODE);
928627f7eb2Smrg break;
929627f7eb2Smrg
930627f7eb2Smrg default:
931627f7eb2Smrg break;
932627f7eb2Smrg }
933627f7eb2Smrg }
934627f7eb2Smrg break;
935627f7eb2Smrg
936627f7eb2Smrg case BT_REAL:
937627f7eb2Smrg
938627f7eb2Smrg if (gfc_init_expr_flag)
939627f7eb2Smrg {
940627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2003, "Noninteger "
941627f7eb2Smrg "exponent in an initialization "
942627f7eb2Smrg "expression at %L", &op2->where))
943627f7eb2Smrg {
944627f7eb2Smrg gfc_free_expr (result);
945627f7eb2Smrg return ARITH_PROHIBIT;
946627f7eb2Smrg }
947627f7eb2Smrg }
948627f7eb2Smrg
949627f7eb2Smrg if (mpfr_cmp_si (op1->value.real, 0) < 0)
950627f7eb2Smrg {
951627f7eb2Smrg gfc_error ("Raising a negative REAL at %L to "
952627f7eb2Smrg "a REAL power is prohibited", &op1->where);
953627f7eb2Smrg gfc_free_expr (result);
954627f7eb2Smrg return ARITH_PROHIBIT;
955627f7eb2Smrg }
956627f7eb2Smrg
957627f7eb2Smrg mpfr_pow (result->value.real, op1->value.real, op2->value.real,
958627f7eb2Smrg GFC_RND_MODE);
959627f7eb2Smrg break;
960627f7eb2Smrg
961627f7eb2Smrg case BT_COMPLEX:
962627f7eb2Smrg {
963627f7eb2Smrg if (gfc_init_expr_flag)
964627f7eb2Smrg {
965627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2003, "Noninteger "
966627f7eb2Smrg "exponent in an initialization "
967627f7eb2Smrg "expression at %L", &op2->where))
968627f7eb2Smrg {
969627f7eb2Smrg gfc_free_expr (result);
970627f7eb2Smrg return ARITH_PROHIBIT;
971627f7eb2Smrg }
972627f7eb2Smrg }
973627f7eb2Smrg
974627f7eb2Smrg mpc_pow (result->value.complex, op1->value.complex,
975627f7eb2Smrg op2->value.complex, GFC_MPC_RND_MODE);
976627f7eb2Smrg }
977627f7eb2Smrg break;
978627f7eb2Smrg default:
979627f7eb2Smrg gfc_internal_error ("arith_power(): unknown type");
980627f7eb2Smrg }
981627f7eb2Smrg
982627f7eb2Smrg if (rc == ARITH_OK)
983627f7eb2Smrg rc = gfc_range_check (result);
984627f7eb2Smrg
985627f7eb2Smrg return check_result (rc, op1, result, resultp);
986627f7eb2Smrg }
987627f7eb2Smrg
988627f7eb2Smrg
989627f7eb2Smrg /* Concatenate two string constants. */
990627f7eb2Smrg
991627f7eb2Smrg static arith
gfc_arith_concat(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)992627f7eb2Smrg gfc_arith_concat (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
993627f7eb2Smrg {
994627f7eb2Smrg gfc_expr *result;
995627f7eb2Smrg size_t len;
996627f7eb2Smrg
997*4c3eb207Smrg /* By cleverly playing around with constructors, it is possible
998627f7eb2Smrg to get mismaching types here. */
999627f7eb2Smrg if (op1->ts.type != BT_CHARACTER || op2->ts.type != BT_CHARACTER
1000627f7eb2Smrg || op1->ts.kind != op2->ts.kind)
1001627f7eb2Smrg return ARITH_WRONGCONCAT;
1002627f7eb2Smrg
1003627f7eb2Smrg result = gfc_get_constant_expr (BT_CHARACTER, op1->ts.kind,
1004627f7eb2Smrg &op1->where);
1005627f7eb2Smrg
1006627f7eb2Smrg len = op1->value.character.length + op2->value.character.length;
1007627f7eb2Smrg
1008627f7eb2Smrg result->value.character.string = gfc_get_wide_string (len + 1);
1009627f7eb2Smrg result->value.character.length = len;
1010627f7eb2Smrg
1011627f7eb2Smrg memcpy (result->value.character.string, op1->value.character.string,
1012627f7eb2Smrg op1->value.character.length * sizeof (gfc_char_t));
1013627f7eb2Smrg
1014627f7eb2Smrg memcpy (&result->value.character.string[op1->value.character.length],
1015627f7eb2Smrg op2->value.character.string,
1016627f7eb2Smrg op2->value.character.length * sizeof (gfc_char_t));
1017627f7eb2Smrg
1018627f7eb2Smrg result->value.character.string[len] = '\0';
1019627f7eb2Smrg
1020627f7eb2Smrg *resultp = result;
1021627f7eb2Smrg
1022627f7eb2Smrg return ARITH_OK;
1023627f7eb2Smrg }
1024627f7eb2Smrg
1025627f7eb2Smrg /* Comparison between real values; returns 0 if (op1 .op. op2) is true.
1026627f7eb2Smrg This function mimics mpfr_cmp but takes NaN into account. */
1027627f7eb2Smrg
1028627f7eb2Smrg static int
compare_real(gfc_expr * op1,gfc_expr * op2,gfc_intrinsic_op op)1029627f7eb2Smrg compare_real (gfc_expr *op1, gfc_expr *op2, gfc_intrinsic_op op)
1030627f7eb2Smrg {
1031627f7eb2Smrg int rc;
1032627f7eb2Smrg switch (op)
1033627f7eb2Smrg {
1034627f7eb2Smrg case INTRINSIC_EQ:
1035627f7eb2Smrg rc = mpfr_equal_p (op1->value.real, op2->value.real) ? 0 : 1;
1036627f7eb2Smrg break;
1037627f7eb2Smrg case INTRINSIC_GT:
1038627f7eb2Smrg rc = mpfr_greater_p (op1->value.real, op2->value.real) ? 1 : -1;
1039627f7eb2Smrg break;
1040627f7eb2Smrg case INTRINSIC_GE:
1041627f7eb2Smrg rc = mpfr_greaterequal_p (op1->value.real, op2->value.real) ? 1 : -1;
1042627f7eb2Smrg break;
1043627f7eb2Smrg case INTRINSIC_LT:
1044627f7eb2Smrg rc = mpfr_less_p (op1->value.real, op2->value.real) ? -1 : 1;
1045627f7eb2Smrg break;
1046627f7eb2Smrg case INTRINSIC_LE:
1047627f7eb2Smrg rc = mpfr_lessequal_p (op1->value.real, op2->value.real) ? -1 : 1;
1048627f7eb2Smrg break;
1049627f7eb2Smrg default:
1050627f7eb2Smrg gfc_internal_error ("compare_real(): Bad operator");
1051627f7eb2Smrg }
1052627f7eb2Smrg
1053627f7eb2Smrg return rc;
1054627f7eb2Smrg }
1055627f7eb2Smrg
1056627f7eb2Smrg /* Comparison operators. Assumes that the two expression nodes
1057627f7eb2Smrg contain two constants of the same type. The op argument is
1058627f7eb2Smrg needed to handle NaN correctly. */
1059627f7eb2Smrg
1060627f7eb2Smrg int
gfc_compare_expr(gfc_expr * op1,gfc_expr * op2,gfc_intrinsic_op op)1061627f7eb2Smrg gfc_compare_expr (gfc_expr *op1, gfc_expr *op2, gfc_intrinsic_op op)
1062627f7eb2Smrg {
1063627f7eb2Smrg int rc;
1064627f7eb2Smrg
1065627f7eb2Smrg switch (op1->ts.type)
1066627f7eb2Smrg {
1067627f7eb2Smrg case BT_INTEGER:
1068627f7eb2Smrg rc = mpz_cmp (op1->value.integer, op2->value.integer);
1069627f7eb2Smrg break;
1070627f7eb2Smrg
1071627f7eb2Smrg case BT_REAL:
1072627f7eb2Smrg rc = compare_real (op1, op2, op);
1073627f7eb2Smrg break;
1074627f7eb2Smrg
1075627f7eb2Smrg case BT_CHARACTER:
1076627f7eb2Smrg rc = gfc_compare_string (op1, op2);
1077627f7eb2Smrg break;
1078627f7eb2Smrg
1079627f7eb2Smrg case BT_LOGICAL:
1080627f7eb2Smrg rc = ((!op1->value.logical && op2->value.logical)
1081627f7eb2Smrg || (op1->value.logical && !op2->value.logical));
1082627f7eb2Smrg break;
1083627f7eb2Smrg
1084627f7eb2Smrg default:
1085627f7eb2Smrg gfc_internal_error ("gfc_compare_expr(): Bad basic type");
1086627f7eb2Smrg }
1087627f7eb2Smrg
1088627f7eb2Smrg return rc;
1089627f7eb2Smrg }
1090627f7eb2Smrg
1091627f7eb2Smrg
1092627f7eb2Smrg /* Compare a pair of complex numbers. Naturally, this is only for
1093627f7eb2Smrg equality and inequality. */
1094627f7eb2Smrg
1095627f7eb2Smrg static int
compare_complex(gfc_expr * op1,gfc_expr * op2)1096627f7eb2Smrg compare_complex (gfc_expr *op1, gfc_expr *op2)
1097627f7eb2Smrg {
1098627f7eb2Smrg return mpc_cmp (op1->value.complex, op2->value.complex) == 0;
1099627f7eb2Smrg }
1100627f7eb2Smrg
1101627f7eb2Smrg
1102627f7eb2Smrg /* Given two constant strings and the inverse collating sequence, compare the
1103627f7eb2Smrg strings. We return -1 for a < b, 0 for a == b and 1 for a > b.
1104627f7eb2Smrg We use the processor's default collating sequence. */
1105627f7eb2Smrg
1106627f7eb2Smrg int
gfc_compare_string(gfc_expr * a,gfc_expr * b)1107627f7eb2Smrg gfc_compare_string (gfc_expr *a, gfc_expr *b)
1108627f7eb2Smrg {
1109627f7eb2Smrg size_t len, alen, blen, i;
1110627f7eb2Smrg gfc_char_t ac, bc;
1111627f7eb2Smrg
1112627f7eb2Smrg alen = a->value.character.length;
1113627f7eb2Smrg blen = b->value.character.length;
1114627f7eb2Smrg
1115627f7eb2Smrg len = MAX(alen, blen);
1116627f7eb2Smrg
1117627f7eb2Smrg for (i = 0; i < len; i++)
1118627f7eb2Smrg {
1119627f7eb2Smrg ac = ((i < alen) ? a->value.character.string[i] : ' ');
1120627f7eb2Smrg bc = ((i < blen) ? b->value.character.string[i] : ' ');
1121627f7eb2Smrg
1122627f7eb2Smrg if (ac < bc)
1123627f7eb2Smrg return -1;
1124627f7eb2Smrg if (ac > bc)
1125627f7eb2Smrg return 1;
1126627f7eb2Smrg }
1127627f7eb2Smrg
1128627f7eb2Smrg /* Strings are equal */
1129627f7eb2Smrg return 0;
1130627f7eb2Smrg }
1131627f7eb2Smrg
1132627f7eb2Smrg
1133627f7eb2Smrg int
gfc_compare_with_Cstring(gfc_expr * a,const char * b,bool case_sensitive)1134627f7eb2Smrg gfc_compare_with_Cstring (gfc_expr *a, const char *b, bool case_sensitive)
1135627f7eb2Smrg {
1136627f7eb2Smrg size_t len, alen, blen, i;
1137627f7eb2Smrg gfc_char_t ac, bc;
1138627f7eb2Smrg
1139627f7eb2Smrg alen = a->value.character.length;
1140627f7eb2Smrg blen = strlen (b);
1141627f7eb2Smrg
1142627f7eb2Smrg len = MAX(alen, blen);
1143627f7eb2Smrg
1144627f7eb2Smrg for (i = 0; i < len; i++)
1145627f7eb2Smrg {
1146627f7eb2Smrg ac = ((i < alen) ? a->value.character.string[i] : ' ');
1147627f7eb2Smrg bc = ((i < blen) ? b[i] : ' ');
1148627f7eb2Smrg
1149627f7eb2Smrg if (!case_sensitive)
1150627f7eb2Smrg {
1151627f7eb2Smrg ac = TOLOWER (ac);
1152627f7eb2Smrg bc = TOLOWER (bc);
1153627f7eb2Smrg }
1154627f7eb2Smrg
1155627f7eb2Smrg if (ac < bc)
1156627f7eb2Smrg return -1;
1157627f7eb2Smrg if (ac > bc)
1158627f7eb2Smrg return 1;
1159627f7eb2Smrg }
1160627f7eb2Smrg
1161627f7eb2Smrg /* Strings are equal */
1162627f7eb2Smrg return 0;
1163627f7eb2Smrg }
1164627f7eb2Smrg
1165627f7eb2Smrg
1166627f7eb2Smrg /* Specific comparison subroutines. */
1167627f7eb2Smrg
1168627f7eb2Smrg static arith
gfc_arith_eq(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)1169627f7eb2Smrg gfc_arith_eq (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
1170627f7eb2Smrg {
1171627f7eb2Smrg gfc_expr *result;
1172627f7eb2Smrg
1173627f7eb2Smrg result = gfc_get_constant_expr (BT_LOGICAL, gfc_default_logical_kind,
1174627f7eb2Smrg &op1->where);
1175627f7eb2Smrg result->value.logical = (op1->ts.type == BT_COMPLEX)
1176627f7eb2Smrg ? compare_complex (op1, op2)
1177627f7eb2Smrg : (gfc_compare_expr (op1, op2, INTRINSIC_EQ) == 0);
1178627f7eb2Smrg
1179627f7eb2Smrg *resultp = result;
1180627f7eb2Smrg return ARITH_OK;
1181627f7eb2Smrg }
1182627f7eb2Smrg
1183627f7eb2Smrg
1184627f7eb2Smrg static arith
gfc_arith_ne(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)1185627f7eb2Smrg gfc_arith_ne (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
1186627f7eb2Smrg {
1187627f7eb2Smrg gfc_expr *result;
1188627f7eb2Smrg
1189627f7eb2Smrg result = gfc_get_constant_expr (BT_LOGICAL, gfc_default_logical_kind,
1190627f7eb2Smrg &op1->where);
1191627f7eb2Smrg result->value.logical = (op1->ts.type == BT_COMPLEX)
1192627f7eb2Smrg ? !compare_complex (op1, op2)
1193627f7eb2Smrg : (gfc_compare_expr (op1, op2, INTRINSIC_EQ) != 0);
1194627f7eb2Smrg
1195627f7eb2Smrg *resultp = result;
1196627f7eb2Smrg return ARITH_OK;
1197627f7eb2Smrg }
1198627f7eb2Smrg
1199627f7eb2Smrg
1200627f7eb2Smrg static arith
gfc_arith_gt(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)1201627f7eb2Smrg gfc_arith_gt (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
1202627f7eb2Smrg {
1203627f7eb2Smrg gfc_expr *result;
1204627f7eb2Smrg
1205627f7eb2Smrg result = gfc_get_constant_expr (BT_LOGICAL, gfc_default_logical_kind,
1206627f7eb2Smrg &op1->where);
1207627f7eb2Smrg result->value.logical = (gfc_compare_expr (op1, op2, INTRINSIC_GT) > 0);
1208627f7eb2Smrg *resultp = result;
1209627f7eb2Smrg
1210627f7eb2Smrg return ARITH_OK;
1211627f7eb2Smrg }
1212627f7eb2Smrg
1213627f7eb2Smrg
1214627f7eb2Smrg static arith
gfc_arith_ge(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)1215627f7eb2Smrg gfc_arith_ge (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
1216627f7eb2Smrg {
1217627f7eb2Smrg gfc_expr *result;
1218627f7eb2Smrg
1219627f7eb2Smrg result = gfc_get_constant_expr (BT_LOGICAL, gfc_default_logical_kind,
1220627f7eb2Smrg &op1->where);
1221627f7eb2Smrg result->value.logical = (gfc_compare_expr (op1, op2, INTRINSIC_GE) >= 0);
1222627f7eb2Smrg *resultp = result;
1223627f7eb2Smrg
1224627f7eb2Smrg return ARITH_OK;
1225627f7eb2Smrg }
1226627f7eb2Smrg
1227627f7eb2Smrg
1228627f7eb2Smrg static arith
gfc_arith_lt(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)1229627f7eb2Smrg gfc_arith_lt (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
1230627f7eb2Smrg {
1231627f7eb2Smrg gfc_expr *result;
1232627f7eb2Smrg
1233627f7eb2Smrg result = gfc_get_constant_expr (BT_LOGICAL, gfc_default_logical_kind,
1234627f7eb2Smrg &op1->where);
1235627f7eb2Smrg result->value.logical = (gfc_compare_expr (op1, op2, INTRINSIC_LT) < 0);
1236627f7eb2Smrg *resultp = result;
1237627f7eb2Smrg
1238627f7eb2Smrg return ARITH_OK;
1239627f7eb2Smrg }
1240627f7eb2Smrg
1241627f7eb2Smrg
1242627f7eb2Smrg static arith
gfc_arith_le(gfc_expr * op1,gfc_expr * op2,gfc_expr ** resultp)1243627f7eb2Smrg gfc_arith_le (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
1244627f7eb2Smrg {
1245627f7eb2Smrg gfc_expr *result;
1246627f7eb2Smrg
1247627f7eb2Smrg result = gfc_get_constant_expr (BT_LOGICAL, gfc_default_logical_kind,
1248627f7eb2Smrg &op1->where);
1249627f7eb2Smrg result->value.logical = (gfc_compare_expr (op1, op2, INTRINSIC_LE) <= 0);
1250627f7eb2Smrg *resultp = result;
1251627f7eb2Smrg
1252627f7eb2Smrg return ARITH_OK;
1253627f7eb2Smrg }
1254627f7eb2Smrg
1255627f7eb2Smrg
1256627f7eb2Smrg static arith
reduce_unary(arith (* eval)(gfc_expr *,gfc_expr **),gfc_expr * op,gfc_expr ** result)1257627f7eb2Smrg reduce_unary (arith (*eval) (gfc_expr *, gfc_expr **), gfc_expr *op,
1258627f7eb2Smrg gfc_expr **result)
1259627f7eb2Smrg {
1260627f7eb2Smrg gfc_constructor_base head;
1261627f7eb2Smrg gfc_constructor *c;
1262627f7eb2Smrg gfc_expr *r;
1263627f7eb2Smrg arith rc;
1264627f7eb2Smrg
1265627f7eb2Smrg if (op->expr_type == EXPR_CONSTANT)
1266627f7eb2Smrg return eval (op, result);
1267627f7eb2Smrg
1268627f7eb2Smrg rc = ARITH_OK;
1269627f7eb2Smrg head = gfc_constructor_copy (op->value.constructor);
1270627f7eb2Smrg for (c = gfc_constructor_first (head); c; c = gfc_constructor_next (c))
1271627f7eb2Smrg {
1272627f7eb2Smrg rc = reduce_unary (eval, c->expr, &r);
1273627f7eb2Smrg
1274627f7eb2Smrg if (rc != ARITH_OK)
1275627f7eb2Smrg break;
1276627f7eb2Smrg
1277627f7eb2Smrg gfc_replace_expr (c->expr, r);
1278627f7eb2Smrg }
1279627f7eb2Smrg
1280627f7eb2Smrg if (rc != ARITH_OK)
1281627f7eb2Smrg gfc_constructor_free (head);
1282627f7eb2Smrg else
1283627f7eb2Smrg {
1284627f7eb2Smrg gfc_constructor *c = gfc_constructor_first (head);
1285627f7eb2Smrg r = gfc_get_array_expr (c->expr->ts.type, c->expr->ts.kind,
1286627f7eb2Smrg &op->where);
1287627f7eb2Smrg r->shape = gfc_copy_shape (op->shape, op->rank);
1288627f7eb2Smrg r->rank = op->rank;
1289627f7eb2Smrg r->value.constructor = head;
1290627f7eb2Smrg *result = r;
1291627f7eb2Smrg }
1292627f7eb2Smrg
1293627f7eb2Smrg return rc;
1294627f7eb2Smrg }
1295627f7eb2Smrg
1296627f7eb2Smrg
1297627f7eb2Smrg static arith
reduce_binary_ac(arith (* eval)(gfc_expr *,gfc_expr *,gfc_expr **),gfc_expr * op1,gfc_expr * op2,gfc_expr ** result)1298627f7eb2Smrg reduce_binary_ac (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **),
1299627f7eb2Smrg gfc_expr *op1, gfc_expr *op2, gfc_expr **result)
1300627f7eb2Smrg {
1301627f7eb2Smrg gfc_constructor_base head;
1302627f7eb2Smrg gfc_constructor *c;
1303627f7eb2Smrg gfc_expr *r;
1304627f7eb2Smrg arith rc = ARITH_OK;
1305627f7eb2Smrg
1306627f7eb2Smrg head = gfc_constructor_copy (op1->value.constructor);
1307627f7eb2Smrg for (c = gfc_constructor_first (head); c; c = gfc_constructor_next (c))
1308627f7eb2Smrg {
1309627f7eb2Smrg if (c->expr->expr_type == EXPR_CONSTANT)
1310627f7eb2Smrg rc = eval (c->expr, op2, &r);
1311627f7eb2Smrg else
1312627f7eb2Smrg rc = reduce_binary_ac (eval, c->expr, op2, &r);
1313627f7eb2Smrg
1314627f7eb2Smrg if (rc != ARITH_OK)
1315627f7eb2Smrg break;
1316627f7eb2Smrg
1317627f7eb2Smrg gfc_replace_expr (c->expr, r);
1318627f7eb2Smrg }
1319627f7eb2Smrg
1320627f7eb2Smrg if (rc != ARITH_OK)
1321627f7eb2Smrg gfc_constructor_free (head);
1322627f7eb2Smrg else
1323627f7eb2Smrg {
1324627f7eb2Smrg gfc_constructor *c = gfc_constructor_first (head);
1325627f7eb2Smrg r = gfc_get_array_expr (c->expr->ts.type, c->expr->ts.kind,
1326627f7eb2Smrg &op1->where);
1327627f7eb2Smrg r->shape = gfc_copy_shape (op1->shape, op1->rank);
1328627f7eb2Smrg r->rank = op1->rank;
1329627f7eb2Smrg r->value.constructor = head;
1330627f7eb2Smrg *result = r;
1331627f7eb2Smrg }
1332627f7eb2Smrg
1333627f7eb2Smrg return rc;
1334627f7eb2Smrg }
1335627f7eb2Smrg
1336627f7eb2Smrg
1337627f7eb2Smrg static arith
reduce_binary_ca(arith (* eval)(gfc_expr *,gfc_expr *,gfc_expr **),gfc_expr * op1,gfc_expr * op2,gfc_expr ** result)1338627f7eb2Smrg reduce_binary_ca (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **),
1339627f7eb2Smrg gfc_expr *op1, gfc_expr *op2, gfc_expr **result)
1340627f7eb2Smrg {
1341627f7eb2Smrg gfc_constructor_base head;
1342627f7eb2Smrg gfc_constructor *c;
1343627f7eb2Smrg gfc_expr *r;
1344627f7eb2Smrg arith rc = ARITH_OK;
1345627f7eb2Smrg
1346627f7eb2Smrg head = gfc_constructor_copy (op2->value.constructor);
1347627f7eb2Smrg for (c = gfc_constructor_first (head); c; c = gfc_constructor_next (c))
1348627f7eb2Smrg {
1349627f7eb2Smrg if (c->expr->expr_type == EXPR_CONSTANT)
1350627f7eb2Smrg rc = eval (op1, c->expr, &r);
1351627f7eb2Smrg else
1352627f7eb2Smrg rc = reduce_binary_ca (eval, op1, c->expr, &r);
1353627f7eb2Smrg
1354627f7eb2Smrg if (rc != ARITH_OK)
1355627f7eb2Smrg break;
1356627f7eb2Smrg
1357627f7eb2Smrg gfc_replace_expr (c->expr, r);
1358627f7eb2Smrg }
1359627f7eb2Smrg
1360627f7eb2Smrg if (rc != ARITH_OK)
1361627f7eb2Smrg gfc_constructor_free (head);
1362627f7eb2Smrg else
1363627f7eb2Smrg {
1364627f7eb2Smrg gfc_constructor *c = gfc_constructor_first (head);
1365627f7eb2Smrg r = gfc_get_array_expr (c->expr->ts.type, c->expr->ts.kind,
1366627f7eb2Smrg &op2->where);
1367627f7eb2Smrg r->shape = gfc_copy_shape (op2->shape, op2->rank);
1368627f7eb2Smrg r->rank = op2->rank;
1369627f7eb2Smrg r->value.constructor = head;
1370627f7eb2Smrg *result = r;
1371627f7eb2Smrg }
1372627f7eb2Smrg
1373627f7eb2Smrg return rc;
1374627f7eb2Smrg }
1375627f7eb2Smrg
1376627f7eb2Smrg
1377627f7eb2Smrg /* We need a forward declaration of reduce_binary. */
1378627f7eb2Smrg static arith reduce_binary (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **),
1379627f7eb2Smrg gfc_expr *op1, gfc_expr *op2, gfc_expr **result);
1380627f7eb2Smrg
1381627f7eb2Smrg
1382627f7eb2Smrg static arith
reduce_binary_aa(arith (* eval)(gfc_expr *,gfc_expr *,gfc_expr **),gfc_expr * op1,gfc_expr * op2,gfc_expr ** result)1383627f7eb2Smrg reduce_binary_aa (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **),
1384627f7eb2Smrg gfc_expr *op1, gfc_expr *op2, gfc_expr **result)
1385627f7eb2Smrg {
1386627f7eb2Smrg gfc_constructor_base head;
1387627f7eb2Smrg gfc_constructor *c, *d;
1388627f7eb2Smrg gfc_expr *r;
1389627f7eb2Smrg arith rc = ARITH_OK;
1390627f7eb2Smrg
1391627f7eb2Smrg if (!gfc_check_conformance (op1, op2, "elemental binary operation"))
1392627f7eb2Smrg return ARITH_INCOMMENSURATE;
1393627f7eb2Smrg
1394627f7eb2Smrg head = gfc_constructor_copy (op1->value.constructor);
1395627f7eb2Smrg for (c = gfc_constructor_first (head),
1396627f7eb2Smrg d = gfc_constructor_first (op2->value.constructor);
1397627f7eb2Smrg c && d;
1398627f7eb2Smrg c = gfc_constructor_next (c), d = gfc_constructor_next (d))
1399627f7eb2Smrg {
1400627f7eb2Smrg rc = reduce_binary (eval, c->expr, d->expr, &r);
1401627f7eb2Smrg if (rc != ARITH_OK)
1402627f7eb2Smrg break;
1403627f7eb2Smrg
1404627f7eb2Smrg gfc_replace_expr (c->expr, r);
1405627f7eb2Smrg }
1406627f7eb2Smrg
1407627f7eb2Smrg if (c || d)
1408627f7eb2Smrg rc = ARITH_INCOMMENSURATE;
1409627f7eb2Smrg
1410627f7eb2Smrg if (rc != ARITH_OK)
1411627f7eb2Smrg gfc_constructor_free (head);
1412627f7eb2Smrg else
1413627f7eb2Smrg {
1414627f7eb2Smrg gfc_constructor *c = gfc_constructor_first (head);
1415627f7eb2Smrg r = gfc_get_array_expr (c->expr->ts.type, c->expr->ts.kind,
1416627f7eb2Smrg &op1->where);
1417627f7eb2Smrg r->shape = gfc_copy_shape (op1->shape, op1->rank);
1418627f7eb2Smrg r->rank = op1->rank;
1419627f7eb2Smrg r->value.constructor = head;
1420627f7eb2Smrg *result = r;
1421627f7eb2Smrg }
1422627f7eb2Smrg
1423627f7eb2Smrg return rc;
1424627f7eb2Smrg }
1425627f7eb2Smrg
1426627f7eb2Smrg
1427627f7eb2Smrg static arith
reduce_binary(arith (* eval)(gfc_expr *,gfc_expr *,gfc_expr **),gfc_expr * op1,gfc_expr * op2,gfc_expr ** result)1428627f7eb2Smrg reduce_binary (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **),
1429627f7eb2Smrg gfc_expr *op1, gfc_expr *op2, gfc_expr **result)
1430627f7eb2Smrg {
1431627f7eb2Smrg if (op1->expr_type == EXPR_CONSTANT && op2->expr_type == EXPR_CONSTANT)
1432627f7eb2Smrg return eval (op1, op2, result);
1433627f7eb2Smrg
1434627f7eb2Smrg if (op1->expr_type == EXPR_CONSTANT && op2->expr_type == EXPR_ARRAY)
1435627f7eb2Smrg return reduce_binary_ca (eval, op1, op2, result);
1436627f7eb2Smrg
1437627f7eb2Smrg if (op1->expr_type == EXPR_ARRAY && op2->expr_type == EXPR_CONSTANT)
1438627f7eb2Smrg return reduce_binary_ac (eval, op1, op2, result);
1439627f7eb2Smrg
1440627f7eb2Smrg return reduce_binary_aa (eval, op1, op2, result);
1441627f7eb2Smrg }
1442627f7eb2Smrg
1443627f7eb2Smrg
1444627f7eb2Smrg typedef union
1445627f7eb2Smrg {
1446627f7eb2Smrg arith (*f2)(gfc_expr *, gfc_expr **);
1447627f7eb2Smrg arith (*f3)(gfc_expr *, gfc_expr *, gfc_expr **);
1448627f7eb2Smrg }
1449627f7eb2Smrg eval_f;
1450627f7eb2Smrg
1451627f7eb2Smrg /* High level arithmetic subroutines. These subroutines go into
1452627f7eb2Smrg eval_intrinsic(), which can do one of several things to its
1453627f7eb2Smrg operands. If the operands are incompatible with the intrinsic
1454627f7eb2Smrg operation, we return a node pointing to the operands and hope that
1455627f7eb2Smrg an operator interface is found during resolution.
1456627f7eb2Smrg
1457627f7eb2Smrg If the operands are compatible and are constants, then we try doing
1458627f7eb2Smrg the arithmetic. We also handle the cases where either or both
1459627f7eb2Smrg operands are array constructors. */
1460627f7eb2Smrg
1461627f7eb2Smrg static gfc_expr *
eval_intrinsic(gfc_intrinsic_op op,eval_f eval,gfc_expr * op1,gfc_expr * op2)1462627f7eb2Smrg eval_intrinsic (gfc_intrinsic_op op,
1463627f7eb2Smrg eval_f eval, gfc_expr *op1, gfc_expr *op2)
1464627f7eb2Smrg {
1465627f7eb2Smrg gfc_expr temp, *result;
1466627f7eb2Smrg int unary;
1467627f7eb2Smrg arith rc;
1468627f7eb2Smrg
1469627f7eb2Smrg gfc_clear_ts (&temp.ts);
1470627f7eb2Smrg
1471627f7eb2Smrg switch (op)
1472627f7eb2Smrg {
1473627f7eb2Smrg /* Logical unary */
1474627f7eb2Smrg case INTRINSIC_NOT:
1475627f7eb2Smrg if (op1->ts.type != BT_LOGICAL)
1476627f7eb2Smrg goto runtime;
1477627f7eb2Smrg
1478627f7eb2Smrg temp.ts.type = BT_LOGICAL;
1479627f7eb2Smrg temp.ts.kind = gfc_default_logical_kind;
1480627f7eb2Smrg unary = 1;
1481627f7eb2Smrg break;
1482627f7eb2Smrg
1483627f7eb2Smrg /* Logical binary operators */
1484627f7eb2Smrg case INTRINSIC_OR:
1485627f7eb2Smrg case INTRINSIC_AND:
1486627f7eb2Smrg case INTRINSIC_NEQV:
1487627f7eb2Smrg case INTRINSIC_EQV:
1488627f7eb2Smrg if (op1->ts.type != BT_LOGICAL || op2->ts.type != BT_LOGICAL)
1489627f7eb2Smrg goto runtime;
1490627f7eb2Smrg
1491627f7eb2Smrg temp.ts.type = BT_LOGICAL;
1492627f7eb2Smrg temp.ts.kind = gfc_default_logical_kind;
1493627f7eb2Smrg unary = 0;
1494627f7eb2Smrg break;
1495627f7eb2Smrg
1496627f7eb2Smrg /* Numeric unary */
1497627f7eb2Smrg case INTRINSIC_UPLUS:
1498627f7eb2Smrg case INTRINSIC_UMINUS:
1499627f7eb2Smrg if (!gfc_numeric_ts (&op1->ts))
1500627f7eb2Smrg goto runtime;
1501627f7eb2Smrg
1502627f7eb2Smrg temp.ts = op1->ts;
1503627f7eb2Smrg unary = 1;
1504627f7eb2Smrg break;
1505627f7eb2Smrg
1506627f7eb2Smrg case INTRINSIC_PARENTHESES:
1507627f7eb2Smrg temp.ts = op1->ts;
1508627f7eb2Smrg unary = 1;
1509627f7eb2Smrg break;
1510627f7eb2Smrg
1511627f7eb2Smrg /* Additional restrictions for ordering relations. */
1512627f7eb2Smrg case INTRINSIC_GE:
1513627f7eb2Smrg case INTRINSIC_GE_OS:
1514627f7eb2Smrg case INTRINSIC_LT:
1515627f7eb2Smrg case INTRINSIC_LT_OS:
1516627f7eb2Smrg case INTRINSIC_LE:
1517627f7eb2Smrg case INTRINSIC_LE_OS:
1518627f7eb2Smrg case INTRINSIC_GT:
1519627f7eb2Smrg case INTRINSIC_GT_OS:
1520627f7eb2Smrg if (op1->ts.type == BT_COMPLEX || op2->ts.type == BT_COMPLEX)
1521627f7eb2Smrg {
1522627f7eb2Smrg temp.ts.type = BT_LOGICAL;
1523627f7eb2Smrg temp.ts.kind = gfc_default_logical_kind;
1524627f7eb2Smrg goto runtime;
1525627f7eb2Smrg }
1526627f7eb2Smrg
1527627f7eb2Smrg /* Fall through */
1528627f7eb2Smrg case INTRINSIC_EQ:
1529627f7eb2Smrg case INTRINSIC_EQ_OS:
1530627f7eb2Smrg case INTRINSIC_NE:
1531627f7eb2Smrg case INTRINSIC_NE_OS:
1532627f7eb2Smrg if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER)
1533627f7eb2Smrg {
1534627f7eb2Smrg unary = 0;
1535627f7eb2Smrg temp.ts.type = BT_LOGICAL;
1536627f7eb2Smrg temp.ts.kind = gfc_default_logical_kind;
1537627f7eb2Smrg
1538627f7eb2Smrg /* If kind mismatch, exit and we'll error out later. */
1539627f7eb2Smrg if (op1->ts.kind != op2->ts.kind)
1540627f7eb2Smrg goto runtime;
1541627f7eb2Smrg
1542627f7eb2Smrg break;
1543627f7eb2Smrg }
1544627f7eb2Smrg
1545627f7eb2Smrg gcc_fallthrough ();
1546627f7eb2Smrg /* Numeric binary */
1547627f7eb2Smrg case INTRINSIC_PLUS:
1548627f7eb2Smrg case INTRINSIC_MINUS:
1549627f7eb2Smrg case INTRINSIC_TIMES:
1550627f7eb2Smrg case INTRINSIC_DIVIDE:
1551627f7eb2Smrg case INTRINSIC_POWER:
1552627f7eb2Smrg if (!gfc_numeric_ts (&op1->ts) || !gfc_numeric_ts (&op2->ts))
1553627f7eb2Smrg goto runtime;
1554627f7eb2Smrg
1555627f7eb2Smrg /* Insert any necessary type conversions to make the operands
1556627f7eb2Smrg compatible. */
1557627f7eb2Smrg
1558627f7eb2Smrg temp.expr_type = EXPR_OP;
1559627f7eb2Smrg gfc_clear_ts (&temp.ts);
1560627f7eb2Smrg temp.value.op.op = op;
1561627f7eb2Smrg
1562627f7eb2Smrg temp.value.op.op1 = op1;
1563627f7eb2Smrg temp.value.op.op2 = op2;
1564627f7eb2Smrg
1565627f7eb2Smrg gfc_type_convert_binary (&temp, warn_conversion || warn_conversion_extra);
1566627f7eb2Smrg
1567627f7eb2Smrg if (op == INTRINSIC_EQ || op == INTRINSIC_NE
1568627f7eb2Smrg || op == INTRINSIC_GE || op == INTRINSIC_GT
1569627f7eb2Smrg || op == INTRINSIC_LE || op == INTRINSIC_LT
1570627f7eb2Smrg || op == INTRINSIC_EQ_OS || op == INTRINSIC_NE_OS
1571627f7eb2Smrg || op == INTRINSIC_GE_OS || op == INTRINSIC_GT_OS
1572627f7eb2Smrg || op == INTRINSIC_LE_OS || op == INTRINSIC_LT_OS)
1573627f7eb2Smrg {
1574627f7eb2Smrg temp.ts.type = BT_LOGICAL;
1575627f7eb2Smrg temp.ts.kind = gfc_default_logical_kind;
1576627f7eb2Smrg }
1577627f7eb2Smrg
1578627f7eb2Smrg unary = 0;
1579627f7eb2Smrg break;
1580627f7eb2Smrg
1581627f7eb2Smrg /* Character binary */
1582627f7eb2Smrg case INTRINSIC_CONCAT:
1583627f7eb2Smrg if (op1->ts.type != BT_CHARACTER || op2->ts.type != BT_CHARACTER
1584627f7eb2Smrg || op1->ts.kind != op2->ts.kind)
1585627f7eb2Smrg goto runtime;
1586627f7eb2Smrg
1587627f7eb2Smrg temp.ts.type = BT_CHARACTER;
1588627f7eb2Smrg temp.ts.kind = op1->ts.kind;
1589627f7eb2Smrg unary = 0;
1590627f7eb2Smrg break;
1591627f7eb2Smrg
1592627f7eb2Smrg case INTRINSIC_USER:
1593627f7eb2Smrg goto runtime;
1594627f7eb2Smrg
1595627f7eb2Smrg default:
1596627f7eb2Smrg gfc_internal_error ("eval_intrinsic(): Bad operator");
1597627f7eb2Smrg }
1598627f7eb2Smrg
1599627f7eb2Smrg if (op1->expr_type != EXPR_CONSTANT
1600627f7eb2Smrg && (op1->expr_type != EXPR_ARRAY
1601627f7eb2Smrg || !gfc_is_constant_expr (op1) || !gfc_expanded_ac (op1)))
1602627f7eb2Smrg goto runtime;
1603627f7eb2Smrg
1604627f7eb2Smrg if (op2 != NULL
1605627f7eb2Smrg && op2->expr_type != EXPR_CONSTANT
1606627f7eb2Smrg && (op2->expr_type != EXPR_ARRAY
1607627f7eb2Smrg || !gfc_is_constant_expr (op2) || !gfc_expanded_ac (op2)))
1608627f7eb2Smrg goto runtime;
1609627f7eb2Smrg
1610627f7eb2Smrg if (unary)
1611627f7eb2Smrg rc = reduce_unary (eval.f2, op1, &result);
1612627f7eb2Smrg else
1613627f7eb2Smrg rc = reduce_binary (eval.f3, op1, op2, &result);
1614627f7eb2Smrg
1615627f7eb2Smrg
1616627f7eb2Smrg /* Something went wrong. */
1617627f7eb2Smrg if (op == INTRINSIC_POWER && rc == ARITH_PROHIBIT)
1618627f7eb2Smrg return NULL;
1619627f7eb2Smrg
1620627f7eb2Smrg if (rc != ARITH_OK)
1621627f7eb2Smrg {
1622627f7eb2Smrg gfc_error (gfc_arith_error (rc), &op1->where);
1623627f7eb2Smrg if (rc == ARITH_OVERFLOW)
1624627f7eb2Smrg goto done;
1625627f7eb2Smrg
1626627f7eb2Smrg if (rc == ARITH_DIV0 && op2->ts.type == BT_INTEGER)
1627627f7eb2Smrg gfc_seen_div0 = true;
1628627f7eb2Smrg
1629627f7eb2Smrg return NULL;
1630627f7eb2Smrg }
1631627f7eb2Smrg
1632627f7eb2Smrg done:
1633627f7eb2Smrg
1634627f7eb2Smrg gfc_free_expr (op1);
1635627f7eb2Smrg gfc_free_expr (op2);
1636627f7eb2Smrg return result;
1637627f7eb2Smrg
1638627f7eb2Smrg runtime:
1639627f7eb2Smrg /* Create a run-time expression. */
1640627f7eb2Smrg result = gfc_get_operator_expr (&op1->where, op, op1, op2);
1641627f7eb2Smrg result->ts = temp.ts;
1642627f7eb2Smrg
1643627f7eb2Smrg return result;
1644627f7eb2Smrg }
1645627f7eb2Smrg
1646627f7eb2Smrg
1647627f7eb2Smrg /* Modify type of expression for zero size array. */
1648627f7eb2Smrg
1649627f7eb2Smrg static gfc_expr *
eval_type_intrinsic0(gfc_intrinsic_op iop,gfc_expr * op)1650627f7eb2Smrg eval_type_intrinsic0 (gfc_intrinsic_op iop, gfc_expr *op)
1651627f7eb2Smrg {
1652627f7eb2Smrg if (op == NULL)
1653627f7eb2Smrg gfc_internal_error ("eval_type_intrinsic0(): op NULL");
1654627f7eb2Smrg
1655627f7eb2Smrg switch (iop)
1656627f7eb2Smrg {
1657627f7eb2Smrg case INTRINSIC_GE:
1658627f7eb2Smrg case INTRINSIC_GE_OS:
1659627f7eb2Smrg case INTRINSIC_LT:
1660627f7eb2Smrg case INTRINSIC_LT_OS:
1661627f7eb2Smrg case INTRINSIC_LE:
1662627f7eb2Smrg case INTRINSIC_LE_OS:
1663627f7eb2Smrg case INTRINSIC_GT:
1664627f7eb2Smrg case INTRINSIC_GT_OS:
1665627f7eb2Smrg case INTRINSIC_EQ:
1666627f7eb2Smrg case INTRINSIC_EQ_OS:
1667627f7eb2Smrg case INTRINSIC_NE:
1668627f7eb2Smrg case INTRINSIC_NE_OS:
1669627f7eb2Smrg op->ts.type = BT_LOGICAL;
1670627f7eb2Smrg op->ts.kind = gfc_default_logical_kind;
1671627f7eb2Smrg break;
1672627f7eb2Smrg
1673627f7eb2Smrg default:
1674627f7eb2Smrg break;
1675627f7eb2Smrg }
1676627f7eb2Smrg
1677627f7eb2Smrg return op;
1678627f7eb2Smrg }
1679627f7eb2Smrg
1680627f7eb2Smrg
1681627f7eb2Smrg /* Return nonzero if the expression is a zero size array. */
1682627f7eb2Smrg
1683627f7eb2Smrg static int
gfc_zero_size_array(gfc_expr * e)1684627f7eb2Smrg gfc_zero_size_array (gfc_expr *e)
1685627f7eb2Smrg {
1686627f7eb2Smrg if (e->expr_type != EXPR_ARRAY)
1687627f7eb2Smrg return 0;
1688627f7eb2Smrg
1689627f7eb2Smrg return e->value.constructor == NULL;
1690627f7eb2Smrg }
1691627f7eb2Smrg
1692627f7eb2Smrg
1693627f7eb2Smrg /* Reduce a binary expression where at least one of the operands
1694627f7eb2Smrg involves a zero-length array. Returns NULL if neither of the
1695627f7eb2Smrg operands is a zero-length array. */
1696627f7eb2Smrg
1697627f7eb2Smrg static gfc_expr *
reduce_binary0(gfc_expr * op1,gfc_expr * op2)1698627f7eb2Smrg reduce_binary0 (gfc_expr *op1, gfc_expr *op2)
1699627f7eb2Smrg {
1700627f7eb2Smrg if (gfc_zero_size_array (op1))
1701627f7eb2Smrg {
1702627f7eb2Smrg gfc_free_expr (op2);
1703627f7eb2Smrg return op1;
1704627f7eb2Smrg }
1705627f7eb2Smrg
1706627f7eb2Smrg if (gfc_zero_size_array (op2))
1707627f7eb2Smrg {
1708627f7eb2Smrg gfc_free_expr (op1);
1709627f7eb2Smrg return op2;
1710627f7eb2Smrg }
1711627f7eb2Smrg
1712627f7eb2Smrg return NULL;
1713627f7eb2Smrg }
1714627f7eb2Smrg
1715627f7eb2Smrg
1716627f7eb2Smrg static gfc_expr *
eval_intrinsic_f2(gfc_intrinsic_op op,arith (* eval)(gfc_expr *,gfc_expr **),gfc_expr * op1,gfc_expr * op2)1717627f7eb2Smrg eval_intrinsic_f2 (gfc_intrinsic_op op,
1718627f7eb2Smrg arith (*eval) (gfc_expr *, gfc_expr **),
1719627f7eb2Smrg gfc_expr *op1, gfc_expr *op2)
1720627f7eb2Smrg {
1721627f7eb2Smrg gfc_expr *result;
1722627f7eb2Smrg eval_f f;
1723627f7eb2Smrg
1724627f7eb2Smrg if (op2 == NULL)
1725627f7eb2Smrg {
1726627f7eb2Smrg if (gfc_zero_size_array (op1))
1727627f7eb2Smrg return eval_type_intrinsic0 (op, op1);
1728627f7eb2Smrg }
1729627f7eb2Smrg else
1730627f7eb2Smrg {
1731627f7eb2Smrg result = reduce_binary0 (op1, op2);
1732627f7eb2Smrg if (result != NULL)
1733627f7eb2Smrg return eval_type_intrinsic0 (op, result);
1734627f7eb2Smrg }
1735627f7eb2Smrg
1736627f7eb2Smrg f.f2 = eval;
1737627f7eb2Smrg return eval_intrinsic (op, f, op1, op2);
1738627f7eb2Smrg }
1739627f7eb2Smrg
1740627f7eb2Smrg
1741627f7eb2Smrg static gfc_expr *
eval_intrinsic_f3(gfc_intrinsic_op op,arith (* eval)(gfc_expr *,gfc_expr *,gfc_expr **),gfc_expr * op1,gfc_expr * op2)1742627f7eb2Smrg eval_intrinsic_f3 (gfc_intrinsic_op op,
1743627f7eb2Smrg arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **),
1744627f7eb2Smrg gfc_expr *op1, gfc_expr *op2)
1745627f7eb2Smrg {
1746627f7eb2Smrg gfc_expr *result;
1747627f7eb2Smrg eval_f f;
1748627f7eb2Smrg
1749627f7eb2Smrg result = reduce_binary0 (op1, op2);
1750627f7eb2Smrg if (result != NULL)
1751627f7eb2Smrg return eval_type_intrinsic0(op, result);
1752627f7eb2Smrg
1753627f7eb2Smrg f.f3 = eval;
1754627f7eb2Smrg return eval_intrinsic (op, f, op1, op2);
1755627f7eb2Smrg }
1756627f7eb2Smrg
1757627f7eb2Smrg
1758627f7eb2Smrg gfc_expr *
gfc_parentheses(gfc_expr * op)1759627f7eb2Smrg gfc_parentheses (gfc_expr *op)
1760627f7eb2Smrg {
1761627f7eb2Smrg if (gfc_is_constant_expr (op))
1762627f7eb2Smrg return op;
1763627f7eb2Smrg
1764627f7eb2Smrg return eval_intrinsic_f2 (INTRINSIC_PARENTHESES, gfc_arith_identity,
1765627f7eb2Smrg op, NULL);
1766627f7eb2Smrg }
1767627f7eb2Smrg
1768627f7eb2Smrg gfc_expr *
gfc_uplus(gfc_expr * op)1769627f7eb2Smrg gfc_uplus (gfc_expr *op)
1770627f7eb2Smrg {
1771627f7eb2Smrg return eval_intrinsic_f2 (INTRINSIC_UPLUS, gfc_arith_identity, op, NULL);
1772627f7eb2Smrg }
1773627f7eb2Smrg
1774627f7eb2Smrg
1775627f7eb2Smrg gfc_expr *
gfc_uminus(gfc_expr * op)1776627f7eb2Smrg gfc_uminus (gfc_expr *op)
1777627f7eb2Smrg {
1778627f7eb2Smrg return eval_intrinsic_f2 (INTRINSIC_UMINUS, gfc_arith_uminus, op, NULL);
1779627f7eb2Smrg }
1780627f7eb2Smrg
1781627f7eb2Smrg
1782627f7eb2Smrg gfc_expr *
gfc_add(gfc_expr * op1,gfc_expr * op2)1783627f7eb2Smrg gfc_add (gfc_expr *op1, gfc_expr *op2)
1784627f7eb2Smrg {
1785627f7eb2Smrg return eval_intrinsic_f3 (INTRINSIC_PLUS, gfc_arith_plus, op1, op2);
1786627f7eb2Smrg }
1787627f7eb2Smrg
1788627f7eb2Smrg
1789627f7eb2Smrg gfc_expr *
gfc_subtract(gfc_expr * op1,gfc_expr * op2)1790627f7eb2Smrg gfc_subtract (gfc_expr *op1, gfc_expr *op2)
1791627f7eb2Smrg {
1792627f7eb2Smrg return eval_intrinsic_f3 (INTRINSIC_MINUS, gfc_arith_minus, op1, op2);
1793627f7eb2Smrg }
1794627f7eb2Smrg
1795627f7eb2Smrg
1796627f7eb2Smrg gfc_expr *
gfc_multiply(gfc_expr * op1,gfc_expr * op2)1797627f7eb2Smrg gfc_multiply (gfc_expr *op1, gfc_expr *op2)
1798627f7eb2Smrg {
1799627f7eb2Smrg return eval_intrinsic_f3 (INTRINSIC_TIMES, gfc_arith_times, op1, op2);
1800627f7eb2Smrg }
1801627f7eb2Smrg
1802627f7eb2Smrg
1803627f7eb2Smrg gfc_expr *
gfc_divide(gfc_expr * op1,gfc_expr * op2)1804627f7eb2Smrg gfc_divide (gfc_expr *op1, gfc_expr *op2)
1805627f7eb2Smrg {
1806627f7eb2Smrg return eval_intrinsic_f3 (INTRINSIC_DIVIDE, gfc_arith_divide, op1, op2);
1807627f7eb2Smrg }
1808627f7eb2Smrg
1809627f7eb2Smrg
1810627f7eb2Smrg gfc_expr *
gfc_power(gfc_expr * op1,gfc_expr * op2)1811627f7eb2Smrg gfc_power (gfc_expr *op1, gfc_expr *op2)
1812627f7eb2Smrg {
1813627f7eb2Smrg return eval_intrinsic_f3 (INTRINSIC_POWER, arith_power, op1, op2);
1814627f7eb2Smrg }
1815627f7eb2Smrg
1816627f7eb2Smrg
1817627f7eb2Smrg gfc_expr *
gfc_concat(gfc_expr * op1,gfc_expr * op2)1818627f7eb2Smrg gfc_concat (gfc_expr *op1, gfc_expr *op2)
1819627f7eb2Smrg {
1820627f7eb2Smrg return eval_intrinsic_f3 (INTRINSIC_CONCAT, gfc_arith_concat, op1, op2);
1821627f7eb2Smrg }
1822627f7eb2Smrg
1823627f7eb2Smrg
1824627f7eb2Smrg gfc_expr *
gfc_and(gfc_expr * op1,gfc_expr * op2)1825627f7eb2Smrg gfc_and (gfc_expr *op1, gfc_expr *op2)
1826627f7eb2Smrg {
1827627f7eb2Smrg return eval_intrinsic_f3 (INTRINSIC_AND, gfc_arith_and, op1, op2);
1828627f7eb2Smrg }
1829627f7eb2Smrg
1830627f7eb2Smrg
1831627f7eb2Smrg gfc_expr *
gfc_or(gfc_expr * op1,gfc_expr * op2)1832627f7eb2Smrg gfc_or (gfc_expr *op1, gfc_expr *op2)
1833627f7eb2Smrg {
1834627f7eb2Smrg return eval_intrinsic_f3 (INTRINSIC_OR, gfc_arith_or, op1, op2);
1835627f7eb2Smrg }
1836627f7eb2Smrg
1837627f7eb2Smrg
1838627f7eb2Smrg gfc_expr *
gfc_not(gfc_expr * op1)1839627f7eb2Smrg gfc_not (gfc_expr *op1)
1840627f7eb2Smrg {
1841627f7eb2Smrg return eval_intrinsic_f2 (INTRINSIC_NOT, gfc_arith_not, op1, NULL);
1842627f7eb2Smrg }
1843627f7eb2Smrg
1844627f7eb2Smrg
1845627f7eb2Smrg gfc_expr *
gfc_eqv(gfc_expr * op1,gfc_expr * op2)1846627f7eb2Smrg gfc_eqv (gfc_expr *op1, gfc_expr *op2)
1847627f7eb2Smrg {
1848627f7eb2Smrg return eval_intrinsic_f3 (INTRINSIC_EQV, gfc_arith_eqv, op1, op2);
1849627f7eb2Smrg }
1850627f7eb2Smrg
1851627f7eb2Smrg
1852627f7eb2Smrg gfc_expr *
gfc_neqv(gfc_expr * op1,gfc_expr * op2)1853627f7eb2Smrg gfc_neqv (gfc_expr *op1, gfc_expr *op2)
1854627f7eb2Smrg {
1855627f7eb2Smrg return eval_intrinsic_f3 (INTRINSIC_NEQV, gfc_arith_neqv, op1, op2);
1856627f7eb2Smrg }
1857627f7eb2Smrg
1858627f7eb2Smrg
1859627f7eb2Smrg gfc_expr *
gfc_eq(gfc_expr * op1,gfc_expr * op2,gfc_intrinsic_op op)1860627f7eb2Smrg gfc_eq (gfc_expr *op1, gfc_expr *op2, gfc_intrinsic_op op)
1861627f7eb2Smrg {
1862627f7eb2Smrg return eval_intrinsic_f3 (op, gfc_arith_eq, op1, op2);
1863627f7eb2Smrg }
1864627f7eb2Smrg
1865627f7eb2Smrg
1866627f7eb2Smrg gfc_expr *
gfc_ne(gfc_expr * op1,gfc_expr * op2,gfc_intrinsic_op op)1867627f7eb2Smrg gfc_ne (gfc_expr *op1, gfc_expr *op2, gfc_intrinsic_op op)
1868627f7eb2Smrg {
1869627f7eb2Smrg return eval_intrinsic_f3 (op, gfc_arith_ne, op1, op2);
1870627f7eb2Smrg }
1871627f7eb2Smrg
1872627f7eb2Smrg
1873627f7eb2Smrg gfc_expr *
gfc_gt(gfc_expr * op1,gfc_expr * op2,gfc_intrinsic_op op)1874627f7eb2Smrg gfc_gt (gfc_expr *op1, gfc_expr *op2, gfc_intrinsic_op op)
1875627f7eb2Smrg {
1876627f7eb2Smrg return eval_intrinsic_f3 (op, gfc_arith_gt, op1, op2);
1877627f7eb2Smrg }
1878627f7eb2Smrg
1879627f7eb2Smrg
1880627f7eb2Smrg gfc_expr *
gfc_ge(gfc_expr * op1,gfc_expr * op2,gfc_intrinsic_op op)1881627f7eb2Smrg gfc_ge (gfc_expr *op1, gfc_expr *op2, gfc_intrinsic_op op)
1882627f7eb2Smrg {
1883627f7eb2Smrg return eval_intrinsic_f3 (op, gfc_arith_ge, op1, op2);
1884627f7eb2Smrg }
1885627f7eb2Smrg
1886627f7eb2Smrg
1887627f7eb2Smrg gfc_expr *
gfc_lt(gfc_expr * op1,gfc_expr * op2,gfc_intrinsic_op op)1888627f7eb2Smrg gfc_lt (gfc_expr *op1, gfc_expr *op2, gfc_intrinsic_op op)
1889627f7eb2Smrg {
1890627f7eb2Smrg return eval_intrinsic_f3 (op, gfc_arith_lt, op1, op2);
1891627f7eb2Smrg }
1892627f7eb2Smrg
1893627f7eb2Smrg
1894627f7eb2Smrg gfc_expr *
gfc_le(gfc_expr * op1,gfc_expr * op2,gfc_intrinsic_op op)1895627f7eb2Smrg gfc_le (gfc_expr *op1, gfc_expr *op2, gfc_intrinsic_op op)
1896627f7eb2Smrg {
1897627f7eb2Smrg return eval_intrinsic_f3 (op, gfc_arith_le, op1, op2);
1898627f7eb2Smrg }
1899627f7eb2Smrg
1900627f7eb2Smrg
1901627f7eb2Smrg /******* Simplification of intrinsic functions with constant arguments *****/
1902627f7eb2Smrg
1903627f7eb2Smrg
1904627f7eb2Smrg /* Deal with an arithmetic error. */
1905627f7eb2Smrg
1906627f7eb2Smrg static void
arith_error(arith rc,gfc_typespec * from,gfc_typespec * to,locus * where)1907627f7eb2Smrg arith_error (arith rc, gfc_typespec *from, gfc_typespec *to, locus *where)
1908627f7eb2Smrg {
1909627f7eb2Smrg switch (rc)
1910627f7eb2Smrg {
1911627f7eb2Smrg case ARITH_OK:
1912627f7eb2Smrg gfc_error ("Arithmetic OK converting %s to %s at %L",
1913627f7eb2Smrg gfc_typename (from), gfc_typename (to), where);
1914627f7eb2Smrg break;
1915627f7eb2Smrg case ARITH_OVERFLOW:
1916627f7eb2Smrg gfc_error ("Arithmetic overflow converting %s to %s at %L. This check "
1917627f7eb2Smrg "can be disabled with the option %<-fno-range-check%>",
1918627f7eb2Smrg gfc_typename (from), gfc_typename (to), where);
1919627f7eb2Smrg break;
1920627f7eb2Smrg case ARITH_UNDERFLOW:
1921627f7eb2Smrg gfc_error ("Arithmetic underflow converting %s to %s at %L. This check "
1922627f7eb2Smrg "can be disabled with the option %<-fno-range-check%>",
1923627f7eb2Smrg gfc_typename (from), gfc_typename (to), where);
1924627f7eb2Smrg break;
1925627f7eb2Smrg case ARITH_NAN:
1926627f7eb2Smrg gfc_error ("Arithmetic NaN converting %s to %s at %L. This check "
1927627f7eb2Smrg "can be disabled with the option %<-fno-range-check%>",
1928627f7eb2Smrg gfc_typename (from), gfc_typename (to), where);
1929627f7eb2Smrg break;
1930627f7eb2Smrg case ARITH_DIV0:
1931627f7eb2Smrg gfc_error ("Division by zero converting %s to %s at %L",
1932627f7eb2Smrg gfc_typename (from), gfc_typename (to), where);
1933627f7eb2Smrg break;
1934627f7eb2Smrg case ARITH_INCOMMENSURATE:
1935627f7eb2Smrg gfc_error ("Array operands are incommensurate converting %s to %s at %L",
1936627f7eb2Smrg gfc_typename (from), gfc_typename (to), where);
1937627f7eb2Smrg break;
1938627f7eb2Smrg case ARITH_ASYMMETRIC:
1939627f7eb2Smrg gfc_error ("Integer outside symmetric range implied by Standard Fortran"
1940627f7eb2Smrg " converting %s to %s at %L",
1941627f7eb2Smrg gfc_typename (from), gfc_typename (to), where);
1942627f7eb2Smrg break;
1943627f7eb2Smrg default:
1944627f7eb2Smrg gfc_internal_error ("gfc_arith_error(): Bad error code");
1945627f7eb2Smrg }
1946627f7eb2Smrg
1947627f7eb2Smrg /* TODO: Do something about the error, i.e., throw exception, return
1948627f7eb2Smrg NaN, etc. */
1949627f7eb2Smrg }
1950627f7eb2Smrg
1951627f7eb2Smrg /* Returns true if significant bits were lost when converting real
1952627f7eb2Smrg constant r from from_kind to to_kind. */
1953627f7eb2Smrg
1954627f7eb2Smrg static bool
wprecision_real_real(mpfr_t r,int from_kind,int to_kind)1955627f7eb2Smrg wprecision_real_real (mpfr_t r, int from_kind, int to_kind)
1956627f7eb2Smrg {
1957627f7eb2Smrg mpfr_t rv, diff;
1958627f7eb2Smrg bool ret;
1959627f7eb2Smrg
1960627f7eb2Smrg gfc_set_model_kind (to_kind);
1961627f7eb2Smrg mpfr_init (rv);
1962627f7eb2Smrg gfc_set_model_kind (from_kind);
1963627f7eb2Smrg mpfr_init (diff);
1964627f7eb2Smrg
1965627f7eb2Smrg mpfr_set (rv, r, GFC_RND_MODE);
1966627f7eb2Smrg mpfr_sub (diff, rv, r, GFC_RND_MODE);
1967627f7eb2Smrg
1968627f7eb2Smrg ret = ! mpfr_zero_p (diff);
1969627f7eb2Smrg mpfr_clear (rv);
1970627f7eb2Smrg mpfr_clear (diff);
1971627f7eb2Smrg return ret;
1972627f7eb2Smrg }
1973627f7eb2Smrg
1974627f7eb2Smrg /* Return true if conversion from an integer to a real loses precision. */
1975627f7eb2Smrg
1976627f7eb2Smrg static bool
wprecision_int_real(mpz_t n,mpfr_t r)1977627f7eb2Smrg wprecision_int_real (mpz_t n, mpfr_t r)
1978627f7eb2Smrg {
1979627f7eb2Smrg bool ret;
1980627f7eb2Smrg mpz_t i;
1981627f7eb2Smrg mpz_init (i);
1982627f7eb2Smrg mpfr_get_z (i, r, GFC_RND_MODE);
1983627f7eb2Smrg mpz_sub (i, i, n);
1984627f7eb2Smrg ret = mpz_cmp_si (i, 0) != 0;
1985627f7eb2Smrg mpz_clear (i);
1986627f7eb2Smrg return ret;
1987627f7eb2Smrg }
1988627f7eb2Smrg
1989627f7eb2Smrg /* Convert integers to integers. */
1990627f7eb2Smrg
1991627f7eb2Smrg gfc_expr *
gfc_int2int(gfc_expr * src,int kind)1992627f7eb2Smrg gfc_int2int (gfc_expr *src, int kind)
1993627f7eb2Smrg {
1994627f7eb2Smrg gfc_expr *result;
1995627f7eb2Smrg arith rc;
1996627f7eb2Smrg
1997627f7eb2Smrg result = gfc_get_constant_expr (BT_INTEGER, kind, &src->where);
1998627f7eb2Smrg
1999627f7eb2Smrg mpz_set (result->value.integer, src->value.integer);
2000627f7eb2Smrg
2001627f7eb2Smrg if ((rc = gfc_check_integer_range (result->value.integer, kind)) != ARITH_OK)
2002627f7eb2Smrg {
2003627f7eb2Smrg if (rc == ARITH_ASYMMETRIC)
2004627f7eb2Smrg {
2005627f7eb2Smrg gfc_warning (0, gfc_arith_error (rc), &src->where);
2006627f7eb2Smrg }
2007627f7eb2Smrg else
2008627f7eb2Smrg {
2009627f7eb2Smrg arith_error (rc, &src->ts, &result->ts, &src->where);
2010627f7eb2Smrg gfc_free_expr (result);
2011627f7eb2Smrg return NULL;
2012627f7eb2Smrg }
2013627f7eb2Smrg }
2014627f7eb2Smrg
2015627f7eb2Smrg /* If we do not trap numeric overflow, we need to convert the number to
2016627f7eb2Smrg signed, throwing away high-order bits if necessary. */
2017627f7eb2Smrg if (flag_range_check == 0)
2018627f7eb2Smrg {
2019627f7eb2Smrg int k;
2020627f7eb2Smrg
2021627f7eb2Smrg k = gfc_validate_kind (BT_INTEGER, kind, false);
2022627f7eb2Smrg gfc_convert_mpz_to_signed (result->value.integer,
2023627f7eb2Smrg gfc_integer_kinds[k].bit_size);
2024627f7eb2Smrg
2025627f7eb2Smrg if (warn_conversion && !src->do_not_warn && kind < src->ts.kind)
2026627f7eb2Smrg gfc_warning_now (OPT_Wconversion, "Conversion from %qs to %qs at %L",
2027627f7eb2Smrg gfc_typename (&src->ts), gfc_typename (&result->ts),
2028627f7eb2Smrg &src->where);
2029627f7eb2Smrg }
2030627f7eb2Smrg return result;
2031627f7eb2Smrg }
2032627f7eb2Smrg
2033627f7eb2Smrg
2034627f7eb2Smrg /* Convert integers to reals. */
2035627f7eb2Smrg
2036627f7eb2Smrg gfc_expr *
gfc_int2real(gfc_expr * src,int kind)2037627f7eb2Smrg gfc_int2real (gfc_expr *src, int kind)
2038627f7eb2Smrg {
2039627f7eb2Smrg gfc_expr *result;
2040627f7eb2Smrg arith rc;
2041627f7eb2Smrg
2042627f7eb2Smrg result = gfc_get_constant_expr (BT_REAL, kind, &src->where);
2043627f7eb2Smrg
2044627f7eb2Smrg mpfr_set_z (result->value.real, src->value.integer, GFC_RND_MODE);
2045627f7eb2Smrg
2046627f7eb2Smrg if ((rc = gfc_check_real_range (result->value.real, kind)) != ARITH_OK)
2047627f7eb2Smrg {
2048627f7eb2Smrg arith_error (rc, &src->ts, &result->ts, &src->where);
2049627f7eb2Smrg gfc_free_expr (result);
2050627f7eb2Smrg return NULL;
2051627f7eb2Smrg }
2052627f7eb2Smrg
2053627f7eb2Smrg if (warn_conversion
2054627f7eb2Smrg && wprecision_int_real (src->value.integer, result->value.real))
2055627f7eb2Smrg gfc_warning (OPT_Wconversion, "Change of value in conversion "
2056627f7eb2Smrg "from %qs to %qs at %L",
2057627f7eb2Smrg gfc_typename (&src->ts),
2058627f7eb2Smrg gfc_typename (&result->ts),
2059627f7eb2Smrg &src->where);
2060627f7eb2Smrg
2061627f7eb2Smrg return result;
2062627f7eb2Smrg }
2063627f7eb2Smrg
2064627f7eb2Smrg
2065627f7eb2Smrg /* Convert default integer to default complex. */
2066627f7eb2Smrg
2067627f7eb2Smrg gfc_expr *
gfc_int2complex(gfc_expr * src,int kind)2068627f7eb2Smrg gfc_int2complex (gfc_expr *src, int kind)
2069627f7eb2Smrg {
2070627f7eb2Smrg gfc_expr *result;
2071627f7eb2Smrg arith rc;
2072627f7eb2Smrg
2073627f7eb2Smrg result = gfc_get_constant_expr (BT_COMPLEX, kind, &src->where);
2074627f7eb2Smrg
2075627f7eb2Smrg mpc_set_z (result->value.complex, src->value.integer, GFC_MPC_RND_MODE);
2076627f7eb2Smrg
2077627f7eb2Smrg if ((rc = gfc_check_real_range (mpc_realref (result->value.complex), kind))
2078627f7eb2Smrg != ARITH_OK)
2079627f7eb2Smrg {
2080627f7eb2Smrg arith_error (rc, &src->ts, &result->ts, &src->where);
2081627f7eb2Smrg gfc_free_expr (result);
2082627f7eb2Smrg return NULL;
2083627f7eb2Smrg }
2084627f7eb2Smrg
2085627f7eb2Smrg if (warn_conversion
2086627f7eb2Smrg && wprecision_int_real (src->value.integer,
2087627f7eb2Smrg mpc_realref (result->value.complex)))
2088627f7eb2Smrg gfc_warning_now (OPT_Wconversion, "Change of value in conversion "
2089627f7eb2Smrg "from %qs to %qs at %L",
2090627f7eb2Smrg gfc_typename (&src->ts),
2091627f7eb2Smrg gfc_typename (&result->ts),
2092627f7eb2Smrg &src->where);
2093627f7eb2Smrg
2094627f7eb2Smrg return result;
2095627f7eb2Smrg }
2096627f7eb2Smrg
2097627f7eb2Smrg
2098627f7eb2Smrg /* Convert default real to default integer. */
2099627f7eb2Smrg
2100627f7eb2Smrg gfc_expr *
gfc_real2int(gfc_expr * src,int kind)2101627f7eb2Smrg gfc_real2int (gfc_expr *src, int kind)
2102627f7eb2Smrg {
2103627f7eb2Smrg gfc_expr *result;
2104627f7eb2Smrg arith rc;
2105627f7eb2Smrg bool did_warn = false;
2106627f7eb2Smrg
2107627f7eb2Smrg result = gfc_get_constant_expr (BT_INTEGER, kind, &src->where);
2108627f7eb2Smrg
2109627f7eb2Smrg gfc_mpfr_to_mpz (result->value.integer, src->value.real, &src->where);
2110627f7eb2Smrg
2111627f7eb2Smrg if ((rc = gfc_check_integer_range (result->value.integer, kind)) != ARITH_OK)
2112627f7eb2Smrg {
2113627f7eb2Smrg arith_error (rc, &src->ts, &result->ts, &src->where);
2114627f7eb2Smrg gfc_free_expr (result);
2115627f7eb2Smrg return NULL;
2116627f7eb2Smrg }
2117627f7eb2Smrg
2118627f7eb2Smrg /* If there was a fractional part, warn about this. */
2119627f7eb2Smrg
2120627f7eb2Smrg if (warn_conversion)
2121627f7eb2Smrg {
2122627f7eb2Smrg mpfr_t f;
2123627f7eb2Smrg mpfr_init (f);
2124627f7eb2Smrg mpfr_frac (f, src->value.real, GFC_RND_MODE);
2125627f7eb2Smrg if (mpfr_cmp_si (f, 0) != 0)
2126627f7eb2Smrg {
2127627f7eb2Smrg gfc_warning_now (OPT_Wconversion, "Change of value in conversion "
2128627f7eb2Smrg "from %qs to %qs at %L", gfc_typename (&src->ts),
2129627f7eb2Smrg gfc_typename (&result->ts), &src->where);
2130627f7eb2Smrg did_warn = true;
2131627f7eb2Smrg }
2132627f7eb2Smrg }
2133627f7eb2Smrg if (!did_warn && warn_conversion_extra)
2134627f7eb2Smrg {
2135627f7eb2Smrg gfc_warning_now (OPT_Wconversion_extra, "Conversion from %qs to %qs "
2136627f7eb2Smrg "at %L", gfc_typename (&src->ts),
2137627f7eb2Smrg gfc_typename (&result->ts), &src->where);
2138627f7eb2Smrg }
2139627f7eb2Smrg
2140627f7eb2Smrg return result;
2141627f7eb2Smrg }
2142627f7eb2Smrg
2143627f7eb2Smrg
2144627f7eb2Smrg /* Convert real to real. */
2145627f7eb2Smrg
2146627f7eb2Smrg gfc_expr *
gfc_real2real(gfc_expr * src,int kind)2147627f7eb2Smrg gfc_real2real (gfc_expr *src, int kind)
2148627f7eb2Smrg {
2149627f7eb2Smrg gfc_expr *result;
2150627f7eb2Smrg arith rc;
2151627f7eb2Smrg bool did_warn = false;
2152627f7eb2Smrg
2153627f7eb2Smrg result = gfc_get_constant_expr (BT_REAL, kind, &src->where);
2154627f7eb2Smrg
2155627f7eb2Smrg mpfr_set (result->value.real, src->value.real, GFC_RND_MODE);
2156627f7eb2Smrg
2157627f7eb2Smrg rc = gfc_check_real_range (result->value.real, kind);
2158627f7eb2Smrg
2159627f7eb2Smrg if (rc == ARITH_UNDERFLOW)
2160627f7eb2Smrg {
2161627f7eb2Smrg if (warn_underflow)
2162627f7eb2Smrg gfc_warning (OPT_Woverflow, gfc_arith_error (rc), &src->where);
2163627f7eb2Smrg mpfr_set_ui (result->value.real, 0, GFC_RND_MODE);
2164627f7eb2Smrg }
2165627f7eb2Smrg else if (rc != ARITH_OK)
2166627f7eb2Smrg {
2167627f7eb2Smrg arith_error (rc, &src->ts, &result->ts, &src->where);
2168627f7eb2Smrg gfc_free_expr (result);
2169627f7eb2Smrg return NULL;
2170627f7eb2Smrg }
2171627f7eb2Smrg
2172627f7eb2Smrg /* As a special bonus, don't warn about REAL values which are not changed by
2173627f7eb2Smrg the conversion if -Wconversion is specified and -Wconversion-extra is
2174627f7eb2Smrg not. */
2175627f7eb2Smrg
2176627f7eb2Smrg if ((warn_conversion || warn_conversion_extra) && src->ts.kind > kind)
2177627f7eb2Smrg {
2178627f7eb2Smrg int w = warn_conversion ? OPT_Wconversion : OPT_Wconversion_extra;
2179627f7eb2Smrg
2180627f7eb2Smrg /* Calculate the difference between the constant and the rounded
2181627f7eb2Smrg value and check it against zero. */
2182627f7eb2Smrg
2183627f7eb2Smrg if (wprecision_real_real (src->value.real, src->ts.kind, kind))
2184627f7eb2Smrg {
2185627f7eb2Smrg gfc_warning_now (w, "Change of value in conversion from "
2186627f7eb2Smrg "%qs to %qs at %L",
2187627f7eb2Smrg gfc_typename (&src->ts), gfc_typename (&result->ts),
2188627f7eb2Smrg &src->where);
2189627f7eb2Smrg /* Make sure the conversion warning is not emitted again. */
2190627f7eb2Smrg did_warn = true;
2191627f7eb2Smrg }
2192627f7eb2Smrg }
2193627f7eb2Smrg
2194627f7eb2Smrg if (!did_warn && warn_conversion_extra)
2195627f7eb2Smrg gfc_warning_now (OPT_Wconversion_extra, "Conversion from %qs to %qs "
2196627f7eb2Smrg "at %L", gfc_typename(&src->ts),
2197627f7eb2Smrg gfc_typename(&result->ts), &src->where);
2198627f7eb2Smrg
2199627f7eb2Smrg return result;
2200627f7eb2Smrg }
2201627f7eb2Smrg
2202627f7eb2Smrg
2203627f7eb2Smrg /* Convert real to complex. */
2204627f7eb2Smrg
2205627f7eb2Smrg gfc_expr *
gfc_real2complex(gfc_expr * src,int kind)2206627f7eb2Smrg gfc_real2complex (gfc_expr *src, int kind)
2207627f7eb2Smrg {
2208627f7eb2Smrg gfc_expr *result;
2209627f7eb2Smrg arith rc;
2210627f7eb2Smrg bool did_warn = false;
2211627f7eb2Smrg
2212627f7eb2Smrg result = gfc_get_constant_expr (BT_COMPLEX, kind, &src->where);
2213627f7eb2Smrg
2214627f7eb2Smrg mpc_set_fr (result->value.complex, src->value.real, GFC_MPC_RND_MODE);
2215627f7eb2Smrg
2216627f7eb2Smrg rc = gfc_check_real_range (mpc_realref (result->value.complex), kind);
2217627f7eb2Smrg
2218627f7eb2Smrg if (rc == ARITH_UNDERFLOW)
2219627f7eb2Smrg {
2220627f7eb2Smrg if (warn_underflow)
2221627f7eb2Smrg gfc_warning (OPT_Woverflow, gfc_arith_error (rc), &src->where);
2222627f7eb2Smrg mpfr_set_ui (mpc_realref (result->value.complex), 0, GFC_RND_MODE);
2223627f7eb2Smrg }
2224627f7eb2Smrg else if (rc != ARITH_OK)
2225627f7eb2Smrg {
2226627f7eb2Smrg arith_error (rc, &src->ts, &result->ts, &src->where);
2227627f7eb2Smrg gfc_free_expr (result);
2228627f7eb2Smrg return NULL;
2229627f7eb2Smrg }
2230627f7eb2Smrg
2231627f7eb2Smrg if ((warn_conversion || warn_conversion_extra) && src->ts.kind > kind)
2232627f7eb2Smrg {
2233627f7eb2Smrg int w = warn_conversion ? OPT_Wconversion : OPT_Wconversion_extra;
2234627f7eb2Smrg
2235627f7eb2Smrg if (wprecision_real_real (src->value.real, src->ts.kind, kind))
2236627f7eb2Smrg {
2237627f7eb2Smrg gfc_warning_now (w, "Change of value in conversion from "
2238627f7eb2Smrg "%qs to %qs at %L",
2239627f7eb2Smrg gfc_typename (&src->ts), gfc_typename (&result->ts),
2240627f7eb2Smrg &src->where);
2241627f7eb2Smrg /* Make sure the conversion warning is not emitted again. */
2242627f7eb2Smrg did_warn = true;
2243627f7eb2Smrg }
2244627f7eb2Smrg }
2245627f7eb2Smrg
2246627f7eb2Smrg if (!did_warn && warn_conversion_extra)
2247627f7eb2Smrg gfc_warning_now (OPT_Wconversion_extra, "Conversion from %qs to %qs "
2248627f7eb2Smrg "at %L", gfc_typename(&src->ts),
2249627f7eb2Smrg gfc_typename(&result->ts), &src->where);
2250627f7eb2Smrg
2251627f7eb2Smrg return result;
2252627f7eb2Smrg }
2253627f7eb2Smrg
2254627f7eb2Smrg
2255627f7eb2Smrg /* Convert complex to integer. */
2256627f7eb2Smrg
2257627f7eb2Smrg gfc_expr *
gfc_complex2int(gfc_expr * src,int kind)2258627f7eb2Smrg gfc_complex2int (gfc_expr *src, int kind)
2259627f7eb2Smrg {
2260627f7eb2Smrg gfc_expr *result;
2261627f7eb2Smrg arith rc;
2262627f7eb2Smrg bool did_warn = false;
2263627f7eb2Smrg
2264627f7eb2Smrg result = gfc_get_constant_expr (BT_INTEGER, kind, &src->where);
2265627f7eb2Smrg
2266627f7eb2Smrg gfc_mpfr_to_mpz (result->value.integer, mpc_realref (src->value.complex),
2267627f7eb2Smrg &src->where);
2268627f7eb2Smrg
2269627f7eb2Smrg if ((rc = gfc_check_integer_range (result->value.integer, kind)) != ARITH_OK)
2270627f7eb2Smrg {
2271627f7eb2Smrg arith_error (rc, &src->ts, &result->ts, &src->where);
2272627f7eb2Smrg gfc_free_expr (result);
2273627f7eb2Smrg return NULL;
2274627f7eb2Smrg }
2275627f7eb2Smrg
2276627f7eb2Smrg if (warn_conversion || warn_conversion_extra)
2277627f7eb2Smrg {
2278627f7eb2Smrg int w = warn_conversion ? OPT_Wconversion : OPT_Wconversion_extra;
2279627f7eb2Smrg
2280627f7eb2Smrg /* See if we discarded an imaginary part. */
2281627f7eb2Smrg if (mpfr_cmp_si (mpc_imagref (src->value.complex), 0) != 0)
2282627f7eb2Smrg {
2283627f7eb2Smrg gfc_warning_now (w, "Non-zero imaginary part discarded "
2284627f7eb2Smrg "in conversion from %qs to %qs at %L",
2285627f7eb2Smrg gfc_typename(&src->ts), gfc_typename (&result->ts),
2286627f7eb2Smrg &src->where);
2287627f7eb2Smrg did_warn = true;
2288627f7eb2Smrg }
2289627f7eb2Smrg
2290627f7eb2Smrg else {
2291627f7eb2Smrg mpfr_t f;
2292627f7eb2Smrg
2293627f7eb2Smrg mpfr_init (f);
2294627f7eb2Smrg mpfr_frac (f, src->value.real, GFC_RND_MODE);
2295627f7eb2Smrg if (mpfr_cmp_si (f, 0) != 0)
2296627f7eb2Smrg {
2297627f7eb2Smrg gfc_warning_now (w, "Change of value in conversion from "
2298627f7eb2Smrg "%qs to %qs at %L", gfc_typename (&src->ts),
2299627f7eb2Smrg gfc_typename (&result->ts), &src->where);
2300627f7eb2Smrg did_warn = true;
2301627f7eb2Smrg }
2302627f7eb2Smrg mpfr_clear (f);
2303627f7eb2Smrg }
2304627f7eb2Smrg
2305627f7eb2Smrg if (!did_warn && warn_conversion_extra)
2306627f7eb2Smrg {
2307627f7eb2Smrg gfc_warning_now (OPT_Wconversion_extra, "Conversion from %qs to %qs "
2308627f7eb2Smrg "at %L", gfc_typename (&src->ts),
2309627f7eb2Smrg gfc_typename (&result->ts), &src->where);
2310627f7eb2Smrg }
2311627f7eb2Smrg }
2312627f7eb2Smrg
2313627f7eb2Smrg return result;
2314627f7eb2Smrg }
2315627f7eb2Smrg
2316627f7eb2Smrg
2317627f7eb2Smrg /* Convert complex to real. */
2318627f7eb2Smrg
2319627f7eb2Smrg gfc_expr *
gfc_complex2real(gfc_expr * src,int kind)2320627f7eb2Smrg gfc_complex2real (gfc_expr *src, int kind)
2321627f7eb2Smrg {
2322627f7eb2Smrg gfc_expr *result;
2323627f7eb2Smrg arith rc;
2324627f7eb2Smrg bool did_warn = false;
2325627f7eb2Smrg
2326627f7eb2Smrg result = gfc_get_constant_expr (BT_REAL, kind, &src->where);
2327627f7eb2Smrg
2328627f7eb2Smrg mpc_real (result->value.real, src->value.complex, GFC_RND_MODE);
2329627f7eb2Smrg
2330627f7eb2Smrg rc = gfc_check_real_range (result->value.real, kind);
2331627f7eb2Smrg
2332627f7eb2Smrg if (rc == ARITH_UNDERFLOW)
2333627f7eb2Smrg {
2334627f7eb2Smrg if (warn_underflow)
2335627f7eb2Smrg gfc_warning (OPT_Woverflow, gfc_arith_error (rc), &src->where);
2336627f7eb2Smrg mpfr_set_ui (result->value.real, 0, GFC_RND_MODE);
2337627f7eb2Smrg }
2338627f7eb2Smrg if (rc != ARITH_OK)
2339627f7eb2Smrg {
2340627f7eb2Smrg arith_error (rc, &src->ts, &result->ts, &src->where);
2341627f7eb2Smrg gfc_free_expr (result);
2342627f7eb2Smrg return NULL;
2343627f7eb2Smrg }
2344627f7eb2Smrg
2345627f7eb2Smrg if (warn_conversion || warn_conversion_extra)
2346627f7eb2Smrg {
2347627f7eb2Smrg int w = warn_conversion ? OPT_Wconversion : OPT_Wconversion_extra;
2348627f7eb2Smrg
2349627f7eb2Smrg /* See if we discarded an imaginary part. */
2350627f7eb2Smrg if (mpfr_cmp_si (mpc_imagref (src->value.complex), 0) != 0)
2351627f7eb2Smrg {
2352627f7eb2Smrg gfc_warning (w, "Non-zero imaginary part discarded "
2353627f7eb2Smrg "in conversion from %qs to %qs at %L",
2354627f7eb2Smrg gfc_typename(&src->ts), gfc_typename (&result->ts),
2355627f7eb2Smrg &src->where);
2356627f7eb2Smrg did_warn = true;
2357627f7eb2Smrg }
2358627f7eb2Smrg
2359627f7eb2Smrg /* Calculate the difference between the real constant and the rounded
2360627f7eb2Smrg value and check it against zero. */
2361627f7eb2Smrg
2362627f7eb2Smrg if (kind > src->ts.kind
2363627f7eb2Smrg && wprecision_real_real (mpc_realref (src->value.complex),
2364627f7eb2Smrg src->ts.kind, kind))
2365627f7eb2Smrg {
2366627f7eb2Smrg gfc_warning_now (w, "Change of value in conversion from "
2367627f7eb2Smrg "%qs to %qs at %L",
2368627f7eb2Smrg gfc_typename (&src->ts), gfc_typename (&result->ts),
2369627f7eb2Smrg &src->where);
2370627f7eb2Smrg /* Make sure the conversion warning is not emitted again. */
2371627f7eb2Smrg did_warn = true;
2372627f7eb2Smrg }
2373627f7eb2Smrg }
2374627f7eb2Smrg
2375627f7eb2Smrg if (!did_warn && warn_conversion_extra)
2376627f7eb2Smrg gfc_warning_now (OPT_Wconversion, "Conversion from %qs to %qs at %L",
2377627f7eb2Smrg gfc_typename(&src->ts), gfc_typename (&result->ts),
2378627f7eb2Smrg &src->where);
2379627f7eb2Smrg
2380627f7eb2Smrg return result;
2381627f7eb2Smrg }
2382627f7eb2Smrg
2383627f7eb2Smrg
2384627f7eb2Smrg /* Convert complex to complex. */
2385627f7eb2Smrg
2386627f7eb2Smrg gfc_expr *
gfc_complex2complex(gfc_expr * src,int kind)2387627f7eb2Smrg gfc_complex2complex (gfc_expr *src, int kind)
2388627f7eb2Smrg {
2389627f7eb2Smrg gfc_expr *result;
2390627f7eb2Smrg arith rc;
2391627f7eb2Smrg bool did_warn = false;
2392627f7eb2Smrg
2393627f7eb2Smrg result = gfc_get_constant_expr (BT_COMPLEX, kind, &src->where);
2394627f7eb2Smrg
2395627f7eb2Smrg mpc_set (result->value.complex, src->value.complex, GFC_MPC_RND_MODE);
2396627f7eb2Smrg
2397627f7eb2Smrg rc = gfc_check_real_range (mpc_realref (result->value.complex), kind);
2398627f7eb2Smrg
2399627f7eb2Smrg if (rc == ARITH_UNDERFLOW)
2400627f7eb2Smrg {
2401627f7eb2Smrg if (warn_underflow)
2402627f7eb2Smrg gfc_warning (OPT_Woverflow, gfc_arith_error (rc), &src->where);
2403627f7eb2Smrg mpfr_set_ui (mpc_realref (result->value.complex), 0, GFC_RND_MODE);
2404627f7eb2Smrg }
2405627f7eb2Smrg else if (rc != ARITH_OK)
2406627f7eb2Smrg {
2407627f7eb2Smrg arith_error (rc, &src->ts, &result->ts, &src->where);
2408627f7eb2Smrg gfc_free_expr (result);
2409627f7eb2Smrg return NULL;
2410627f7eb2Smrg }
2411627f7eb2Smrg
2412627f7eb2Smrg rc = gfc_check_real_range (mpc_imagref (result->value.complex), kind);
2413627f7eb2Smrg
2414627f7eb2Smrg if (rc == ARITH_UNDERFLOW)
2415627f7eb2Smrg {
2416627f7eb2Smrg if (warn_underflow)
2417627f7eb2Smrg gfc_warning (OPT_Woverflow, gfc_arith_error (rc), &src->where);
2418627f7eb2Smrg mpfr_set_ui (mpc_imagref (result->value.complex), 0, GFC_RND_MODE);
2419627f7eb2Smrg }
2420627f7eb2Smrg else if (rc != ARITH_OK)
2421627f7eb2Smrg {
2422627f7eb2Smrg arith_error (rc, &src->ts, &result->ts, &src->where);
2423627f7eb2Smrg gfc_free_expr (result);
2424627f7eb2Smrg return NULL;
2425627f7eb2Smrg }
2426627f7eb2Smrg
2427627f7eb2Smrg if ((warn_conversion || warn_conversion_extra) && src->ts.kind > kind
2428627f7eb2Smrg && (wprecision_real_real (mpc_realref (src->value.complex),
2429627f7eb2Smrg src->ts.kind, kind)
2430627f7eb2Smrg || wprecision_real_real (mpc_imagref (src->value.complex),
2431627f7eb2Smrg src->ts.kind, kind)))
2432627f7eb2Smrg {
2433627f7eb2Smrg int w = warn_conversion ? OPT_Wconversion : OPT_Wconversion_extra;
2434627f7eb2Smrg
2435627f7eb2Smrg gfc_warning_now (w, "Change of value in conversion from "
2436627f7eb2Smrg "%qs to %qs at %L",
2437627f7eb2Smrg gfc_typename (&src->ts), gfc_typename (&result->ts),
2438627f7eb2Smrg &src->where);
2439627f7eb2Smrg did_warn = true;
2440627f7eb2Smrg }
2441627f7eb2Smrg
2442627f7eb2Smrg if (!did_warn && warn_conversion_extra && src->ts.kind != kind)
2443627f7eb2Smrg gfc_warning_now (OPT_Wconversion_extra, "Conversion from %qs to %qs "
2444627f7eb2Smrg "at %L", gfc_typename(&src->ts),
2445627f7eb2Smrg gfc_typename (&result->ts), &src->where);
2446627f7eb2Smrg
2447627f7eb2Smrg return result;
2448627f7eb2Smrg }
2449627f7eb2Smrg
2450627f7eb2Smrg
2451627f7eb2Smrg /* Logical kind conversion. */
2452627f7eb2Smrg
2453627f7eb2Smrg gfc_expr *
gfc_log2log(gfc_expr * src,int kind)2454627f7eb2Smrg gfc_log2log (gfc_expr *src, int kind)
2455627f7eb2Smrg {
2456627f7eb2Smrg gfc_expr *result;
2457627f7eb2Smrg
2458627f7eb2Smrg result = gfc_get_constant_expr (BT_LOGICAL, kind, &src->where);
2459627f7eb2Smrg result->value.logical = src->value.logical;
2460627f7eb2Smrg
2461627f7eb2Smrg return result;
2462627f7eb2Smrg }
2463627f7eb2Smrg
2464627f7eb2Smrg
2465627f7eb2Smrg /* Convert logical to integer. */
2466627f7eb2Smrg
2467627f7eb2Smrg gfc_expr *
gfc_log2int(gfc_expr * src,int kind)2468627f7eb2Smrg gfc_log2int (gfc_expr *src, int kind)
2469627f7eb2Smrg {
2470627f7eb2Smrg gfc_expr *result;
2471627f7eb2Smrg
2472627f7eb2Smrg result = gfc_get_constant_expr (BT_INTEGER, kind, &src->where);
2473627f7eb2Smrg mpz_set_si (result->value.integer, src->value.logical);
2474627f7eb2Smrg
2475627f7eb2Smrg return result;
2476627f7eb2Smrg }
2477627f7eb2Smrg
2478627f7eb2Smrg
2479627f7eb2Smrg /* Convert integer to logical. */
2480627f7eb2Smrg
2481627f7eb2Smrg gfc_expr *
gfc_int2log(gfc_expr * src,int kind)2482627f7eb2Smrg gfc_int2log (gfc_expr *src, int kind)
2483627f7eb2Smrg {
2484627f7eb2Smrg gfc_expr *result;
2485627f7eb2Smrg
2486627f7eb2Smrg result = gfc_get_constant_expr (BT_LOGICAL, kind, &src->where);
2487627f7eb2Smrg result->value.logical = (mpz_cmp_si (src->value.integer, 0) != 0);
2488627f7eb2Smrg
2489627f7eb2Smrg return result;
2490627f7eb2Smrg }
2491627f7eb2Smrg
2492627f7eb2Smrg /* Convert character to character. We only use wide strings internally,
2493627f7eb2Smrg so we only set the kind. */
2494627f7eb2Smrg
2495627f7eb2Smrg gfc_expr *
gfc_character2character(gfc_expr * src,int kind)2496627f7eb2Smrg gfc_character2character (gfc_expr *src, int kind)
2497627f7eb2Smrg {
2498627f7eb2Smrg gfc_expr *result;
2499627f7eb2Smrg result = gfc_copy_expr (src);
2500627f7eb2Smrg result->ts.kind = kind;
2501627f7eb2Smrg
2502627f7eb2Smrg return result;
2503627f7eb2Smrg }
2504627f7eb2Smrg
2505627f7eb2Smrg /* Helper function to set the representation in a Hollerith conversion.
2506627f7eb2Smrg This assumes that the ts.type and ts.kind of the result have already
2507627f7eb2Smrg been set. */
2508627f7eb2Smrg
2509627f7eb2Smrg static void
hollerith2representation(gfc_expr * result,gfc_expr * src)2510627f7eb2Smrg hollerith2representation (gfc_expr *result, gfc_expr *src)
2511627f7eb2Smrg {
2512627f7eb2Smrg size_t src_len, result_len;
2513627f7eb2Smrg
2514627f7eb2Smrg src_len = src->representation.length - src->ts.u.pad;
2515627f7eb2Smrg gfc_target_expr_size (result, &result_len);
2516627f7eb2Smrg
2517627f7eb2Smrg if (src_len > result_len)
2518627f7eb2Smrg {
2519*4c3eb207Smrg gfc_warning (OPT_Wcharacter_truncation, "The Hollerith constant at %L "
2520*4c3eb207Smrg "is truncated in conversion to %qs", &src->where,
2521*4c3eb207Smrg gfc_typename(&result->ts));
2522627f7eb2Smrg }
2523627f7eb2Smrg
2524627f7eb2Smrg result->representation.string = XCNEWVEC (char, result_len + 1);
2525627f7eb2Smrg memcpy (result->representation.string, src->representation.string,
2526627f7eb2Smrg MIN (result_len, src_len));
2527627f7eb2Smrg
2528627f7eb2Smrg if (src_len < result_len)
2529627f7eb2Smrg memset (&result->representation.string[src_len], ' ', result_len - src_len);
2530627f7eb2Smrg
2531627f7eb2Smrg result->representation.string[result_len] = '\0'; /* For debugger */
2532627f7eb2Smrg result->representation.length = result_len;
2533627f7eb2Smrg }
2534627f7eb2Smrg
2535627f7eb2Smrg
2536*4c3eb207Smrg /* Helper function to set the representation in a character conversion.
2537*4c3eb207Smrg This assumes that the ts.type and ts.kind of the result have already
2538*4c3eb207Smrg been set. */
2539*4c3eb207Smrg
2540*4c3eb207Smrg static void
character2representation(gfc_expr * result,gfc_expr * src)2541*4c3eb207Smrg character2representation (gfc_expr *result, gfc_expr *src)
2542*4c3eb207Smrg {
2543*4c3eb207Smrg size_t src_len, result_len, i;
2544*4c3eb207Smrg src_len = src->value.character.length;
2545*4c3eb207Smrg gfc_target_expr_size (result, &result_len);
2546*4c3eb207Smrg
2547*4c3eb207Smrg if (src_len > result_len)
2548*4c3eb207Smrg gfc_warning (OPT_Wcharacter_truncation, "The character constant at %L is "
2549*4c3eb207Smrg "truncated in conversion to %s", &src->where,
2550*4c3eb207Smrg gfc_typename(&result->ts));
2551*4c3eb207Smrg
2552*4c3eb207Smrg result->representation.string = XCNEWVEC (char, result_len + 1);
2553*4c3eb207Smrg
2554*4c3eb207Smrg for (i = 0; i < MIN (result_len, src_len); i++)
2555*4c3eb207Smrg result->representation.string[i] = (char) src->value.character.string[i];
2556*4c3eb207Smrg
2557*4c3eb207Smrg if (src_len < result_len)
2558*4c3eb207Smrg memset (&result->representation.string[src_len], ' ',
2559*4c3eb207Smrg result_len - src_len);
2560*4c3eb207Smrg
2561*4c3eb207Smrg result->representation.string[result_len] = '\0'; /* For debugger. */
2562*4c3eb207Smrg result->representation.length = result_len;
2563*4c3eb207Smrg }
2564*4c3eb207Smrg
2565627f7eb2Smrg /* Convert Hollerith to integer. The constant will be padded or truncated. */
2566627f7eb2Smrg
2567627f7eb2Smrg gfc_expr *
gfc_hollerith2int(gfc_expr * src,int kind)2568627f7eb2Smrg gfc_hollerith2int (gfc_expr *src, int kind)
2569627f7eb2Smrg {
2570627f7eb2Smrg gfc_expr *result;
2571627f7eb2Smrg result = gfc_get_constant_expr (BT_INTEGER, kind, &src->where);
2572627f7eb2Smrg
2573627f7eb2Smrg hollerith2representation (result, src);
2574627f7eb2Smrg gfc_interpret_integer (kind, (unsigned char *) result->representation.string,
2575627f7eb2Smrg result->representation.length, result->value.integer);
2576627f7eb2Smrg
2577627f7eb2Smrg return result;
2578627f7eb2Smrg }
2579627f7eb2Smrg
2580*4c3eb207Smrg /* Convert character to integer. The constant will be padded or truncated. */
2581*4c3eb207Smrg
2582*4c3eb207Smrg gfc_expr *
gfc_character2int(gfc_expr * src,int kind)2583*4c3eb207Smrg gfc_character2int (gfc_expr *src, int kind)
2584*4c3eb207Smrg {
2585*4c3eb207Smrg gfc_expr *result;
2586*4c3eb207Smrg result = gfc_get_constant_expr (BT_INTEGER, kind, &src->where);
2587*4c3eb207Smrg
2588*4c3eb207Smrg character2representation (result, src);
2589*4c3eb207Smrg gfc_interpret_integer (kind, (unsigned char *) result->representation.string,
2590*4c3eb207Smrg result->representation.length, result->value.integer);
2591*4c3eb207Smrg return result;
2592*4c3eb207Smrg }
2593627f7eb2Smrg
2594627f7eb2Smrg /* Convert Hollerith to real. The constant will be padded or truncated. */
2595627f7eb2Smrg
2596627f7eb2Smrg gfc_expr *
gfc_hollerith2real(gfc_expr * src,int kind)2597627f7eb2Smrg gfc_hollerith2real (gfc_expr *src, int kind)
2598627f7eb2Smrg {
2599627f7eb2Smrg gfc_expr *result;
2600627f7eb2Smrg result = gfc_get_constant_expr (BT_REAL, kind, &src->where);
2601627f7eb2Smrg
2602627f7eb2Smrg hollerith2representation (result, src);
2603627f7eb2Smrg gfc_interpret_float (kind, (unsigned char *) result->representation.string,
2604627f7eb2Smrg result->representation.length, result->value.real);
2605627f7eb2Smrg
2606627f7eb2Smrg return result;
2607627f7eb2Smrg }
2608627f7eb2Smrg
2609*4c3eb207Smrg /* Convert character to real. The constant will be padded or truncated. */
2610*4c3eb207Smrg
2611*4c3eb207Smrg gfc_expr *
gfc_character2real(gfc_expr * src,int kind)2612*4c3eb207Smrg gfc_character2real (gfc_expr *src, int kind)
2613*4c3eb207Smrg {
2614*4c3eb207Smrg gfc_expr *result;
2615*4c3eb207Smrg result = gfc_get_constant_expr (BT_REAL, kind, &src->where);
2616*4c3eb207Smrg
2617*4c3eb207Smrg character2representation (result, src);
2618*4c3eb207Smrg gfc_interpret_float (kind, (unsigned char *) result->representation.string,
2619*4c3eb207Smrg result->representation.length, result->value.real);
2620*4c3eb207Smrg
2621*4c3eb207Smrg return result;
2622*4c3eb207Smrg }
2623*4c3eb207Smrg
2624627f7eb2Smrg
2625627f7eb2Smrg /* Convert Hollerith to complex. The constant will be padded or truncated. */
2626627f7eb2Smrg
2627627f7eb2Smrg gfc_expr *
gfc_hollerith2complex(gfc_expr * src,int kind)2628627f7eb2Smrg gfc_hollerith2complex (gfc_expr *src, int kind)
2629627f7eb2Smrg {
2630627f7eb2Smrg gfc_expr *result;
2631627f7eb2Smrg result = gfc_get_constant_expr (BT_COMPLEX, kind, &src->where);
2632627f7eb2Smrg
2633627f7eb2Smrg hollerith2representation (result, src);
2634627f7eb2Smrg gfc_interpret_complex (kind, (unsigned char *) result->representation.string,
2635627f7eb2Smrg result->representation.length, result->value.complex);
2636627f7eb2Smrg
2637627f7eb2Smrg return result;
2638627f7eb2Smrg }
2639627f7eb2Smrg
2640*4c3eb207Smrg /* Convert character to complex. The constant will be padded or truncated. */
2641*4c3eb207Smrg
2642*4c3eb207Smrg gfc_expr *
gfc_character2complex(gfc_expr * src,int kind)2643*4c3eb207Smrg gfc_character2complex (gfc_expr *src, int kind)
2644*4c3eb207Smrg {
2645*4c3eb207Smrg gfc_expr *result;
2646*4c3eb207Smrg result = gfc_get_constant_expr (BT_COMPLEX, kind, &src->where);
2647*4c3eb207Smrg
2648*4c3eb207Smrg character2representation (result, src);
2649*4c3eb207Smrg gfc_interpret_complex (kind, (unsigned char *) result->representation.string,
2650*4c3eb207Smrg result->representation.length, result->value.complex);
2651*4c3eb207Smrg
2652*4c3eb207Smrg return result;
2653*4c3eb207Smrg }
2654*4c3eb207Smrg
2655627f7eb2Smrg
2656627f7eb2Smrg /* Convert Hollerith to character. */
2657627f7eb2Smrg
2658627f7eb2Smrg gfc_expr *
gfc_hollerith2character(gfc_expr * src,int kind)2659627f7eb2Smrg gfc_hollerith2character (gfc_expr *src, int kind)
2660627f7eb2Smrg {
2661627f7eb2Smrg gfc_expr *result;
2662627f7eb2Smrg
2663627f7eb2Smrg result = gfc_copy_expr (src);
2664627f7eb2Smrg result->ts.type = BT_CHARACTER;
2665627f7eb2Smrg result->ts.kind = kind;
2666627f7eb2Smrg result->ts.u.pad = 0;
2667627f7eb2Smrg
2668627f7eb2Smrg result->value.character.length = result->representation.length;
2669627f7eb2Smrg result->value.character.string
2670627f7eb2Smrg = gfc_char_to_widechar (result->representation.string);
2671627f7eb2Smrg
2672627f7eb2Smrg return result;
2673627f7eb2Smrg }
2674627f7eb2Smrg
2675627f7eb2Smrg
2676627f7eb2Smrg /* Convert Hollerith to logical. The constant will be padded or truncated. */
2677627f7eb2Smrg
2678627f7eb2Smrg gfc_expr *
gfc_hollerith2logical(gfc_expr * src,int kind)2679627f7eb2Smrg gfc_hollerith2logical (gfc_expr *src, int kind)
2680627f7eb2Smrg {
2681627f7eb2Smrg gfc_expr *result;
2682627f7eb2Smrg result = gfc_get_constant_expr (BT_LOGICAL, kind, &src->where);
2683627f7eb2Smrg
2684627f7eb2Smrg hollerith2representation (result, src);
2685627f7eb2Smrg gfc_interpret_logical (kind, (unsigned char *) result->representation.string,
2686627f7eb2Smrg result->representation.length, &result->value.logical);
2687627f7eb2Smrg
2688627f7eb2Smrg return result;
2689627f7eb2Smrg }
2690*4c3eb207Smrg
2691*4c3eb207Smrg /* Convert character to logical. The constant will be padded or truncated. */
2692*4c3eb207Smrg
2693*4c3eb207Smrg gfc_expr *
gfc_character2logical(gfc_expr * src,int kind)2694*4c3eb207Smrg gfc_character2logical (gfc_expr *src, int kind)
2695*4c3eb207Smrg {
2696*4c3eb207Smrg gfc_expr *result;
2697*4c3eb207Smrg result = gfc_get_constant_expr (BT_LOGICAL, kind, &src->where);
2698*4c3eb207Smrg
2699*4c3eb207Smrg character2representation (result, src);
2700*4c3eb207Smrg gfc_interpret_logical (kind, (unsigned char *) result->representation.string,
2701*4c3eb207Smrg result->representation.length, &result->value.logical);
2702*4c3eb207Smrg
2703*4c3eb207Smrg return result;
2704*4c3eb207Smrg }
2705