xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/fortran/arith.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
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