Bug Summary

File:build/gcc/fortran/trans-intrinsic.cc
Warning:line 1975, column 4
Value stored to 'lhs_type' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-suse-linux -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name trans-intrinsic.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/buildworker/marxinbox-gcc-clang-static-analyzer/objdir/gcc -resource-dir /usr/lib64/clang/15.0.7 -D IN_GCC_FRONTEND -D IN_GCC -D HAVE_CONFIG_H -I . -I fortran -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../include -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libcpp/include -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libcody -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libdecnumber -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libdecnumber/bid -I ../libdecnumber -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libbacktrace -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/13/../../../../include/c++/13 -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/13/../../../../include/c++/13/x86_64-suse-linux -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/13/../../../../include/c++/13/backward -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/13/../../../../x86_64-suse-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-narrowing -Wwrite-strings -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -fdeprecated-macro -fdebug-compilation-dir=/buildworker/marxinbox-gcc-clang-static-analyzer/objdir/gcc -ferror-limit 19 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=plist-html -analyzer-config silence-checkers=core.NullDereference -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /buildworker/marxinbox-gcc-clang-static-analyzer/objdir/clang-static-analyzer/2023-03-27-141847-20772-1/report-TxymJs.plist -x c++ /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc
1/* Intrinsic translation
2 Copyright (C) 2002-2023 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
21
22/* trans-intrinsic.cc-- generate GENERIC trees for calls to intrinsics. */
23
24#include "config.h"
25#include "system.h"
26#include "coretypes.h"
27#include "memmodel.h"
28#include "tm.h" /* For UNITS_PER_WORD. */
29#include "tree.h"
30#include "gfortran.h"
31#include "trans.h"
32#include "stringpool.h"
33#include "fold-const.h"
34#include "internal-fn.h"
35#include "tree-nested.h"
36#include "stor-layout.h"
37#include "toplev.h" /* For rest_of_decl_compilation. */
38#include "arith.h"
39#include "trans-const.h"
40#include "trans-types.h"
41#include "trans-array.h"
42#include "dependency.h" /* For CAF array alias analysis. */
43#include "attribs.h"
44#include "realmpfr.h"
45
46/* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
47
48/* This maps Fortran intrinsic math functions to external library or GCC
49 builtin functions. */
50typedef struct GTY(()) gfc_intrinsic_map_t {
51 /* The explicit enum is required to work around inadequacies in the
52 garbage collection/gengtype parsing mechanism. */
53 enum gfc_isym_id id;
54
55 /* Enum value from the "language-independent", aka C-centric, part
56 of gcc, or END_BUILTINS of no such value set. */
57 enum built_in_function float_built_in;
58 enum built_in_function double_built_in;
59 enum built_in_function long_double_built_in;
60 enum built_in_function complex_float_built_in;
61 enum built_in_function complex_double_built_in;
62 enum built_in_function complex_long_double_built_in;
63
64 /* True if the naming pattern is to prepend "c" for complex and
65 append "f" for kind=4. False if the naming pattern is to
66 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
67 bool libm_name;
68
69 /* True if a complex version of the function exists. */
70 bool complex_available;
71
72 /* True if the function should be marked const. */
73 bool is_constant;
74
75 /* The base library name of this function. */
76 const char *name;
77
78 /* Cache decls created for the various operand types. */
79 tree real4_decl;
80 tree real8_decl;
81 tree real10_decl;
82 tree real16_decl;
83 tree complex4_decl;
84 tree complex8_decl;
85 tree complex10_decl;
86 tree complex16_decl;
87}
88gfc_intrinsic_map_t;
89
90/* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
91 defines complex variants of all of the entries in mathbuiltins.def
92 except for atan2. */
93#define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
94 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
95 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
96 true, false, true, NAME, NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null, \
97 NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null},
98
99#define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
100 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
101 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
102 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE(tree) __null, NULL_TREE(tree) __null, \
103 NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null},
104
105#define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
106 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
107 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
108 false, HAVE_COMPLEX, true, NAME, NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null, \
109 NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null }
110
111#define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
112 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
113 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
114 true, false, CONST, NAME, NULL_TREE(tree) __null, NULL_TREE(tree) __null, \
115 NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null, NULL_TREE(tree) __null},
116
117static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
118{
119 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
120 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
121 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
122#include "mathbuiltins.def"
123
124 /* Functions in libgfortran. */
125 LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
126 LIB_FUNCTION (SIND, "sind", false),
127 LIB_FUNCTION (COSD, "cosd", false),
128 LIB_FUNCTION (TAND, "tand", false),
129
130 /* End the list. */
131 LIB_FUNCTION (NONE, NULL__null, false)
132
133};
134#undef OTHER_BUILTIN
135#undef LIB_FUNCTION
136#undef DEFINE_MATH_BUILTIN
137#undef DEFINE_MATH_BUILTIN_C
138
139
140enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
141
142
143/* Find the correct variant of a given builtin from its argument. */
144static tree
145builtin_decl_for_precision (enum built_in_function base_built_in,
146 int precision)
147{
148 enum built_in_function i = END_BUILTINS;
149
150 gfc_intrinsic_map_t *m;
151 for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
152 ;
153
154 if (precision == TYPE_PRECISION (float_type_node)((tree_class_check ((global_trees[TI_FLOAT_TYPE]), (tcc_type)
, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 154, __FUNCTION__))->type_common.precision)
)
155 i = m->float_built_in;
156 else if (precision == TYPE_PRECISION (double_type_node)((tree_class_check ((global_trees[TI_DOUBLE_TYPE]), (tcc_type
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 156, __FUNCTION__))->type_common.precision)
)
157 i = m->double_built_in;
158 else if (precision == TYPE_PRECISION (long_double_type_node)((tree_class_check ((global_trees[TI_LONG_DOUBLE_TYPE]), (tcc_type
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 158, __FUNCTION__))->type_common.precision)
159 && (!gfc_real16_is_float128
160 || long_double_type_nodeglobal_trees[TI_LONG_DOUBLE_TYPE] != gfc_float128_type_node))
161 i = m->long_double_built_in;
162 else if (precision == TYPE_PRECISION (gfc_float128_type_node)((tree_class_check ((gfc_float128_type_node), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 162, __FUNCTION__))->type_common.precision)
)
163 {
164 /* Special treatment, because it is not exactly a built-in, but
165 a library function. */
166 return m->real16_decl;
167 }
168
169 return (i == END_BUILTINS ? NULL_TREE(tree) __null : builtin_decl_explicit (i));
170}
171
172
173tree
174gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
175 int kind)
176{
177 int i = gfc_validate_kind (BT_REAL, kind, false);
178
179 if (gfc_real_kinds[i].c_float128)
180 {
181 /* For _Float128, the story is a bit different, because we return
182 a decl to a library function rather than a built-in. */
183 gfc_intrinsic_map_t *m;
184 for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
185 ;
186
187 return m->real16_decl;
188 }
189
190 return builtin_decl_for_precision (double_built_in,
191 gfc_real_kinds[i].mode_precision);
192}
193
194
195/* Evaluate the arguments to an intrinsic function. The value
196 of NARGS may be less than the actual number of arguments in EXPR
197 to allow optional "KIND" arguments that are not included in the
198 generated code to be ignored. */
199
200static void
201gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
202 tree *argarray, int nargs)
203{
204 gfc_actual_arglist *actual;
205 gfc_expr *e;
206 gfc_intrinsic_arg *formal;
207 gfc_se argse;
208 int curr_arg;
209
210 formal = expr->value.function.isym->formal;
211 actual = expr->value.function.actual;
212
213 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
214 actual = actual->next,
215 formal = formal ? formal->next : NULL__null)
216 {
217 gcc_assert (actual)((void)(!(actual) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 217, __FUNCTION__), 0 : 0))
;
218 e = actual->expr;
219 /* Skip omitted optional arguments. */
220 if (!e)
221 {
222 --curr_arg;
223 continue;
224 }
225
226 /* Evaluate the parameter. This will substitute scalarized
227 references automatically. */
228 gfc_init_se (&argse, se);
229
230 if (e->ts.type == BT_CHARACTER)
231 {
232 gfc_conv_expr (&argse, e);
233 gfc_conv_string_parameter (&argse);
234 argarray[curr_arg++] = argse.string_length;
235 gcc_assert (curr_arg < nargs)((void)(!(curr_arg < nargs) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 235, __FUNCTION__), 0 : 0))
;
236 }
237 else
238 gfc_conv_expr_val (&argse, e);
239
240 /* If an optional argument is itself an optional dummy argument,
241 check its presence and substitute a null if absent. */
242 if (e->expr_type == EXPR_VARIABLE
243 && e->symtree->n.sym->attr.optional
244 && formal
245 && formal->optional)
246 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
247
248 gfc_add_block_to_block (&se->pre, &argse.pre);
249 gfc_add_block_to_block (&se->post, &argse.post);
250 argarray[curr_arg] = argse.expr;
251 }
252}
253
254/* Count the number of actual arguments to the intrinsic function EXPR
255 including any "hidden" string length arguments. */
256
257static unsigned int
258gfc_intrinsic_argument_list_length (gfc_expr *expr)
259{
260 int n = 0;
261 gfc_actual_arglist *actual;
262
263 for (actual = expr->value.function.actual; actual; actual = actual->next)
264 {
265 if (!actual->expr)
266 continue;
267
268 if (actual->expr->ts.type == BT_CHARACTER)
269 n += 2;
270 else
271 n++;
272 }
273
274 return n;
275}
276
277
278/* Conversions between different types are output by the frontend as
279 intrinsic functions. We implement these directly with inline code. */
280
281static void
282gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
283{
284 tree type;
285 tree *args;
286 int nargs;
287
288 nargs = gfc_intrinsic_argument_list_length (expr);
289 args = XALLOCAVEC (tree, nargs)((tree *) __builtin_alloca(sizeof (tree) * (nargs)));
290
291 /* Evaluate all the arguments passed. Whilst we're only interested in the
292 first one here, there are other parts of the front-end that assume this
293 and will trigger an ICE if it's not the case. */
294 type = gfc_typenode_for_spec (&expr->ts);
295 gcc_assert (expr->value.function.actual->expr)((void)(!(expr->value.function.actual->expr) ? fancy_abort
("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 295, __FUNCTION__), 0 : 0))
;
296 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
297
298 /* Conversion between character kinds involves a call to a library
299 function. */
300 if (expr->ts.type == BT_CHARACTER)
301 {
302 tree fndecl, var, addr, tmp;
303
304 if (expr->ts.kind == 1
305 && expr->value.function.actual->expr->ts.kind == 4)
306 fndecl = gfor_fndecl_convert_char4_to_char1;
307 else if (expr->ts.kind == 4
308 && expr->value.function.actual->expr->ts.kind == 1)
309 fndecl = gfor_fndecl_convert_char1_to_char4;
310 else
311 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 311, __FUNCTION__))
;
312
313 /* Create the variable storing the converted value. */
314 type = gfc_get_pchar_type (expr->ts.kind);
315 var = gfc_create_var (type, "str");
316 addr = gfc_build_addr_expr (build_pointer_type (type), var);
317
318 /* Call the library function that will perform the conversion. */
319 gcc_assert (nargs >= 2)((void)(!(nargs >= 2) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 319, __FUNCTION__), 0 : 0))
;
320 tmp = build_call_expr_loc (input_location,
321 fndecl, 3, addr, args[0], args[1]);
322 gfc_add_expr_to_block (&se->pre, tmp);
323
324 /* Free the temporary afterwards. */
325 tmp = gfc_call_free (var);
326 gfc_add_expr_to_block (&se->post, tmp);
327
328 se->expr = var;
329 se->string_length = args[0];
330
331 return;
332 }
333
334 /* Conversion from complex to non-complex involves taking the real
335 component of the value. */
336 if (TREE_CODE (TREE_TYPE (args[0]))((enum tree_code) (((contains_struct_check ((args[0]), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 336, __FUNCTION__))->typed.type))->base.code)
== COMPLEX_TYPE
337 && expr->ts.type != BT_COMPLEX)
338 {
339 tree artype;
340
341 artype = TREE_TYPE (TREE_TYPE (args[0]))((contains_struct_check ((((contains_struct_check ((args[0]),
(TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 341, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 341, __FUNCTION__))->typed.type)
;
342 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
343 args[0]);
344 }
345
346 se->expr = convert (type, args[0]);
347}
348
349/* This is needed because the gcc backend only implements
350 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
351 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
352 Similarly for CEILING. */
353
354static tree
355build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
356{
357 tree tmp;
358 tree cond;
359 tree argtype;
360 tree intval;
361
362 argtype = TREE_TYPE (arg)((contains_struct_check ((arg), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 362, __FUNCTION__))->typed.type)
;
363 arg = gfc_evaluate_now (arg, pblock);
364
365 intval = convert (type, arg);
366 intval = gfc_evaluate_now (intval, pblock);
367
368 tmp = convert (argtype, intval);
369 cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
370 logical_type_node, tmp, arg);
371
372 tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
373 intval, build_int_cst (type, 1));
374 tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
375 return tmp;
376}
377
378
379/* Round to nearest integer, away from zero. */
380
381static tree
382build_round_expr (tree arg, tree restype)
383{
384 tree argtype;
385 tree fn;
386 int argprec, resprec;
387
388 argtype = TREE_TYPE (arg)((contains_struct_check ((arg), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 388, __FUNCTION__))->typed.type)
;
389 argprec = TYPE_PRECISION (argtype)((tree_class_check ((argtype), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 389, __FUNCTION__))->type_common.precision)
;
390 resprec = TYPE_PRECISION (restype)((tree_class_check ((restype), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 390, __FUNCTION__))->type_common.precision)
;
391
392 /* Depending on the type of the result, choose the int intrinsic (iround,
393 available only as a builtin, therefore cannot use it for _Float128), long
394 int intrinsic (lround family) or long long intrinsic (llround). If we
395 don't have an appropriate function that converts directly to the integer
396 type (such as kind == 16), just use ROUND, and then convert the result to
397 an integer. We might also need to convert the result afterwards. */
398 if (resprec <= INT_TYPE_SIZE32 && argprec <= LONG_DOUBLE_TYPE_SIZE(((global_options.x_target_flags & (1U << 17)) != 0
) ? 64 : (((global_options.x_target_flags & (1U << 16
)) != 0) ? 128 : 80))
)
399 fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
400 else if (resprec <= LONG_TYPE_SIZE(((global_options.x_ix86_isa_flags & (1UL << 58)) !=
0) ? 32 : ((8) * (((global_options.x_ix86_isa_flags & (1UL
<< 1)) != 0) ? 8 : 4)))
)
401 fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
402 else if (resprec <= LONG_LONG_TYPE_SIZE64)
403 fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
404 else if (resprec >= argprec)
405 fn = builtin_decl_for_precision (BUILT_IN_ROUND, argprec);
406 else
407 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 407, __FUNCTION__))
;
408
409 return convert (restype, build_call_expr_loc (input_location,
410 fn, 1, arg));
411}
412
413
414/* Convert a real to an integer using a specific rounding mode.
415 Ideally we would just build the corresponding GENERIC node,
416 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
417
418static tree
419build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
420 enum rounding_mode op)
421{
422 switch (op)
423 {
424 case RND_FLOOR:
425 return build_fixbound_expr (pblock, arg, type, 0);
426
427 case RND_CEIL:
428 return build_fixbound_expr (pblock, arg, type, 1);
429
430 case RND_ROUND:
431 return build_round_expr (arg, type);
432
433 case RND_TRUNC:
434 return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
435
436 default:
437 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 437, __FUNCTION__))
;
438 }
439}
440
441
442/* Round a real value using the specified rounding mode.
443 We use a temporary integer of that same kind size as the result.
444 Values larger than those that can be represented by this kind are
445 unchanged, as they will not be accurate enough to represent the
446 rounding.
447 huge = HUGE (KIND (a))
448 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
449 */
450
451static void
452gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
453{
454 tree type;
455 tree itype;
456 tree arg[2];
457 tree tmp;
458 tree cond;
459 tree decl;
460 mpfr_t huge;
461 int n, nargs;
462 int kind;
463
464 kind = expr->ts.kind;
465 nargs = gfc_intrinsic_argument_list_length (expr);
466
467 decl = NULL_TREE(tree) __null;
468 /* We have builtin functions for some cases. */
469 switch (op)
470 {
471 case RND_ROUND:
472 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
473 break;
474
475 case RND_TRUNC:
476 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
477 break;
478
479 default:
480 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 480, __FUNCTION__))
;
481 }
482
483 /* Evaluate the argument. */
484 gcc_assert (expr->value.function.actual->expr)((void)(!(expr->value.function.actual->expr) ? fancy_abort
("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 484, __FUNCTION__), 0 : 0))
;
485 gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
486
487 /* Use a builtin function if one exists. */
488 if (decl != NULL_TREE(tree) __null)
489 {
490 se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
491 return;
492 }
493
494 /* This code is probably redundant, but we'll keep it lying around just
495 in case. */
496 type = gfc_typenode_for_spec (&expr->ts);
497 arg[0] = gfc_evaluate_now (arg[0], &se->pre);
498
499 /* Test if the value is too large to handle sensibly. */
500 gfc_set_model_kind (kind);
501 mpfr_init (huge);
502 n = gfc_validate_kind (BT_INTEGER, kind, false);
503 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODEMPFR_RNDN);
504 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
505 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, arg[0],
506 tmp);
507
508 mpfr_neg (huge, huge, GFC_RND_MODEMPFR_RNDN);
509 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
510 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, arg[0],
511 tmp);
512 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, logical_type_node,
513 cond, tmp);
514 itype = gfc_get_int_type (kind);
515
516 tmp = build_fix_expr (&se->pre, arg[0], itype, op);
517 tmp = convert (type, tmp);
518 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
519 arg[0]);
520 mpfr_clear (huge);
521}
522
523
524/* Convert to an integer using the specified rounding mode. */
525
526static void
527gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
528{
529 tree type;
530 tree *args;
531 int nargs;
532
533 nargs = gfc_intrinsic_argument_list_length (expr);
534 args = XALLOCAVEC (tree, nargs)((tree *) __builtin_alloca(sizeof (tree) * (nargs)));
535
536 /* Evaluate the argument, we process all arguments even though we only
537 use the first one for code generation purposes. */
538 type = gfc_typenode_for_spec (&expr->ts);
539 gcc_assert (expr->value.function.actual->expr)((void)(!(expr->value.function.actual->expr) ? fancy_abort
("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 539, __FUNCTION__), 0 : 0))
;
540 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
541
542 if (TREE_CODE (TREE_TYPE (args[0]))((enum tree_code) (((contains_struct_check ((args[0]), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 542, __FUNCTION__))->typed.type))->base.code)
== INTEGER_TYPE)
543 {
544 /* Conversion to a different integer kind. */
545 se->expr = convert (type, args[0]);
546 }
547 else
548 {
549 /* Conversion from complex to non-complex involves taking the real
550 component of the value. */
551 if (TREE_CODE (TREE_TYPE (args[0]))((enum tree_code) (((contains_struct_check ((args[0]), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 551, __FUNCTION__))->typed.type))->base.code)
== COMPLEX_TYPE
552 && expr->ts.type != BT_COMPLEX)
553 {
554 tree artype;
555
556 artype = TREE_TYPE (TREE_TYPE (args[0]))((contains_struct_check ((((contains_struct_check ((args[0]),
(TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 556, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 556, __FUNCTION__))->typed.type)
;
557 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
558 args[0]);
559 }
560
561 se->expr = build_fix_expr (&se->pre, args[0], type, op);
562 }
563}
564
565
566/* Get the imaginary component of a value. */
567
568static void
569gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
570{
571 tree arg;
572
573 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
574 se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
575 TREE_TYPE (TREE_TYPE (arg))((contains_struct_check ((((contains_struct_check ((arg), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 575, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 575, __FUNCTION__))->typed.type)
, arg);
576}
577
578
579/* Get the complex conjugate of a value. */
580
581static void
582gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
583{
584 tree arg;
585
586 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
587 se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg)((contains_struct_check ((arg), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 587, __FUNCTION__))->typed.type)
, arg);
588}
589
590
591
592static tree
593define_quad_builtin (const char *name, tree type, bool is_const)
594{
595 tree fndecl;
596 fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name)(__builtin_constant_p (name) ? get_identifier_with_length ((name
), strlen (name)) : get_identifier (name))
,
597 type);
598
599 /* Mark the decl as external. */
600 DECL_EXTERNAL (fndecl)((contains_struct_check ((fndecl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 600, __FUNCTION__))->decl_common.decl_flag_1)
= 1;
601 TREE_PUBLIC (fndecl)((fndecl)->base.public_flag) = 1;
602
603 /* Mark it __attribute__((const)). */
604 TREE_READONLY (fndecl)((non_type_check ((fndecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 604, __FUNCTION__))->base.readonly_flag)
= is_const;
605
606 rest_of_decl_compilation (fndecl, 1, 0);
607
608 return fndecl;
609}
610
611/* Add SIMD attribute for FNDECL built-in if the built-in
612 name is in VECTORIZED_BUILTINS. */
613
614static void
615add_simd_flag_for_built_in (tree fndecl)
616{
617 if (gfc_vectorized_builtins == NULL__null
618 || fndecl == NULL_TREE(tree) __null)
619 return;
620
621 const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl))((const char *) (tree_check ((((contains_struct_check ((fndecl
), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 621, __FUNCTION__))->decl_minimal.name)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 621, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str
)
;
622 int *clauses = gfc_vectorized_builtins->get (name);
623 if (clauses)
624 {
625 for (unsigned i = 0; i < 3; i++)
626 if (*clauses & (1 << i))
627 {
628 gfc_simd_clause simd_type = (gfc_simd_clause)*clauses;
629 tree omp_clause = NULL_TREE(tree) __null;
630 if (simd_type == SIMD_NONE)
631 ; /* No SIMD clause. */
632 else
633 {
634 omp_clause_code code
635 = (simd_type == SIMD_INBRANCH
636 ? OMP_CLAUSE_INBRANCH : OMP_CLAUSE_NOTINBRANCH);
637 omp_clause = build_omp_clause (UNKNOWN_LOCATION((location_t) 0), code);
638 omp_clause = build_tree_list (NULL_TREE(tree) __null, omp_clause);
639 }
640
641 DECL_ATTRIBUTES (fndecl)((contains_struct_check ((fndecl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 641, __FUNCTION__))->decl_common.attributes)
642 = tree_cons (get_identifier ("omp declare simd")(__builtin_constant_p ("omp declare simd") ? get_identifier_with_length
(("omp declare simd"), strlen ("omp declare simd")) : get_identifier
("omp declare simd"))
, omp_clause,
643 DECL_ATTRIBUTES (fndecl)((contains_struct_check ((fndecl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 643, __FUNCTION__))->decl_common.attributes)
);
644 }
645 }
646}
647
648 /* Set SIMD attribute to all built-in functions that are mentioned
649 in gfc_vectorized_builtins vector. */
650
651void
652gfc_adjust_builtins (void)
653{
654 gfc_intrinsic_map_t *m;
655 for (m = gfc_intrinsic_map;
656 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
657 {
658 add_simd_flag_for_built_in (m->real4_decl);
659 add_simd_flag_for_built_in (m->complex4_decl);
660 add_simd_flag_for_built_in (m->real8_decl);
661 add_simd_flag_for_built_in (m->complex8_decl);
662 add_simd_flag_for_built_in (m->real10_decl);
663 add_simd_flag_for_built_in (m->complex10_decl);
664 add_simd_flag_for_built_in (m->real16_decl);
665 add_simd_flag_for_built_in (m->complex16_decl);
666 add_simd_flag_for_built_in (m->real16_decl);
667 add_simd_flag_for_built_in (m->complex16_decl);
668 }
669
670 /* Release all strings. */
671 if (gfc_vectorized_builtins != NULL__null)
672 {
673 for (hash_map<nofree_string_hash, int>::iterator it
674 = gfc_vectorized_builtins->begin ();
675 it != gfc_vectorized_builtins->end (); ++it)
676 free (CONST_CAST (char *, (*it).first)(const_cast<char *> (((*it).first))));
677
678 delete gfc_vectorized_builtins;
679 gfc_vectorized_builtins = NULL__null;
680 }
681}
682
683/* Initialize function decls for library functions. The external functions
684 are created as required. Builtin functions are added here. */
685
686void
687gfc_build_intrinsic_lib_fndecls (void)
688{
689 gfc_intrinsic_map_t *m;
690 tree quad_decls[END_BUILTINS + 1];
691
692 if (gfc_real16_is_float128)
693 {
694 /* If we have soft-float types, we create the decls for their
695 C99-like library functions. For now, we only handle _Float128
696 q-suffixed or IEC 60559 f128-suffixed functions. */
697
698 tree type, complex_type, func_1, func_2, func_3, func_cabs, func_frexp;
699 tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
700
701 memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
702
703 type = gfc_float128_type_node;
704 complex_type = gfc_complex_float128_type_node;
705 /* type (*) (type) */
706 func_1 = build_function_type_list (type, type, NULL_TREE(tree) __null);
707 /* int (*) (type) */
708 func_iround = build_function_type_list (integer_type_nodeinteger_types[itk_int],
709 type, NULL_TREE(tree) __null);
710 /* long (*) (type) */
711 func_lround = build_function_type_list (long_integer_type_nodeinteger_types[itk_long],
712 type, NULL_TREE(tree) __null);
713 /* long long (*) (type) */
714 func_llround = build_function_type_list (long_long_integer_type_nodeinteger_types[itk_long_long],
715 type, NULL_TREE(tree) __null);
716 /* type (*) (type, type) */
717 func_2 = build_function_type_list (type, type, type, NULL_TREE(tree) __null);
718 /* type (*) (type, type, type) */
719 func_3 = build_function_type_list (type, type, type, type, NULL_TREE(tree) __null);
720 /* type (*) (type, &int) */
721 func_frexp
722 = build_function_type_list (type,
723 type,
724 build_pointer_type (integer_type_nodeinteger_types[itk_int]),
725 NULL_TREE(tree) __null);
726 /* type (*) (type, int) */
727 func_scalbn = build_function_type_list (type,
728 type, integer_type_nodeinteger_types[itk_int], NULL_TREE(tree) __null);
729 /* type (*) (complex type) */
730 func_cabs = build_function_type_list (type, complex_type, NULL_TREE(tree) __null);
731 /* complex type (*) (complex type, complex type) */
732 func_cpow
733 = build_function_type_list (complex_type,
734 complex_type, complex_type, NULL_TREE(tree) __null);
735
736#define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
737#define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
738#define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
739
740 /* Only these built-ins are actually needed here. These are used directly
741 from the code, when calling builtin_decl_for_precision() or
742 builtin_decl_for_float_type(). The others are all constructed by
743 gfc_get_intrinsic_lib_fndecl(). */
744#define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
745 quad_decls[BUILT_IN_ ## ID] \
746 = define_quad_builtin (gfc_real16_use_iec_60559 \
747 ? NAME "f128" : NAME "q", func_ ## TYPE, \
748 CONST);
749
750#include "mathbuiltins.def"
751
752#undef OTHER_BUILTIN
753#undef LIB_FUNCTION
754#undef DEFINE_MATH_BUILTIN
755#undef DEFINE_MATH_BUILTIN_C
756
757 /* There is one built-in we defined manually, because it gets called
758 with builtin_decl_for_precision() or builtin_decl_for_float_type()
759 even though it is not an OTHER_BUILTIN: it is SQRT. */
760 quad_decls[BUILT_IN_SQRT]
761 = define_quad_builtin (gfc_real16_use_iec_60559
762 ? "sqrtf128" : "sqrtq", func_1, true);
763 }
764
765 /* Add GCC builtin functions. */
766 for (m = gfc_intrinsic_map;
767 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
768 {
769 if (m->float_built_in != END_BUILTINS)
770 m->real4_decl = builtin_decl_explicit (m->float_built_in);
771 if (m->complex_float_built_in != END_BUILTINS)
772 m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
773 if (m->double_built_in != END_BUILTINS)
774 m->real8_decl = builtin_decl_explicit (m->double_built_in);
775 if (m->complex_double_built_in != END_BUILTINS)
776 m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
777
778 /* If real(kind=10) exists, it is always long double. */
779 if (m->long_double_built_in != END_BUILTINS)
780 m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
781 if (m->complex_long_double_built_in != END_BUILTINS)
782 m->complex10_decl
783 = builtin_decl_explicit (m->complex_long_double_built_in);
784
785 if (!gfc_real16_is_float128)
786 {
787 if (m->long_double_built_in != END_BUILTINS)
788 m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
789 if (m->complex_long_double_built_in != END_BUILTINS)
790 m->complex16_decl
791 = builtin_decl_explicit (m->complex_long_double_built_in);
792 }
793 else if (quad_decls[m->double_built_in] != NULL_TREE(tree) __null)
794 {
795 /* Quad-precision function calls are constructed when first
796 needed by builtin_decl_for_precision(), except for those
797 that will be used directly (define by OTHER_BUILTIN). */
798 m->real16_decl = quad_decls[m->double_built_in];
799 }
800 else if (quad_decls[m->complex_double_built_in] != NULL_TREE(tree) __null)
801 {
802 /* Same thing for the complex ones. */
803 m->complex16_decl = quad_decls[m->double_built_in];
804 }
805 }
806}
807
808
809/* Create a fndecl for a simple intrinsic library function. */
810
811static tree
812gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
813{
814 tree type;
815 vec<tree, va_gc> *argtypes;
816 tree fndecl;
817 gfc_actual_arglist *actual;
818 tree *pdecl;
819 gfc_typespec *ts;
820 char name[GFC_MAX_SYMBOL_LEN63 + 3];
821
822 ts = &expr->ts;
823 if (ts->type == BT_REAL)
824 {
825 switch (ts->kind)
826 {
827 case 4:
828 pdecl = &m->real4_decl;
829 break;
830 case 8:
831 pdecl = &m->real8_decl;
832 break;
833 case 10:
834 pdecl = &m->real10_decl;
835 break;
836 case 16:
837 pdecl = &m->real16_decl;
838 break;
839 default:
840 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 840, __FUNCTION__))
;
841 }
842 }
843 else if (ts->type == BT_COMPLEX)
844 {
845 gcc_assert (m->complex_available)((void)(!(m->complex_available) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 845, __FUNCTION__), 0 : 0))
;
846
847 switch (ts->kind)
848 {
849 case 4:
850 pdecl = &m->complex4_decl;
851 break;
852 case 8:
853 pdecl = &m->complex8_decl;
854 break;
855 case 10:
856 pdecl = &m->complex10_decl;
857 break;
858 case 16:
859 pdecl = &m->complex16_decl;
860 break;
861 default:
862 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 862, __FUNCTION__))
;
863 }
864 }
865 else
866 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 866, __FUNCTION__))
;
867
868 if (*pdecl)
869 return *pdecl;
870
871 if (m->libm_name)
872 {
873 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
874 if (gfc_real_kinds[n].c_float)
875 snprintf (name, sizeof (name), "%s%s%s",
876 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
877 else if (gfc_real_kinds[n].c_double)
878 snprintf (name, sizeof (name), "%s%s",
879 ts->type == BT_COMPLEX ? "c" : "", m->name);
880 else if (gfc_real_kinds[n].c_long_double)
881 snprintf (name, sizeof (name), "%s%s%s",
882 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
883 else if (gfc_real_kinds[n].c_float128)
884 snprintf (name, sizeof (name), "%s%s%s",
885 ts->type == BT_COMPLEX ? "c" : "", m->name,
886 gfc_real_kinds[n].use_iec_60559 ? "f128" : "q");
887 else
888 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 888, __FUNCTION__))
;
889 }
890 else
891 {
892 snprintf (name, sizeof (name), PREFIX ("%s_%c%d")"_gfortran_" "%s_%c%d", m->name,
893 ts->type == BT_COMPLEX ? 'c' : 'r',
894 gfc_type_abi_kind (ts));
895 }
896
897 argtypes = NULL__null;
898 for (actual = expr->value.function.actual; actual; actual = actual->next)
899 {
900 type = gfc_typenode_for_spec (&actual->expr->ts);
901 vec_safe_push (argtypes, type);
902 }
903 type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes)build_function_type_array (gfc_typenode_for_spec (ts), vec_safe_length
(argtypes), vec_safe_address (argtypes))
;
904 fndecl = build_decl (input_location,
905 FUNCTION_DECL, get_identifier (name)(__builtin_constant_p (name) ? get_identifier_with_length ((name
), strlen (name)) : get_identifier (name))
, type);
906
907 /* Mark the decl as external. */
908 DECL_EXTERNAL (fndecl)((contains_struct_check ((fndecl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 908, __FUNCTION__))->decl_common.decl_flag_1)
= 1;
909 TREE_PUBLIC (fndecl)((fndecl)->base.public_flag) = 1;
910
911 /* Mark it __attribute__((const)), if possible. */
912 TREE_READONLY (fndecl)((non_type_check ((fndecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 912, __FUNCTION__))->base.readonly_flag)
= m->is_constant;
913
914 rest_of_decl_compilation (fndecl, 1, 0);
915
916 (*pdecl) = fndecl;
917 return fndecl;
918}
919
920
921/* Convert an intrinsic function into an external or builtin call. */
922
923static void
924gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
925{
926 gfc_intrinsic_map_t *m;
927 tree fndecl;
928 tree rettype;
929 tree *args;
930 unsigned int num_args;
931 gfc_isym_id id;
932
933 id = expr->value.function.isym->id;
934 /* Find the entry for this function. */
935 for (m = gfc_intrinsic_map;
936 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
937 {
938 if (id == m->id)
939 break;
940 }
941
942 if (m->id == GFC_ISYM_NONE)
943 {
944 gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
945 expr->value.function.name, id);
946 }
947
948 /* Get the decl and generate the call. */
949 num_args = gfc_intrinsic_argument_list_length (expr);
950 args = XALLOCAVEC (tree, num_args)((tree *) __builtin_alloca(sizeof (tree) * (num_args)));
951
952 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
953 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
954 rettype = TREE_TYPE (TREE_TYPE (fndecl))((contains_struct_check ((((contains_struct_check ((fndecl), (
TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 954, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 954, __FUNCTION__))->typed.type)
;
955
956 fndecl = build_addr (fndecl);
957 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
958}
959
960
961/* If bounds-checking is enabled, create code to verify at runtime that the
962 string lengths for both expressions are the same (needed for e.g. MERGE).
963 If bounds-checking is not enabled, does nothing. */
964
965void
966gfc_trans_same_strlen_check (const char* intr_name, locus* where,
967 tree a, tree b, stmtblock_t* target)
968{
969 tree cond;
970 tree name;
971
972 /* If bounds-checking is disabled, do nothing. */
973 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS(1<<0)))
974 return;
975
976 /* Compare the two string lengths. */
977 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, a, b);
978
979 /* Output the runtime-check. */
980 name = gfc_build_cstring_const (intr_name);
981 name = gfc_build_addr_expr (pchar_type_node, name);
982 gfc_trans_runtime_check (true, false, cond, target, where,
983 "Unequal character lengths (%ld/%ld) in %s",
984 fold_convert (long_integer_type_node, a)fold_convert_loc (((location_t) 0), integer_types[itk_long], a
)
,
985 fold_convert (long_integer_type_node, b)fold_convert_loc (((location_t) 0), integer_types[itk_long], b
)
, name);
986}
987
988
989/* The EXPONENT(X) intrinsic function is translated into
990 int ret;
991 return isfinite(X) ? (frexp (X, &ret) , ret) : huge
992 so that if X is a NaN or infinity, the result is HUGE(0).
993 */
994
995static void
996gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
997{
998 tree arg, type, res, tmp, frexp, cond, huge;
999 int i;
1000
1001 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
1002 expr->value.function.actual->expr->ts.kind);
1003
1004 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
1005 arg = gfc_evaluate_now (arg, &se->pre);
1006
1007 i = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
1008 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_c_int_kind);
1009 cond = build_call_expr_loc (input_location,
1010 builtin_decl_explicit (BUILT_IN_ISFINITE),
1011 1, arg);
1012
1013 res = gfc_create_var (integer_type_nodeinteger_types[itk_int], NULL__null);
1014 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
1015 gfc_build_addr_expr (NULL_TREE(tree) __null, res));
1016 tmp = fold_build2_loc (input_location, COMPOUND_EXPR, integer_type_nodeinteger_types[itk_int],
1017 tmp, res);
1018 se->expr = fold_build3_loc (input_location, COND_EXPR, integer_type_nodeinteger_types[itk_int],
1019 cond, tmp, huge);
1020
1021 type = gfc_typenode_for_spec (&expr->ts);
1022 se->expr = fold_convert (type, se->expr)fold_convert_loc (((location_t) 0), type, se->expr);
1023}
1024
1025
1026/* Fill in the following structure
1027 struct caf_vector_t {
1028 size_t nvec; // size of the vector
1029 union {
1030 struct {
1031 void *vector;
1032 int kind;
1033 } v;
1034 struct {
1035 ptrdiff_t lower_bound;
1036 ptrdiff_t upper_bound;
1037 ptrdiff_t stride;
1038 } triplet;
1039 } u;
1040 } */
1041
1042static void
1043conv_caf_vector_subscript_elem (stmtblock_t *block, int i, tree desc,
1044 tree lower, tree upper, tree stride,
1045 tree vector, int kind, tree nvec)
1046{
1047 tree field, type, tmp;
1048
1049 desc = gfc_build_array_ref (desc, gfc_rank_cst[i], NULL_TREE(tree) __null);
1050 type = TREE_TYPE (desc)((contains_struct_check ((desc), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1050, __FUNCTION__))->typed.type)
;
1051
1052 field = gfc_advance_chain (TYPE_FIELDS (type)((tree_check3 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1052, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 0);
1053 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1053, __FUNCTION__))->typed.type)
,
1054 desc, field, NULL_TREE(tree) __null);
1055 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), nvec)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1055, __FUNCTION__))->typed.type), nvec)
);
1056
1057 /* Access union. */
1058 field = gfc_advance_chain (TYPE_FIELDS (type)((tree_check3 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1058, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 1);
1059 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1059, __FUNCTION__))->typed.type)
,
1060 desc, field, NULL_TREE(tree) __null);
1061 type = TREE_TYPE (desc)((contains_struct_check ((desc), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1061, __FUNCTION__))->typed.type)
;
1062
1063 /* Access the inner struct. */
1064 field = gfc_advance_chain (TYPE_FIELDS (type)((tree_check3 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1064, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, vector != NULL_TREE(tree) __null ? 0 : 1);
1065 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1065, __FUNCTION__))->typed.type)
,
1066 desc, field, NULL_TREE(tree) __null);
1067 type = TREE_TYPE (desc)((contains_struct_check ((desc), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1067, __FUNCTION__))->typed.type)
;
1068
1069 if (vector != NULL_TREE(tree) __null)
1070 {
1071 /* Set vector and kind. */
1072 field = gfc_advance_chain (TYPE_FIELDS (type)((tree_check3 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1072, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 0);
1073 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1073, __FUNCTION__))->typed.type)
,
1074 desc, field, NULL_TREE(tree) __null);
1075 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), vector)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1075, __FUNCTION__))->typed.type), vector)
);
1076 field = gfc_advance_chain (TYPE_FIELDS (type)((tree_check3 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1076, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 1);
1077 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1077, __FUNCTION__))->typed.type)
,
1078 desc, field, NULL_TREE(tree) __null);
1079 gfc_add_modify (block, tmp, build_int_cst (integer_type_nodeinteger_types[itk_int], kind));
1080 }
1081 else
1082 {
1083 /* Set dim.lower/upper/stride. */
1084 field = gfc_advance_chain (TYPE_FIELDS (type)((tree_check3 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1084, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 0);
1085 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1085, __FUNCTION__))->typed.type)
,
1086 desc, field, NULL_TREE(tree) __null);
1087 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), lower)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1087, __FUNCTION__))->typed.type), lower)
);
1088
1089 field = gfc_advance_chain (TYPE_FIELDS (type)((tree_check3 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1089, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 1);
1090 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1090, __FUNCTION__))->typed.type)
,
1091 desc, field, NULL_TREE(tree) __null);
1092 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), upper)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1092, __FUNCTION__))->typed.type), upper)
);
1093
1094 field = gfc_advance_chain (TYPE_FIELDS (type)((tree_check3 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1094, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 2);
1095 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1095, __FUNCTION__))->typed.type)
,
1096 desc, field, NULL_TREE(tree) __null);
1097 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), stride)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1097, __FUNCTION__))->typed.type), stride)
);
1098 }
1099}
1100
1101
1102static tree
1103conv_caf_vector_subscript (stmtblock_t *block, tree desc, gfc_array_ref *ar)
1104{
1105 gfc_se argse;
1106 tree var, lower, upper = NULL_TREE(tree) __null, stride = NULL_TREE(tree) __null, vector, nvec;
1107 tree lbound, ubound, tmp;
1108 int i;
1109
1110 var = gfc_create_var (gfc_get_caf_vector_type (ar->dimen), "vector");
1111
1112 for (i = 0; i < ar->dimen; i++)
1113 switch (ar->dimen_type[i])
1114 {
1115 case DIMEN_RANGE:
1116 if (ar->end[i])
1117 {
1118 gfc_init_se (&argse, NULL__null);
1119 gfc_conv_expr (&argse, ar->end[i]);
1120 gfc_add_block_to_block (block, &argse.pre);
1121 upper = gfc_evaluate_now (argse.expr, block);
1122 }
1123 else
1124 upper = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
1125 if (ar->stride[i])
1126 {
1127 gfc_init_se (&argse, NULL__null);
1128 gfc_conv_expr (&argse, ar->stride[i]);
1129 gfc_add_block_to_block (block, &argse.pre);
1130 stride = gfc_evaluate_now (argse.expr, block);
1131 }
1132 else
1133 stride = gfc_index_one_nodegfc_rank_cst[1];
1134
1135 /* Fall through. */
1136 case DIMEN_ELEMENT:
1137 if (ar->start[i])
1138 {
1139 gfc_init_se (&argse, NULL__null);
1140 gfc_conv_expr (&argse, ar->start[i]);
1141 gfc_add_block_to_block (block, &argse.pre);
1142 lower = gfc_evaluate_now (argse.expr, block);
1143 }
1144 else
1145 lower = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
1146 if (ar->dimen_type[i] == DIMEN_ELEMENT)
1147 {
1148 upper = lower;
1149 stride = gfc_index_one_nodegfc_rank_cst[1];
1150 }
1151 vector = NULL_TREE(tree) __null;
1152 nvec = size_zero_nodeglobal_trees[TI_SIZE_ZERO];
1153 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1154 vector, 0, nvec);
1155 break;
1156
1157 case DIMEN_VECTOR:
1158 gfc_init_se (&argse, NULL__null);
1159 argse.descriptor_only = 1;
1160 gfc_conv_expr_descriptor (&argse, ar->start[i]);
1161 gfc_add_block_to_block (block, &argse.pre);
1162 vector = argse.expr;
1163 lbound = gfc_conv_descriptor_lbound_get (vector, gfc_rank_cst[0]);
1164 ubound = gfc_conv_descriptor_ubound_get (vector, gfc_rank_cst[0]);
1165 nvec = gfc_conv_array_extent_dim (lbound, ubound, NULL__null);
1166 tmp = gfc_conv_descriptor_stride_get (vector, gfc_rank_cst[0]);
1167 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1168 TREE_TYPE (nvec)((contains_struct_check ((nvec), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1168, __FUNCTION__))->typed.type)
, nvec, tmp);
1169 lower = gfc_index_zero_nodegfc_rank_cst[0];
1170 upper = gfc_index_zero_nodegfc_rank_cst[0];
1171 stride = gfc_index_zero_nodegfc_rank_cst[0];
1172 vector = gfc_conv_descriptor_data_get (vector);
1173 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1174 vector, ar->start[i]->ts.kind, nvec);
1175 break;
1176 default:
1177 gcc_unreachable()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1177, __FUNCTION__))
;
1178 }
1179 return gfc_build_addr_expr (NULL_TREE(tree) __null, var);
1180}
1181
1182
1183static tree
1184compute_component_offset (tree field, tree type)
1185{
1186 tree tmp;
1187 if (DECL_FIELD_BIT_OFFSET (field)((tree_check ((field), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1187, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_offset
)
!= NULL_TREE(tree) __null
1188 && !integer_zerop (DECL_FIELD_BIT_OFFSET (field)((tree_check ((field), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1188, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_offset
)
))
1189 {
1190 tmp = fold_build2 (TRUNC_DIV_EXPR, type,fold_build2_loc (((location_t) 0), TRUNC_DIV_EXPR, type, ((tree_check
((field), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1191, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_offset
), global_trees[TI_BITSIZE_UNIT] )
1191 DECL_FIELD_BIT_OFFSET (field),fold_build2_loc (((location_t) 0), TRUNC_DIV_EXPR, type, ((tree_check
((field), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1191, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_offset
), global_trees[TI_BITSIZE_UNIT] )
1192 bitsize_unit_node)fold_build2_loc (((location_t) 0), TRUNC_DIV_EXPR, type, ((tree_check
((field), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1191, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_offset
), global_trees[TI_BITSIZE_UNIT] )
;
1193 return fold_build2 (PLUS_EXPR, type, DECL_FIELD_OFFSET (field), tmp)fold_build2_loc (((location_t) 0), PLUS_EXPR, type, ((tree_check
((field), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1193, __FUNCTION__, (FIELD_DECL)))->field_decl.offset), tmp
)
;
1194 }
1195 else
1196 return DECL_FIELD_OFFSET (field)((tree_check ((field), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1196, __FUNCTION__, (FIELD_DECL)))->field_decl.offset)
;
1197}
1198
1199
1200static tree
1201conv_expr_ref_to_caf_ref (stmtblock_t *block, gfc_expr *expr)
1202{
1203 gfc_ref *ref = expr->ref, *last_comp_ref;
1204 tree caf_ref = NULL_TREE(tree) __null, prev_caf_ref = NULL_TREE(tree) __null, reference_type, tmp, tmp2,
1205 field, last_type, inner_struct, mode, mode_rhs, dim_array, dim, dim_type,
1206 start, end, stride, vector, nvec;
1207 gfc_se se;
1208 bool ref_static_array = false;
1209 tree last_component_ref_tree = NULL_TREE(tree) __null;
1210 int i, last_type_n;
1211
1212 if (expr->symtree)
1213 {
1214 last_component_ref_tree = expr->symtree->n.sym->backend_decl;
1215 ref_static_array = !expr->symtree->n.sym->attr.allocatable
1216 && !expr->symtree->n.sym->attr.pointer;
1217 }
1218
1219 /* Prevent uninit-warning. */
1220 reference_type = NULL_TREE(tree) __null;
1221
1222 /* Skip refs upto the first coarray-ref. */
1223 last_comp_ref = NULL__null;
1224 while (ref && (ref->type != REF_ARRAY || ref->u.ar.codimen == 0))
1225 {
1226 /* Remember the type of components skipped. */
1227 if (ref->type == REF_COMPONENT)
1228 last_comp_ref = ref;
1229 ref = ref->next;
1230 }
1231 /* When a component was skipped, get the type information of the last
1232 component ref, else get the type from the symbol. */
1233 if (last_comp_ref)
1234 {
1235 last_type = gfc_typenode_for_spec (&last_comp_ref->u.c.component->ts);
1236 last_type_n = last_comp_ref->u.c.component->ts.type;
1237 }
1238 else
1239 {
1240 last_type = gfc_typenode_for_spec (&expr->symtree->n.sym->ts);
1241 last_type_n = expr->symtree->n.sym->ts.type;
1242 }
1243
1244 while (ref)
1245 {
1246 if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0
1247 && ref->u.ar.dimen == 0)
1248 {
1249 /* Skip pure coindexes. */
1250 ref = ref->next;
1251 continue;
1252 }
1253 tmp = gfc_create_var (gfc_get_caf_reference_type (), "caf_ref");
1254 reference_type = TREE_TYPE (tmp)((contains_struct_check ((tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1254, __FUNCTION__))->typed.type)
;
1255
1256 if (caf_ref == NULL_TREE(tree) __null)
1257 caf_ref = tmp;
1258
1259 /* Construct the chain of refs. */
1260 if (prev_caf_ref != NULL_TREE(tree) __null)
1261 {
1262 field = gfc_advance_chain (TYPE_FIELDS (reference_type)((tree_check3 ((reference_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1262, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 0);
1263 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1264 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1264, __FUNCTION__))->typed.type)
, prev_caf_ref, field,
1265 NULL_TREE(tree) __null);
1266 gfc_add_modify (block, tmp2, gfc_build_addr_expr (TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1266, __FUNCTION__))->typed.type)
,
1267 tmp));
1268 }
1269 prev_caf_ref = tmp;
1270
1271 switch (ref->type)
1272 {
1273 case REF_COMPONENT:
1274 last_type = gfc_typenode_for_spec (&ref->u.c.component->ts);
1275 last_type_n = ref->u.c.component->ts.type;
1276 /* Set the type of the ref. */
1277 field = gfc_advance_chain (TYPE_FIELDS (reference_type)((tree_check3 ((reference_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1277, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 1);
1278 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1279 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1279, __FUNCTION__))->typed.type)
, prev_caf_ref, field,
1280 NULL_TREE(tree) __null);
1281 gfc_add_modify (block, tmp, build_int_cst (integer_type_nodeinteger_types[itk_int],
1282 GFC_CAF_REF_COMPONENT));
1283
1284 /* Ref the c in union u. */
1285 field = gfc_advance_chain (TYPE_FIELDS (reference_type)((tree_check3 ((reference_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1285, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 3);
1286 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1287 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1287, __FUNCTION__))->typed.type)
, prev_caf_ref, field,
1288 NULL_TREE(tree) __null);
1289 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field))((tree_check3 ((((contains_struct_check ((field), (TS_TYPED),
"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1289, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1289, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 0);
1290 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1291 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1291, __FUNCTION__))->typed.type)
, tmp, field,
1292 NULL_TREE(tree) __null);
1293
1294 /* Set the offset. */
1295 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct))((tree_check3 ((((contains_struct_check ((inner_struct), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1295, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1295, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 0);
1296 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1297 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1297, __FUNCTION__))->typed.type)
, inner_struct, field,
1298 NULL_TREE(tree) __null);
1299 /* Computing the offset is somewhat harder. The bit_offset has to be
1300 taken into account. When the bit_offset in the field_decl is non-
1301 null, divide it by the bitsize_unit and add it to the regular
1302 offset. */
1303 tmp2 = compute_component_offset (ref->u.c.component->backend_decl,
1304 TREE_TYPE (tmp)((contains_struct_check ((tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1304, __FUNCTION__))->typed.type)
);
1305 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1305, __FUNCTION__))->typed.type), tmp2)
);
1306
1307 /* Set caf_token_offset. */
1308 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct))((tree_check3 ((((contains_struct_check ((inner_struct), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1308, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1308, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 1);
1309 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1310 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1310, __FUNCTION__))->typed.type)
, inner_struct, field,
1311 NULL_TREE(tree) __null);
1312 if ((ref->u.c.component->attr.allocatable
1313 || ref->u.c.component->attr.pointer)
1314 && ref->u.c.component->attr.dimension)
1315 {
1316 tree arr_desc_token_offset;
1317 /* Get the token field from the descriptor. */
1318 arr_desc_token_offset = TREE_OPERAND ((*((const_cast<tree*> (tree_operand_check ((gfc_conv_descriptor_token
(ref->u.c.component->backend_decl)), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1319, __FUNCTION__)))))
1319 gfc_conv_descriptor_token (ref->u.c.component->backend_decl), 1)(*((const_cast<tree*> (tree_operand_check ((gfc_conv_descriptor_token
(ref->u.c.component->backend_decl)), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1319, __FUNCTION__)))))
;
1320 arr_desc_token_offset
1321 = compute_component_offset (arr_desc_token_offset,
1322 TREE_TYPE (tmp)((contains_struct_check ((tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1322, __FUNCTION__))->typed.type)
);
1323 tmp2 = fold_build2_loc (input_location, PLUS_EXPR,
1324 TREE_TYPE (tmp2)((contains_struct_check ((tmp2), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1324, __FUNCTION__))->typed.type)
, tmp2,
1325 arr_desc_token_offset);
1326 }
1327 else if (ref->u.c.component->caf_token)
1328 tmp2 = compute_component_offset (ref->u.c.component->caf_token,
1329 TREE_TYPE (tmp)((contains_struct_check ((tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1329, __FUNCTION__))->typed.type)
);
1330 else
1331 tmp2 = integer_zero_nodeglobal_trees[TI_INTEGER_ZERO];
1332 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1332, __FUNCTION__))->typed.type), tmp2)
);
1333
1334 /* Remember whether this ref was to a non-allocatable/non-pointer
1335 component so the next array ref can be tailored correctly. */
1336 ref_static_array = !ref->u.c.component->attr.allocatable
1337 && !ref->u.c.component->attr.pointer;
1338 last_component_ref_tree = ref_static_array
1339 ? ref->u.c.component->backend_decl : NULL_TREE(tree) __null;
1340 break;
1341 case REF_ARRAY:
1342 if (ref_static_array && ref->u.ar.as->type == AS_DEFERRED)
1343 ref_static_array = false;
1344 /* Set the type of the ref. */
1345 field = gfc_advance_chain (TYPE_FIELDS (reference_type)((tree_check3 ((reference_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1345, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 1);
1346 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1347 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1347, __FUNCTION__))->typed.type)
, prev_caf_ref, field,
1348 NULL_TREE(tree) __null);
1349 gfc_add_modify (block, tmp, build_int_cst (integer_type_nodeinteger_types[itk_int],
1350 ref_static_array
1351 ? GFC_CAF_REF_STATIC_ARRAY
1352 : GFC_CAF_REF_ARRAY));
1353
1354 /* Ref the a in union u. */
1355 field = gfc_advance_chain (TYPE_FIELDS (reference_type)((tree_check3 ((reference_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1355, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 3);
1356 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1357 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1357, __FUNCTION__))->typed.type)
, prev_caf_ref, field,
1358 NULL_TREE(tree) __null);
1359 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field))((tree_check3 ((((contains_struct_check ((field), (TS_TYPED),
"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1359, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1359, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 1);
1360 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1361 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1361, __FUNCTION__))->typed.type)
, tmp, field,
1362 NULL_TREE(tree) __null);
1363
1364 /* Set the static_array_type in a for static arrays. */
1365 if (ref_static_array)
1366 {
1367 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct))((tree_check3 ((((contains_struct_check ((inner_struct), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1367, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1367, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
,
1368 1);
1369 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1370 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1370, __FUNCTION__))->typed.type)
, inner_struct, field,
1371 NULL_TREE(tree) __null);
1372 gfc_add_modify (block, tmp, build_int_cst (TREE_TYPE (tmp)((contains_struct_check ((tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1372, __FUNCTION__))->typed.type)
,
1373 last_type_n));
1374 }
1375 /* Ref the mode in the inner_struct. */
1376 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct))((tree_check3 ((((contains_struct_check ((inner_struct), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1376, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1376, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 0);
1377 mode = fold_build3_loc (input_location, COMPONENT_REF,
1378 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1378, __FUNCTION__))->typed.type)
, inner_struct, field,
1379 NULL_TREE(tree) __null);
1380 /* Ref the dim in the inner_struct. */
1381 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct))((tree_check3 ((((contains_struct_check ((inner_struct), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1381, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1381, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 2);
1382 dim_array = fold_build3_loc (input_location, COMPONENT_REF,
1383 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1383, __FUNCTION__))->typed.type)
, inner_struct, field,
1384 NULL_TREE(tree) __null);
1385 for (i = 0; i < ref->u.ar.dimen; ++i)
1386 {
1387 /* Ref dim i. */
1388 dim = gfc_build_array_ref (dim_array, gfc_rank_cst[i], NULL_TREE(tree) __null);
1389 dim_type = TREE_TYPE (dim)((contains_struct_check ((dim), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1389, __FUNCTION__))->typed.type)
;
1390 mode_rhs = start = end = stride = NULL_TREE(tree) __null;
1391 switch (ref->u.ar.dimen_type[i])
1392 {
1393 case DIMEN_RANGE:
1394 if (ref->u.ar.end[i])
1395 {
1396 gfc_init_se (&se, NULL__null);
1397 gfc_conv_expr (&se, ref->u.ar.end[i]);
1398 gfc_add_block_to_block (block, &se.pre);
1399 if (ref_static_array)
1400 {
1401 /* Make the index zero-based, when reffing a static
1402 array. */
1403 end = se.expr;
1404 gfc_init_se (&se, NULL__null);
1405 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1406 gfc_add_block_to_block (block, &se.pre);
1407 se.expr = fold_build2 (MINUS_EXPR,fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, end, fold_convert_loc (((location_t) 0), gfc_array_index_type
, se.expr) )
1408 gfc_array_index_type,fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, end, fold_convert_loc (((location_t) 0), gfc_array_index_type
, se.expr) )
1409 end, fold_convert (fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, end, fold_convert_loc (((location_t) 0), gfc_array_index_type
, se.expr) )
1410 gfc_array_index_type,fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, end, fold_convert_loc (((location_t) 0), gfc_array_index_type
, se.expr) )
1411 se.expr))fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, end, fold_convert_loc (((location_t) 0), gfc_array_index_type
, se.expr) )
;
1412 }
1413 end = gfc_evaluate_now (fold_convert (fold_convert_loc (((location_t) 0), gfc_array_index_type, se.
expr)
1414 gfc_array_index_type,fold_convert_loc (((location_t) 0), gfc_array_index_type, se.
expr)
1415 se.expr)fold_convert_loc (((location_t) 0), gfc_array_index_type, se.
expr)
,
1416 block);
1417 }
1418 else if (ref_static_array)
1419 end = fold_build2 (MINUS_EXPR,fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, gfc_conv_array_ubound ( last_component_ref_tree, i), gfc_conv_array_lbound
( last_component_ref_tree, i) )
1420 gfc_array_index_type,fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, gfc_conv_array_ubound ( last_component_ref_tree, i), gfc_conv_array_lbound
( last_component_ref_tree, i) )
1421 gfc_conv_array_ubound (fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, gfc_conv_array_ubound ( last_component_ref_tree, i), gfc_conv_array_lbound
( last_component_ref_tree, i) )
1422 last_component_ref_tree, i),fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, gfc_conv_array_ubound ( last_component_ref_tree, i), gfc_conv_array_lbound
( last_component_ref_tree, i) )
1423 gfc_conv_array_lbound (fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, gfc_conv_array_ubound ( last_component_ref_tree, i), gfc_conv_array_lbound
( last_component_ref_tree, i) )
1424 last_component_ref_tree, i))fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, gfc_conv_array_ubound ( last_component_ref_tree, i), gfc_conv_array_lbound
( last_component_ref_tree, i) )
;
1425 else
1426 {
1427 end = NULL_TREE(tree) __null;
1428 mode_rhs = build_int_cst (unsigned_char_type_nodeinteger_types[itk_unsigned_char],
1429 GFC_CAF_ARR_REF_OPEN_END);
1430 }
1431 if (ref->u.ar.stride[i])
1432 {
1433 gfc_init_se (&se, NULL__null);
1434 gfc_conv_expr (&se, ref->u.ar.stride[i]);
1435 gfc_add_block_to_block (block, &se.pre);
1436 stride = gfc_evaluate_now (fold_convert (fold_convert_loc (((location_t) 0), gfc_array_index_type, se.
expr)
1437 gfc_array_index_type,fold_convert_loc (((location_t) 0), gfc_array_index_type, se.
expr)
1438 se.expr)fold_convert_loc (((location_t) 0), gfc_array_index_type, se.
expr)
,
1439 block);
1440 if (ref_static_array)
1441 {
1442 /* Make the index zero-based, when reffing a static
1443 array. */
1444 stride = fold_build2 (MULT_EXPR,fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, gfc_conv_array_stride ( last_component_ref_tree, i), stride
)
1445 gfc_array_index_type,fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, gfc_conv_array_stride ( last_component_ref_tree, i), stride
)
1446 gfc_conv_array_stride (fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, gfc_conv_array_stride ( last_component_ref_tree, i), stride
)
1447 last_component_ref_tree,fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, gfc_conv_array_stride ( last_component_ref_tree, i), stride
)
1448 i),fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, gfc_conv_array_stride ( last_component_ref_tree, i), stride
)
1449 stride)fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, gfc_conv_array_stride ( last_component_ref_tree, i), stride
)
;
1450 gcc_assert (end != NULL_TREE)((void)(!(end != (tree) __null) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1450, __FUNCTION__), 0 : 0))
;
1451 /* Multiply with the product of array's stride and
1452 the step of the ref to a virtual upper bound.
1453 We cannot compute the actual upper bound here or
1454 the caflib would compute the extend
1455 incorrectly. */
1456 end = fold_build2 (MULT_EXPR, gfc_array_index_type,fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, end, gfc_conv_array_stride ( last_component_ref_tree, i) )
1457 end, gfc_conv_array_stride (fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, end, gfc_conv_array_stride ( last_component_ref_tree, i) )
1458 last_component_ref_tree,fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, end, gfc_conv_array_stride ( last_component_ref_tree, i) )
1459 i))fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, end, gfc_conv_array_stride ( last_component_ref_tree, i) )
;
1460 end = gfc_evaluate_now (end, block);
1461 stride = gfc_evaluate_now (stride, block);
1462 }
1463 }
1464 else if (ref_static_array)
1465 {
1466 stride = gfc_conv_array_stride (last_component_ref_tree,
1467 i);
1468 end = fold_build2 (MULT_EXPR, gfc_array_index_type,fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, end, stride )
1469 end, stride)fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, end, stride )
;
1470 end = gfc_evaluate_now (end, block);
1471 }
1472 else
1473 /* Always set a ref stride of one to make caflib's
1474 handling easier. */
1475 stride = gfc_index_one_nodegfc_rank_cst[1];
1476
1477 /* Fall through. */
1478 case DIMEN_ELEMENT:
1479 if (ref->u.ar.start[i])
1480 {
1481 gfc_init_se (&se, NULL__null);
1482 gfc_conv_expr (&se, ref->u.ar.start[i]);
1483 gfc_add_block_to_block (block, &se.pre);
1484 if (ref_static_array)
1485 {
1486 /* Make the index zero-based, when reffing a static
1487 array. */
1488 start = fold_convert (gfc_array_index_type, se.expr)fold_convert_loc (((location_t) 0), gfc_array_index_type, se.
expr)
;
1489 gfc_init_se (&se, NULL__null);
1490 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1491 gfc_add_block_to_block (block, &se.pre);
1492 se.expr = fold_build2 (MINUS_EXPR,fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, start, fold_convert_loc (((location_t) 0), gfc_array_index_type
, se.expr) )
1493 gfc_array_index_type,fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, start, fold_convert_loc (((location_t) 0), gfc_array_index_type
, se.expr) )
1494 start, fold_convert (fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, start, fold_convert_loc (((location_t) 0), gfc_array_index_type
, se.expr) )
1495 gfc_array_index_type,fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, start, fold_convert_loc (((location_t) 0), gfc_array_index_type
, se.expr) )
1496 se.expr))fold_build2_loc (((location_t) 0), MINUS_EXPR, gfc_array_index_type
, start, fold_convert_loc (((location_t) 0), gfc_array_index_type
, se.expr) )
;
1497 /* Multiply with the stride. */
1498 se.expr = fold_build2 (MULT_EXPR,fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, se.expr, gfc_conv_array_stride ( last_component_ref_tree, i
) )
1499 gfc_array_index_type,fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, se.expr, gfc_conv_array_stride ( last_component_ref_tree, i
) )
1500 se.expr,fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, se.expr, gfc_conv_array_stride ( last_component_ref_tree, i
) )
1501 gfc_conv_array_stride (fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, se.expr, gfc_conv_array_stride ( last_component_ref_tree, i
) )
1502 last_component_ref_tree,fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, se.expr, gfc_conv_array_stride ( last_component_ref_tree, i
) )
1503 i))fold_build2_loc (((location_t) 0), MULT_EXPR, gfc_array_index_type
, se.expr, gfc_conv_array_stride ( last_component_ref_tree, i
) )
;
1504 }
1505 start = gfc_evaluate_now (fold_convert (fold_convert_loc (((location_t) 0), gfc_array_index_type, se.
expr)
1506 gfc_array_index_type,fold_convert_loc (((location_t) 0), gfc_array_index_type, se.
expr)
1507 se.expr)fold_convert_loc (((location_t) 0), gfc_array_index_type, se.
expr)
,
1508 block);
1509 if (mode_rhs == NULL_TREE(tree) __null)
1510 mode_rhs = build_int_cst (unsigned_char_type_nodeinteger_types[itk_unsigned_char],
1511 ref->u.ar.dimen_type[i]
1512 == DIMEN_ELEMENT
1513 ? GFC_CAF_ARR_REF_SINGLE
1514 : GFC_CAF_ARR_REF_RANGE);
1515 }
1516 else if (ref_static_array)
1517 {
1518 start = integer_zero_nodeglobal_trees[TI_INTEGER_ZERO];
1519 mode_rhs = build_int_cst (unsigned_char_type_nodeinteger_types[itk_unsigned_char],
1520 ref->u.ar.start[i] == NULL__null
1521 ? GFC_CAF_ARR_REF_FULL
1522 : GFC_CAF_ARR_REF_RANGE);
1523 }
1524 else if (end == NULL_TREE(tree) __null)
1525 mode_rhs = build_int_cst (unsigned_char_type_nodeinteger_types[itk_unsigned_char],
1526 GFC_CAF_ARR_REF_FULL);
1527 else
1528 mode_rhs = build_int_cst (unsigned_char_type_nodeinteger_types[itk_unsigned_char],
1529 GFC_CAF_ARR_REF_OPEN_START);
1530
1531 /* Ref the s in dim. */
1532 field = gfc_advance_chain (TYPE_FIELDS (dim_type)((tree_check3 ((dim_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1532, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 0);
1533 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1534 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1534, __FUNCTION__))->typed.type)
, dim, field,
1535 NULL_TREE(tree) __null);
1536
1537 /* Set start in s. */
1538 if (start != NULL_TREE(tree) __null)
1539 {
1540 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp))((tree_check3 ((((contains_struct_check ((tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1540, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1540, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
,
1541 0);
1542 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1543 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1543, __FUNCTION__))->typed.type)
, tmp, field,
1544 NULL_TREE(tree) __null);
1545 gfc_add_modify (block, tmp2,
1546 fold_convert (TREE_TYPE (tmp2), start)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(tmp2), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1546, __FUNCTION__))->typed.type), start)
);
1547 }
1548
1549 /* Set end in s. */
1550 if (end != NULL_TREE(tree) __null)
1551 {
1552 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp))((tree_check3 ((((contains_struct_check ((tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1552, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1552, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
,
1553 1);
1554 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1555 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1555, __FUNCTION__))->typed.type)
, tmp, field,
1556 NULL_TREE(tree) __null);
1557 gfc_add_modify (block, tmp2,
1558 fold_convert (TREE_TYPE (tmp2), end)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(tmp2), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1558, __FUNCTION__))->typed.type), end)
);
1559 }
1560
1561 /* Set end in s. */
1562 if (stride != NULL_TREE(tree) __null)
1563 {
1564 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp))((tree_check3 ((((contains_struct_check ((tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1564, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1564, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
,
1565 2);
1566 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1567 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1567, __FUNCTION__))->typed.type)
, tmp, field,
1568 NULL_TREE(tree) __null);
1569 gfc_add_modify (block, tmp2,
1570 fold_convert (TREE_TYPE (tmp2), stride)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(tmp2), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1570, __FUNCTION__))->typed.type), stride)
);
1571 }
1572 break;
1573 case DIMEN_VECTOR:
1574 /* TODO: In case of static array. */
1575 gcc_assert (!ref_static_array)((void)(!(!ref_static_array) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1575, __FUNCTION__), 0 : 0))
;
1576 mode_rhs = build_int_cst (unsigned_char_type_nodeinteger_types[itk_unsigned_char],
1577 GFC_CAF_ARR_REF_VECTOR);
1578 gfc_init_se (&se, NULL__null);
1579 se.descriptor_only = 1;
1580 gfc_conv_expr_descriptor (&se, ref->u.ar.start[i]);
1581 gfc_add_block_to_block (block, &se.pre);
1582 vector = se.expr;
1583 tmp = gfc_conv_descriptor_lbound_get (vector,
1584 gfc_rank_cst[0]);
1585 tmp2 = gfc_conv_descriptor_ubound_get (vector,
1586 gfc_rank_cst[0]);
1587 nvec = gfc_conv_array_extent_dim (tmp, tmp2, NULL__null);
1588 tmp = gfc_conv_descriptor_stride_get (vector,
1589 gfc_rank_cst[0]);
1590 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1591 TREE_TYPE (nvec)((contains_struct_check ((nvec), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1591, __FUNCTION__))->typed.type)
, nvec, tmp);
1592 vector = gfc_conv_descriptor_data_get (vector);
1593
1594 /* Ref the v in dim. */
1595 field = gfc_advance_chain (TYPE_FIELDS (dim_type)((tree_check3 ((dim_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1595, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 1);
1596 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1597 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1597, __FUNCTION__))->typed.type)
, dim, field,
1598 NULL_TREE(tree) __null);
1599
1600 /* Set vector in v. */
1601 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp))((tree_check3 ((((contains_struct_check ((tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1601, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1601, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 0);
1602 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1603 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1603, __FUNCTION__))->typed.type)
, tmp, field,
1604 NULL_TREE(tree) __null);
1605 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),fold_convert_loc (((location_t) 0), ((contains_struct_check (
(tmp2), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1605, __FUNCTION__))->typed.type), vector)
1606 vector)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(tmp2), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1605, __FUNCTION__))->typed.type), vector)
);
1607
1608 /* Set nvec in v. */
1609 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp))((tree_check3 ((((contains_struct_check ((tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1609, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1609, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 1);
1610 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1611 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1611, __FUNCTION__))->typed.type)
, tmp, field,
1612 NULL_TREE(tree) __null);
1613 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),fold_convert_loc (((location_t) 0), ((contains_struct_check (
(tmp2), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1613, __FUNCTION__))->typed.type), nvec)
1614 nvec)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(tmp2), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1613, __FUNCTION__))->typed.type), nvec)
);
1615
1616 /* Set kind in v. */
1617 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp))((tree_check3 ((((contains_struct_check ((tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1617, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1617, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 2);
1618 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1619 TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1619, __FUNCTION__))->typed.type)
, tmp, field,
1620 NULL_TREE(tree) __null);
1621 gfc_add_modify (block, tmp2, build_int_cst (integer_type_nodeinteger_types[itk_int],
1622 ref->u.ar.start[i]->ts.kind));
1623 break;
1624 default:
1625 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1625, __FUNCTION__))
;
1626 }
1627 /* Set the mode for dim i. */
1628 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE(tree) __null);
1629 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp),fold_convert_loc (((location_t) 0), ((contains_struct_check (
(tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1629, __FUNCTION__))->typed.type), mode_rhs)
1630 mode_rhs)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1629, __FUNCTION__))->typed.type), mode_rhs)
);
1631 }
1632
1633 /* Set the mode for dim i+1 to GFC_ARR_REF_NONE. */
1634 if (i < GFC_MAX_DIMENSIONS15)
1635 {
1636 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE(tree) __null);
1637 gfc_add_modify (block, tmp,
1638 build_int_cst (unsigned_char_type_nodeinteger_types[itk_unsigned_char],
1639 GFC_CAF_ARR_REF_NONE));
1640 }
1641 break;
1642 default:
1643 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1643, __FUNCTION__))
;
1644 }
1645
1646 /* Set the size of the current type. */
1647 field = gfc_advance_chain (TYPE_FIELDS (reference_type)((tree_check3 ((reference_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1647, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 2);
1648 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1648, __FUNCTION__))->typed.type)
,
1649 prev_caf_ref, field, NULL_TREE(tree) __null);
1650 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),fold_convert_loc (((location_t) 0), ((contains_struct_check (
(field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1650, __FUNCTION__))->typed.type), ((tree_class_check ((
last_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1651, __FUNCTION__))->type_common.size_unit))
1651 TYPE_SIZE_UNIT (last_type))fold_convert_loc (((location_t) 0), ((contains_struct_check (
(field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1650, __FUNCTION__))->typed.type), ((tree_class_check ((
last_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1651, __FUNCTION__))->type_common.size_unit))
);
1652
1653 ref = ref->next;
1654 }
1655
1656 if (prev_caf_ref != NULL_TREE(tree) __null)
1657 {
1658 field = gfc_advance_chain (TYPE_FIELDS (reference_type)((tree_check3 ((reference_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1658, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
, 0);
1659 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field)((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1659, __FUNCTION__))->typed.type)
,
1660 prev_caf_ref, field, NULL_TREE(tree) __null);
1661 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),fold_convert_loc (((location_t) 0), ((contains_struct_check (
(field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1661, __FUNCTION__))->typed.type), global_trees[TI_NULL_POINTER
])
1662 null_pointer_node)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1661, __FUNCTION__))->typed.type), global_trees[TI_NULL_POINTER
])
);
1663 }
1664 return caf_ref != NULL_TREE(tree) __null ? gfc_build_addr_expr (NULL_TREE(tree) __null, caf_ref)
1665 : NULL_TREE(tree) __null;
1666}
1667
1668/* Get data from a remote coarray. */
1669
1670static void
1671gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
1672 tree may_require_tmp, bool may_realloc,
1673 symbol_attribute *caf_attr)
1674{
1675 gfc_expr *array_expr, *tmp_stat;
1676 gfc_se argse;
1677 tree caf_decl, token, offset, image_index, tmp;
1678 tree res_var, dst_var, type, kind, vec, stat;
1679 tree caf_reference;
1680 symbol_attribute caf_attr_store;
1681
1682 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB)((void)(!(global_options.x_flag_coarray == GFC_FCOARRAY_LIB) ?
fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1682, __FUNCTION__), 0 : 0))
;
1683
1684 if (se->ss && se->ss->info->useflags)
1685 {
1686 /* Access the previously obtained result. */
1687 gfc_conv_tmp_array_ref (se);
1688 return;
1689 }
1690
1691 /* If lhs is set, the CAF_GET intrinsic has already been stripped. */
1692 array_expr = (lhs == NULL_TREE(tree) __null) ? expr->value.function.actual->expr : expr;
1693 type = gfc_typenode_for_spec (&array_expr->ts);
1694
1695 if (caf_attr == NULL__null)
1696 {
1697 caf_attr_store = gfc_caf_attr (array_expr);
1698 caf_attr = &caf_attr_store;
1699 }
1700
1701 res_var = lhs;
1702 dst_var = lhs;
1703
1704 vec = null_pointer_nodeglobal_trees[TI_NULL_POINTER];
1705 tmp_stat = gfc_find_stat_co (expr);
1706
1707 if (tmp_stat)
1708 {
1709 gfc_se stat_se;
1710 gfc_init_se (&stat_se, NULL__null);
1711 gfc_conv_expr_reference (&stat_se, tmp_stat);
1712 stat = stat_se.expr;
1713 gfc_add_block_to_block (&se->pre, &stat_se.pre);
1714 gfc_add_block_to_block (&se->post, &stat_se.post);
1715 }
1716 else
1717 stat = null_pointer_nodeglobal_trees[TI_NULL_POINTER];
1718
1719 /* Only use the new get_by_ref () where it is necessary. I.e., when the lhs
1720 is reallocatable or the right-hand side has allocatable components. */
1721 if (caf_attr->alloc_comp || caf_attr->pointer_comp || may_realloc)
1722 {
1723 /* Get using caf_get_by_ref. */
1724 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, array_expr);
1725
1726 if (caf_reference != NULL_TREE(tree) __null)
1727 {
1728 if (lhs == NULL_TREE(tree) __null)
1729 {
1730 if (array_expr->ts.type == BT_CHARACTER)
1731 gfc_init_se (&argse, NULL__null);
1732 if (array_expr->rank == 0)
1733 {
1734 symbol_attribute attr;
1735 gfc_clear_attr (&attr);
1736 if (array_expr->ts.type == BT_CHARACTER)
1737 {
1738 res_var = gfc_conv_string_tmp (se,
1739 build_pointer_type (type),
1740 array_expr->ts.u.cl->backend_decl);
1741 argse.string_length = array_expr->ts.u.cl->backend_decl;
1742 }
1743 else
1744 res_var = gfc_create_var (type, "caf_res");
1745 dst_var = gfc_conv_scalar_to_descriptor (se, res_var, attr);
1746 dst_var = gfc_build_addr_expr (NULL_TREE(tree) __null, dst_var);
1747 }
1748 else
1749 {
1750 /* Create temporary. */
1751 if (array_expr->ts.type == BT_CHARACTER)
1752 gfc_conv_expr_descriptor (&argse, array_expr);
1753 may_realloc = gfc_trans_create_temp_array (&se->pre,
1754 &se->post,
1755 se->ss, type,
1756 NULL_TREE(tree) __null, false,
1757 false, false,
1758 &array_expr->where)
1759 == NULL_TREE(tree) __null;
1760 res_var = se->ss->info->data.array.descriptor;
1761 dst_var = gfc_build_addr_expr (NULL_TREE(tree) __null, res_var);
1762 if (may_realloc)
1763 {
1764 tmp = gfc_conv_descriptor_data_get (res_var);
1765 tmp = gfc_deallocate_with_status (tmp, NULL_TREE(tree) __null,
1766 NULL_TREE(tree) __null, NULL_TREE(tree) __null,
1767 NULL_TREE(tree) __null, true,
1768 NULL__null,
1769 GFC_CAF_COARRAY_NOCOARRAY);
1770 gfc_add_expr_to_block (&se->post, tmp);
1771 }
1772 }
1773 }
1774
1775 kind = build_int_cst (integer_type_nodeinteger_types[itk_int], expr->ts.kind);
1776 if (lhs_kind == NULL_TREE(tree) __null)
1777 lhs_kind = kind;
1778
1779 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1780 if (TREE_CODE (TREE_TYPE (caf_decl))((enum tree_code) (((contains_struct_check ((caf_decl), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1780, __FUNCTION__))->typed.type))->base.code)
== REFERENCE_TYPE)
1781 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1782 image_index = gfc_caf_get_image_index (&se->pre, array_expr,
1783 caf_decl);
1784 gfc_get_caf_token_offset (se, &token, NULL__null, caf_decl, NULL__null,
1785 array_expr);
1786
1787 /* No overlap possible as we have generated a temporary. */
1788 if (lhs == NULL_TREE(tree) __null)
1789 may_require_tmp = boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE];
1790
1791 /* It guarantees memory consistency within the same segment. */
1792 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1793 tmp = build5_loc (input_location, ASM_EXPR, void_type_nodeglobal_trees[TI_VOID_TYPE],
1794 gfc_build_string_const (1, ""), NULL_TREE(tree) __null,
1795 NULL_TREE(tree) __null, tree_cons (NULL_TREE(tree) __null, tmp, NULL_TREE(tree) __null),
1796 NULL_TREE(tree) __null);
1797 ASM_VOLATILE_P (tmp)((tree_check ((tmp), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1797, __FUNCTION__, (ASM_EXPR)))->base.public_flag)
= 1;
1798 gfc_add_expr_to_block (&se->pre, tmp);
1799
1800 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get_by_ref,
1801 10, token, image_index, dst_var,
1802 caf_reference, lhs_kind, kind,
1803 may_require_tmp,
1804 may_realloc ? boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE] :
1805 boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE],
1806 stat, build_int_cst (integer_type_nodeinteger_types[itk_int],
1807 array_expr->ts.type));
1808
1809 gfc_add_expr_to_block (&se->pre, tmp);
1810
1811 if (se->ss)
1812 gfc_advance_se_ss_chain (se);
1813
1814 se->expr = res_var;
1815 if (array_expr->ts.type == BT_CHARACTER)
1816 se->string_length = argse.string_length;
1817
1818 return;
1819 }
1820 }
1821
1822 gfc_init_se (&argse, NULL__null);
1823 if (array_expr->rank == 0)
1824 {
1825 symbol_attribute attr;
1826
1827 gfc_clear_attr (&attr);
1828 gfc_conv_expr (&argse, array_expr);
1829
1830 if (lhs == NULL_TREE(tree) __null)
1831 {
1832 gfc_clear_attr (&attr);
1833 if (array_expr->ts.type == BT_CHARACTER)
1834 res_var = gfc_conv_string_tmp (se, build_pointer_type (type),
1835 argse.string_length);
1836 else
1837 res_var = gfc_create_var (type, "caf_res");
1838 dst_var = gfc_conv_scalar_to_descriptor (&argse, res_var, attr);
1839 dst_var = gfc_build_addr_expr (NULL_TREE(tree) __null, dst_var);
1840 }
1841 argse.expr = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
1842 argse.expr = gfc_build_addr_expr (NULL_TREE(tree) __null, argse.expr);
1843 }
1844 else
1845 {
1846 /* If has_vector, pass descriptor for whole array and the
1847 vector bounds separately. */
1848 gfc_array_ref *ar, ar2;
1849 bool has_vector = false;
1850
1851 if (gfc_is_coindexed (expr) && gfc_has_vector_subscript (expr))
1852 {
1853 has_vector = true;
1854 ar = gfc_find_array_ref (expr);
1855 ar2 = *ar;
1856 memset (ar, '\0', sizeof (*ar));
1857 ar->as = ar2.as;
1858 ar->type = AR_FULL;
1859 }
1860 // TODO: Check whether argse.want_coarray = 1 can help with the below.
1861 gfc_conv_expr_descriptor (&argse, array_expr);
1862 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1863 has the wrong type if component references are done. */
1864 gfc_add_modify (&argse.pre, gfc_conv_descriptor_dtype (argse.expr),
1865 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1866 : array_expr->rank,
1867 type));
1868 if (has_vector)
1869 {
1870 vec = conv_caf_vector_subscript (&argse.pre, argse.expr, &ar2);
1871 *ar = ar2;
1872 }
1873
1874 if (lhs == NULL_TREE(tree) __null)
1875 {
1876 /* Create temporary. */
1877 for (int n = 0; n < se->ss->loop->dimen; n++)
1878 if (se->loop->to[n] == NULL_TREE(tree) __null)
1879 {
1880 se->loop->from[n] = gfc_conv_descriptor_lbound_get (argse.expr,
1881 gfc_rank_cst[n]);
1882 se->loop->to[n] = gfc_conv_descriptor_ubound_get (argse.expr,
1883 gfc_rank_cst[n]);
1884 }
1885 gfc_trans_create_temp_array (&argse.pre, &argse.post, se->ss, type,
1886 NULL_TREE(tree) __null, false, true, false,
1887 &array_expr->where);
1888 res_var = se->ss->info->data.array.descriptor;
1889 dst_var = gfc_build_addr_expr (NULL_TREE(tree) __null, res_var);
1890 }
1891 argse.expr = gfc_build_addr_expr (NULL_TREE(tree) __null, argse.expr);
1892 }
1893
1894 kind = build_int_cst (integer_type_nodeinteger_types[itk_int], expr->ts.kind);
1895 if (lhs_kind == NULL_TREE(tree) __null)
1896 lhs_kind = kind;
1897
1898 gfc_add_block_to_block (&se->pre, &argse.pre);
1899 gfc_add_block_to_block (&se->post, &argse.post);
1900
1901 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1902 if (TREE_CODE (TREE_TYPE (caf_decl))((enum tree_code) (((contains_struct_check ((caf_decl), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1902, __FUNCTION__))->typed.type))->base.code)
== REFERENCE_TYPE)
1903 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1904 image_index = gfc_caf_get_image_index (&se->pre, array_expr, caf_decl);
1905 gfc_get_caf_token_offset (se, &token, &offset, caf_decl, argse.expr,
1906 array_expr);
1907
1908 /* No overlap possible as we have generated a temporary. */
1909 if (lhs == NULL_TREE(tree) __null)
1910 may_require_tmp = boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE];
1911
1912 /* It guarantees memory consistency within the same segment. */
1913 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1914 tmp = build5_loc (input_location, ASM_EXPR, void_type_nodeglobal_trees[TI_VOID_TYPE],
1915 gfc_build_string_const (1, ""), NULL_TREE(tree) __null, NULL_TREE(tree) __null,
1916 tree_cons (NULL_TREE(tree) __null, tmp, NULL_TREE(tree) __null), NULL_TREE(tree) __null);
1917 ASM_VOLATILE_P (tmp)((tree_check ((tmp), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1917, __FUNCTION__, (ASM_EXPR)))->base.public_flag)
= 1;
1918 gfc_add_expr_to_block (&se->pre, tmp);
1919
1920 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get, 10,
1921 token, offset, image_index, argse.expr, vec,
1922 dst_var, kind, lhs_kind, may_require_tmp, stat);
1923
1924 gfc_add_expr_to_block (&se->pre, tmp);
1925
1926 if (se->ss)
1927 gfc_advance_se_ss_chain (se);
1928
1929 se->expr = res_var;
1930 if (array_expr->ts.type == BT_CHARACTER)
1931 se->string_length = argse.string_length;
1932}
1933
1934
1935/* Send data to a remote coarray. */
1936
1937static tree
1938conv_caf_send (gfc_code *code) {
1939 gfc_expr *lhs_expr, *rhs_expr, *tmp_stat, *tmp_team;
1940 gfc_se lhs_se, rhs_se;
1941 stmtblock_t block;
1942 tree caf_decl, token, offset, image_index, tmp, lhs_kind, rhs_kind;
1943 tree may_require_tmp, src_stat, dst_stat, dst_team;
1944 tree lhs_type = NULL_TREE(tree) __null;
1945 tree vec = null_pointer_nodeglobal_trees[TI_NULL_POINTER], rhs_vec = null_pointer_nodeglobal_trees[TI_NULL_POINTER];
1946 symbol_attribute lhs_caf_attr, rhs_caf_attr;
1947
1948 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB)((void)(!(global_options.x_flag_coarray == GFC_FCOARRAY_LIB) ?
fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1948, __FUNCTION__), 0 : 0))
;
1949
1950 lhs_expr = code->ext.actual->expr;
1951 rhs_expr = code->ext.actual->next->expr;
1952 may_require_tmp = gfc_check_dependency (lhs_expr, rhs_expr, true) == 0
1953 ? boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE] : boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE];
1954 gfc_init_block (&block);
1955
1956 lhs_caf_attr = gfc_caf_attr (lhs_expr);
1957 rhs_caf_attr = gfc_caf_attr (rhs_expr);
1958 src_stat = dst_stat = null_pointer_nodeglobal_trees[TI_NULL_POINTER];
1959 dst_team = null_pointer_nodeglobal_trees[TI_NULL_POINTER];
1960
1961 /* LHS. */
1962 gfc_init_se (&lhs_se, NULL__null);
1963 if (lhs_expr->rank == 0)
1964 {
1965 if (lhs_expr->ts.type == BT_CHARACTER && lhs_expr->ts.deferred)
1966 {
1967 lhs_se.expr = gfc_get_tree_for_caf_expr (lhs_expr);
1968 lhs_se.expr = gfc_build_addr_expr (NULL_TREE(tree) __null, lhs_se.expr);
1969 }
1970 else
1971 {
1972 symbol_attribute attr;
1973 gfc_clear_attr (&attr);
1974 gfc_conv_expr (&lhs_se, lhs_expr);
1975 lhs_type = TREE_TYPE (lhs_se.expr)((contains_struct_check ((lhs_se.expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 1975, __FUNCTION__))->typed.type)
;
Value stored to 'lhs_type' is never read
1976 lhs_se.expr = gfc_conv_scalar_to_descriptor (&lhs_se, lhs_se.expr,
1977 attr);
1978 lhs_se.expr = gfc_build_addr_expr (NULL_TREE(tree) __null, lhs_se.expr);
1979 }
1980 }
1981 else if ((lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
1982 && lhs_caf_attr.codimension)
1983 {
1984 lhs_se.want_pointer = 1;
1985 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1986 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1987 has the wrong type if component references are done. */
1988 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1989 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1990 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1991 gfc_get_dtype_rank_type (
1992 gfc_has_vector_subscript (lhs_expr)
1993 ? gfc_find_array_ref (lhs_expr)->dimen
1994 : lhs_expr->rank,
1995 lhs_type));
1996 }
1997 else
1998 {
1999 bool has_vector = gfc_has_vector_subscript (lhs_expr);
2000
2001 if (gfc_is_coindexed (lhs_expr) || !has_vector)
2002 {
2003 /* If has_vector, pass descriptor for whole array and the
2004 vector bounds separately. */
2005 gfc_array_ref *ar, ar2;
2006 bool has_tmp_lhs_array = false;
2007 if (has_vector)
2008 {
2009 has_tmp_lhs_array = true;
2010 ar = gfc_find_array_ref (lhs_expr);
2011 ar2 = *ar;
2012 memset (ar, '\0', sizeof (*ar));
2013 ar->as = ar2.as;
2014 ar->type = AR_FULL;
2015 }
2016 lhs_se.want_pointer = 1;
2017 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
2018 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but
2019 that has the wrong type if component references are done. */
2020 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
2021 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
2022 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2023 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2024 : lhs_expr->rank,
2025 lhs_type));
2026 if (has_tmp_lhs_array)
2027 {
2028 vec = conv_caf_vector_subscript (&block, lhs_se.expr, &ar2);
2029 *ar = ar2;
2030 }
2031 }
2032 else
2033 {
2034 /* Special casing for arr1 ([...]) = arr2[...], i.e. caf_get to
2035 indexed array expression. This is rewritten to:
2036
2037 tmp_array = arr2[...]
2038 arr1 ([...]) = tmp_array
2039
2040 because using the standard gfc_conv_expr (lhs_expr) did the
2041 assignment with lhs and rhs exchanged. */
2042
2043 gfc_ss *lss_for_tmparray, *lss_real;
2044 gfc_loopinfo loop;
2045 gfc_se se;
2046 stmtblock_t body;
2047 tree tmparr_desc, src;
2048 tree index = gfc_index_zero_nodegfc_rank_cst[0];
2049 tree stride = gfc_index_zero_nodegfc_rank_cst[0];
2050 int n;
2051
2052 /* Walk both sides of the assignment, once to get the shape of the
2053 temporary array to create right. */
2054 lss_for_tmparray = gfc_walk_expr (lhs_expr);
2055 /* And a second time to be able to create an assignment of the
2056 temporary to the lhs_expr. gfc_trans_create_temp_array replaces
2057 the tree in the descriptor with the one for the temporary
2058 array. */
2059 lss_real = gfc_walk_expr (lhs_expr);
2060 gfc_init_loopinfo (&loop);
2061 gfc_add_ss_to_loop (&loop, lss_for_tmparray);
2062 gfc_add_ss_to_loop (&loop, lss_real);
2063 gfc_conv_ss_startstride (&loop);
2064 gfc_conv_loop_setup (&loop, &lhs_expr->where);
2065 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
2066 gfc_trans_create_temp_array (&lhs_se.pre, &lhs_se.post,
2067 lss_for_tmparray, lhs_type, NULL_TREE(tree) __null,
2068 false, true, false,
2069 &lhs_expr->where);
2070 tmparr_desc = lss_for_tmparray->info->data.array.descriptor;
2071 gfc_start_scalarized_body (&loop, &body);
2072 gfc_init_se (&se, NULL__null);
2073 gfc_copy_loopinfo_to_se (&se, &loop);
2074 se.ss = lss_real;
2075 gfc_conv_expr (&se, lhs_expr);
2076 gfc_add_block_to_block (&body, &se.pre);
2077
2078 /* Walk over all indexes of the loop. */
2079 for (n = loop.dimen - 1; n > 0; --n)
2080 {
2081 tmp = loop.loopvar[n];
2082 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2083 gfc_array_index_type, tmp, loop.from[n]);
2084 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2085 gfc_array_index_type, tmp, index);
2086
2087 stride = fold_build2_loc (input_location, MINUS_EXPR,
2088 gfc_array_index_type,
2089 loop.to[n - 1], loop.from[n - 1]);
2090 stride = fold_build2_loc (input_location, PLUS_EXPR,
2091 gfc_array_index_type,
2092 stride, gfc_index_one_nodegfc_rank_cst[1]);
2093
2094 index = fold_build2_loc (input_location, MULT_EXPR,
2095 gfc_array_index_type, tmp, stride);
2096 }
2097
2098 index = fold_build2_loc (input_location, MINUS_EXPR,
2099 gfc_array_index_type,
2100 index, loop.from[0]);
2101
2102 index = fold_build2_loc (input_location, PLUS_EXPR,
2103 gfc_array_index_type,
2104 loop.loopvar[0], index);
2105
2106 src = build_fold_indirect_ref (gfc_conv_array_data (tmparr_desc))build_fold_indirect_ref_loc (((location_t) 0), gfc_conv_array_data
(tmparr_desc))
;
2107 src = gfc_build_array_ref (src, index, NULL__null);
2108 /* Now create the assignment of lhs_expr = tmp_array. */
2109 gfc_add_modify (&body, se.expr, src);
2110 gfc_add_block_to_block (&body, &se.post);
2111 lhs_se.expr = gfc_build_addr_expr (NULL_TREE(tree) __null, tmparr_desc);
2112 gfc_trans_scalarizing_loops (&loop, &body);
2113 gfc_add_block_to_block (&loop.pre, &loop.post);
2114 gfc_add_expr_to_block (&lhs_se.post, gfc_finish_block (&loop.pre));
2115 gfc_free_ss (lss_for_tmparray);
2116 gfc_free_ss (lss_real);
2117 }
2118 }
2119
2120 lhs_kind = build_int_cst (integer_type_nodeinteger_types[itk_int], lhs_expr->ts.kind);
2121
2122 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
2123 temporary and a loop. */
2124 if (!gfc_is_coindexed (lhs_expr)
2125 && (!lhs_caf_attr.codimension
2126 || !(lhs_expr->rank > 0
2127 && (lhs_caf_attr.allocatable || lhs_caf_attr.pointer))))
2128 {
2129 bool lhs_may_realloc = lhs_expr->rank > 0 && lhs_caf_attr.allocatable;
2130 gcc_assert (gfc_is_coindexed (rhs_expr))((void)(!(gfc_is_coindexed (rhs_expr)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2130, __FUNCTION__), 0 : 0))
;
2131 gfc_init_se (&rhs_se, NULL__null);
2132 if (lhs_expr->rank == 0 && lhs_caf_attr.allocatable)
2133 {
2134 gfc_se scal_se;
2135 gfc_init_se (&scal_se, NULL__null);
2136 scal_se.want_pointer = 1;
2137 gfc_conv_expr (&scal_se, lhs_expr);
2138 /* Ensure scalar on lhs is allocated. */
2139 gfc_add_block_to_block (&block, &scal_se.pre);
2140
2141 gfc_allocate_using_malloc (&scal_se.pre, scal_se.expr,
2142 TYPE_SIZE_UNIT (((tree_class_check ((gfc_typenode_for_spec (&lhs_expr->
ts)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2143, __FUNCTION__))->type_common.size_unit)
2143 gfc_typenode_for_spec (&lhs_expr->ts))((tree_class_check ((gfc_typenode_for_spec (&lhs_expr->
ts)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2143, __FUNCTION__))->type_common.size_unit)
,
2144 NULL_TREE(tree) __null);
2145 tmp = fold_build2 (EQ_EXPR, logical_type_node, scal_se.expr,fold_build2_loc (((location_t) 0), EQ_EXPR, logical_type_node
, scal_se.expr, global_trees[TI_NULL_POINTER] )
2146 null_pointer_node)fold_build2_loc (((location_t) 0), EQ_EXPR, logical_type_node
, scal_se.expr, global_trees[TI_NULL_POINTER] )
;
2147 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_nodeglobal_trees[TI_VOID_TYPE],
2148 tmp, gfc_finish_block (&scal_se.pre),
2149 build_empty_stmt (input_location));
2150 gfc_add_expr_to_block (&block, tmp);
2151 }
2152 else
2153 lhs_may_realloc = lhs_may_realloc
2154 && gfc_full_array_ref_p (lhs_expr->ref, NULL__null);
2155 gfc_add_block_to_block (&block, &lhs_se.pre);
2156 gfc_conv_intrinsic_caf_get (&rhs_se, rhs_expr, lhs_se.expr, lhs_kind,
2157 may_require_tmp, lhs_may_realloc,
2158 &rhs_caf_attr);
2159 gfc_add_block_to_block (&block, &rhs_se.pre);
2160 gfc_add_block_to_block (&block, &rhs_se.post);
2161 gfc_add_block_to_block (&block, &lhs_se.post);
2162 return gfc_finish_block (&block);
2163 }
2164
2165 gfc_add_block_to_block (&block, &lhs_se.pre);
2166
2167 /* Obtain token, offset and image index for the LHS. */
2168 caf_decl = gfc_get_tree_for_caf_expr (lhs_expr);
2169 if (TREE_CODE (TREE_TYPE (caf_decl))((enum tree_code) (((contains_struct_check ((caf_decl), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2169, __FUNCTION__))->typed.type))->base.code)
== REFERENCE_TYPE)
2170 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2171 image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl);
2172 tmp = lhs_se.expr;
2173 if (lhs_caf_attr.alloc_comp)
2174 gfc_get_caf_token_offset (&lhs_se, &token, NULL__null, caf_decl, NULL_TREE(tree) __null,
2175 NULL__null);
2176 else
2177 gfc_get_caf_token_offset (&lhs_se, &token, &offset, caf_decl, tmp,
2178 lhs_expr);
2179 lhs_se.expr = tmp;
2180
2181 /* RHS. */
2182 gfc_init_se (&rhs_se, NULL__null);
2183 if (rhs_expr->expr_type == EXPR_FUNCTION && rhs_expr->value.function.isym
2184 && rhs_expr->value.function.isym->id == GFC_ISYM_CONVERSION)
2185 rhs_expr = rhs_expr->value.function.actual->expr;
2186 if (rhs_expr->rank == 0)
2187 {
2188 symbol_attribute attr;
2189 gfc_clear_attr (&attr);
2190 gfc_conv_expr (&rhs_se, rhs_expr);
2191 rhs_se.expr = gfc_conv_scalar_to_descriptor (&rhs_se, rhs_se.expr, attr);
2192 rhs_se.expr = gfc_build_addr_expr (NULL_TREE(tree) __null, rhs_se.expr);
2193 }
2194 else if ((rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2195 && rhs_caf_attr.codimension)
2196 {
2197 tree tmp2;
2198 rhs_se.want_pointer = 1;
2199 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2200 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2201 has the wrong type if component references are done. */
2202 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2203 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2204 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2205 gfc_get_dtype_rank_type (
2206 gfc_has_vector_subscript (rhs_expr)
2207 ? gfc_find_array_ref (rhs_expr)->dimen
2208 : rhs_expr->rank,
2209 tmp2));
2210 }
2211 else
2212 {
2213 /* If has_vector, pass descriptor for whole array and the
2214 vector bounds separately. */
2215 gfc_array_ref *ar, ar2;
2216 bool has_vector = false;
2217 tree tmp2;
2218
2219 if (gfc_is_coindexed (rhs_expr) && gfc_has_vector_subscript (rhs_expr))
2220 {
2221 has_vector = true;
2222 ar = gfc_find_array_ref (rhs_expr);
2223 ar2 = *ar;
2224 memset (ar, '\0', sizeof (*ar));
2225 ar->as = ar2.as;
2226 ar->type = AR_FULL;
2227 }
2228 rhs_se.want_pointer = 1;
2229 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2230 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2231 has the wrong type if component references are done. */
2232 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2233 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2234 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2235 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2236 : rhs_expr->rank,
2237 tmp2));
2238 if (has_vector)
2239 {
2240 rhs_vec = conv_caf_vector_subscript (&block, rhs_se.expr, &ar2);
2241 *ar = ar2;
2242 }
2243 }
2244
2245 gfc_add_block_to_block (&block, &rhs_se.pre);
2246
2247 rhs_kind = build_int_cst (integer_type_nodeinteger_types[itk_int], rhs_expr->ts.kind);
2248
2249 tmp_stat = gfc_find_stat_co (lhs_expr);
2250
2251 if (tmp_stat)
2252 {
2253 gfc_se stat_se;
2254 gfc_init_se (&stat_se, NULL__null);
2255 gfc_conv_expr_reference (&stat_se, tmp_stat);
2256 dst_stat = stat_se.expr;
2257 gfc_add_block_to_block (&block, &stat_se.pre);
2258 gfc_add_block_to_block (&block, &stat_se.post);
2259 }
2260
2261 tmp_team = gfc_find_team_co (lhs_expr);
2262
2263 if (tmp_team)
2264 {
2265 gfc_se team_se;
2266 gfc_init_se (&team_se, NULL__null);
2267 gfc_conv_expr_reference (&team_se, tmp_team);
2268 dst_team = team_se.expr;
2269 gfc_add_block_to_block (&block, &team_se.pre);
2270 gfc_add_block_to_block (&block, &team_se.post);
2271 }
2272
2273 if (!gfc_is_coindexed (rhs_expr))
2274 {
2275 if (lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
2276 {
2277 tree reference, dst_realloc;
2278 reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2279 dst_realloc = lhs_caf_attr.allocatable ? boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]
2280 : boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE];
2281 tmp = build_call_expr_loc (input_location,
2282 gfor_fndecl_caf_send_by_ref,
2283 10, token, image_index, rhs_se.expr,
2284 reference, lhs_kind, rhs_kind,
2285 may_require_tmp, dst_realloc, src_stat,
2286 build_int_cst (integer_type_nodeinteger_types[itk_int],
2287 lhs_expr->ts.type));
2288 }
2289 else
2290 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 11,
2291 token, offset, image_index, lhs_se.expr, vec,
2292 rhs_se.expr, lhs_kind, rhs_kind,
2293 may_require_tmp, src_stat, dst_team);
2294 }
2295 else
2296 {
2297 tree rhs_token, rhs_offset, rhs_image_index;
2298
2299 /* It guarantees memory consistency within the same segment. */
2300 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2301 tmp = build5_loc (input_location, ASM_EXPR, void_type_nodeglobal_trees[TI_VOID_TYPE],
2302 gfc_build_string_const (1, ""), NULL_TREE(tree) __null, NULL_TREE(tree) __null,
2303 tree_cons (NULL_TREE(tree) __null, tmp, NULL_TREE(tree) __null), NULL_TREE(tree) __null);
2304 ASM_VOLATILE_P (tmp)((tree_check ((tmp), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2304, __FUNCTION__, (ASM_EXPR)))->base.public_flag)
= 1;
2305 gfc_add_expr_to_block (&block, tmp);
2306
2307 caf_decl = gfc_get_tree_for_caf_expr (rhs_expr);
2308 if (TREE_CODE (TREE_TYPE (caf_decl))((enum tree_code) (((contains_struct_check ((caf_decl), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2308, __FUNCTION__))->typed.type))->base.code)
== REFERENCE_TYPE)
2309 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2310 rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl);
2311 tmp = rhs_se.expr;
2312 if (rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2313 {
2314 tmp_stat = gfc_find_stat_co (lhs_expr);
2315
2316 if (tmp_stat)
2317 {
2318 gfc_se stat_se;
2319 gfc_init_se (&stat_se, NULL__null);
2320 gfc_conv_expr_reference (&stat_se, tmp_stat);
2321 src_stat = stat_se.expr;
2322 gfc_add_block_to_block (&block, &stat_se.pre);
2323 gfc_add_block_to_block (&block, &stat_se.post);
2324 }
2325
2326 gfc_get_caf_token_offset (&rhs_se, &rhs_token, NULL__null, caf_decl,
2327 NULL_TREE(tree) __null, NULL__null);
2328 tree lhs_reference, rhs_reference;
2329 lhs_reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2330 rhs_reference = conv_expr_ref_to_caf_ref (&block, rhs_expr);
2331 tmp = build_call_expr_loc (input_location,
2332 gfor_fndecl_caf_sendget_by_ref, 13,
2333 token, image_index, lhs_reference,
2334 rhs_token, rhs_image_index, rhs_reference,
2335 lhs_kind, rhs_kind, may_require_tmp,
2336 dst_stat, src_stat,
2337 build_int_cst (integer_type_nodeinteger_types[itk_int],
2338 lhs_expr->ts.type),
2339 build_int_cst (integer_type_nodeinteger_types[itk_int],
2340 rhs_expr->ts.type));
2341 }
2342 else
2343 {
2344 gfc_get_caf_token_offset (&rhs_se, &rhs_token, &rhs_offset, caf_decl,
2345 tmp, rhs_expr);
2346 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget,
2347 14, token, offset, image_index,
2348 lhs_se.expr, vec, rhs_token, rhs_offset,
2349 rhs_image_index, tmp, rhs_vec, lhs_kind,
2350 rhs_kind, may_require_tmp, src_stat);
2351 }
2352 }
2353 gfc_add_expr_to_block (&block, tmp);
2354 gfc_add_block_to_block (&block, &lhs_se.post);
2355 gfc_add_block_to_block (&block, &rhs_se.post);
2356
2357 /* It guarantees memory consistency within the same segment. */
2358 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2359 tmp = build5_loc (input_location, ASM_EXPR, void_type_nodeglobal_trees[TI_VOID_TYPE],
2360 gfc_build_string_const (1, ""), NULL_TREE(tree) __null, NULL_TREE(tree) __null,
2361 tree_cons (NULL_TREE(tree) __null, tmp, NULL_TREE(tree) __null), NULL_TREE(tree) __null);
2362 ASM_VOLATILE_P (tmp)((tree_check ((tmp), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2362, __FUNCTION__, (ASM_EXPR)))->base.public_flag)
= 1;
2363 gfc_add_expr_to_block (&block, tmp);
2364
2365 return gfc_finish_block (&block);
2366}
2367
2368
2369static void
2370trans_this_image (gfc_se * se, gfc_expr *expr)
2371{
2372 stmtblock_t loop;
2373 tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
2374 lbound, ubound, extent, ml;
2375 gfc_se argse;
2376 int rank, corank;
2377 gfc_expr *distance = expr->value.function.actual->next->next->expr;
2378
2379 if (expr->value.function.actual->expr
2380 && !gfc_is_coarray (expr->value.function.actual->expr))
2381 distance = expr->value.function.actual->expr;
2382
2383 /* The case -fcoarray=single is handled elsewhere. */
2384 gcc_assert (flag_coarray != GFC_FCOARRAY_SINGLE)((void)(!(global_options.x_flag_coarray != GFC_FCOARRAY_SINGLE
) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2384, __FUNCTION__), 0 : 0))
;
2385
2386 /* Argument-free version: THIS_IMAGE(). */
2387 if (distance || expr->value.function.actual->expr == NULL__null)
2388 {
2389 if (distance)
2390 {
2391 gfc_init_se (&argse, NULL__null);
2392 gfc_conv_expr_val (&argse, distance);
2393 gfc_add_block_to_block (&se->pre, &argse.pre);
2394 gfc_add_block_to_block (&se->post, &argse.post);
2395 tmp = fold_convert (integer_type_node, argse.expr)fold_convert_loc (((location_t) 0), integer_types[itk_int], argse
.expr)
;
2396 }
2397 else
2398 tmp = integer_zero_nodeglobal_trees[TI_INTEGER_ZERO];
2399 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2400 tmp);
2401 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),fold_convert_loc (((location_t) 0), gfc_get_int_type (gfc_default_integer_kind
), tmp)
2402 tmp)fold_convert_loc (((location_t) 0), gfc_get_int_type (gfc_default_integer_kind
), tmp)
;
2403 return;
2404 }
2405
2406 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
2407
2408 type = gfc_get_int_type (gfc_default_integer_kind);
2409 corank = gfc_get_corank (expr->value.function.actual->expr);
2410 rank = expr->value.function.actual->expr->rank;
2411
2412 /* Obtain the descriptor of the COARRAY. */
2413 gfc_init_se (&argse, NULL__null);
2414 argse.want_coarray = 1;
2415 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2416 gfc_add_block_to_block (&se->pre, &argse.pre);
2417 gfc_add_block_to_block (&se->post, &argse.post);
2418 desc = argse.expr;
2419
2420 if (se->ss)
2421 {
2422 /* Create an implicit second parameter from the loop variable. */
2423 gcc_assert (!expr->value.function.actual->next->expr)((void)(!(!expr->value.function.actual->next->expr) ?
fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2423, __FUNCTION__), 0 : 0))
;
2424 gcc_assert (corank > 0)((void)(!(corank > 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2424, __FUNCTION__), 0 : 0))
;
2425 gcc_assert (se->loop->dimen == 1)((void)(!(se->loop->dimen == 1) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2425, __FUNCTION__), 0 : 0))
;
2426 gcc_assert (se->ss->info->expr == expr)((void)(!(se->ss->info->expr == expr) ? fancy_abort (
"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2426, __FUNCTION__), 0 : 0))
;
2427
2428 dim_arg = se->loop->loopvar[0];
2429 dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
2430 gfc_array_index_type, dim_arg,
2431 build_int_cst (TREE_TYPE (dim_arg)((contains_struct_check ((dim_arg), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2431, __FUNCTION__))->typed.type)
, 1));
2432 gfc_advance_se_ss_chain (se);
2433 }
2434 else
2435 {
2436 /* Use the passed DIM= argument. */
2437 gcc_assert (expr->value.function.actual->next->expr)((void)(!(expr->value.function.actual->next->expr) ?
fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2437, __FUNCTION__), 0 : 0))
;
2438 gfc_init_se (&argse, NULL__null);
2439 gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
2440 gfc_array_index_type);
2441 gfc_add_block_to_block (&se->pre, &argse.pre);
2442 dim_arg = argse.expr;
2443
2444 if (INTEGER_CST_P (dim_arg)(((enum tree_code) (dim_arg)->base.code) == INTEGER_CST))
2445 {
2446 if (wi::ltu_p (wi::to_wide (dim_arg), 1)
2447 || wi::gtu_p (wi::to_wide (dim_arg),
2448 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))(((tree_class_check ((((contains_struct_check ((desc), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2448, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2448, __FUNCTION__))->type_with_lang_specific.lang_specific
)->corank)
))
2449 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2450 "dimension index", expr->value.function.isym->name,
2451 &expr->where);
2452 }
2453 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS(1<<0))
2454 {
2455 dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
2456 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2457 dim_arg,
2458 build_int_cst (TREE_TYPE (dim_arg)((contains_struct_check ((dim_arg), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2458, __FUNCTION__))->typed.type)
, 1));
2459 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))(((tree_class_check ((((contains_struct_check ((desc), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2459, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2459, __FUNCTION__))->type_with_lang_specific.lang_specific
)->corank)
];
2460 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2461 dim_arg, tmp);
2462 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2463 logical_type_node, cond, tmp);
2464 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2465 gfc_msg_fault);
2466 }
2467 }
2468
2469 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
2470 one always has a dim_arg argument.
2471
2472 m = this_image() - 1
2473 if (corank == 1)
2474 {
2475 sub(1) = m + lcobound(corank)
2476 return;
2477 }
2478 i = rank
2479 min_var = min (rank + corank - 2, rank + dim_arg - 1)
2480 for (;;)
2481 {
2482 extent = gfc_extent(i)
2483 ml = m
2484 m = m/extent
2485 if (i >= min_var)
2486 goto exit_label
2487 i++
2488 }
2489 exit_label:
2490 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
2491 : m + lcobound(corank)
2492 */
2493
2494 /* this_image () - 1. */
2495 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2496 integer_zero_nodeglobal_trees[TI_INTEGER_ZERO]);
2497 tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
2498 fold_convert (type, tmp)fold_convert_loc (((location_t) 0), type, tmp), build_int_cst (type, 1));
2499 if (corank == 1)
2500 {
2501 /* sub(1) = m + lcobound(corank). */
2502 lbound = gfc_conv_descriptor_lbound_get (desc,
2503 build_int_cst (TREE_TYPE (gfc_array_index_type)((contains_struct_check ((gfc_array_index_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2503, __FUNCTION__))->typed.type)
,
2504 corank+rank-1));
2505 lbound = fold_convert (type, lbound)fold_convert_loc (((location_t) 0), type, lbound);
2506 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2507
2508 se->expr = tmp;
2509 return;
2510 }
2511
2512 m = gfc_create_var (type, NULL__null);
2513 ml = gfc_create_var (type, NULL__null);
2514 loop_var = gfc_create_var (integer_type_nodeinteger_types[itk_int], NULL__null);
2515 min_var = gfc_create_var (integer_type_nodeinteger_types[itk_int], NULL__null);
2516
2517 /* m = this_image () - 1. */
2518 gfc_add_modify (&se->pre, m, tmp);
2519
2520 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
2521 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_nodeinteger_types[itk_int],
2522 fold_convert (integer_type_node, dim_arg)fold_convert_loc (((location_t) 0), integer_types[itk_int], dim_arg
)
,
2523 build_int_cst (integer_type_nodeinteger_types[itk_int], rank - 1));
2524 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_nodeinteger_types[itk_int],
2525 build_int_cst (integer_type_nodeinteger_types[itk_int], rank + corank - 2),
2526 tmp);
2527 gfc_add_modify (&se->pre, min_var, tmp);
2528
2529 /* i = rank. */
2530 tmp = build_int_cst (integer_type_nodeinteger_types[itk_int], rank);
2531 gfc_add_modify (&se->pre, loop_var, tmp);
2532
2533 exit_label = gfc_build_label_decl (NULL_TREE(tree) __null);
2534 TREE_USED (exit_label)((exit_label)->base.used_flag) = 1;
2535
2536 /* Loop body. */
2537 gfc_init_block (&loop);
2538
2539 /* ml = m. */
2540 gfc_add_modify (&loop, ml, m);
2541
2542 /* extent = ... */
2543 lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
2544 ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
2545 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL__null);
2546 extent = fold_convert (type, extent)fold_convert_loc (((location_t) 0), type, extent);
2547
2548 /* m = m/extent. */
2549 gfc_add_modify (&loop, m,
2550 fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
2551 m, extent));
2552
2553 /* Exit condition: if (i >= min_var) goto exit_label. */
2554 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, loop_var,
2555 min_var);
2556 tmp = build1_v (GOTO_EXPR, exit_label)fold_build1_loc (input_location, GOTO_EXPR, global_trees[TI_VOID_TYPE
], exit_label)
;
2557 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_nodeglobal_trees[TI_VOID_TYPE], cond, tmp,
2558 build_empty_stmt (input_location));
2559 gfc_add_expr_to_block (&loop, tmp);
2560
2561 /* Increment loop variable: i++. */
2562 gfc_add_modify (&loop, loop_var,
2563 fold_build2_loc (input_location, PLUS_EXPR, integer_type_nodeinteger_types[itk_int],
2564 loop_var,
2565 build_int_cst (integer_type_nodeinteger_types[itk_int], 1)));
2566
2567 /* Making the loop... actually loop! */
2568 tmp = gfc_finish_block (&loop);
2569 tmp = build1_v (LOOP_EXPR, tmp)fold_build1_loc (input_location, LOOP_EXPR, global_trees[TI_VOID_TYPE
], tmp)
;
2570 gfc_add_expr_to_block (&se->pre, tmp);
2571
2572 /* The exit label. */
2573 tmp = build1_v (LABEL_EXPR, exit_label)fold_build1_loc (input_location, LABEL_EXPR, global_trees[TI_VOID_TYPE
], exit_label)
;
2574 gfc_add_expr_to_block (&se->pre, tmp);
2575
2576 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
2577 : m + lcobound(corank) */
2578
2579 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, dim_arg,
2580 build_int_cst (TREE_TYPE (dim_arg)((contains_struct_check ((dim_arg), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2580, __FUNCTION__))->typed.type)
, corank));
2581
2582 lbound = gfc_conv_descriptor_lbound_get (desc,
2583 fold_build2_loc (input_location, PLUS_EXPR,
2584 gfc_array_index_type, dim_arg,
2585 build_int_cst (TREE_TYPE (dim_arg)((contains_struct_check ((dim_arg), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2585, __FUNCTION__))->typed.type)
, rank-1)));
2586 lbound = fold_convert (type, lbound)fold_convert_loc (((location_t) 0), type, lbound);
2587
2588 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
2589 fold_build2_loc (input_location, MULT_EXPR, type,
2590 m, extent));
2591 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2592
2593 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
2594 fold_build2_loc (input_location, PLUS_EXPR, type,
2595 m, lbound));
2596}
2597
2598
2599/* Convert a call to image_status. */
2600
2601static void
2602conv_intrinsic_image_status (gfc_se *se, gfc_expr *expr)
2603{
2604 unsigned int num_args;
2605 tree *args, tmp;
2606
2607 num_args = gfc_intrinsic_argument_list_length (expr);
2608 args = XALLOCAVEC (tree, num_args)((tree *) __builtin_alloca(sizeof (tree) * (num_args)));
2609 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2610 /* In args[0] the number of the image the status is desired for has to be
2611 given. */
2612
2613 if (flag_coarrayglobal_options.x_flag_coarray == GFC_FCOARRAY_SINGLE)
2614 {
2615 tree arg;
2616 arg = gfc_evaluate_now (args[0], &se->pre);
2617 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2618 fold_convert (integer_type_node, arg)fold_convert_loc (((location_t) 0), integer_types[itk_int], arg
)
,
2619 integer_one_nodeglobal_trees[TI_INTEGER_ONE]);
2620 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_nodeinteger_types[itk_int],
2621 tmp, integer_zero_nodeglobal_trees[TI_INTEGER_ZERO],
2622 build_int_cst (integer_type_nodeinteger_types[itk_int],
2623 GFC_STAT_STOPPED_IMAGE));
2624 }
2625 else if (flag_coarrayglobal_options.x_flag_coarray == GFC_FCOARRAY_LIB)
2626 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_image_status, 2,
2627 args[0], build_int_cst (integer_type_nodeinteger_types[itk_int], -1));
2628 else
2629 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2629, __FUNCTION__))
;
2630
2631 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp)fold_convert_loc (((location_t) 0), gfc_get_int_type (gfc_default_integer_kind
), tmp)
;
2632}
2633
2634static void
2635conv_intrinsic_team_number (gfc_se *se, gfc_expr *expr)
2636{
2637 unsigned int num_args;
2638
2639 tree *args, tmp;
2640
2641 num_args = gfc_intrinsic_argument_list_length (expr);
2642 args = XALLOCAVEC (tree, num_args)((tree *) __builtin_alloca(sizeof (tree) * (num_args)));
2643 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2644
2645 if (flag_coarrayglobal_options.x_flag_coarray ==
2646 GFC_FCOARRAY_SINGLE && expr->value.function.actual->expr)
2647 {
2648 tree arg;
2649
2650 arg = gfc_evaluate_now (args[0], &se->pre);
2651 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2652 fold_convert (integer_type_node, arg)fold_convert_loc (((location_t) 0), integer_types[itk_int], arg
)
,
2653 integer_one_nodeglobal_trees[TI_INTEGER_ONE]);
2654 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_nodeinteger_types[itk_int],
2655 tmp, integer_zero_nodeglobal_trees[TI_INTEGER_ZERO],
2656 build_int_cst (integer_type_nodeinteger_types[itk_int],
2657 GFC_STAT_STOPPED_IMAGE));
2658 }
2659 else if (flag_coarrayglobal_options.x_flag_coarray == GFC_FCOARRAY_SINGLE)
2660 {
2661 // the value -1 represents that no team has been created yet
2662 tmp = build_int_cst (integer_type_nodeinteger_types[itk_int], -1);
2663 }
2664 else if (flag_coarrayglobal_options.x_flag_coarray == GFC_FCOARRAY_LIB && expr->value.function.actual->expr)
2665 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2666 args[0], build_int_cst (integer_type_nodeinteger_types[itk_int], -1));
2667 else if (flag_coarrayglobal_options.x_flag_coarray == GFC_FCOARRAY_LIB)
2668 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2669 integer_zero_nodeglobal_trees[TI_INTEGER_ZERO], build_int_cst (integer_type_nodeinteger_types[itk_int], -1));
2670 else
2671 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2671, __FUNCTION__))
;
2672
2673 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp)fold_convert_loc (((location_t) 0), gfc_get_int_type (gfc_default_integer_kind
), tmp)
;
2674}
2675
2676
2677static void
2678trans_image_index (gfc_se * se, gfc_expr *expr)
2679{
2680 tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
2681 tmp, invalid_bound;
2682 gfc_se argse, subse;
2683 int rank, corank, codim;
2684
2685 type = gfc_get_int_type (gfc_default_integer_kind);
2686 corank = gfc_get_corank (expr->value.function.actual->expr);
2687 rank = expr->value.function.actual->expr->rank;
2688
2689 /* Obtain the descriptor of the COARRAY. */
2690 gfc_init_se (&argse, NULL__null);
2691 argse.want_coarray = 1;
2692 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2693 gfc_add_block_to_block (&se->pre, &argse.pre);
2694 gfc_add_block_to_block (&se->post, &argse.post);
2695 desc = argse.expr;
2696
2697 /* Obtain a handle to the SUB argument. */
2698 gfc_init_se (&subse, NULL__null);
2699 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
2700 gfc_add_block_to_block (&se->pre, &subse.pre);
2701 gfc_add_block_to_block (&se->post, &subse.post);
2702 subdesc = build_fold_indirect_ref_loc (input_location,
2703 gfc_conv_descriptor_data_get (subse.expr));
2704
2705 /* Fortran 2008 does not require that the values remain in the cobounds,
2706 thus we need explicitly check this - and return 0 if they are exceeded. */
2707
2708 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2709 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL__null);
2710 invalid_bound = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2711 fold_convert (gfc_array_index_type, tmp)fold_convert_loc (((location_t) 0), gfc_array_index_type, tmp
)
,
2712 lbound);
2713
2714 for (codim = corank + rank - 2; codim >= rank; codim--)
2715 {
2716 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2717 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2718 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL__null);
2719 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2720 fold_convert (gfc_array_index_type, tmp)fold_convert_loc (((location_t) 0), gfc_array_index_type, tmp
)
,
2721 lbound);
2722 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2723 logical_type_node, invalid_bound, cond);
2724 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2725 fold_convert (gfc_array_index_type, tmp)fold_convert_loc (((location_t) 0), gfc_array_index_type, tmp
)
,
2726 ubound);
2727 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2728 logical_type_node, invalid_bound, cond);
2729 }
2730
2731 invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
2732
2733 /* See Fortran 2008, C.10 for the following algorithm. */
2734
2735 /* coindex = sub(corank) - lcobound(n). */
2736 coindex = fold_convert (gfc_array_index_type,fold_convert_loc (((location_t) 0), gfc_array_index_type, gfc_build_array_ref
(subdesc, gfc_rank_cst[corank-1], __null))
2737 gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],fold_convert_loc (((location_t) 0), gfc_array_index_type, gfc_build_array_ref
(subdesc, gfc_rank_cst[corank-1], __null))
2738 NULL))fold_convert_loc (((location_t) 0), gfc_array_index_type, gfc_build_array_ref
(subdesc, gfc_rank_cst[corank-1], __null))
;
2739 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2740 coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2741 fold_convert (gfc_array_index_type, coindex)fold_convert_loc (((location_t) 0), gfc_array_index_type, coindex
)
,
2742 lbound);
2743
2744 for (codim = corank + rank - 2; codim >= rank; codim--)
2745 {
2746 tree extent, ubound;
2747
2748 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
2749 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2750 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2751 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL__null);
2752
2753 /* coindex *= extent. */
2754 coindex = fold_build2_loc (input_location, MULT_EXPR,
2755 gfc_array_index_type, coindex, extent);
2756
2757 /* coindex += sub(codim). */
2758 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL__null);
2759 coindex = fold_build2_loc (input_location, PLUS_EXPR,
2760 gfc_array_index_type, coindex,
2761 fold_convert (gfc_array_index_type, tmp)fold_convert_loc (((location_t) 0), gfc_array_index_type, tmp
)
);
2762
2763 /* coindex -= lbound(codim). */
2764 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2765 coindex = fold_build2_loc (input_location, MINUS_EXPR,
2766 gfc_array_index_type, coindex, lbound);
2767 }
2768
2769 coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
2770 fold_convert(type, coindex)fold_convert_loc (((location_t) 0), type, coindex),
2771 build_int_cst (type, 1));
2772
2773 /* Return 0 if "coindex" exceeds num_images(). */
2774
2775 if (flag_coarrayglobal_options.x_flag_coarray == GFC_FCOARRAY_SINGLE)
2776 num_images = build_int_cst (type, 1);
2777 else
2778 {
2779 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2780 integer_zero_nodeglobal_trees[TI_INTEGER_ZERO],
2781 build_int_cst (integer_type_nodeinteger_types[itk_int], -1));
2782 num_images = fold_convert (type, tmp)fold_convert_loc (((location_t) 0), type, tmp);
2783 }
2784
2785 tmp = gfc_create_var (type, NULL__null);
2786 gfc_add_modify (&se->pre, tmp, coindex);
2787
2788 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, tmp,
2789 num_images);
2790 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, logical_type_node,
2791 cond,
2792 fold_convert (logical_type_node, invalid_bound)fold_convert_loc (((location_t) 0), logical_type_node, invalid_bound
)
);
2793 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
2794 build_int_cst (type, 0), tmp);
2795}
2796
2797static void
2798trans_num_images (gfc_se * se, gfc_expr *expr)
2799{
2800 tree tmp, distance, failed;
2801 gfc_se argse;
2802
2803 if (expr->value.function.actual->expr)
2804 {
2805 gfc_init_se (&argse, NULL__null);
2806 gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
2807 gfc_add_block_to_block (&se->pre, &argse.pre);
2808 gfc_add_block_to_block (&se->post, &argse.post);
2809 distance = fold_convert (integer_type_node, argse.expr)fold_convert_loc (((location_t) 0), integer_types[itk_int], argse
.expr)
;
2810 }
2811 else
2812 distance = integer_zero_nodeglobal_trees[TI_INTEGER_ZERO];
2813
2814 if (expr->value.function.actual->next->expr)
2815 {
2816 gfc_init_se (&argse, NULL__null);
2817 gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
2818 gfc_add_block_to_block (&se->pre, &argse.pre);
2819 gfc_add_block_to_block (&se->post, &argse.post);
2820 failed = fold_convert (integer_type_node, argse.expr)fold_convert_loc (((location_t) 0), integer_types[itk_int], argse
.expr)
;
2821 }
2822 else
2823 failed = build_int_cst (integer_type_nodeinteger_types[itk_int], -1);
2824 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2825 distance, failed);
2826 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp)fold_convert_loc (((location_t) 0), gfc_get_int_type (gfc_default_integer_kind
), tmp)
;
2827}
2828
2829
2830static void
2831gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
2832{
2833 gfc_se argse;
2834
2835 gfc_init_se (&argse, NULL__null);
2836 argse.data_not_needed = 1;
2837 argse.descriptor_only = 1;
2838
2839 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2840 gfc_add_block_to_block (&se->pre, &argse.pre);
2841 gfc_add_block_to_block (&se->post, &argse.post);
2842
2843 se->expr = gfc_conv_descriptor_rank (argse.expr);
2844 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),fold_convert_loc (((location_t) 0), gfc_get_int_type (gfc_default_integer_kind
), se->expr)
2845 se->expr)fold_convert_loc (((location_t) 0), gfc_get_int_type (gfc_default_integer_kind
), se->expr)
;
2846}
2847
2848
2849static void
2850gfc_conv_intrinsic_is_contiguous (gfc_se * se, gfc_expr * expr)
2851{
2852 gfc_expr *arg;
2853 arg = expr->value.function.actual->expr;
2854 gfc_conv_is_contiguous_expr (se, arg);
2855 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr)fold_convert_loc (((location_t) 0), gfc_typenode_for_spec (&
expr->ts), se->expr)
;
2856}
2857
2858/* This function does the work for gfc_conv_intrinsic_is_contiguous,
2859 plus it can be called directly. */
2860
2861void
2862gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg)
2863{
2864 gfc_ss *ss;
2865 gfc_se argse;
2866 tree desc, tmp, stride, extent, cond;
2867 int i;
2868 tree fncall0;
2869 gfc_array_spec *as;
2870
2871 if (arg->ts.type == BT_CLASS)
2872 gfc_add_class_array_ref (arg);
2873
2874 ss = gfc_walk_expr (arg);
2875 gcc_assert (ss != gfc_ss_terminator)((void)(!(ss != gfc_ss_terminator) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2875, __FUNCTION__), 0 : 0))
;
2876 gfc_init_se (&argse, NULL__null);
2877 argse.data_not_needed = 1;
2878 gfc_conv_expr_descriptor (&argse, arg);
2879
2880 as = gfc_get_full_arrayspec_from_expr (arg);
2881
2882 /* Create: stride[0] == 1 && stride[1] == extend[0]*stride[0] && ...
2883 Note in addition that zero-sized arrays don't count as contiguous. */
2884
2885 if (as && as->type == AS_ASSUMED_RANK)
2886 {
2887 /* Build the call to is_contiguous0. */
2888 argse.want_pointer = 1;
2889 gfc_conv_expr_descriptor (&argse, arg);
2890 gfc_add_block_to_block (&se->pre, &argse.pre);
2891 gfc_add_block_to_block (&se->post, &argse.post);
2892 desc = gfc_evaluate_now (argse.expr, &se->pre);
2893 fncall0 = build_call_expr_loc (input_location,
2894 gfor_fndecl_is_contiguous0, 1, desc);
2895 se->expr = fncall0;
2896 se->expr = convert (logical_type_node, se->expr);
2897 }
2898 else
2899 {
2900 gfc_add_block_to_block (&se->pre, &argse.pre);
2901 gfc_add_block_to_block (&se->post, &argse.post);
2902 desc = gfc_evaluate_now (argse.expr, &se->pre);
2903
2904 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[0]);
2905 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE],
2906 stride, build_int_cst (TREE_TYPE (stride)((contains_struct_check ((stride), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2906, __FUNCTION__))->typed.type)
, 1));
2907
2908 for (i = 0; i < arg->rank - 1; i++)
2909 {
2910 tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
2911 extent = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
2912 extent = fold_build2_loc (input_location, MINUS_EXPR,
2913 gfc_array_index_type, extent, tmp);
2914 extent = fold_build2_loc (input_location, PLUS_EXPR,
2915 gfc_array_index_type, extent,
2916 gfc_index_one_nodegfc_rank_cst[1]);
2917 tmp = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[i]);
2918 tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp)((contains_struct_check ((tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2918, __FUNCTION__))->typed.type)
,
2919 tmp, extent);
2920 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[i+1]);
2921 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE],
2922 stride, tmp);
2923 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2924 boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE], cond, tmp);
2925 }
2926 se->expr = cond;
2927 }
2928}
2929
2930
2931/* Evaluate a single upper or lower bound. */
2932/* TODO: bound intrinsic generates way too much unnecessary code. */
2933
2934static void
2935gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, enum gfc_isym_id op)
2936{
2937 gfc_actual_arglist *arg;
2938 gfc_actual_arglist *arg2;
2939 tree desc;
2940 tree type;
2941 tree bound;
2942 tree tmp;
2943 tree cond, cond1;
2944 tree ubound;
2945 tree lbound;
2946 tree size;
2947 gfc_se argse;
2948 gfc_array_spec * as;
2949 bool assumed_rank_lb_one;
2950
2951 arg = expr->value.function.actual;
2952 arg2 = arg->next;
2953
2954 if (se->ss)
2955 {
2956 /* Create an implicit second parameter from the loop variable. */
2957 gcc_assert (!arg2->expr || op == GFC_ISYM_SHAPE)((void)(!(!arg2->expr || op == GFC_ISYM_SHAPE) ? fancy_abort
("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2957, __FUNCTION__), 0 : 0))
;
2958 gcc_assert (se->loop->dimen == 1)((void)(!(se->loop->dimen == 1) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2958, __FUNCTION__), 0 : 0))
;
2959 gcc_assert (se->ss->info->expr == expr)((void)(!(se->ss->info->expr == expr) ? fancy_abort (
"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2959, __FUNCTION__), 0 : 0))
;
2960 gfc_advance_se_ss_chain (se);
2961 bound = se->loop->loopvar[0];
2962 bound = fold_build2_loc (input_location, MINUS_EXPR,
2963 gfc_array_index_type, bound,
2964 se->loop->from[0]);
2965 }
2966 else
2967 {
2968 /* use the passed argument. */
2969 gcc_assert (arg2->expr)((void)(!(arg2->expr) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2969, __FUNCTION__), 0 : 0))
;
2970 gfc_init_se (&argse, NULL__null);
2971 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
2972 gfc_add_block_to_block (&se->pre, &argse.pre);
2973 bound = argse.expr;
2974 /* Convert from one based to zero based. */
2975 bound = fold_build2_loc (input_location, MINUS_EXPR,
2976 gfc_array_index_type, bound,
2977 gfc_index_one_nodegfc_rank_cst[1]);
2978 }
2979
2980 /* TODO: don't re-evaluate the descriptor on each iteration. */
2981 /* Get a descriptor for the first parameter. */
2982 gfc_init_se (&argse, NULL__null);
2983 gfc_conv_expr_descriptor (&argse, arg->expr);
2984 gfc_add_block_to_block (&se->pre, &argse.pre);
2985 gfc_add_block_to_block (&se->post, &argse.post);
2986
2987 desc = argse.expr;
2988
2989 as = gfc_get_full_arrayspec_from_expr (arg->expr);
2990
2991 if (INTEGER_CST_P (bound)(((enum tree_code) (bound)->base.code) == INTEGER_CST))
2992 {
2993 gcc_assert (op != GFC_ISYM_SHAPE)((void)(!(op != GFC_ISYM_SHAPE) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2993, __FUNCTION__), 0 : 0))
;
2994 if (((!as || as->type != AS_ASSUMED_RANK)
2995 && wi::geu_p (wi::to_wide (bound),
2996 GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))(((tree_class_check ((((contains_struct_check ((desc), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2996, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 2996, __FUNCTION__))->type_with_lang_specific.lang_specific
)->rank)
))
2997 || wi::gtu_p (wi::to_wide (bound), GFC_MAX_DIMENSIONS15))
2998 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2999 "dimension index",
3000 (op == GFC_ISYM_UBOUND) ? "UBOUND" : "LBOUND",
3001 &expr->where);
3002 }
3003
3004 if (!INTEGER_CST_P (bound)(((enum tree_code) (bound)->base.code) == INTEGER_CST) || (as && as->type == AS_ASSUMED_RANK))
3005 {
3006 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS(1<<0))
3007 {
3008 bound = gfc_evaluate_now (bound, &se->pre);
3009 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3010 bound, build_int_cst (TREE_TYPE (bound)((contains_struct_check ((bound), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3010, __FUNCTION__))->typed.type)
, 0));
3011 if (as && as->type == AS_ASSUMED_RANK)
3012 tmp = gfc_conv_descriptor_rank (desc);
3013 else
3014 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))(((tree_class_check ((((contains_struct_check ((desc), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3014, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3014, __FUNCTION__))->type_with_lang_specific.lang_specific
)->rank)
];
3015 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
3016 bound, fold_convert(TREE_TYPE (bound), tmp)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(bound), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3016, __FUNCTION__))->typed.type), tmp)
);
3017 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
3018 logical_type_node, cond, tmp);
3019 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
3020 gfc_msg_fault);
3021 }
3022 }
3023
3024 /* Take care of the lbound shift for assumed-rank arrays that are
3025 nonallocatable and nonpointers. Those have a lbound of 1. */
3026 assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
3027 && ((arg->expr->ts.type != BT_CLASS
3028 && !arg->expr->symtree->n.sym->attr.allocatable
3029 && !arg->expr->symtree->n.sym->attr.pointer)
3030 || (arg->expr->ts.type == BT_CLASS
3031 && !CLASS_DATA (arg->expr)arg->expr->ts.u.derived->components->attr.allocatable
3032 && !CLASS_DATA (arg->expr)arg->expr->ts.u.derived->components->attr.class_pointer));
3033
3034 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
3035 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
3036 size = fold_build2_loc (input_location, MINUS_EXPR,
3037 gfc_array_index_type, ubound, lbound);
3038 size = fold_build2_loc (input_location, PLUS_EXPR,
3039 gfc_array_index_type, size, gfc_index_one_nodegfc_rank_cst[1]);
3040
3041 /* 13.14.53: Result value for LBOUND
3042
3043 Case (i): For an array section or for an array expression other than a
3044 whole array or array structure component, LBOUND(ARRAY, DIM)
3045 has the value 1. For a whole array or array structure
3046 component, LBOUND(ARRAY, DIM) has the value:
3047 (a) equal to the lower bound for subscript DIM of ARRAY if
3048 dimension DIM of ARRAY does not have extent zero
3049 or if ARRAY is an assumed-size array of rank DIM,
3050 or (b) 1 otherwise.
3051
3052 13.14.113: Result value for UBOUND
3053
3054 Case (i): For an array section or for an array expression other than a
3055 whole array or array structure component, UBOUND(ARRAY, DIM)
3056 has the value equal to the number of elements in the given
3057 dimension; otherwise, it has a value equal to the upper bound
3058 for subscript DIM of ARRAY if dimension DIM of ARRAY does
3059 not have size zero and has value zero if dimension DIM has
3060 size zero. */
3061
3062 if (op == GFC_ISYM_LBOUND && assumed_rank_lb_one)
3063 se->expr = gfc_index_one_nodegfc_rank_cst[1];
3064 else if (as)
3065 {
3066 if (op == GFC_ISYM_UBOUND)
3067 {
3068 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3069 size, gfc_index_zero_nodegfc_rank_cst[0]);
3070 se->expr = fold_build3_loc (input_location, COND_EXPR,
3071 gfc_array_index_type, cond,
3072 (assumed_rank_lb_one ? size : ubound),
3073 gfc_index_zero_nodegfc_rank_cst[0]);
3074 }
3075 else if (op == GFC_ISYM_LBOUND)
3076 {
3077 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3078 size, gfc_index_zero_nodegfc_rank_cst[0]);
3079 if (as->type == AS_ASSUMED_SIZE)
3080 {
3081 cond1 = fold_build2_loc (input_location, EQ_EXPR,
3082 logical_type_node, bound,
3083 build_int_cst (TREE_TYPE (bound)((contains_struct_check ((bound), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3083, __FUNCTION__))->typed.type)
,
3084 arg->expr->rank - 1));
3085 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3086 logical_type_node, cond, cond1);
3087 }
3088 se->expr = fold_build3_loc (input_location, COND_EXPR,
3089 gfc_array_index_type, cond,
3090 lbound, gfc_index_one_nodegfc_rank_cst[1]);
3091 }
3092 else if (op == GFC_ISYM_SHAPE)
3093 se->expr = size;
3094 else
3095 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3095, __FUNCTION__))
;
3096
3097 /* According to F2018 16.9.172, para 5, an assumed rank object,
3098 argument associated with and assumed size array, has the ubound
3099 of the final dimension set to -1 and UBOUND must return this.
3100 Similarly for the SHAPE intrinsic. */
3101 if (op != GFC_ISYM_LBOUND && assumed_rank_lb_one)
3102 {
3103 tree minus_one = build_int_cst (gfc_array_index_type, -1);
3104 tree rank = fold_convert (gfc_array_index_type,fold_convert_loc (((location_t) 0), gfc_array_index_type, gfc_conv_descriptor_rank
(desc))
3105 gfc_conv_descriptor_rank (desc))fold_convert_loc (((location_t) 0), gfc_array_index_type, gfc_conv_descriptor_rank
(desc))
;
3106 rank = fold_build2_loc (input_location, PLUS_EXPR,
3107 gfc_array_index_type, rank, minus_one);
3108
3109 /* Fix the expression to stop it from becoming even more
3110 complicated. */
3111 se->expr = gfc_evaluate_now (se->expr, &se->pre);
3112
3113 /* Descriptors for assumed-size arrays have ubound = -1
3114 in the last dimension. */
3115 cond1 = fold_build2_loc (input_location, EQ_EXPR,
3116 logical_type_node, ubound, minus_one);
3117 cond = fold_build2_loc (input_location, EQ_EXPR,
3118 logical_type_node, bound, rank);
3119 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3120 logical_type_node, cond, cond1);
3121 se->expr = fold_build3_loc (input_location, COND_EXPR,
3122 gfc_array_index_type, cond,
3123 minus_one, se->expr);
3124 }
3125 }
3126 else /* as is null; this is an old-fashioned 1-based array. */
3127 {
3128 if (op != GFC_ISYM_LBOUND)
3129 {
3130 se->expr = fold_build2_loc (input_location, MAX_EXPR,
3131 gfc_array_index_type, size,
3132 gfc_index_zero_nodegfc_rank_cst[0]);
3133 }
3134 else
3135 se->expr = gfc_index_one_nodegfc_rank_cst[1];
3136 }
3137
3138
3139 type = gfc_typenode_for_spec (&expr->ts);
3140 se->expr = convert (type, se->expr);
3141}
3142
3143
3144static void
3145conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
3146{
3147 gfc_actual_arglist *arg;
3148 gfc_actual_arglist *arg2;
3149 gfc_se argse;
3150 tree bound, resbound, resbound2, desc, cond, tmp;
3151 tree type;
3152 int corank;
3153
3154 gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND((void)(!(expr->value.function.isym->id == GFC_ISYM_LCOBOUND
|| expr->value.function.isym->id == GFC_ISYM_UCOBOUND ||
expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE) ?
fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3156, __FUNCTION__), 0 : 0))
3155 || expr->value.function.isym->id == GFC_ISYM_UCOBOUND((void)(!(expr->value.function.isym->id == GFC_ISYM_LCOBOUND
|| expr->value.function.isym->id == GFC_ISYM_UCOBOUND ||
expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE) ?
fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3156, __FUNCTION__), 0 : 0))
3156 || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE)((void)(!(expr->value.function.isym->id == GFC_ISYM_LCOBOUND
|| expr->value.function.isym->id == GFC_ISYM_UCOBOUND ||
expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE) ?
fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3156, __FUNCTION__), 0 : 0))
;
3157
3158 arg = expr->value.function.actual;
3159 arg2 = arg->next;
3160
3161 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE)((void)(!(arg->expr->expr_type == EXPR_VARIABLE) ? fancy_abort
("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3161, __FUNCTION__), 0 : 0))
;
3162 corank = gfc_get_corank (arg->expr);
3163
3164 gfc_init_se (&argse, NULL__null);
3165 argse.want_coarray = 1;
3166
3167 gfc_conv_expr_descriptor (&argse, arg->expr);
3168 gfc_add_block_to_block (&se->pre, &argse.pre);
3169 gfc_add_block_to_block (&se->post, &argse.post);
3170 desc = argse.expr;
3171
3172 if (se->ss)
3173 {
3174 /* Create an implicit second parameter from the loop variable. */
3175 gcc_assert (!arg2->expr)((void)(!(!arg2->expr) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3175, __FUNCTION__), 0 : 0))
;
3176 gcc_assert (corank > 0)((void)(!(corank > 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3176, __FUNCTION__), 0 : 0))
;
3177 gcc_assert (se->loop->dimen == 1)((void)(!(se->loop->dimen == 1) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3177, __FUNCTION__), 0 : 0))
;
3178 gcc_assert (se->ss->info->expr == expr)((void)(!(se->ss->info->expr == expr) ? fancy_abort (
"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3178, __FUNCTION__), 0 : 0))
;
3179
3180 bound = se->loop->loopvar[0];
3181 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3182 bound, gfc_rank_cst[arg->expr->rank]);
3183 gfc_advance_se_ss_chain (se);
3184 }
3185 else
3186 {
3187 /* use the passed argument. */
3188 gcc_assert (arg2->expr)((void)(!(arg2->expr) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3188, __FUNCTION__), 0 : 0))
;
3189 gfc_init_se (&argse, NULL__null);
3190 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
3191 gfc_add_block_to_block (&se->pre, &argse.pre);
3192 bound = argse.expr;
3193
3194 if (INTEGER_CST_P (bound)(((enum tree_code) (bound)->base.code) == INTEGER_CST))
3195 {
3196 if (wi::ltu_p (wi::to_wide (bound), 1)
3197 || wi::gtu_p (wi::to_wide (bound),
3198 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))(((tree_class_check ((((contains_struct_check ((desc), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3198, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3198, __FUNCTION__))->type_with_lang_specific.lang_specific
)->corank)
))
3199 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
3200 "dimension index", expr->value.function.isym->name,
3201 &expr->where);
3202 }
3203 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS(1<<0))
3204 {
3205 bound = gfc_evaluate_now (bound, &se->pre);
3206 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3207 bound, build_int_cst (TREE_TYPE (bound)((contains_struct_check ((bound), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3207, __FUNCTION__))->typed.type)
, 1));
3208 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))(((tree_class_check ((((contains_struct_check ((desc), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3208, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3208, __FUNCTION__))->type_with_lang_specific.lang_specific
)->corank)
];
3209 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3210 bound, tmp);
3211 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
3212 logical_type_node, cond, tmp);
3213 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
3214 gfc_msg_fault);
3215 }
3216
3217
3218 /* Subtract 1 to get to zero based and add dimensions. */
3219 switch (arg->expr->rank)
3220 {
3221 case 0:
3222 bound = fold_build2_loc (input_location, MINUS_EXPR,
3223 gfc_array_index_type, bound,
3224 gfc_index_one_nodegfc_rank_cst[1]);
3225 case 1:
3226 break;
3227 default:
3228 bound = fold_build2_loc (input_location, PLUS_EXPR,
3229 gfc_array_index_type, bound,
3230 gfc_rank_cst[arg->expr->rank - 1]);
3231 }
3232 }
3233
3234 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
3235
3236 /* Handle UCOBOUND with special handling of the last codimension. */
3237 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
3238 {
3239 /* Last codimension: For -fcoarray=single just return
3240 the lcobound - otherwise add
3241 ceiling (real (num_images ()) / real (size)) - 1
3242 = (num_images () + size - 1) / size - 1
3243 = (num_images - 1) / size(),
3244 where size is the product of the extent of all but the last
3245 codimension. */
3246
3247 if (flag_coarrayglobal_options.x_flag_coarray != GFC_FCOARRAY_SINGLE && corank > 1)
3248 {
3249 tree cosize;
3250
3251 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
3252 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3253 2, integer_zero_nodeglobal_trees[TI_INTEGER_ZERO],
3254 build_int_cst (integer_type_nodeinteger_types[itk_int], -1));
3255 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3256 gfc_array_index_type,
3257 fold_convert (gfc_array_index_type, tmp)fold_convert_loc (((location_t) 0), gfc_array_index_type, tmp
)
,
3258 build_int_cst (gfc_array_index_type, 1));
3259 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
3260 gfc_array_index_type, tmp,
3261 fold_convert (gfc_array_index_type, cosize)fold_convert_loc (((location_t) 0), gfc_array_index_type, cosize
)
);
3262 resbound = fold_build2_loc (input_location, PLUS_EXPR,
3263 gfc_array_index_type, resbound, tmp);
3264 }
3265 else if (flag_coarrayglobal_options.x_flag_coarray != GFC_FCOARRAY_SINGLE)
3266 {
3267 /* ubound = lbound + num_images() - 1. */
3268 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3269 2, integer_zero_nodeglobal_trees[TI_INTEGER_ZERO],
3270 build_int_cst (integer_type_nodeinteger_types[itk_int], -1));
3271 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3272 gfc_array_index_type,
3273 fold_convert (gfc_array_index_type, tmp)fold_convert_loc (((location_t) 0), gfc_array_index_type, tmp
)
,
3274 build_int_cst (gfc_array_index_type, 1));
3275 resbound = fold_build2_loc (input_location, PLUS_EXPR,
3276 gfc_array_index_type, resbound, tmp);
3277 }
3278
3279 if (corank > 1)
3280 {
3281 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3282 bound,
3283 build_int_cst (TREE_TYPE (bound)((contains_struct_check ((bound), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3283, __FUNCTION__))->typed.type)
,
3284 arg->expr->rank + corank - 1));
3285
3286 resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
3287 se->expr = fold_build3_loc (input_location, COND_EXPR,
3288 gfc_array_index_type, cond,
3289 resbound, resbound2);
3290 }
3291 else
3292 se->expr = resbound;
3293 }
3294 else
3295 se->expr = resbound;
3296
3297 type = gfc_typenode_for_spec (&expr->ts);
3298 se->expr = convert (type, se->expr);
3299}
3300
3301
3302static void
3303conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
3304{
3305 gfc_actual_arglist *array_arg;
3306 gfc_actual_arglist *dim_arg;
3307 gfc_se argse;
3308 tree desc, tmp;
3309
3310 array_arg = expr->value.function.actual;
3311 dim_arg = array_arg->next;
3312
3313 gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE)((void)(!(array_arg->expr->expr_type == EXPR_VARIABLE) ?
fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3313, __FUNCTION__), 0 : 0))
;
3314
3315 gfc_init_se (&argse, NULL__null);
3316 gfc_conv_expr_descriptor (&argse, array_arg->expr);
3317 gfc_add_block_to_block (&se->pre, &argse.pre);
3318 gfc_add_block_to_block (&se->post, &argse.post);
3319 desc = argse.expr;
3320
3321 gcc_assert (dim_arg->expr)((void)(!(dim_arg->expr) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3321, __FUNCTION__), 0 : 0))
;
3322 gfc_init_se (&argse, NULL__null);
3323 gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
3324 gfc_add_block_to_block (&se->pre, &argse.pre);
3325 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3326 argse.expr, gfc_index_one_nodegfc_rank_cst[1]);
3327 se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
3328}
3329
3330static void
3331gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
3332{
3333 tree arg, cabs;
3334
3335 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3336
3337 switch (expr->value.function.actual->expr->ts.type)
3338 {
3339 case BT_INTEGER:
3340 case BT_REAL:
3341 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg)((contains_struct_check ((arg), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3341, __FUNCTION__))->typed.type)
,
3342 arg);
3343 break;
3344
3345 case BT_COMPLEX:
3346 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
3347 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
3348 break;
3349
3350 default:
3351 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3351, __FUNCTION__))
;
3352 }
3353}
3354
3355
3356/* Create a complex value from one or two real components. */
3357
3358static void
3359gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
3360{
3361 tree real;
3362 tree imag;
3363 tree type;
3364 tree *args;
3365 unsigned int num_args;
3366
3367 num_args = gfc_intrinsic_argument_list_length (expr);
3368 args = XALLOCAVEC (tree, num_args)((tree *) __builtin_alloca(sizeof (tree) * (num_args)));
3369
3370 type = gfc_typenode_for_spec (&expr->ts);
3371 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
3372 real = convert (TREE_TYPE (type)((contains_struct_check ((type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3372, __FUNCTION__))->typed.type)
, args[0]);
3373 if (both)
3374 imag = convert (TREE_TYPE (type)((contains_struct_check ((type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3374, __FUNCTION__))->typed.type)
, args[1]);
3375 else if (TREE_CODE (TREE_TYPE (args[0]))((enum tree_code) (((contains_struct_check ((args[0]), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3375, __FUNCTION__))->typed.type))->base.code)
== COMPLEX_TYPE)
3376 {
3377 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
3378 TREE_TYPE (TREE_TYPE (args[0]))((contains_struct_check ((((contains_struct_check ((args[0]),
(TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3378, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3378, __FUNCTION__))->typed.type)
, args[0]);
3379 imag = convert (TREE_TYPE (type)((contains_struct_check ((type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3379, __FUNCTION__))->typed.type)
, imag);
3380 }
3381 else
3382 imag = build_real_from_int_cst (TREE_TYPE (type)((contains_struct_check ((type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3382, __FUNCTION__))->typed.type)
, integer_zero_nodeglobal_trees[TI_INTEGER_ZERO]);
3383
3384 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
3385}
3386
3387
3388/* Remainder function MOD(A, P) = A - INT(A / P) * P
3389 MODULO(A, P) = A - FLOOR (A / P) * P
3390
3391 The obvious algorithms above are numerically instable for large
3392 arguments, hence these intrinsics are instead implemented via calls
3393 to the fmod family of functions. It is the responsibility of the
3394 user to ensure that the second argument is non-zero. */
3395
3396static void
3397gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
3398{
3399 tree type;
3400 tree tmp;
3401 tree test;
3402 tree test2;
3403 tree fmod;
3404 tree zero;
3405 tree args[2];
3406
3407 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3408
3409 switch (expr->ts.type)
3410 {
3411 case BT_INTEGER:
3412 /* Integer case is easy, we've got a builtin op. */
3413 type = TREE_TYPE (args[0])((contains_struct_check ((args[0]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3413, __FUNCTION__))->typed.type)
;
3414
3415 if (modulo)
3416 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
3417 args[0], args[1]);
3418 else
3419 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
3420 args[0], args[1]);
3421 break;
3422
3423 case BT_REAL:
3424 fmod = NULL_TREE(tree) __null;
3425 /* Check if we have a builtin fmod. */
3426 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
3427
3428 /* The builtin should always be available. */
3429 gcc_assert (fmod != NULL_TREE)((void)(!(fmod != (tree) __null) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3429, __FUNCTION__), 0 : 0))
;
3430
3431 tmp = build_addr (fmod);
3432 se->expr = build_call_array_loc (input_location,
3433 TREE_TYPE (TREE_TYPE (fmod))((contains_struct_check ((((contains_struct_check ((fmod), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3433, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3433, __FUNCTION__))->typed.type)
,
3434 tmp, 2, args);
3435 if (modulo == 0)
3436 return;
3437
3438 type = TREE_TYPE (args[0])((contains_struct_check ((args[0]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3438, __FUNCTION__))->typed.type)
;
3439
3440 args[0] = gfc_evaluate_now (args[0], &se->pre);
3441 args[1] = gfc_evaluate_now (args[1], &se->pre);
3442
3443 /* Definition:
3444 modulo = arg - floor (arg/arg2) * arg2
3445
3446 In order to calculate the result accurately, we use the fmod
3447 function as follows.
3448
3449 res = fmod (arg, arg2);
3450 if (res)
3451 {
3452 if ((arg < 0) xor (arg2 < 0))
3453 res += arg2;
3454 }
3455 else
3456 res = copysign (0., arg2);
3457
3458 => As two nested ternary exprs:
3459
3460 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
3461 : copysign (0., arg2);
3462
3463 */
3464
3465 zero = gfc_build_const (type, integer_zero_nodeglobal_trees[TI_INTEGER_ZERO]);
3466 tmp = gfc_evaluate_now (se->expr, &se->pre);
3467 if (!flag_signed_zerosglobal_options.x_flag_signed_zeros)
3468 {
3469 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3470 args[0], zero);
3471 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3472 args[1], zero);
3473 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3474 logical_type_node, test, test2);
3475 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3476 tmp, zero);
3477 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3478 logical_type_node, test, test2);
3479 test = gfc_evaluate_now (test, &se->pre);
3480 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3481 fold_build2_loc (input_location,
3482 PLUS_EXPR,
3483 type, tmp, args[1]),
3484 tmp);
3485 }
3486 else
3487 {
3488 tree expr1, copysign, cscall;
3489 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
3490 expr->ts.kind);
3491 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3492 args[0], zero);
3493 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3494 args[1], zero);
3495 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3496 logical_type_node, test, test2);
3497 expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
3498 fold_build2_loc (input_location,
3499 PLUS_EXPR,
3500 type, tmp, args[1]),
3501 tmp);
3502 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3503 tmp, zero);
3504 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
3505 args[1]);
3506 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3507 expr1, cscall);
3508 }
3509 return;
3510
3511 default:
3512 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3512, __FUNCTION__))
;
3513 }
3514}
3515
3516/* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
3517 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
3518 where the right shifts are logical (i.e. 0's are shifted in).
3519 Because SHIFT_EXPR's want shifts strictly smaller than the integral
3520 type width, we have to special-case both S == 0 and S == BITSIZE(J):
3521 DSHIFTL(I,J,0) = I
3522 DSHIFTL(I,J,BITSIZE) = J
3523 DSHIFTR(I,J,0) = J
3524 DSHIFTR(I,J,BITSIZE) = I. */
3525
3526static void
3527gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
3528{
3529 tree type, utype, stype, arg1, arg2, shift, res, left, right;
3530 tree args[3], cond, tmp;
3531 int bitsize;
3532
3533 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3534
3535 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]))((void)(!(((contains_struct_check ((args[0]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3535, __FUNCTION__))->typed.type) == ((contains_struct_check
((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3535, __FUNCTION__))->typed.type)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3535, __FUNCTION__), 0 : 0))
;
3536 type = TREE_TYPE (args[0])((contains_struct_check ((args[0]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3536, __FUNCTION__))->typed.type)
;
3537 bitsize = TYPE_PRECISION (type)((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3537, __FUNCTION__))->type_common.precision)
;
3538 utype = unsigned_type_for (type);
3539 stype = TREE_TYPE (args[2])((contains_struct_check ((args[2]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3539, __FUNCTION__))->typed.type)
;
3540
3541 arg1 = gfc_evaluate_now (args[0], &se->pre);
3542 arg2 = gfc_evaluate_now (args[1], &se->pre);
3543 shift = gfc_evaluate_now (args[2], &se->pre);
3544
3545 /* The generic case. */
3546 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
3547 build_int_cst (stype, bitsize), shift);
3548 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3549 arg1, dshiftl ? shift : tmp);
3550
3551 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
3552 fold_convert (utype, arg2)fold_convert_loc (((location_t) 0), utype, arg2), dshiftl ? tmp : shift);
3553 right = fold_convert (type, right)fold_convert_loc (((location_t) 0), type, right);
3554
3555 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
3556
3557 /* Special cases. */
3558 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3559 build_int_cst (stype, 0));
3560 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3561 dshiftl ? arg1 : arg2, res);
3562
3563 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3564 build_int_cst (stype, bitsize));
3565 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3566 dshiftl ? arg2 : arg1, res);
3567
3568 se->expr = res;
3569}
3570
3571
3572/* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
3573
3574static void
3575gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
3576{
3577 tree val;
3578 tree tmp;
3579 tree type;
3580 tree zero;
3581 tree args[2];
3582
3583 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3584 type = TREE_TYPE (args[0])((contains_struct_check ((args[0]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3584, __FUNCTION__))->typed.type)
;
3585
3586 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
3587 val = gfc_evaluate_now (val, &se->pre);
3588
3589 zero = gfc_build_const (type, integer_zero_nodeglobal_trees[TI_INTEGER_ZERO]);
3590 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node, val, zero);
3591 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
3592}
3593
3594
3595/* SIGN(A, B) is absolute value of A times sign of B.
3596 The real value versions use library functions to ensure the correct
3597 handling of negative zero. Integer case implemented as:
3598 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
3599 */
3600
3601static void
3602gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
3603{
3604 tree tmp;
3605 tree type;
3606 tree args[2];
3607
3608 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3609 if (expr->ts.type == BT_REAL)
3610 {
3611 tree abs;
3612
3613 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
3614 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
3615
3616 /* We explicitly have to ignore the minus sign. We do so by using
3617 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
3618 if (!flag_sign_zeroglobal_options.x_flag_sign_zero
3619 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1])))((((enum mode_class) mode_class[((((enum tree_code) ((tree_class_check
((((contains_struct_check ((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(((contains_struct_check ((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)) : (((contains_struct_check
((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type))->type_common.mode)
]) == MODE_FLOAT || ((enum mode_class) mode_class[((((enum tree_code
) ((tree_class_check ((((contains_struct_check ((args[1]), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(((contains_struct_check ((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)) : (((contains_struct_check
((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type))->type_common.mode)
]) == MODE_DECIMAL_FLOAT || ((enum mode_class) mode_class[(((
(enum tree_code) ((tree_class_check ((((contains_struct_check
((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(((contains_struct_check ((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)) : (((contains_struct_check
((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type))->type_common.mode)
]) == MODE_COMPLEX_FLOAT || ((enum mode_class) mode_class[(((
(enum tree_code) ((tree_class_check ((((contains_struct_check
((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(((contains_struct_check ((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)) : (((contains_struct_check
((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type))->type_common.mode)
]) == MODE_VECTOR_FLOAT) && ((real_format_for_mode[((
(enum mode_class) mode_class[as_a <scalar_float_mode> (
(mode_to_inner (((((enum tree_code) ((tree_class_check ((((contains_struct_check
((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(((contains_struct_check ((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)) : (((contains_struct_check
((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type))->type_common.mode)
)))]) == MODE_DECIMAL_FLOAT) ? (((as_a <scalar_float_mode>
((mode_to_inner (((((enum tree_code) ((tree_class_check ((((
contains_struct_check ((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(((contains_struct_check ((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)) : (((contains_struct_check
((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type))->type_common.mode)
)))) - MIN_MODE_DECIMAL_FLOAT) + (MAX_MODE_FLOAT - MIN_MODE_FLOAT
+ 1)) : ((enum mode_class) mode_class[as_a <scalar_float_mode
> ((mode_to_inner (((((enum tree_code) ((tree_class_check (
(((contains_struct_check ((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(((contains_struct_check ((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)) : (((contains_struct_check
((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type))->type_common.mode)
)))]) == MODE_FLOAT ? ((as_a <scalar_float_mode> ((mode_to_inner
(((((enum tree_code) ((tree_class_check ((((contains_struct_check
((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(((contains_struct_check ((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type)) : (((contains_struct_check
((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__))->typed.type))->type_common.mode)
)))) - MIN_MODE_FLOAT) : ((fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3619, __FUNCTION__)), 0)]))->has_signed_zero)
)
3620 {
3621 tree cond, zero;
3622 zero = build_real_from_int_cst (TREE_TYPE (args[1])((contains_struct_check ((args[1]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3622, __FUNCTION__))->typed.type)
, integer_zero_nodeglobal_trees[TI_INTEGER_ZERO]);
3623 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3624 args[1], zero);
3625 se->expr = fold_build3_loc (input_location, COND_EXPR,
3626 TREE_TYPE (args[0])((contains_struct_check ((args[0]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3626, __FUNCTION__))->typed.type)
, cond,
3627 build_call_expr_loc (input_location, abs, 1,
3628 args[0]),
3629 build_call_expr_loc (input_location, tmp, 2,
3630 args[0], args[1]));
3631 }
3632 else
3633 se->expr = build_call_expr_loc (input_location, tmp, 2,
3634 args[0], args[1]);
3635 return;
3636 }
3637
3638 /* Having excluded floating point types, we know we are now dealing
3639 with signed integer types. */
3640 type = TREE_TYPE (args[0])((contains_struct_check ((args[0]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3640, __FUNCTION__))->typed.type)
;
3641
3642 /* Args[0] is used multiple times below. */
3643 args[0] = gfc_evaluate_now (args[0], &se->pre);
3644
3645 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
3646 the signs of A and B are the same, and of all ones if they differ. */
3647 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
3648 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
3649 build_int_cst (type, TYPE_PRECISION (type)((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3649, __FUNCTION__))->type_common.precision)
- 1));
3650 tmp = gfc_evaluate_now (tmp, &se->pre);
3651
3652 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
3653 is all ones (i.e. -1). */
3654 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
3655 fold_build2_loc (input_location, PLUS_EXPR,
3656 type, args[0], tmp), tmp);
3657}
3658
3659
3660/* Test for the presence of an optional argument. */
3661
3662static void
3663gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
3664{
3665 gfc_expr *arg;
3666
3667 arg = expr->value.function.actual->expr;
3668 gcc_assert (arg->expr_type == EXPR_VARIABLE)((void)(!(arg->expr_type == EXPR_VARIABLE) ? fancy_abort (
"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3668, __FUNCTION__), 0 : 0))
;
3669 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
3670 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
3671}
3672
3673
3674/* Calculate the double precision product of two single precision values. */
3675
3676static void
3677gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
3678{
3679 tree type;
3680 tree args[2];
3681
3682 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3683
3684 /* Convert the args to double precision before multiplying. */
3685 type = gfc_typenode_for_spec (&expr->ts);
3686 args[0] = convert (type, args[0]);
3687 args[1] = convert (type, args[1]);
3688 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
3689 args[1]);
3690}
3691
3692
3693/* Return a length one character string containing an ascii character. */
3694
3695static void
3696gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
3697{
3698 tree arg[2];
3699 tree var;
3700 tree type;
3701 unsigned int num_args;
3702
3703 num_args = gfc_intrinsic_argument_list_length (expr);
3704 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
3705
3706 type = gfc_get_char_type (expr->ts.kind);
3707 var = gfc_create_var (type, "char");
3708
3709 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
3710 gfc_add_modify (&se->pre, var, arg[0]);
3711 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
3712 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
3713}
3714
3715
3716static void
3717gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
3718{
3719 tree var;
3720 tree len;
3721 tree tmp;
3722 tree cond;
3723 tree fndecl;
3724 tree *args;
3725 unsigned int num_args;
3726
3727 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3728 args = XALLOCAVEC (tree, num_args)((tree *) __builtin_alloca(sizeof (tree) * (num_args)));
3729
3730 var = gfc_create_var (pchar_type_node, "pstr");
3731 len = gfc_create_var (gfc_charlen_type_node, "len");
3732
3733 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3734 args[0] = gfc_build_addr_expr (NULL_TREE(tree) __null, var);
3735 args[1] = gfc_build_addr_expr (NULL_TREE(tree) __null, len);
3736
3737 fndecl = build_addr (gfor_fndecl_ctime);
3738 tmp = build_call_array_loc (input_location,
3739 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime))((contains_struct_check ((((contains_struct_check ((gfor_fndecl_ctime
), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3739, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3739, __FUNCTION__))->typed.type)
,
3740 fndecl, num_args, args);
3741 gfc_add_expr_to_block (&se->pre, tmp);
3742
3743 /* Free the temporary afterwards, if necessary. */
3744 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3745 len, build_int_cst (TREE_TYPE (len)((contains_struct_check ((len), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3745, __FUNCTION__))->typed.type)
, 0));
3746 tmp = gfc_call_free (var);
3747 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], cond, tmp, build_empty_stmt (input_location))
;
3748 gfc_add_expr_to_block (&se->post, tmp);
3749
3750 se->expr = var;
3751 se->string_length = len;
3752}
3753
3754
3755static void
3756gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
3757{
3758 tree var;
3759 tree len;
3760 tree tmp;
3761 tree cond;
3762 tree fndecl;
3763 tree *args;
3764 unsigned int num_args;
3765
3766 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3767 args = XALLOCAVEC (tree, num_args)((tree *) __builtin_alloca(sizeof (tree) * (num_args)));
3768
3769 var = gfc_create_var (pchar_type_node, "pstr");
3770 len = gfc_create_var (gfc_charlen_type_node, "len");
3771
3772 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3773 args[0] = gfc_build_addr_expr (NULL_TREE(tree) __null, var);
3774 args[1] = gfc_build_addr_expr (NULL_TREE(tree) __null, len);
3775
3776 fndecl = build_addr (gfor_fndecl_fdate);
3777 tmp = build_call_array_loc (input_location,
3778 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate))((contains_struct_check ((((contains_struct_check ((gfor_fndecl_fdate
), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3778, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3778, __FUNCTION__))->typed.type)
,
3779 fndecl, num_args, args);
3780 gfc_add_expr_to_block (&se->pre, tmp);
3781
3782 /* Free the temporary afterwards, if necessary. */
3783 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3784 len, build_int_cst (TREE_TYPE (len)((contains_struct_check ((len), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 3784, __FUNCTION__))->typed.type)
, 0));
3785 tmp = gfc_call_free (var);
3786 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], cond, tmp, build_empty_stmt (input_location))
;
3787 gfc_add_expr_to_block (&se->post, tmp);
3788
3789 se->expr = var;
3790 se->string_length = len;
3791}
3792
3793
3794/* Generate a direct call to free() for the FREE subroutine. */
3795
3796static tree
3797conv_intrinsic_free (gfc_code *code)
3798{
3799 stmtblock_t block;
3800 gfc_se argse;
3801 tree arg, call;
3802
3803 gfc_init_se (&argse, NULL__null);
3804 gfc_conv_expr (&argse, code->ext.actual->expr);
3805 arg = fold_convert (ptr_type_node, argse.expr)fold_convert_loc (((location_t) 0), global_trees[TI_PTR_TYPE]
, argse.expr)
;
3806
3807 gfc_init_block (&block);
3808 call = build_call_expr_loc (input_location,
3809 builtin_decl_explicit (BUILT_IN_FREE), 1, arg);
3810 gfc_add_expr_to_block (&block, call);
3811 return gfc_finish_block (&block);
3812}
3813
3814
3815/* Call the RANDOM_INIT library subroutine with a hidden argument for
3816 handling seeding on coarray images. */
3817
3818static tree
3819conv_intrinsic_random_init (gfc_code *code)
3820{
3821 stmtblock_t block;
3822 gfc_se se;
3823 tree arg1, arg2, tmp;
3824 /* On none coarray == lib compiles use LOGICAL(4) else regular LOGICAL. */
3825 tree used_bool_type_node = flag_coarrayglobal_options.x_flag_coarray == GFC_FCOARRAY_LIB
3826 ? logical_type_node
3827 : gfc_get_logical_type (4);
3828
3829 /* Make the function call. */
3830 gfc_init_block (&block);
3831 gfc_init_se (&se, NULL__null);
3832
3833 /* Convert REPEATABLE to the desired LOGICAL entity. */
3834 gfc_conv_expr (&se, code->ext.actual->expr);
3835 gfc_add_block_to_block (&block, &se.pre);
3836 arg1 = fold_convert (used_bool_type_node, gfc_evaluate_now (se.expr, &block))fold_convert_loc (((location_t) 0), used_bool_type_node, gfc_evaluate_now
(se.expr, &block))
;
3837 gfc_add_block_to_block (&block, &se.post);
3838
3839 /* Convert IMAGE_DISTINCT to the desired LOGICAL entity. */
3840 gfc_conv_expr (&se, code->ext.actual->next->expr);
3841 gfc_add_block_to_block (&block, &se.pre);
3842 arg2 = fold_convert (used_bool_type_node, gfc_evaluate_now (se.expr, &block))fold_convert_loc (((location_t) 0), used_bool_type_node, gfc_evaluate_now
(se.expr, &block))
;
3843 gfc_add_block_to_block (&block, &se.post);
3844
3845 if (flag_coarrayglobal_options.x_flag_coarray == GFC_FCOARRAY_LIB)
3846 {
3847 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_random_init,
3848 2, arg1, arg2);
3849 }
3850 else
3851 {
3852 /* The ABI for libgfortran needs to be maintained, so a hidden
3853 argument must be include if code is compiled with -fcoarray=single
3854 or without the option. Set to 0. */
3855 tree arg3 = build_int_cst (gfc_get_int_type (4), 0);
3856 tmp = build_call_expr_loc (input_location, gfor_fndecl_random_init,
3857 3, arg1, arg2, arg3);
3858 }
3859
3860 gfc_add_expr_to_block (&block, tmp);
3861
3862 return gfc_finish_block (&block);
3863}
3864
3865
3866/* Call the SYSTEM_CLOCK library functions, handling the type and kind
3867 conversions. */
3868
3869static tree
3870conv_intrinsic_system_clock (gfc_code *code)
3871{
3872 stmtblock_t block;
3873 gfc_se count_se, count_rate_se, count_max_se;
3874 tree arg1 = NULL_TREE(tree) __null, arg2 = NULL_TREE(tree) __null, arg3 = NULL_TREE(tree) __null;
3875 tree tmp;
3876 int least;
3877
3878 gfc_expr *count = code->ext.actual->expr;
3879 gfc_expr *count_rate = code->ext.actual->next->expr;
3880 gfc_expr *count_max = code->ext.actual->next->next->expr;
3881
3882 /* Evaluate our arguments. */
3883 if (count)
3884 {
3885 gfc_init_se (&count_se, NULL__null);
3886 gfc_conv_expr (&count_se, count);
3887 }
3888
3889 if (count_rate)
3890 {
3891 gfc_init_se (&count_rate_se, NULL__null);
3892 gfc_conv_expr (&count_rate_se, count_rate);
3893 }
3894
3895 if (count_max)
3896 {
3897 gfc_init_se (&count_max_se, NULL__null);
3898 gfc_conv_expr (&count_max_se, count_max);
3899 }
3900
3901 /* Find the smallest kind found of the arguments. */
3902 least = 16;
3903 least = (count && count->ts.kind < least) ? count->ts.kind : least;
3904 least = (count_rate && count_rate->ts.kind < least) ? count_rate->ts.kind
3905 : least;
3906 least = (count_max && count_max->ts.kind < least) ? count_max->ts.kind
3907 : least;
3908
3909 /* Prepare temporary variables. */
3910
3911 if (count)
3912 {
3913 if (least >= 8)
3914 arg1 = gfc_create_var (gfc_get_int_type (8), "count");
3915 else if (least == 4)
3916 arg1 = gfc_create_var (gfc_get_int_type (4), "count");
3917 else if (count->ts.kind == 1)
3918 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[0].pedantic_min_int,
3919 count->ts.kind);
3920 else
3921 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[1].pedantic_min_int,
3922 count->ts.kind);
3923 }
3924
3925 if (count_rate)
3926 {
3927 if (least >= 8)
3928 arg2 = gfc_create_var (gfc_get_int_type (8), "count_rate");
3929 else if (least == 4)
3930 arg2 = gfc_create_var (gfc_get_int_type (4), "count_rate");
3931 else
3932 arg2 = integer_zero_nodeglobal_trees[TI_INTEGER_ZERO];
3933 }
3934
3935 if (count_max)
3936 {
3937 if (least >= 8)
3938 arg3 = gfc_create_var (gfc_get_int_type (8), "count_max");
3939 else if (least == 4)
3940 arg3 = gfc_create_var (gfc_get_int_type (4), "count_max");
3941 else
3942 arg3 = integer_zero_nodeglobal_trees[TI_INTEGER_ZERO];
3943 }
3944
3945 /* Make the function call. */
3946 gfc_init_block (&block);
3947
3948if (least <= 2)
3949 {
3950 if (least == 1)
3951 {
3952 arg1 ? gfc_build_addr_expr (NULL_TREE(tree) __null, arg1)
3953 : null_pointer_nodeglobal_trees[TI_NULL_POINTER];
3954 arg2 ? gfc_build_addr_expr (NULL_TREE(tree) __null, arg2)
3955 : null_pointer_nodeglobal_trees[TI_NULL_POINTER];
3956 arg3 ? gfc_build_addr_expr (NULL_TREE(tree) __null, arg3)
3957 : null_pointer_nodeglobal_trees[TI_NULL_POINTER];
3958 }
3959
3960 if (least == 2)
3961 {
3962 arg1 ? gfc_build_addr_expr (NULL_TREE(tree) __null, arg1)
3963 : null_pointer_nodeglobal_trees[TI_NULL_POINTER];
3964 arg2 ? gfc_build_addr_expr (NULL_TREE(tree) __null, arg2)
3965 : null_pointer_nodeglobal_trees[TI_NULL_POINTER];
3966 arg3 ? gfc_build_addr_expr (NULL_TREE(tree) __null, arg3)
3967 : null_pointer_nodeglobal_trees[TI_NULL_POINTER];
3968 }
3969 }
3970else
3971 {
3972 if (least == 4)
3973 {
3974 tmp = build_call_expr_loc (input_location,
3975 gfor_fndecl_system_clock4, 3,
3976 arg1 ? gfc_build_addr_expr (NULL_TREE(tree) __null, arg1)
3977 : null_pointer_nodeglobal_trees[TI_NULL_POINTER],
3978 arg2 ? gfc_build_addr_expr (NULL_TREE(tree) __null, arg2)
3979 : null_pointer_nodeglobal_trees[TI_NULL_POINTER],
3980 arg3 ? gfc_build_addr_expr (NULL_TREE(tree) __null, arg3)
3981 : null_pointer_nodeglobal_trees[TI_NULL_POINTER]);
3982 gfc_add_expr_to_block (&block, tmp);
3983 }
3984 /* Handle kind>=8, 10, or 16 arguments */
3985 if (least >= 8)
3986 {
3987 tmp = build_call_expr_loc (input_location,
3988 gfor_fndecl_system_clock8, 3,
3989 arg1 ? gfc_build_addr_expr (NULL_TREE(tree) __null, arg1)
3990 : null_pointer_nodeglobal_trees[TI_NULL_POINTER],
3991 arg2 ? gfc_build_addr_expr (NULL_TREE(tree) __null, arg2)
3992 : null_pointer_nodeglobal_trees[TI_NULL_POINTER],
3993 arg3 ? gfc_build_addr_expr (NULL_TREE(tree) __null, arg3)
3994 : null_pointer_nodeglobal_trees[TI_NULL_POINTER]);
3995 gfc_add_expr_to_block (&block, tmp);
3996 }
3997 }
3998
3999 /* And store values back if needed. */
4000 if (arg1 && arg1 != count_se.expr)
4001 gfc_add_modify (&block, count_se.expr,
4002 fold_convert (TREE_TYPE (count_se.expr), arg1)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(count_se.expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4002, __FUNCTION__))->typed.type), arg1)
);
4003 if (arg2 && arg2 != count_rate_se.expr)
4004 gfc_add_modify (&block, count_rate_se.expr,
4005 fold_convert (TREE_TYPE (count_rate_se.expr), arg2)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(count_rate_se.expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4005, __FUNCTION__))->typed.type), arg2)
);
4006 if (arg3 && arg3 != count_max_se.expr)
4007 gfc_add_modify (&block, count_max_se.expr,
4008 fold_convert (TREE_TYPE (count_max_se.expr), arg3)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(count_max_se.expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4008, __FUNCTION__))->typed.type), arg3)
);
4009
4010 return gfc_finish_block (&block);
4011}
4012
4013
4014/* Return a character string containing the tty name. */
4015
4016static void
4017gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
4018{
4019 tree var;
4020 tree len;
4021 tree tmp;
4022 tree cond;
4023 tree fndecl;
4024 tree *args;
4025 unsigned int num_args;
4026
4027 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
4028 args = XALLOCAVEC (tree, num_args)((tree *) __builtin_alloca(sizeof (tree) * (num_args)));
4029
4030 var = gfc_create_var (pchar_type_node, "pstr");
4031 len = gfc_create_var (gfc_charlen_type_node, "len");
4032
4033 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
4034 args[0] = gfc_build_addr_expr (NULL_TREE(tree) __null, var);
4035 args[1] = gfc_build_addr_expr (NULL_TREE(tree) __null, len);
4036
4037 fndecl = build_addr (gfor_fndecl_ttynam);
4038 tmp = build_call_array_loc (input_location,
4039 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam))((contains_struct_check ((((contains_struct_check ((gfor_fndecl_ttynam
), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4039, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4039, __FUNCTION__))->typed.type)
,
4040 fndecl, num_args, args);
4041 gfc_add_expr_to_block (&se->pre, tmp);
4042
4043 /* Free the temporary afterwards, if necessary. */
4044 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4045 len, build_int_cst (TREE_TYPE (len)((contains_struct_check ((len), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4045, __FUNCTION__))->typed.type)
, 0));
4046 tmp = gfc_call_free (var);
4047 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], cond, tmp, build_empty_stmt (input_location))
;
4048 gfc_add_expr_to_block (&se->post, tmp);
4049
4050 se->expr = var;
4051 se->string_length = len;
4052}
4053
4054
4055/* Get the minimum/maximum value of all the parameters.
4056 minmax (a1, a2, a3, ...)
4057 {
4058 mvar = a1;
4059 mvar = COMP (mvar, a2)
4060 mvar = COMP (mvar, a3)
4061 ...
4062 return mvar;
4063 }
4064 Where COMP is MIN/MAX_EXPR for integral types or when we don't
4065 care about NaNs, or IFN_FMIN/MAX when the target has support for
4066 fast NaN-honouring min/max. When neither holds expand a sequence
4067 of explicit comparisons. */
4068
4069/* TODO: Mismatching types can occur when specific names are used.
4070 These should be handled during resolution. */
4071static void
4072gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
4073{
4074 tree tmp;
4075 tree mvar;
4076 tree val;
4077 tree *args;
4078 tree type;
4079 tree argtype;
4080 gfc_actual_arglist *argexpr;
4081 unsigned int i, nargs;
4082
4083 nargs = gfc_intrinsic_argument_list_length (expr);
4084 args = XALLOCAVEC (tree, nargs)((tree *) __builtin_alloca(sizeof (tree) * (nargs)));
4085
4086 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
4087 type = gfc_typenode_for_spec (&expr->ts);
4088
4089 /* Only evaluate the argument once. */
4090 if (!VAR_P (args[0])(((enum tree_code) (args[0])->base.code) == VAR_DECL) && !TREE_CONSTANT (args[0])((non_type_check ((args[0]), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4090, __FUNCTION__))->base.constant_flag)
)
4091 args[0] = gfc_evaluate_now (args[0], &se->pre);
4092
4093 /* Determine suitable type of temporary, as a GNU extension allows
4094 different argument kinds. */
4095 argtype = TREE_TYPE (args[0])((contains_struct_check ((args[0]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4095, __FUNCTION__))->typed.type)
;
4096 argexpr = expr->value.function.actual;
4097 for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
4098 {
4099 tree tmptype = TREE_TYPE (args[i])((contains_struct_check ((args[i]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4099, __FUNCTION__))->typed.type)
;
4100 if (TYPE_PRECISION (tmptype)((tree_class_check ((tmptype), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4100, __FUNCTION__))->type_common.precision)
> TYPE_PRECISION (argtype)((tree_class_check ((argtype), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4100, __FUNCTION__))->type_common.precision)
)
4101 argtype = tmptype;
4102 }
4103 mvar = gfc_create_var (argtype, "M");
4104 gfc_add_modify (&se->pre, mvar, convert (argtype, args[0]));
4105
4106 argexpr = expr->value.function.actual;
4107 for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
4108 {
4109 tree cond = NULL_TREE(tree) __null;
4110 val = args[i];
4111
4112 /* Handle absent optional arguments by ignoring the comparison. */
4113 if (argexpr->expr->expr_type == EXPR_VARIABLE
4114 && argexpr->expr->symtree->n.sym->attr.optional
4115 && TREE_CODE (val)((enum tree_code) (val)->base.code) == INDIRECT_REF)
4116 {
4117 cond = fold_build2_loc (input_location,
4118 NE_EXPR, logical_type_node,
4119 TREE_OPERAND (val, 0)(*((const_cast<tree*> (tree_operand_check ((val), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4119, __FUNCTION__)))))
,
4120 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0))((contains_struct_check (((*((const_cast<tree*> (tree_operand_check
((val), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4120, __FUNCTION__)))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4120, __FUNCTION__))->typed.type)
, 0));
4121 }
4122 else if (!VAR_P (val)(((enum tree_code) (val)->base.code) == VAR_DECL) && !TREE_CONSTANT (val)((non_type_check ((val), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4122, __FUNCTION__))->base.constant_flag)
)
4123 /* Only evaluate the argument once. */
4124 val = gfc_evaluate_now (val, &se->pre);
4125
4126 tree calc;
4127 /* For floating point types, the question is what MAX(a, NaN) or
4128 MIN(a, NaN) should return (where "a" is a normal number).
4129 There are valid usecase for returning either one, but the
4130 Fortran standard doesn't specify which one should be chosen.
4131 Also, there is no consensus among other tested compilers. In
4132 short, it's a mess. So lets just do whatever is fastest. */
4133 tree_code code = op == GT_EXPR ? MAX_EXPR : MIN_EXPR;
4134 calc = fold_build2_loc (input_location, code, argtype,
4135 convert (argtype, val), mvar);
4136 tmp = build2_v (MODIFY_EXPR, mvar, calc)fold_build2_loc (input_location, MODIFY_EXPR, global_trees[TI_VOID_TYPE
], mvar, calc)
;
4137
4138 if (cond != NULL_TREE(tree) __null)
4139 tmp = build3_v (COND_EXPR, cond, tmp,fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], cond, tmp, build_empty_stmt (input_location))
4140 build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], cond, tmp, build_empty_stmt (input_location))
;
4141 gfc_add_expr_to_block (&se->pre, tmp);
4142 }
4143 se->expr = convert (type, mvar);
4144}
4145
4146
4147/* Generate library calls for MIN and MAX intrinsics for character
4148 variables. */
4149static void
4150gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
4151{
4152 tree *args;
4153 tree var, len, fndecl, tmp, cond, function;
4154 unsigned int nargs;
4155
4156 nargs = gfc_intrinsic_argument_list_length (expr);
4157 args = XALLOCAVEC (tree, nargs + 4)((tree *) __builtin_alloca(sizeof (tree) * (nargs + 4)));
4158 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
4159
4160 /* Create the result variables. */
4161 len = gfc_create_var (gfc_charlen_type_node, "len");
4162 args[0] = gfc_build_addr_expr (NULL_TREE(tree) __null, len);
4163 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
4164 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
4165 args[2] = build_int_cst (integer_type_nodeinteger_types[itk_int], op);
4166 args[3] = build_int_cst (integer_type_nodeinteger_types[itk_int], nargs / 2);
4167
4168 if (expr->ts.kind == 1)
4169 function = gfor_fndecl_string_minmax;
4170 else if (expr->ts.kind == 4)
4171 function = gfor_fndecl_string_minmax_char4;
4172 else
4173 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4173, __FUNCTION__))
;
4174
4175 /* Make the function call. */
4176 fndecl = build_addr (function);
4177 tmp = build_call_array_loc (input_location,
4178 TREE_TYPE (TREE_TYPE (function))((contains_struct_check ((((contains_struct_check ((function)
, (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4178, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4178, __FUNCTION__))->typed.type)
, fndecl,
4179 nargs + 4, args);
4180 gfc_add_expr_to_block (&se->pre, tmp);
4181
4182 /* Free the temporary afterwards, if necessary. */
4183 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4184 len, build_int_cst (TREE_TYPE (len)((contains_struct_check ((len), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4184, __FUNCTION__))->typed.type)
, 0));
4185 tmp = gfc_call_free (var);
4186 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], cond, tmp, build_empty_stmt (input_location))
;
4187 gfc_add_expr_to_block (&se->post, tmp);
4188
4189 se->expr = var;
4190 se->string_length = len;
4191}
4192
4193
4194/* Create a symbol node for this intrinsic. The symbol from the frontend
4195 has the generic name. */
4196
4197static gfc_symbol *
4198gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
4199{
4200 gfc_symbol *sym;
4201
4202 /* TODO: Add symbols for intrinsic function to the global namespace. */
4203 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5)((void)(!(strlen (expr->value.function.name) <= 63 - 5)
? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4203, __FUNCTION__), 0 : 0))
;
4204 sym = gfc_new_symbol (expr->value.function.name, NULL__null);
4205
4206 sym->ts = expr->ts;
4207 sym->attr.external = 1;
4208 sym->attr.function = 1;
4209 sym->attr.always_explicit = 1;
4210 sym->attr.proc = PROC_INTRINSIC;
4211 sym->attr.flavor = FL_PROCEDURE;
4212 sym->result = sym;
4213 if (expr->rank > 0)
4214 {
4215 sym->attr.dimension = 1;
4216 sym->as = gfc_get_array_spec ()((gfc_array_spec *) xcalloc (1, sizeof (gfc_array_spec)));
4217 sym->as->type = AS_ASSUMED_SHAPE;
4218 sym->as->rank = expr->rank;
4219 }
4220
4221 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
4222 ignore_optional ? expr->value.function.actual
4223 : NULL__null);
4224
4225 return sym;
4226}
4227
4228/* Remove empty actual arguments. */
4229
4230static void
4231remove_empty_actual_arguments (gfc_actual_arglist **ap)
4232{
4233 while (*ap)
4234 {
4235 if ((*ap)->expr == NULL__null)
4236 {
4237 gfc_actual_arglist *r = *ap;
4238 *ap = r->next;
4239 r->next = NULL__null;
4240 gfc_free_actual_arglist (r);
4241 }
4242 else
4243 ap = &((*ap)->next);
4244 }
4245}
4246
4247#define MAX_SPEC_ARG 12
4248
4249/* Make up an fn spec that's right for intrinsic functions that we
4250 want to call. */
4251
4252static char *
4253intrinsic_fnspec (gfc_expr *expr)
4254{
4255 static char fnspec_buf[MAX_SPEC_ARG*2+1];
4256 char *fp;
4257 int i;
4258 int num_char_args;
4259
4260#define ADD_CHAR(c) do { *fp++ = c; *fp++ = ' '; } while(0)
4261
4262 /* Set the fndecl. */
4263 fp = fnspec_buf;
4264 /* Function return value. FIXME: Check if the second letter could
4265 be something other than a space, for further optimization. */
4266 ADD_CHAR ('.');
4267 if (expr->rank == 0)
4268 {
4269 if (expr->ts.type == BT_CHARACTER)
4270 {
4271 ADD_CHAR ('w'); /* Address of character. */
4272 ADD_CHAR ('.'); /* Length of character. */
4273 }
4274 }
4275 else
4276 ADD_CHAR ('w'); /* Return value is a descriptor. */
4277
4278 num_char_args = 0;
4279 for (gfc_actual_arglist *a = expr->value.function.actual; a; a = a->next)
4280 {
4281 if (a->expr == NULL__null)
4282 continue;
4283
4284 if (a->name && strcmp (a->name,"%VAL") == 0)
4285 ADD_CHAR ('.');
4286 else
4287 {
4288 if (a->expr->rank > 0)
4289 ADD_CHAR ('r');
4290 else
4291 ADD_CHAR ('R');
4292 }
4293 num_char_args += a->expr->ts.type == BT_CHARACTER;
4294 gcc_assert (fp - fnspec_buf + num_char_args <= MAX_SPEC_ARG*2)((void)(!(fp - fnspec_buf + num_char_args <= MAX_SPEC_ARG*
2) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4294, __FUNCTION__), 0 : 0))
;
4295 }
4296
4297 for (i = 0; i < num_char_args; i++)
4298 ADD_CHAR ('.');
4299
4300 *fp = '\0';
4301 return fnspec_buf;
4302}
4303
4304#undef MAX_SPEC_ARG
4305#undef ADD_CHAR
4306
4307/* Generate the right symbol for the specific intrinsic function and
4308 modify the expr accordingly. This assumes that absent optional
4309 arguments should be removed. */
4310
4311gfc_symbol *
4312specific_intrinsic_symbol (gfc_expr *expr)
4313{
4314 gfc_symbol *sym;
4315
4316 sym = gfc_find_intrinsic_symbol (expr);
4317 if (sym == NULL__null)
4318 {
4319 sym = gfc_get_intrinsic_function_symbol (expr);
4320 sym->ts = expr->ts;
4321 if (sym->ts.type == BT_CHARACTER && sym->ts.u.cl)
4322 sym->ts.u.cl = gfc_new_charlen (sym->ns, NULL__null);
4323
4324 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
4325 expr->value.function.actual, true);
4326 sym->backend_decl
4327 = gfc_get_extern_function_decl (sym, expr->value.function.actual,
4328 intrinsic_fnspec (expr));
4329 }
4330
4331 remove_empty_actual_arguments (&(expr->value.function.actual));
4332
4333 return sym;
4334}
4335
4336/* Generate a call to an external intrinsic function. FIXME: So far,
4337 this only works for functions which are called with well-defined
4338 types; CSHIFT and friends will come later. */
4339
4340static void
4341gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
4342{
4343 gfc_symbol *sym;
4344 vec<tree, va_gc> *append_args;
4345 bool specific_symbol;
4346
4347 gcc_assert (!se->ss || se->ss->info->expr == expr)((void)(!(!se->ss || se->ss->info->expr == expr) ?
fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4347, __FUNCTION__), 0 : 0))
;
4348
4349 if (se->ss)
4350 gcc_assert (expr->rank > 0)((void)(!(expr->rank > 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4350, __FUNCTION__), 0 : 0))
;
4351 else
4352 gcc_assert (expr->rank == 0)((void)(!(expr->rank == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4352, __FUNCTION__), 0 : 0))
;
4353
4354 switch (expr->value.function.isym->id)
4355 {
4356 case GFC_ISYM_ANY:
4357 case GFC_ISYM_ALL:
4358 case GFC_ISYM_FINDLOC:
4359 case GFC_ISYM_MAXLOC:
4360 case GFC_ISYM_MINLOC:
4361 case GFC_ISYM_MAXVAL:
4362 case GFC_ISYM_MINVAL:
4363 case GFC_ISYM_NORM2:
4364 case GFC_ISYM_PRODUCT:
4365 case GFC_ISYM_SUM:
4366 specific_symbol = true;
4367 break;
4368 default:
4369 specific_symbol = false;
4370 }
4371
4372 if (specific_symbol)
4373 {
4374 /* Need to copy here because specific_intrinsic_symbol modifies
4375 expr to omit the absent optional arguments. */
4376 expr = gfc_copy_expr (expr);
4377 sym = specific_intrinsic_symbol (expr);
4378 }
4379 else
4380 sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
4381
4382 /* Calls to libgfortran_matmul need to be appended special arguments,
4383 to be able to call the BLAS ?gemm functions if required and possible. */
4384 append_args = NULL__null;
4385 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
4386 && !expr->external_blas
4387 && sym->ts.type != BT_LOGICAL)
4388 {
4389 tree cint = gfc_get_int_type (gfc_c_int_kind);
4390
4391 if (flag_external_blasglobal_options.x_flag_external_blas
4392 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
4393 && (sym->ts.kind == 4 || sym->ts.kind == 8))
4394 {
4395 tree gemm_fndecl;
4396
4397 if (sym->ts.type == BT_REAL)
4398 {
4399 if (sym->ts.kind == 4)
4400 gemm_fndecl = gfor_fndecl_sgemm;
4401 else
4402 gemm_fndecl = gfor_fndecl_dgemm;
4403 }
4404 else
4405 {
4406 if (sym->ts.kind == 4)
4407 gemm_fndecl = gfor_fndecl_cgemm;
4408 else
4409 gemm_fndecl = gfor_fndecl_zgemm;
4410 }
4411
4412 vec_alloc (append_args, 3);
4413 append_args->quick_push (build_int_cst (cint, 1));
4414 append_args->quick_push (build_int_cst (cint,
4415 flag_blas_matmul_limitglobal_options.x_flag_blas_matmul_limit));
4416 append_args->quick_push (gfc_build_addr_expr (NULL_TREE(tree) __null,
4417 gemm_fndecl));
4418 }
4419 else
4420 {
4421 vec_alloc (append_args, 3);
4422 append_args->quick_push (build_int_cst (cint, 0));
4423 append_args->quick_push (build_int_cst (cint, 0));
4424 append_args->quick_push (null_pointer_nodeglobal_trees[TI_NULL_POINTER]);
4425 }
4426 }
4427
4428 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
4429 append_args);
4430
4431 if (specific_symbol)
4432 gfc_free_expr (expr);
4433 else
4434 gfc_free_symbol (sym);
4435}
4436
4437/* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
4438 Implemented as
4439 any(a)
4440 {
4441 forall (i=...)
4442 if (a[i] != 0)
4443 return 1
4444 end forall
4445 return 0
4446 }
4447 all(a)
4448 {
4449 forall (i=...)
4450 if (a[i] == 0)
4451 return 0
4452 end forall
4453 return 1
4454 }
4455 */
4456static void
4457gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
4458{
4459 tree resvar;
4460 stmtblock_t block;
4461 stmtblock_t body;
4462 tree type;
4463 tree tmp;
4464 tree found;
4465 gfc_loopinfo loop;
4466 gfc_actual_arglist *actual;
4467 gfc_ss *arrayss;
4468 gfc_se arrayse;
4469 tree exit_label;
4470
4471 if (se->ss)
4472 {
4473 gfc_conv_intrinsic_funcall (se, expr);
4474 return;
4475 }
4476
4477 actual = expr->value.function.actual;
4478 type = gfc_typenode_for_spec (&expr->ts);
4479 /* Initialize the result. */
4480 resvar = gfc_create_var (type, "test");
4481 if (op == EQ_EXPR)
4482 tmp = convert (type, boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]);
4483 else
4484 tmp = convert (type, boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE]);
4485 gfc_add_modify (&se->pre, resvar, tmp);
4486
4487 /* Walk the arguments. */
4488 arrayss = gfc_walk_expr (actual->expr);
4489 gcc_assert (arrayss != gfc_ss_terminator)((void)(!(arrayss != gfc_ss_terminator) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4489, __FUNCTION__), 0 : 0))
;
4490
4491 /* Initialize the scalarizer. */
4492 gfc_init_loopinfo (&loop);
4493 exit_label = gfc_build_label_decl (NULL_TREE(tree) __null);
4494 TREE_USED (exit_label)((exit_label)->base.used_flag) = 1;
4495 gfc_add_ss_to_loop (&loop, arrayss);
4496
4497 /* Initialize the loop. */
4498 gfc_conv_ss_startstride (&loop);
4499 gfc_conv_loop_setup (&loop, &expr->where);
4500
4501 gfc_mark_ss_chain_used (arrayss, 1);
4502 /* Generate the loop body. */
4503 gfc_start_scalarized_body (&loop, &body);
4504
4505 /* If the condition matches then set the return value. */
4506 gfc_start_block (&block);
4507 if (op == EQ_EXPR)
4508 tmp = convert (type, boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE]);
4509 else
4510 tmp = convert (type, boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]);
4511 gfc_add_modify (&block, resvar, tmp);
4512
4513 /* And break out of the loop. */
4514 tmp = build1_v (GOTO_EXPR, exit_label)fold_build1_loc (input_location, GOTO_EXPR, global_trees[TI_VOID_TYPE
], exit_label)
;
4515 gfc_add_expr_to_block (&block, tmp);
4516
4517 found = gfc_finish_block (&block);
4518
4519 /* Check this element. */
4520 gfc_init_se (&arrayse, NULL__null);
4521 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4522 arrayse.ss = arrayss;
4523 gfc_conv_expr_val (&arrayse, actual->expr);
4524
4525 gfc_add_block_to_block (&body, &arrayse.pre);
4526 tmp = fold_build2_loc (input_location, op, logical_type_node, arrayse.expr,
4527 build_int_cst (TREE_TYPE (arrayse.expr)((contains_struct_check ((arrayse.expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4527, __FUNCTION__))->typed.type)
, 0));
4528 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], tmp, found, build_empty_stmt (input_location))
;
4529 gfc_add_expr_to_block (&body, tmp);
4530 gfc_add_block_to_block (&body, &arrayse.post);
4531
4532 gfc_trans_scalarizing_loops (&loop, &body);
4533
4534 /* Add the exit label. */
4535 tmp = build1_v (LABEL_EXPR, exit_label)fold_build1_loc (input_location, LABEL_EXPR, global_trees[TI_VOID_TYPE
], exit_label)
;
4536 gfc_add_expr_to_block (&loop.pre, tmp);
4537
4538 gfc_add_block_to_block (&se->pre, &loop.pre);
4539 gfc_add_block_to_block (&se->pre, &loop.post);
4540 gfc_cleanup_loop (&loop);
4541
4542 se->expr = resvar;
4543}
4544
4545
4546/* Generate the constant 180 / pi, which is used in the conversion
4547 of acosd(), asind(), atand(), atan2d(). */
4548
4549static tree
4550rad2deg (int kind)
4551{
4552 tree retval;
4553 mpfr_t pi, t0;
4554
4555 gfc_set_model_kind (kind);
4556 mpfr_init (pi);
4557 mpfr_init (t0);
4558 mpfr_set_si (t0, 180, GFC_RND_MODEMPFR_RNDN);
4559 mpfr_const_pi (pi, GFC_RND_MODEMPFR_RNDN);
4560 mpfr_div (t0, t0, pi, GFC_RND_MODEMPFR_RNDN);
4561 retval = gfc_conv_mpfr_to_tree (t0, kind, 0);
4562 mpfr_clear (t0);
4563 mpfr_clear (pi);
4564 return retval;
4565}
4566
4567
4568static gfc_intrinsic_map_t *
4569gfc_lookup_intrinsic (gfc_isym_id id)
4570{
4571 gfc_intrinsic_map_t *m = gfc_intrinsic_map;
4572 for (; m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
4573 if (id == m->id)
4574 break;
4575 gcc_assert (id == m->id)((void)(!(id == m->id) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4575, __FUNCTION__), 0 : 0))
;
4576 return m;
4577}
4578
4579
4580/* ACOSD(x) is translated into ACOS(x) * 180 / pi.
4581 ASIND(x) is translated into ASIN(x) * 180 / pi.
4582 ATAND(x) is translated into ATAN(x) * 180 / pi. */
4583
4584static void
4585gfc_conv_intrinsic_atrigd (gfc_se * se, gfc_expr * expr, gfc_isym_id id)
4586{
4587 tree arg;
4588 tree atrigd;
4589 tree type;
4590 gfc_intrinsic_map_t *m;
4591
4592 type = gfc_typenode_for_spec (&expr->ts);
4593
4594 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4595
4596 switch (id)
4597 {
4598 case GFC_ISYM_ACOSD:
4599 m = gfc_lookup_intrinsic (GFC_ISYM_ACOS);
4600 break;
4601 case GFC_ISYM_ASIND:
4602 m = gfc_lookup_intrinsic (GFC_ISYM_ASIN);
4603 break;
4604 case GFC_ISYM_ATAND:
4605 m = gfc_lookup_intrinsic (GFC_ISYM_ATAN);
4606 break;
4607 default:
4608 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4608, __FUNCTION__))
;
4609 }
4610 atrigd = gfc_get_intrinsic_lib_fndecl (m, expr);
4611 atrigd = build_call_expr_loc (input_location, atrigd, 1, arg);
4612
4613 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, atrigd,
4614 fold_convert (type, rad2deg (expr->ts.kind))fold_convert_loc (((location_t) 0), type, rad2deg (expr->ts
.kind))
);
4615}
4616
4617
4618/* COTAN(X) is translated into -TAN(X+PI/2) for REAL argument and
4619 COS(X) / SIN(X) for COMPLEX argument. */
4620
4621static void
4622gfc_conv_intrinsic_cotan (gfc_se *se, gfc_expr *expr)
4623{
4624 gfc_intrinsic_map_t *m;
4625 tree arg;
4626 tree type;
4627
4628 type = gfc_typenode_for_spec (&expr->ts);
4629 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4630
4631 if (expr->ts.type == BT_REAL)
4632 {
4633 tree tan;
4634 tree tmp;
4635 mpfr_t pio2;
4636
4637 /* Create pi/2. */
4638 gfc_set_model_kind (expr->ts.kind);
4639 mpfr_init (pio2);
4640 mpfr_const_pi (pio2, GFC_RND_MODEMPFR_RNDN);
4641 mpfr_div_ui (pio2, pio2, 2, GFC_RND_MODEMPFR_RNDN);
4642 tmp = gfc_conv_mpfr_to_tree (pio2, expr->ts.kind, 0);
4643 mpfr_clear (pio2);
4644
4645 /* Find tan builtin function. */
4646 m = gfc_lookup_intrinsic (GFC_ISYM_TAN);
4647 tan = gfc_get_intrinsic_lib_fndecl (m, expr);
4648 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, arg, tmp);
4649 tan = build_call_expr_loc (input_location, tan, 1, tmp);
4650 se->expr = fold_build1_loc (input_location, NEGATE_EXPR, type, tan);
4651 }
4652 else
4653 {
4654 tree sin;
4655 tree cos;
4656
4657 /* Find cos builtin function. */
4658 m = gfc_lookup_intrinsic (GFC_ISYM_COS);
4659 cos = gfc_get_intrinsic_lib_fndecl (m, expr);
4660 cos = build_call_expr_loc (input_location, cos, 1, arg);
4661
4662 /* Find sin builtin function. */
4663 m = gfc_lookup_intrinsic (GFC_ISYM_SIN);
4664 sin = gfc_get_intrinsic_lib_fndecl (m, expr);
4665 sin = build_call_expr_loc (input_location, sin, 1, arg);
4666
4667 /* Divide cos by sin. */
4668 se->expr = fold_build2_loc (input_location, RDIV_EXPR, type, cos, sin);
4669 }
4670}
4671
4672
4673/* COTAND(X) is translated into -TAND(X+90) for REAL argument. */
4674
4675static void
4676gfc_conv_intrinsic_cotand (gfc_se *se, gfc_expr *expr)
4677{
4678 tree arg;
4679 tree type;
4680 tree ninety_tree;
4681 mpfr_t ninety;
4682
4683 type = gfc_typenode_for_spec (&expr->ts);
4684 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4685
4686 gfc_set_model_kind (expr->ts.kind);
4687
4688 /* Build the tree for x + 90. */
4689 mpfr_init_set_ui (ninety, 90, GFC_RND_MODE)( mpfr_init(ninety), mpfr_set_ui((ninety), (90), (MPFR_RNDN))
)
;
4690 ninety_tree = gfc_conv_mpfr_to_tree (ninety, expr->ts.kind, 0);
4691 arg = fold_build2_loc (input_location, PLUS_EXPR, type, arg, ninety_tree);
4692 mpfr_clear (ninety);
4693
4694 /* Find tand. */
4695 gfc_intrinsic_map_t *m = gfc_lookup_intrinsic (GFC_ISYM_TAND);
4696 tree tand = gfc_get_intrinsic_lib_fndecl (m, expr);
4697 tand = build_call_expr_loc (input_location, tand, 1, arg);
4698
4699 se->expr = fold_build1_loc (input_location, NEGATE_EXPR, type, tand);
4700}
4701
4702
4703/* ATAN2D(Y,X) is translated into ATAN2(Y,X) * 180 / PI. */
4704
4705static void
4706gfc_conv_intrinsic_atan2d (gfc_se *se, gfc_expr *expr)
4707{
4708 tree args[2];
4709 tree atan2d;
4710 tree type;
4711
4712 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4713 type = TREE_TYPE (args[0])((contains_struct_check ((args[0]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4713, __FUNCTION__))->typed.type)
;
4714
4715 gfc_intrinsic_map_t *m = gfc_lookup_intrinsic (GFC_ISYM_ATAN2);
4716 atan2d = gfc_get_intrinsic_lib_fndecl (m, expr);
4717 atan2d = build_call_expr_loc (input_location, atan2d, 2, args[0], args[1]);
4718
4719 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, atan2d,
4720 rad2deg (expr->ts.kind));
4721}
4722
4723
4724/* COUNT(A) = Number of true elements in A. */
4725static void
4726gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
4727{
4728 tree resvar;
4729 tree type;
4730 stmtblock_t body;
4731 tree tmp;
4732 gfc_loopinfo loop;
4733 gfc_actual_arglist *actual;
4734 gfc_ss *arrayss;
4735 gfc_se arrayse;
4736
4737 if (se->ss)
4738 {
4739 gfc_conv_intrinsic_funcall (se, expr);
4740 return;
4741 }
4742
4743 actual = expr->value.function.actual;
4744
4745 type = gfc_typenode_for_spec (&expr->ts);
4746 /* Initialize the result. */
4747 resvar = gfc_create_var (type, "count");
4748 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
4749
4750 /* Walk the arguments. */
4751 arrayss = gfc_walk_expr (actual->expr);
4752 gcc_assert (arrayss != gfc_ss_terminator)((void)(!(arrayss != gfc_ss_terminator) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4752, __FUNCTION__), 0 : 0))
;
4753
4754 /* Initialize the scalarizer. */
4755 gfc_init_loopinfo (&loop);
4756 gfc_add_ss_to_loop (&loop, arrayss);
4757
4758 /* Initialize the loop. */
4759 gfc_conv_ss_startstride (&loop);
4760 gfc_conv_loop_setup (&loop, &expr->where);
4761
4762 gfc_mark_ss_chain_used (arrayss, 1);
4763 /* Generate the loop body. */
4764 gfc_start_scalarized_body (&loop, &body);
4765
4766 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar)((contains_struct_check ((resvar), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4766, __FUNCTION__))->typed.type)
,
4767 resvar, build_int_cst (TREE_TYPE (resvar)((contains_struct_check ((resvar), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4767, __FUNCTION__))->typed.type)
, 1));
4768 tmp = build2_v (MODIFY_EXPR, resvar, tmp)fold_build2_loc (input_location, MODIFY_EXPR, global_trees[TI_VOID_TYPE
], resvar, tmp)
;
4769
4770 gfc_init_se (&arrayse, NULL__null);
4771 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4772 arrayse.ss = arrayss;
4773 gfc_conv_expr_val (&arrayse, actual->expr);
4774 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], arrayse.expr, tmp, build_empty_stmt (input_location))
4775 build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], arrayse.expr, tmp, build_empty_stmt (input_location))
;
4776
4777 gfc_add_block_to_block (&body, &arrayse.pre);
4778 gfc_add_expr_to_block (&body, tmp);
4779 gfc_add_block_to_block (&body, &arrayse.post);
4780
4781 gfc_trans_scalarizing_loops (&loop, &body);
4782
4783 gfc_add_block_to_block (&se->pre, &loop.pre);
4784 gfc_add_block_to_block (&se->pre, &loop.post);
4785 gfc_cleanup_loop (&loop);
4786
4787 se->expr = resvar;
4788}
4789
4790
4791/* Update given gfc_se to have ss component pointing to the nested gfc_ss
4792 struct and return the corresponding loopinfo. */
4793
4794static gfc_loopinfo *
4795enter_nested_loop (gfc_se *se)
4796{
4797 se->ss = se->ss->nested_ss;
4798 gcc_assert (se->ss == se->ss->loop->ss)((void)(!(se->ss == se->ss->loop->ss) ? fancy_abort
("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4798, __FUNCTION__), 0 : 0))
;
4799
4800 return se->ss->loop;
4801}
4802
4803/* Build the condition for a mask, which may be optional. */
4804
4805static tree
4806conv_mask_condition (gfc_se *maskse, gfc_expr *maskexpr,
4807 bool optional_mask)
4808{
4809 tree present;
4810 tree type;
4811
4812 if (optional_mask)
4813 {
4814 type = TREE_TYPE (maskse->expr)((contains_struct_check ((maskse->expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4814, __FUNCTION__))->typed.type)
;
4815 present = gfc_conv_expr_present (maskexpr->symtree->n.sym);
4816 present = convert (type, present);
4817 present = fold_build1_loc (input_location, TRUTH_NOT_EXPR, type,
4818 present);
4819 return fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
4820 type, present, maskse->expr);
4821 }
4822 else
4823 return maskse->expr;
4824}
4825
4826/* Inline implementation of the sum and product intrinsics. */
4827static void
4828gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
4829 bool norm2)
4830{
4831 tree resvar;
4832 tree scale = NULL_TREE(tree) __null;
4833 tree type;
4834 stmtblock_t body;
4835 stmtblock_t block;
4836 tree tmp;
4837 gfc_loopinfo loop, *ploop;
4838 gfc_actual_arglist *arg_array, *arg_mask;
4839 gfc_ss *arrayss = NULL__null;
4840 gfc_ss *maskss = NULL__null;
4841 gfc_se arrayse;
4842 gfc_se maskse;
4843 gfc_se *parent_se;
4844 gfc_expr *arrayexpr;
4845 gfc_expr *maskexpr;
4846 bool optional_mask;
4847
4848 if (expr->rank > 0)
4849 {
4850 gcc_assert (gfc_inline_intrinsic_function_p (expr))((void)(!(gfc_inline_intrinsic_function_p (expr)) ? fancy_abort
("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4850, __FUNCTION__), 0 : 0))
;
4851 parent_se = se;
4852 }
4853 else
4854 parent_se = NULL__null;
4855
4856 type = gfc_typenode_for_spec (&expr->ts);
4857 /* Initialize the result. */
4858 resvar = gfc_create_var (type, "val");
4859 if (norm2)
4860 {
4861 /* result = 0.0;
4862 scale = 1.0. */
4863 scale = gfc_create_var (type, "scale");
4864 gfc_add_modify (&se->pre, scale,
4865 gfc_build_const (type, integer_one_nodeglobal_trees[TI_INTEGER_ONE]));
4866 tmp = gfc_build_const (type, integer_zero_nodeglobal_trees[TI_INTEGER_ZERO]);
4867 }
4868 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
4869 tmp = gfc_build_const (type, integer_zero_nodeglobal_trees[TI_INTEGER_ZERO]);
4870 else if (op == NE_EXPR)
4871 /* PARITY. */
4872 tmp = convert (type, boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE]);
4873 else if (op == BIT_AND_EXPR)
4874 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
4875 type, integer_one_nodeglobal_trees[TI_INTEGER_ONE]));
4876 else
4877 tmp = gfc_build_const (type, integer_one_nodeglobal_trees[TI_INTEGER_ONE]);
4878
4879 gfc_add_modify (&se->pre, resvar, tmp);
4880
4881 arg_array = expr->value.function.actual;
4882
4883 arrayexpr = arg_array->expr;
4884
4885 if (op == NE_EXPR || norm2)
4886 {
4887 /* PARITY and NORM2. */
4888 maskexpr = NULL__null;
4889 optional_mask = false;
4890 }
4891 else
4892 {
4893 arg_mask = arg_array->next->next;
4894 gcc_assert (arg_mask != NULL)((void)(!(arg_mask != __null) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4894, __FUNCTION__), 0 : 0))
;
4895 maskexpr = arg_mask->expr;
4896 optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
4897 && maskexpr->symtree->n.sym->attr.dummy
4898 && maskexpr->symtree->n.sym->attr.optional;
4899 }
4900
4901 if (expr->rank == 0)
4902 {
4903 /* Walk the arguments. */
4904 arrayss = gfc_walk_expr (arrayexpr);
4905 gcc_assert (arrayss != gfc_ss_terminator)((void)(!(arrayss != gfc_ss_terminator) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4905, __FUNCTION__), 0 : 0))
;
4906
4907 if (maskexpr && maskexpr->rank > 0)
4908 {
4909 maskss = gfc_walk_expr (maskexpr);
4910 gcc_assert (maskss != gfc_ss_terminator)((void)(!(maskss != gfc_ss_terminator) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4910, __FUNCTION__), 0 : 0))
;
4911 }
4912 else
4913 maskss = NULL__null;
4914
4915 /* Initialize the scalarizer. */
4916 gfc_init_loopinfo (&loop);
4917
4918 /* We add the mask first because the number of iterations is
4919 taken from the last ss, and this breaks if an absent
4920 optional argument is used for mask. */
4921
4922 if (maskexpr && maskexpr->rank > 0)
4923 gfc_add_ss_to_loop (&loop, maskss);
4924 gfc_add_ss_to_loop (&loop, arrayss);
4925
4926 /* Initialize the loop. */
4927 gfc_conv_ss_startstride (&loop);
4928 gfc_conv_loop_setup (&loop, &expr->where);
4929
4930 if (maskexpr && maskexpr->rank > 0)
4931 gfc_mark_ss_chain_used (maskss, 1);
4932 gfc_mark_ss_chain_used (arrayss, 1);
4933
4934 ploop = &loop;
4935 }
4936 else
4937 /* All the work has been done in the parent loops. */
4938 ploop = enter_nested_loop (se);
4939
4940 gcc_assert (ploop)((void)(!(ploop) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 4940, __FUNCTION__), 0 : 0))
;
4941
4942 /* Generate the loop body. */
4943 gfc_start_scalarized_body (ploop, &body);
4944
4945 /* If we have a mask, only add this element if the mask is set. */
4946 if (maskexpr && maskexpr->rank > 0)
4947 {
4948 gfc_init_se (&maskse, parent_se);
4949 gfc_copy_loopinfo_to_se (&maskse, ploop);
4950 if (expr->rank == 0)
4951 maskse.ss = maskss;
4952 gfc_conv_expr_val (&maskse, maskexpr);
4953 gfc_add_block_to_block (&body, &maskse.pre);
4954
4955 gfc_start_block (&block);
4956 }
4957 else
4958 gfc_init_block (&block);
4959
4960 /* Do the actual summation/product. */
4961 gfc_init_se (&arrayse, parent_se);
4962 gfc_copy_loopinfo_to_se (&arrayse, ploop);
4963 if (expr->rank == 0)
4964 arrayse.ss = arrayss;
4965 gfc_conv_expr_val (&arrayse, arrayexpr);
4966 gfc_add_block_to_block (&block, &arrayse.pre);
4967
4968 if (norm2)
4969 {
4970 /* if (x (i) != 0.0)
4971 {
4972 absX = abs(x(i))
4973 if (absX > scale)
4974 {
4975 val = scale/absX;
4976 result = 1.0 + result * val * val;
4977 scale = absX;
4978 }
4979 else
4980 {
4981 val = absX/scale;
4982 result += val * val;
4983 }
4984 } */
4985 tree res1, res2, cond, absX, val;
4986 stmtblock_t ifblock1, ifblock2, ifblock3;
4987
4988 gfc_init_block (&ifblock1);
4989
4990 absX = gfc_create_var (type, "absX");
4991 gfc_add_modify (&ifblock1, absX,
4992 fold_build1_loc (input_location, ABS_EXPR, type,
4993 arrayse.expr));
4994 val = gfc_create_var (type, "val");
4995 gfc_add_expr_to_block (&ifblock1, val);
4996
4997 gfc_init_block (&ifblock2);
4998 gfc_add_modify (&ifblock2, val,
4999 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
5000 absX));
5001 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
5002 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
5003 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
5004 gfc_build_const (type, integer_one_nodeglobal_trees[TI_INTEGER_ONE]));
5005 gfc_add_modify (&ifblock2, resvar, res1);
5006 gfc_add_modify (&ifblock2, scale, absX);
5007 res1 = gfc_finish_block (&ifblock2);
5008
5009 gfc_init_block (&ifblock3);
5010 gfc_add_modify (&ifblock3, val,
5011 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
5012 scale));
5013 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
5014 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
5015 gfc_add_modify (&ifblock3, resvar, res2);
5016 res2 = gfc_finish_block (&ifblock3);
5017
5018 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
5019 absX, scale);
5020 tmp = build3_v (COND_EXPR, cond, res1, res2)fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], cond, res1, res2)
;
5021 gfc_add_expr_to_block (&ifblock1, tmp);
5022 tmp = gfc_finish_block (&ifblock1);
5023
5024 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
5025 arrayse.expr,
5026 gfc_build_const (type, integer_zero_nodeglobal_trees[TI_INTEGER_ZERO]));
5027
5028 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], cond, tmp, build_empty_stmt (input_location))
;
5029 gfc_add_expr_to_block (&block, tmp);
5030 }
5031 else
5032 {
5033 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
5034 gfc_add_modify (&block, resvar, tmp);
5035 }
5036
5037 gfc_add_block_to_block (&block, &arrayse.post);
5038
5039 if (maskexpr && maskexpr->rank > 0)
5040 {
5041 /* We enclose the above in if (mask) {...} . If the mask is an
5042 optional argument, generate
5043 IF (.NOT. PRESENT(MASK) .OR. MASK(I)). */
5044 tree ifmask;
5045 tmp = gfc_finish_block (&block);
5046 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5047 tmp = build3_v (COND_EXPR, ifmask, tmp,fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], ifmask, tmp, build_empty_stmt (input_location))
5048 build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], ifmask, tmp, build_empty_stmt (input_location))
;
5049 }
5050 else
5051 tmp = gfc_finish_block (&block);
5052 gfc_add_expr_to_block (&body, tmp);
5053
5054 gfc_trans_scalarizing_loops (ploop, &body);
5055
5056 /* For a scalar mask, enclose the loop in an if statement. */
5057 if (maskexpr && maskexpr->rank == 0)
5058 {
5059 gfc_init_block (&block);
5060 gfc_add_block_to_block (&block, &ploop->pre);
5061 gfc_add_block_to_block (&block, &ploop->post);
5062 tmp = gfc_finish_block (&block);
5063
5064 if (expr->rank > 0)
5065 {
5066 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], se->ss->info->data.scalar.value, tmp, build_empty_stmt
(input_location))
5067 build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], se->ss->info->data.scalar.value, tmp, build_empty_stmt
(input_location))
;
5068 gfc_advance_se_ss_chain (se);
5069 }
5070 else
5071 {
5072 tree ifmask;
5073
5074 gcc_assert (expr->rank == 0)((void)(!(expr->rank == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5074, __FUNCTION__), 0 : 0))
;
5075 gfc_init_se (&maskse, NULL__null);
5076 gfc_conv_expr_val (&maskse, maskexpr);
5077 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5078 tmp = build3_v (COND_EXPR, ifmask, tmp,fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], ifmask, tmp, build_empty_stmt (input_location))
5079 build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], ifmask, tmp, build_empty_stmt (input_location))
;
5080 }
5081
5082 gfc_add_expr_to_block (&block, tmp);
5083 gfc_add_block_to_block (&se->pre, &block);
5084 gcc_assert (se->post.head == NULL)((void)(!(se->post.head == __null) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5084, __FUNCTION__), 0 : 0))
;
5085 }
5086 else
5087 {
5088 gfc_add_block_to_block (&se->pre, &ploop->pre);
5089 gfc_add_block_to_block (&se->pre, &ploop->post);
5090 }
5091
5092 if (expr->rank == 0)
5093 gfc_cleanup_loop (ploop);
5094
5095 if (norm2)
5096 {
5097 /* result = scale * sqrt(result). */
5098 tree sqrt;
5099 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
5100 resvar = build_call_expr_loc (input_location,
5101 sqrt, 1, resvar);
5102 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
5103 }
5104
5105 se->expr = resvar;
5106}
5107
5108
5109/* Inline implementation of the dot_product intrinsic. This function
5110 is based on gfc_conv_intrinsic_arith (the previous function). */
5111static void
5112gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
5113{
5114 tree resvar;
5115 tree type;
5116 stmtblock_t body;
5117 stmtblock_t block;
5118 tree tmp;
5119 gfc_loopinfo loop;
5120 gfc_actual_arglist *actual;
5121 gfc_ss *arrayss1, *arrayss2;
5122 gfc_se arrayse1, arrayse2;
5123 gfc_expr *arrayexpr1, *arrayexpr2;
5124
5125 type = gfc_typenode_for_spec (&expr->ts);
5126
5127 /* Initialize the result. */
5128 resvar = gfc_create_var (type, "val");
5129 if (expr->ts.type == BT_LOGICAL)
5130 tmp = build_int_cst (type, 0);
5131 else
5132 tmp = gfc_build_const (type, integer_zero_nodeglobal_trees[TI_INTEGER_ZERO]);
5133
5134 gfc_add_modify (&se->pre, resvar, tmp);
5135
5136 /* Walk argument #1. */
5137 actual = expr->value.function.actual;
5138 arrayexpr1 = actual->expr;
5139 arrayss1 = gfc_walk_expr (arrayexpr1);
5140 gcc_assert (arrayss1 != gfc_ss_terminator)((void)(!(arrayss1 != gfc_ss_terminator) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5140, __FUNCTION__), 0 : 0))
;
5141
5142 /* Walk argument #2. */
5143 actual = actual->next;
5144 arrayexpr2 = actual->expr;
5145 arrayss2 = gfc_walk_expr (arrayexpr2);
5146 gcc_assert (arrayss2 != gfc_ss_terminator)((void)(!(arrayss2 != gfc_ss_terminator) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5146, __FUNCTION__), 0 : 0))
;
5147
5148 /* Initialize the scalarizer. */
5149 gfc_init_loopinfo (&loop);
5150 gfc_add_ss_to_loop (&loop, arrayss1);
5151 gfc_add_ss_to_loop (&loop, arrayss2);
5152
5153 /* Initialize the loop. */
5154 gfc_conv_ss_startstride (&loop);
5155 gfc_conv_loop_setup (&loop, &expr->where);
5156
5157 gfc_mark_ss_chain_used (arrayss1, 1);
5158 gfc_mark_ss_chain_used (arrayss2, 1);
5159
5160 /* Generate the loop body. */
5161 gfc_start_scalarized_body (&loop, &body);
5162 gfc_init_block (&block);
5163
5164 /* Make the tree expression for [conjg(]array1[)]. */
5165 gfc_init_se (&arrayse1, NULL__null);
5166 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
5167 arrayse1.ss = arrayss1;
5168 gfc_conv_expr_val (&arrayse1, arrayexpr1);
5169 if (expr->ts.type == BT_COMPLEX)
5170 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
5171 arrayse1.expr);
5172 gfc_add_block_to_block (&block, &arrayse1.pre);
5173
5174 /* Make the tree expression for array2. */
5175 gfc_init_se (&arrayse2, NULL__null);
5176 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
5177 arrayse2.ss = arrayss2;
5178 gfc_conv_expr_val (&arrayse2, arrayexpr2);
5179 gfc_add_block_to_block (&block, &arrayse2.pre);
5180
5181 /* Do the actual product and sum. */
5182 if (expr->ts.type == BT_LOGICAL)
5183 {
5184 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
5185 arrayse1.expr, arrayse2.expr);
5186 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
5187 }
5188 else
5189 {
5190 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
5191 arrayse2.expr);
5192 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
5193 }
5194 gfc_add_modify (&block, resvar, tmp);
5195
5196 /* Finish up the loop block and the loop. */
5197 tmp = gfc_finish_block (&block);
5198 gfc_add_expr_to_block (&body, tmp);
5199
5200 gfc_trans_scalarizing_loops (&loop, &body);
5201 gfc_add_block_to_block (&se->pre, &loop.pre);
5202 gfc_add_block_to_block (&se->pre, &loop.post);
5203 gfc_cleanup_loop (&loop);
5204
5205 se->expr = resvar;
5206}
5207
5208
5209/* Remove unneeded kind= argument from actual argument list when the
5210 result conversion is dealt with in a different place. */
5211
5212static void
5213strip_kind_from_actual (gfc_actual_arglist * actual)
5214{
5215 for (gfc_actual_arglist *a = actual; a; a = a->next)
5216 {
5217 if (a && a->name && strcmp (a->name, "kind") == 0)
5218 {
5219 gfc_free_expr (a->expr);
5220 a->expr = NULL__null;
5221 }
5222 }
5223}
5224
5225/* Emit code for minloc or maxloc intrinsic. There are many different cases
5226 we need to handle. For performance reasons we sometimes create two
5227 loops instead of one, where the second one is much simpler.
5228 Examples for minloc intrinsic:
5229 1) Result is an array, a call is generated
5230 2) Array mask is used and NaNs need to be supported:
5231 limit = Infinity;
5232 pos = 0;
5233 S = from;
5234 while (S <= to) {
5235 if (mask[S]) {
5236 if (pos == 0) pos = S + (1 - from);
5237 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
5238 }
5239 S++;
5240 }
5241 goto lab2;
5242 lab1:;
5243 while (S <= to) {
5244 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
5245 S++;
5246 }
5247 lab2:;
5248 3) NaNs need to be supported, but it is known at compile time or cheaply
5249 at runtime whether array is nonempty or not:
5250 limit = Infinity;
5251 pos = 0;
5252 S = from;
5253 while (S <= to) {
5254 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
5255 S++;
5256 }
5257 if (from <= to) pos = 1;
5258 goto lab2;
5259 lab1:;
5260 while (S <= to) {
5261 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
5262 S++;
5263 }
5264 lab2:;
5265 4) NaNs aren't supported, array mask is used:
5266 limit = infinities_supported ? Infinity : huge (limit);
5267 pos = 0;
5268 S = from;
5269 while (S <= to) {
5270 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
5271 S++;
5272 }
5273 goto lab2;
5274 lab1:;
5275 while (S <= to) {
5276 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
5277 S++;
5278 }
5279 lab2:;
5280 5) Same without array mask:
5281 limit = infinities_supported ? Infinity : huge (limit);
5282 pos = (from <= to) ? 1 : 0;
5283 S = from;
5284 while (S <= to) {
5285 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
5286 S++;
5287 }
5288 For 3) and 5), if mask is scalar, this all goes into a conditional,
5289 setting pos = 0; in the else branch.
5290
5291 Since we now also support the BACK argument, instead of using
5292 if (a[S] < limit), we now use
5293
5294 if (back)
5295 cond = a[S] <= limit;
5296 else
5297 cond = a[S] < limit;
5298 if (cond) {
5299 ....
5300
5301 The optimizer is smart enough to move the condition out of the loop.
5302 The are now marked as unlikely to for further speedup. */
5303
5304static void
5305gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
5306{
5307 stmtblock_t body;
5308 stmtblock_t block;
5309 stmtblock_t ifblock;
5310 stmtblock_t elseblock;
5311 tree limit;
5312 tree type;
5313 tree tmp;
5314 tree cond;
5315 tree elsetmp;
5316 tree ifbody;
5317 tree offset;
5318 tree nonempty;
5319 tree lab1, lab2;
5320 tree b_if, b_else;
5321 gfc_loopinfo loop;
5322 gfc_actual_arglist *actual;
5323 gfc_ss *arrayss;
5324 gfc_ss *maskss;
5325 gfc_se arrayse;
5326 gfc_se maskse;
5327 gfc_expr *arrayexpr;
5328 gfc_expr *maskexpr;
5329 gfc_expr *backexpr;
5330 gfc_se backse;
5331 tree pos;
5332 int n;
5333 bool optional_mask;
5334
5335 actual = expr->value.function.actual;
5336
5337 /* The last argument, BACK, is passed by value. Ensure that
5338 by setting its name to %VAL. */
5339 for (gfc_actual_arglist *a = actual; a; a = a->next)
5340 {
5341 if (a->next == NULL__null)
5342 a->name = "%VAL";
5343 }
5344
5345 if (se->ss)
5346 {
5347 gfc_conv_intrinsic_funcall (se, expr);
5348 return;
5349 }
5350
5351 arrayexpr = actual->expr;
5352
5353 /* Special case for character maxloc. Remove unneeded actual
5354 arguments, then call a library function. */
5355
5356 if (arrayexpr->ts.type == BT_CHARACTER)
5357 {
5358 gfc_actual_arglist *a;
5359 a = actual;
5360 strip_kind_from_actual (a);
5361 while (a)
5362 {
5363 if (a->name && strcmp (a->name, "dim") == 0)
5364 {
5365 gfc_free_expr (a->expr);
5366 a->expr = NULL__null;
5367 }
5368 a = a->next;
5369 }
5370 gfc_conv_intrinsic_funcall (se, expr);
5371 return;
5372 }
5373
5374 /* Initialize the result. */
5375 pos = gfc_create_var (gfc_array_index_type, "pos");
5376 offset = gfc_create_var (gfc_array_index_type, "offset");
5377 type = gfc_typenode_for_spec (&expr->ts);
5378
5379 /* Walk the arguments. */
5380 arrayss = gfc_walk_expr (arrayexpr);
5381 gcc_assert (arrayss != gfc_ss_terminator)((void)(!(arrayss != gfc_ss_terminator) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5381, __FUNCTION__), 0 : 0))
;
5382
5383 actual = actual->next->next;
5384 gcc_assert (actual)((void)(!(actual) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5384, __FUNCTION__), 0 : 0))
;
5385 maskexpr = actual->expr;
5386 optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
5387 && maskexpr->symtree->n.sym->attr.dummy
5388 && maskexpr->symtree->n.sym->attr.optional;
5389 backexpr = actual->next->next->expr;
5390 nonempty = NULL__null;
5391 if (maskexpr && maskexpr->rank != 0)
5392 {
5393 maskss = gfc_walk_expr (maskexpr);
5394 gcc_assert (maskss != gfc_ss_terminator)((void)(!(maskss != gfc_ss_terminator) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5394, __FUNCTION__), 0 : 0))
;
5395 }
5396 else
5397 {
5398 mpz_t asize;
5399 if (gfc_array_size (arrayexpr, &asize))
5400 {
5401 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
5402 mpz_clear__gmpz_clear (asize);
5403 nonempty = fold_build2_loc (input_location, GT_EXPR,
5404 logical_type_node, nonempty,
5405 gfc_index_zero_nodegfc_rank_cst[0]);
5406 }
5407 maskss = NULL__null;
5408 }
5409
5410 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
5411 switch (arrayexpr->ts.type)
5412 {
5413 case BT_REAL:
5414 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit)((contains_struct_check ((limit), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5414, __FUNCTION__))->typed.type)
, arrayexpr->ts.kind);
5415 break;
5416
5417 case BT_INTEGER:
5418 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
5419 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
5420 arrayexpr->ts.kind);
5421 break;
5422
5423 default:
5424 gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5424, __FUNCTION__))
;
5425 }
5426
5427 /* We start with the most negative possible value for MAXLOC, and the most
5428 positive possible value for MINLOC. The most negative possible value is
5429 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
5430 possible value is HUGE in both cases. */
5431 if (op == GT_EXPR)
5432 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp)((contains_struct_check ((tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5432, __FUNCTION__))->typed.type)
, tmp);
5433 if (op == GT_EXPR && arrayexpr->ts.type == BT_INTEGER)
5434 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp)((contains_struct_check ((tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5434, __FUNCTION__))->typed.type)
, tmp,
5435 build_int_cst (TREE_TYPE (tmp)((contains_struct_check ((tmp), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5435, __FUNCTION__))->typed.type)
, 1));
5436
5437 gfc_add_modify (&se->pre, limit, tmp);
5438
5439 /* Initialize the scalarizer. */
5440 gfc_init_loopinfo (&loop);
5441
5442 /* We add the mask first because the number of iterations is taken
5443 from the last ss, and this breaks if an absent optional argument
5444 is used for mask. */
5445
5446 if (maskss)
5447 gfc_add_ss_to_loop (&loop, maskss);
5448
5449 gfc_add_ss_to_loop (&loop, arrayss);
5450
5451 /* Initialize the loop. */
5452 gfc_conv_ss_startstride (&loop);
5453
5454 /* The code generated can have more than one loop in sequence (see the
5455 comment at the function header). This doesn't work well with the
5456 scalarizer, which changes arrays' offset when the scalarization loops
5457 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
5458 are currently inlined in the scalar case only (for which loop is of rank
5459 one). As there is no dependency to care about in that case, there is no
5460 temporary, so that we can use the scalarizer temporary code to handle
5461 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
5462 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
5463 to restore offset.
5464 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
5465 should eventually go away. We could either create two loops properly,
5466 or find another way to save/restore the array offsets between the two
5467 loops (without conflicting with temporary management), or use a single
5468 loop minmaxloc implementation. See PR 31067. */
5469 loop.temp_dim = loop.dimen;
5470 gfc_conv_loop_setup (&loop, &expr->where);
5471
5472 gcc_assert (loop.dimen == 1)((void)(!(loop.dimen == 1) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5472, __FUNCTION__), 0 : 0))
;
5473 if (nonempty == NULL__null && maskss == NULL__null && loop.from[0] && loop.to[0])
5474 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
5475 loop.from[0], loop.to[0]);
5476
5477 lab1 = NULL__null;
5478 lab2 = NULL__null;
5479 /* Initialize the position to zero, following Fortran 2003. We are free
5480 to do this because Fortran 95 allows the result of an entirely false
5481 mask to be processor dependent. If we know at compile time the array
5482 is non-empty and no MASK is used, we can initialize to 1 to simplify
5483 the inner loop. */
5484 if (nonempty != NULL__null && !HONOR_NANS (DECL_MODE (limit)((contains_struct_check ((limit), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5484, __FUNCTION__))->decl_common.mode)
))
5485 gfc_add_modify (&loop.pre, pos,
5486 fold_build3_loc (input_location, COND_EXPR,
5487 gfc_array_index_type,
5488 nonempty, gfc_index_one_nodegfc_rank_cst[1],
5489 gfc_index_zero_nodegfc_rank_cst[0]));
5490 else
5491 {
5492 gfc_add_modify (&loop.pre, pos, gfc_index_zero_nodegfc_rank_cst[0]);
5493 lab1 = gfc_build_label_decl (NULL_TREE(tree) __null);
5494 TREE_USED (lab1)((lab1)->base.used_flag) = 1;
5495 lab2 = gfc_build_label_decl (NULL_TREE(tree) __null);
5496 TREE_USED (lab2)((lab2)->base.used_flag) = 1;
5497 }
5498
5499 /* An offset must be added to the loop
5500 counter to obtain the required position. */
5501 gcc_assert (loop.from[0])((void)(!(loop.from[0]) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5501, __FUNCTION__), 0 : 0))
;
5502
5503 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5504 gfc_index_one_nodegfc_rank_cst[1], loop.from[0]);
5505 gfc_add_modify (&loop.pre, offset, tmp);
5506
5507 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
5508 if (maskss)
5509 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
5510 /* Generate the loop body. */
5511 gfc_start_scalarized_body (&loop, &body);
5512
5513 /* If we have a mask, only check this element if the mask is set. */
5514 if (maskss)
5515 {
5516 gfc_init_se (&maskse, NULL__null);
5517 gfc_copy_loopinfo_to_se (&maskse, &loop);
5518 maskse.ss = maskss;
5519 gfc_conv_expr_val (&maskse, maskexpr);
5520 gfc_add_block_to_block (&body, &maskse.pre);
5521
5522 gfc_start_block (&block);
5523 }
5524 else
5525 gfc_init_block (&block);
5526
5527 /* Compare with the current limit. */
5528 gfc_init_se (&arrayse, NULL__null);
5529 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5530 arrayse.ss = arrayss;
5531 gfc_conv_expr_val (&arrayse, arrayexpr);
5532 gfc_add_block_to_block (&block, &arrayse.pre);
5533
5534 gfc_init_se (&backse, NULL__null);
5535 gfc_conv_expr_val (&backse, backexpr);
5536 gfc_add_block_to_block (&block, &backse.pre);
5537
5538 /* We do the following if this is a more extreme value. */
5539 gfc_start_block (&ifblock);
5540
5541 /* Assign the value to the limit... */
5542 gfc_add_modify (&ifblock, limit, arrayse.expr);
5543
5544 if (nonempty == NULL__null && HONOR_NANS (DECL_MODE (limit)((contains_struct_check ((limit), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5544, __FUNCTION__))->decl_common.mode)
))
5545 {
5546 stmtblock_t ifblock2;
5547 tree ifbody2;
5548
5549 gfc_start_block (&ifblock2);
5550 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos)((contains_struct_check ((pos), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5550, __FUNCTION__))->typed.type)
,
5551 loop.loopvar[0], offset);
5552 gfc_add_modify (&ifblock2, pos, tmp);
5553 ifbody2 = gfc_finish_block (&ifblock2);
5554 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, pos,
5555 gfc_index_zero_nodegfc_rank_cst[0]);
5556 tmp = build3_v (COND_EXPR, cond, ifbody2,fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], cond, ifbody2, build_empty_stmt (input_location))
5557 build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], cond, ifbody2, build_empty_stmt (input_location))
;
5558 gfc_add_expr_to_block (&block, tmp);
5559 }
5560
5561 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos)((contains_struct_check ((pos), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5561, __FUNCTION__))->typed.type)
,
5562 loop.loopvar[0], offset);
5563 gfc_add_modify (&ifblock, pos, tmp);
5564
5565 if (lab1)
5566 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1)fold_build1_loc (input_location, GOTO_EXPR, global_trees[TI_VOID_TYPE
], lab1)
);
5567
5568 ifbody = gfc_finish_block (&ifblock);
5569
5570 if (!lab1 || HONOR_NANS (DECL_MODE (limit)((contains_struct_check ((limit), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5570, __FUNCTION__))->decl_common.mode)
))
5571 {
5572 if (lab1)
5573 cond = fold_build2_loc (input_location,
5574 op == GT_EXPR ? GE_EXPR : LE_EXPR,
5575 logical_type_node, arrayse.expr, limit);
5576 else
5577 {
5578 tree ifbody2, elsebody2;
5579
5580 /* We switch to > or >= depending on the value of the BACK argument. */
5581 cond = gfc_create_var (logical_type_node, "cond");
5582
5583 gfc_start_block (&ifblock);
5584 b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5585 logical_type_node, arrayse.expr, limit);
5586
5587 gfc_add_modify (&ifblock, cond, b_if);
5588 ifbody2 = gfc_finish_block (&ifblock);
5589
5590 gfc_start_block (&elseblock);
5591 b_else = fold_build2_loc (input_location, op, logical_type_node,
5592 arrayse.expr, limit);
5593
5594 gfc_add_modify (&elseblock, cond, b_else);
5595 elsebody2 = gfc_finish_block (&elseblock);
5596
5597 tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
5598 backse.expr, ifbody2, elsebody2);
5599
5600 gfc_add_expr_to_block (&block, tmp);
5601 }
5602
5603 cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
5604 ifbody = build3_v (COND_EXPR, cond, ifbody,fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], cond, ifbody, build_empty_stmt (input_location))
5605 build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], cond, ifbody, build_empty_stmt (input_location))
;
5606 }
5607 gfc_add_expr_to_block (&block, ifbody);
5608
5609 if (maskss)
5610 {
5611 /* We enclose the above in if (mask) {...}. If the mask is an
5612 optional argument, generate IF (.NOT. PRESENT(MASK)
5613 .OR. MASK(I)). */
5614
5615 tree ifmask;
5616 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5617 tmp = gfc_finish_block (&block);
5618 tmp = build3_v (COND_EXPR, ifmask, tmp,fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], ifmask, tmp, build_empty_stmt (input_location))
5619 build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], ifmask, tmp, build_empty_stmt (input_location))
;
5620 }
5621 else
5622 tmp = gfc_finish_block (&block);
5623 gfc_add_expr_to_block (&body, tmp);
5624
5625 if (lab1)
5626 {
5627 gfc_trans_scalarized_loop_boundary (&loop, &body);
5628
5629 if (HONOR_NANS (DECL_MODE (limit)((contains_struct_check ((limit), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5629, __FUNCTION__))->decl_common.mode)
))
5630 {
5631 if (nonempty != NULL__null)
5632 {
5633 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node)fold_build2_loc (input_location, MODIFY_EXPR, global_trees[TI_VOID_TYPE
], pos, gfc_rank_cst[1])
;
5634 tmp = build3_v (COND_EXPR, nonempty, ifbody,fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], nonempty, ifbody, build_empty_stmt (input_location))
5635 build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], nonempty, ifbody, build_empty_stmt (input_location))
;
5636 gfc_add_expr_to_block (&loop.code[0], tmp);
5637 }
5638 }
5639
5640 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2)fold_build1_loc (input_location, GOTO_EXPR, global_trees[TI_VOID_TYPE
], lab2)
);
5641 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1)fold_build1_loc (input_location, LABEL_EXPR, global_trees[TI_VOID_TYPE
], lab1)
);
5642
5643 /* If we have a mask, only check this element if the mask is set. */
5644 if (maskss)
5645 {
5646 gfc_init_se (&maskse, NULL__null);
5647 gfc_copy_loopinfo_to_se (&maskse, &loop);
5648 maskse.ss = maskss;
5649 gfc_conv_expr_val (&maskse, maskexpr);
5650 gfc_add_block_to_block (&body, &maskse.pre);
5651
5652 gfc_start_block (&block);
5653 }
5654 else
5655 gfc_init_block (&block);
5656
5657 /* Compare with the current limit. */
5658 gfc_init_se (&arrayse, NULL__null);
5659 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5660 arrayse.ss = arrayss;
5661 gfc_conv_expr_val (&arrayse, arrayexpr);
5662 gfc_add_block_to_block (&block, &arrayse.pre);
5663
5664 /* We do the following if this is a more extreme value. */
5665 gfc_start_block (&ifblock);
5666
5667 /* Assign the value to the limit... */
5668 gfc_add_modify (&ifblock, limit, arrayse.expr);
5669
5670 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos)((contains_struct_check ((pos), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5670, __FUNCTION__))->typed.type)
,
5671 loop.loopvar[0], offset);
5672 gfc_add_modify (&ifblock, pos, tmp);
5673
5674 ifbody = gfc_finish_block (&ifblock);
5675
5676 /* We switch to > or >= depending on the value of the BACK argument. */
5677 {
5678 tree ifbody2, elsebody2;
5679
5680 cond = gfc_create_var (logical_type_node, "cond");
5681
5682 gfc_start_block (&ifblock);
5683 b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5684 logical_type_node, arrayse.expr, limit);
5685
5686 gfc_add_modify (&ifblock, cond, b_if);
5687 ifbody2 = gfc_finish_block (&ifblock);
5688
5689 gfc_start_block (&elseblock);
5690 b_else = fold_build2_loc (input_location, op, logical_type_node,
5691 arrayse.expr, limit);
5692
5693 gfc_add_modify (&elseblock, cond, b_else);
5694 elsebody2 = gfc_finish_block (&elseblock);
5695
5696 tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
5697 backse.expr, ifbody2, elsebody2);
5698 }
5699
5700 gfc_add_expr_to_block (&block, tmp);
5701 cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
5702 tmp = build3_v (COND_EXPR, cond, ifbody,fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], cond, ifbody, build_empty_stmt (input_location))
5703 build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], cond, ifbody, build_empty_stmt (input_location))
;
5704
5705 gfc_add_expr_to_block (&block, tmp);
5706
5707 if (maskss)
5708 {
5709 /* We enclose the above in if (mask) {...}. If the mask is
5710 an optional argument, generate IF (.NOT. PRESENT(MASK)
5711 .OR. MASK(I)).*/
5712
5713 tree ifmask;
5714 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5715 tmp = gfc_finish_block (&block);
5716 tmp = build3_v (COND_EXPR, ifmask, tmp,fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], ifmask, tmp, build_empty_stmt (input_location))
5717 build_empty_stmt (input_location))fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], ifmask, tmp, build_empty_stmt (input_location))
;
5718 }
5719 else
5720 tmp = gfc_finish_block (&block);
5721 gfc_add_expr_to_block (&body, tmp);
5722 /* Avoid initializing loopvar[0] again, it should be left where
5723 it finished by the first loop. */
5724 loop.from[0] = loop.loopvar[0];
5725 }
5726
5727 gfc_trans_scalarizing_loops (&loop, &body);
5728
5729 if (lab2)
5730 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2)fold_build1_loc (input_location, LABEL_EXPR, global_trees[TI_VOID_TYPE
], lab2)
);
5731
5732 /* For a scalar mask, enclose the loop in an if statement. */
5733 if (maskexpr && maskss == NULL__null)
5734 {
5735 tree ifmask;
5736
5737 gfc_init_se (&maskse, NULL__null);
5738 gfc_conv_expr_val (&maskse, maskexpr);
5739 gfc_init_block (&block);
5740 gfc_add_block_to_block (&block, &loop.pre);
5741 gfc_add_block_to_block (&block, &loop.post);
5742 tmp = gfc_finish_block (&block);
5743
5744 /* For the else part of the scalar mask, just initialize
5745 the pos variable the same way as above. */
5746
5747 gfc_init_block (&elseblock);
5748 gfc_add_modify (&elseblock, pos, gfc_index_zero_nodegfc_rank_cst[0]);
5749 elsetmp = gfc_finish_block (&elseblock);
5750 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5751 tmp = build3_v (COND_EXPR, ifmask, tmp, elsetmp)fold_build3_loc (input_location, COND_EXPR, global_trees[TI_VOID_TYPE
], ifmask, tmp, elsetmp)
;
5752 gfc_add_expr_to_block (&block, tmp);
5753 gfc_add_block_to_block (&se->pre, &block);
5754 }
5755 else
5756 {
5757 gfc_add_block_to_block (&se->pre, &loop.pre);
5758 gfc_add_block_to_block (&se->pre, &loop.post);
5759 }
5760 gfc_cleanup_loop (&loop);
5761
5762 se->expr = convert (type, pos);
5763}
5764
5765/* Emit code for findloc. */
5766
5767static void
5768gfc_conv_intrinsic_findloc (gfc_se *se, gfc_expr *expr)
5769{
5770 gfc_actual_arglist *array_arg, *value_arg, *dim_arg, *mask_arg,
5771 *kind_arg, *back_arg;
5772 gfc_expr *value_expr;
5773 int ikind;
5774 tree resvar;
5775 stmtblock_t block;
5776 stmtblock_t body;
5777 stmtblock_t loopblock;
5778 tree type;
5779 tree tmp;
5780 tree found;
5781 tree forward_branch = NULL_TREE(tree) __null;
5782 tree back_branch;
5783 gfc_loopinfo loop;
5784 gfc_ss *arrayss;
5785 gfc_ss *maskss;
5786 gfc_se arrayse;
5787 gfc_se valuese;
5788 gfc_se maskse;
5789 gfc_se backse;
5790 tree exit_label;
5791 gfc_expr *maskexpr;
5792 tree offset;
5793 int i;
5794 bool optional_mask;
5795
5796 array_arg = expr->value.function.actual;
5797 value_arg = array_arg->next;
5798 dim_arg = value_arg->next;
5799 mask_arg = dim_arg->next;
5800 kind_arg = mask_arg->next;
5801 back_arg = kind_arg->next;
5802
5803 /* Remove kind and set ikind. */
5804 if (kind_arg->expr)
5805 {
5806 ikind = mpz_get_si__gmpz_get_si (kind_arg->expr->value.integer);
5807 gfc_free_expr (kind_arg->expr);
5808 kind_arg->expr = NULL__null;
5809 }
5810 else
5811 ikind = gfc_default_integer_kind;
5812
5813 value_expr = value_arg->expr;
5814
5815 /* Unless it's a string, pass VALUE by value. */
5816 if (value_expr->ts.type != BT_CHARACTER)
5817 value_arg->name = "%VAL";
5818
5819 /* Pass BACK argument by value. */
5820 back_arg->name = "%VAL";
5821
5822 /* Call the library if we have a character function or if
5823 rank > 0. */
5824 if (se->ss || array_arg->expr->ts.type == BT_CHARACTER)
5825 {
5826 se->ignore_optional = 1;
5827 if (expr->rank == 0)
5828 {
5829 /* Remove dim argument. */
5830 gfc_free_expr (dim_arg->expr);
5831 dim_arg->expr = NULL__null;
5832 }
5833 gfc_conv_intrinsic_funcall (se, expr);
5834 return;
5835 }
5836
5837 type = gfc_get_int_type (ikind);
5838
5839 /* Initialize the result. */
5840 resvar = gfc_create_var (gfc_array_index_type, "pos");
5841 gfc_add_modify (&se->pre, resvar, build_int_cst (gfc_array_index_type, 0));
5842 offset = gfc_create_var (gfc_array_index_type, "offset");
5843
5844 maskexpr = mask_arg->expr;
5845 optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
5846 && maskexpr->symtree->n.sym->attr.dummy
5847 && maskexpr->symtree->n.sym->attr.optional;
5848
5849 /* Generate two loops, one for BACK=.true. and one for BACK=.false. */
5850
5851 for (i = 0 ; i < 2; i++)
5852 {
5853 /* Walk the arguments. */
5854 arrayss = gfc_walk_expr (array_arg->expr);
5855 gcc_assert (arrayss != gfc_ss_terminator)((void)(!(arrayss != gfc_ss_terminator) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5855, __FUNCTION__), 0 : 0))
;
5856
5857 if (maskexpr && maskexpr->rank != 0)
5858 {
5859 maskss = gfc_walk_expr (maskexpr);
5860 gcc_assert (maskss != gfc_ss_terminator)((void)(!(maskss != gfc_ss_terminator) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/trans-intrinsic.cc"
, 5860, __FUNCTION__), 0 : 0))
;
5861 }
5862 else
5863 maskss = NULL__null;
5864
5865 /* Initialize the scalarizer. */
5866 gfc_init_loopinfo (&loop);
5867 exit_label = gfc_build_label_decl (NULL_TREE(tree) __null);
5868 TREE_USED (exit_label)((exit_label)->base.used_flag) = 1;
5869
5870 /* We add the mask first because the number of iterations is
5871 taken from the last ss, and this breaks if an absent
5872 optional argument is used for mask. */
5873
5874 if (maskss)
5875 gfc_add_ss_to_loop (&loop, maskss);
5876 gfc_add_ss_to_loop (&loop, arrayss);
5877
5878 /* Initialize the loop. */
5879 gfc_conv_ss_startstride (&loop);
5880 gfc_conv_loop_setup (&loop, &expr->where);
5881
5882 /* Calculate the offset. */
5883 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5884 gfc_index_one_nodegfc_rank_cst[1], loop.from[0]);
5885 gfc_add_modify (&loop.pre, offset, tmp);
5886
5887 gfc_mark_ss_chain_used (arrayss, 1);
5888 if (maskss)
5889 gfc_mark_ss_chain_used (maskss, 1);
5890
5891