Fix g++.dg/torture/Wsizeof-pointer-memaccess2.C with -std=c++11
[official-gcc.git] / gcc / c-family / array-notation-common.c
blob8a2f36fc139fe8a374a90f614df4614607d57c0c
1 /* This file is part of the Intel(R) Cilk(TM) Plus support
2 This file contains the builtin functions for Array
3 notations.
4 Copyright (C) 2013-2015 Free Software Foundation, Inc.
5 Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
6 Intel Corporation
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3, or (at your option)
13 any later version.
15 GCC is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "hash-set.h"
28 #include "machmode.h"
29 #include "vec.h"
30 #include "double-int.h"
31 #include "input.h"
32 #include "alias.h"
33 #include "symtab.h"
34 #include "options.h"
35 #include "wide-int.h"
36 #include "inchash.h"
37 #include "tree.h"
38 #include "langhooks.h"
39 #include "tree-iterator.h"
40 #include "c-family/c-common.h"
41 #include "diagnostic-core.h"
43 /* Returns true if the function call in FNDECL is __sec_implicit_index. */
45 bool
46 is_sec_implicit_index_fn (tree fndecl)
48 if (!fndecl)
49 return false;
51 if (TREE_CODE (fndecl) == ADDR_EXPR)
52 fndecl = TREE_OPERAND (fndecl, 0);
54 return
55 (TREE_CODE (fndecl) == FUNCTION_DECL
56 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
57 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CILKPLUS_SEC_IMPLICIT_INDEX);
60 /* Returns the first and only argument for FN, which should be a
61 sec_implicit_index function. FN's location in the source file is as
62 indicated by LOCATION. The argument to FN must be a constant integer
63 expression, otherwise returns -1. */
65 HOST_WIDE_INT
66 extract_sec_implicit_index_arg (location_t location, tree fn)
68 tree fn_arg;
69 HOST_WIDE_INT return_int = 0;
71 if (TREE_CODE (fn) == CALL_EXPR)
73 fn_arg = CALL_EXPR_ARG (fn, 0);
74 if (TREE_CODE (fn_arg) == INTEGER_CST)
75 return_int = int_cst_value (fn_arg);
76 else
78 /* If the location is unknown, and if fn has a location, then use that
79 information so that the user has a better idea where the error
80 could be. */
81 if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn))
82 location = EXPR_LOCATION (fn);
83 error_at (location, "__sec_implicit_index parameter must be an "
84 "integer constant expression");
85 return -1;
88 return return_int;
91 /* Returns true if there is a length mismatch among exprssions that are at the
92 same dimension and one the same side of the equal sign. The Array notation
93 lengths (LIST->LENGTH) is passed in as a 2D vector of trees. */
95 bool
96 length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
98 size_t ii, jj;
99 tree length = NULL_TREE;
101 size_t x = list.length ();
102 size_t y = list[0].length ();
104 for (jj = 0; jj < y; jj++)
106 length = NULL_TREE;
107 for (ii = 0; ii < x; ii++)
109 if (!length)
110 length = list[ii][jj].length;
111 else if (TREE_CODE (length) == INTEGER_CST)
113 /* If length is a INTEGER, and list[ii][jj] is an integer then
114 check if they are equal. If they are not equal then return
115 true. */
116 if (TREE_CODE (list[ii][jj].length) == INTEGER_CST
117 && !tree_int_cst_equal (list[ii][jj].length, length))
119 error_at (loc, "length mismatch in expression");
120 return true;
123 else
124 /* We set the length node as the current node just in case it turns
125 out to be an integer. */
126 length = list[ii][jj].length;
129 return false;
132 /* Given an FNDECL of type FUNCTION_DECL or ADDR_EXPR, return the corresponding
133 BUILT_IN_CILKPLUS_SEC_REDUCE_* being called. If none, return
134 BUILT_IN_NONE. */
136 enum built_in_function
137 is_cilkplus_reduce_builtin (tree fndecl)
139 if (!fndecl)
140 return BUILT_IN_NONE;
141 if (TREE_CODE (fndecl) == ADDR_EXPR)
142 fndecl = TREE_OPERAND (fndecl, 0);
144 if (TREE_CODE (fndecl) == FUNCTION_DECL
145 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
146 switch (DECL_FUNCTION_CODE (fndecl))
148 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
149 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
150 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
151 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
152 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
153 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
154 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
155 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
156 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
157 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
158 case BUILT_IN_CILKPLUS_SEC_REDUCE:
159 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
160 return DECL_FUNCTION_CODE (fndecl);
161 default:
162 break;
165 return BUILT_IN_NONE;
168 /* This function will recurse into EXPR finding any
169 ARRAY_NOTATION_EXPRs and calculate the overall rank of EXPR,
170 storing it in *RANK. LOC is the location of the original expression.
172 ORIG_EXPR is the original expression used to display if any rank
173 mismatch errors are found.
175 Upon entry, *RANK must be either 0, or the rank of a parent
176 expression that must have the same rank as the one being
177 calculated. It is illegal to have multiple array notation with different
178 rank in the same expression (see examples below for clarification).
180 If there were any rank mismatches while calculating the rank, an
181 error will be issued, and FALSE will be returned. Otherwise, TRUE
182 is returned.
184 If IGNORE_BUILTIN_FN is TRUE, ignore array notation specific
185 built-in functions (__sec_reduce_*, etc).
187 Here are some examples of array notations and their rank:
189 Expression RANK
191 X (a variable) 0
192 *Y (a pointer) 0
193 A[5] 0
194 B[5][10] 0
195 A[:] 1
196 B[0:10] 1
197 C[0:10:2] 1
198 D[5][0:10:2] 1 (since D[5] is considered "scalar")
199 D[5][:][10] 1
200 E[:] + 5 1
201 F[:][:][:] + 5 + X 3
202 F[:][:][:] + E[:] + 5 + X RANKMISMATCH-ERROR since rank (E[:]) = 1 and
203 rank (F[:][:][:]) = 3. They must be equal
204 or have a rank of zero.
205 F[:][5][10] + E[:] * 5 + *Y 1
207 int func (int);
208 func (A[:]) 1
209 func (B[:][:][:][:]) 4
211 int func2 (int, int)
212 func2 (A[:], B[:][:][:][:]) RANKMISMATCH-ERROR -- Since Rank (A[:]) = 1
213 and Rank (B[:][:][:][:]) = 4
215 A[:] + func (B[:][:][:][:]) RANKMISMATCH-ERROR
216 func2 (A[:], B[:]) + func (A) 1
220 bool
221 find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
222 size_t *rank)
224 tree ii_tree;
225 size_t ii = 0, current_rank = 0;
227 if (TREE_CODE (expr) == ARRAY_NOTATION_REF)
229 ii_tree = expr;
230 while (ii_tree)
232 if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
234 current_rank++;
235 ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
237 else if (handled_component_p (ii_tree)
238 || TREE_CODE (ii_tree) == INDIRECT_REF)
239 ii_tree = TREE_OPERAND (ii_tree, 0);
240 else if (TREE_CODE (ii_tree) == PARM_DECL
241 || TREE_CODE (ii_tree) == VAR_DECL)
242 break;
243 else
244 gcc_unreachable ();
246 if (*rank == 0)
247 /* In this case, all the expressions this function has encountered thus
248 far have been scalars or expressions with zero rank. Please see
249 header comment for examples of such expression. */
250 *rank = current_rank;
251 else if (*rank != current_rank)
253 /* In this case, find rank is being recursed through a set of
254 expression of the form A <OPERATION> B, where A and B both have
255 array notations in them and the rank of A is not equal to rank of
257 A simple example of such case is the following: X[:] + Y[:][:] */
258 *rank = current_rank;
259 return false;
262 else if (TREE_CODE (expr) == STATEMENT_LIST)
264 tree_stmt_iterator ii_tsi;
265 for (ii_tsi = tsi_start (expr); !tsi_end_p (ii_tsi);
266 tsi_next (&ii_tsi))
267 if (!find_rank (loc, orig_expr, *tsi_stmt_ptr (ii_tsi),
268 ignore_builtin_fn, rank))
269 return false;
271 else
273 if (TREE_CODE (expr) == CALL_EXPR)
275 tree func_name = CALL_EXPR_FN (expr);
276 tree prev_arg = NULL_TREE, arg;
277 call_expr_arg_iterator iter;
278 size_t prev_rank = 0;
279 if (TREE_CODE (func_name) == ADDR_EXPR)
280 if (!ignore_builtin_fn)
281 if (is_cilkplus_reduce_builtin (func_name))
282 /* If it is a built-in function, then we know it returns a
283 scalar. */
284 return true;
285 if (!find_rank (loc, orig_expr, func_name, ignore_builtin_fn, rank))
286 return false;
287 FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
289 if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
291 if (prev_arg && EXPR_HAS_LOCATION (prev_arg)
292 && prev_rank != *rank)
293 error_at (EXPR_LOCATION (prev_arg),
294 "rank mismatch between %qE and %qE", prev_arg,
295 arg);
296 else if (prev_arg && prev_rank != *rank)
297 /* Here the original expression is printed as a "heads-up"
298 to the programmer. This is because since there is no
299 location information for the offending argument, the
300 error could be in some internally generated code that is
301 not visible for the programmer. Thus, the correct fix
302 may lie in the original expression. */
303 error_at (loc, "rank mismatch in expression %qE",
304 orig_expr);
305 return false;
307 prev_arg = arg;
308 prev_rank = *rank;
311 else
313 tree prev_arg = NULL_TREE;
314 for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (expr)); ii++)
316 if (TREE_OPERAND (expr, ii)
317 && !find_rank (loc, orig_expr, TREE_OPERAND (expr, ii),
318 ignore_builtin_fn, rank))
320 if (prev_arg && EXPR_HAS_LOCATION (prev_arg))
321 error_at (EXPR_LOCATION (prev_arg),
322 "rank mismatch between %qE and %qE", prev_arg,
323 TREE_OPERAND (expr, ii));
324 return false;
326 prev_arg = TREE_OPERAND (expr, ii);
330 return true;
333 /* Extracts all array notations in NODE and stores them in ARRAY_LIST. If
334 IGNORE_BUILTIN_FN is set, then array notations inside array notation
335 specific built-in functions are ignored. The NODE can be constants,
336 VAR_DECL, PARM_DECLS, STATEMENT_LISTS or full expressions. */
338 void
339 extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
340 vec<tree, va_gc> **array_list)
342 size_t ii = 0;
344 if (!node)
345 return;
346 if (TREE_CODE (node) == ARRAY_NOTATION_REF)
348 vec_safe_push (*array_list, node);
349 return;
351 if (TREE_CODE (node) == DECL_EXPR)
353 tree x = DECL_EXPR_DECL (node);
354 if (DECL_INITIAL (x))
355 extract_array_notation_exprs (DECL_INITIAL (x),
356 ignore_builtin_fn,
357 array_list);
359 else if (TREE_CODE (node) == STATEMENT_LIST)
361 tree_stmt_iterator ii_tsi;
362 for (ii_tsi = tsi_start (node); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
363 extract_array_notation_exprs (*tsi_stmt_ptr (ii_tsi),
364 ignore_builtin_fn, array_list);
366 else if (TREE_CODE (node) == CALL_EXPR)
368 tree arg;
369 call_expr_arg_iterator iter;
370 if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (node)))
372 if (ignore_builtin_fn)
373 return;
374 else
376 vec_safe_push (*array_list, node);
377 return;
380 if (is_sec_implicit_index_fn (CALL_EXPR_FN (node)))
382 vec_safe_push (*array_list, node);
383 return;
385 /* This will extract array notations in function pointers. */
386 extract_array_notation_exprs (CALL_EXPR_FN (node), ignore_builtin_fn,
387 array_list);
388 FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
389 extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
391 else
392 for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++)
393 if (TREE_OPERAND (node, ii))
394 extract_array_notation_exprs (TREE_OPERAND (node, ii),
395 ignore_builtin_fn, array_list);
396 return;
399 /* LIST contains all the array notations found in *ORIG and ARRAY_OPERAND
400 contains the expanded ARRAY_REF. E.g., if LIST[<some_index>] contains
401 an array_notation expression, then ARRAY_OPERAND[<some_index>] contains its
402 expansion. If *ORIG matches LIST[<some_index>] then *ORIG is set to
403 ARRAY_OPERAND[<some_index>]. This function recursively steps through
404 all the sub-trees of *ORIG, if it is larger than a single
405 ARRAY_NOTATION_REF. */
407 void
408 replace_array_notations (tree *orig, bool ignore_builtin_fn,
409 vec<tree, va_gc> *list,
410 vec<tree, va_gc> *array_operand)
412 size_t ii = 0;
413 extern tree build_c_cast (location_t, tree, tree);
414 tree node = NULL_TREE, node_replacement = NULL_TREE;
416 if (vec_safe_length (list) == 0)
417 return;
419 if (TREE_CODE (*orig) == ARRAY_NOTATION_REF)
421 for (ii = 0; vec_safe_iterate (list, ii, &node); ii++)
422 if (*orig == node)
424 node_replacement = (*array_operand)[ii];
425 *orig = node_replacement;
428 else if (TREE_CODE (*orig) == STATEMENT_LIST)
430 tree_stmt_iterator ii_tsi;
431 for (ii_tsi = tsi_start (*orig); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
432 replace_array_notations (tsi_stmt_ptr (ii_tsi), ignore_builtin_fn, list,
433 array_operand);
435 else if (TREE_CODE (*orig) == CALL_EXPR)
437 tree arg;
438 call_expr_arg_iterator iter;
439 if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (*orig)))
441 if (!ignore_builtin_fn)
443 for (ii = 0; vec_safe_iterate (list, ii, &node); ii++)
444 if (*orig == node)
446 node_replacement = (*array_operand)[ii];
447 *orig = node_replacement;
450 return;
452 if (is_sec_implicit_index_fn (CALL_EXPR_FN (*orig)))
454 for (ii = 0; vec_safe_iterate (list, ii, &node); ii++)
455 if (*orig == node)
457 node_replacement = (*array_operand)[ii];
458 *orig = build_c_cast (EXPR_LOCATION (*orig),
459 TREE_TYPE (*orig), node_replacement);
461 return;
463 /* Fixes array notations in array notations in function pointers. */
464 replace_array_notations (&CALL_EXPR_FN (*orig), ignore_builtin_fn, list,
465 array_operand);
466 ii = 0;
467 FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
469 replace_array_notations (&arg, ignore_builtin_fn, list,
470 array_operand);
471 CALL_EXPR_ARG (*orig, ii) = arg;
472 ii++;
475 else
477 for (ii = 0; ii < (size_t) TREE_CODE_LENGTH (TREE_CODE (*orig)); ii++)
478 if (TREE_OPERAND (*orig, ii))
479 replace_array_notations (&TREE_OPERAND (*orig, ii), ignore_builtin_fn,
480 list, array_operand);
482 return;
485 /* Callback for walk_tree. Find all the scalar expressions in *TP and push
486 them in DATA struct, typecasted to (void *). If *WALK_SUBTREES is set to 0
487 then do not go into the *TP's subtrees. Since this function steps through
488 all the subtrees, *TP and TP can be NULL_TREE and NULL, respectively. The
489 function returns NULL_TREE unconditionally. */
491 tree
492 find_inv_trees (tree *tp, int *walk_subtrees, void *data)
494 struct inv_list *i_list = (struct inv_list *) data;
495 unsigned int ii = 0;
497 if (!tp || !*tp)
498 return NULL_TREE;
499 if (TREE_CONSTANT (*tp))
500 return NULL_TREE; /* No need to save constant to a variable. */
501 if (TREE_CODE (*tp) != COMPOUND_EXPR && !contains_array_notation_expr (*tp))
503 vec_safe_push (i_list->list_values, *tp);
504 *walk_subtrees = 0;
506 else if (TREE_CODE (*tp) == ARRAY_NOTATION_REF
507 || TREE_CODE (*tp) == ARRAY_REF
508 || TREE_CODE (*tp) == CALL_EXPR)
509 /* No need to step through the internals of array notation. */
510 *walk_subtrees = 0;
511 else
513 *walk_subtrees = 1;
515 /* This function is used by C and C++ front-ends. In C++, additional
516 tree codes such as TARGET_EXPR must be eliminated. These codes are
517 passed into additional_tcodes and are walked through and checked. */
518 for (ii = 0; ii < vec_safe_length (i_list->additional_tcodes); ii++)
519 if (TREE_CODE (*tp) == (*(i_list->additional_tcodes))[ii])
520 *walk_subtrees = 0;
522 return NULL_TREE;
525 /* Callback for walk_tree. Replace all the scalar expressions in *TP with the
526 appropriate replacement stored in the struct *DATA (typecasted to void*).
527 The subtrees are not touched if *WALK_SUBTREES is set to zero. */
529 tree
530 replace_inv_trees (tree *tp, int *walk_subtrees, void *data)
532 size_t ii = 0;
533 tree t, r;
534 struct inv_list *i_list = (struct inv_list *) data;
536 if (vec_safe_length (i_list->list_values))
538 for (ii = 0; vec_safe_iterate (i_list->list_values, ii, &t); ii++)
539 if (simple_cst_equal (*tp, t) == 1)
541 vec_safe_iterate (i_list->replacement, ii, &r);
542 gcc_assert (r != NULL_TREE);
543 *tp = r;
544 *walk_subtrees = 0;
547 else
548 *walk_subtrees = 0;
549 return NULL_TREE;
552 /* Returns true if EXPR or any of its subtrees contain ARRAY_NOTATION_EXPR
553 node. */
555 bool
556 contains_array_notation_expr (tree expr)
558 vec<tree, va_gc> *array_list = NULL;
560 if (!expr)
561 return false;
562 if (TREE_CODE (expr) == FUNCTION_DECL)
563 if (is_cilkplus_reduce_builtin (expr))
564 return true;
566 extract_array_notation_exprs (expr, false, &array_list);
567 if (vec_safe_length (array_list) == 0)
568 return false;
569 else
570 return true;
573 /* This function will check if OP is a CALL_EXPR that is a built-in array
574 notation function. If so, then we will return its type to be the type of
575 the array notation inside. */
577 tree
578 find_correct_array_notation_type (tree op)
580 tree fn_arg, return_type = NULL_TREE;
582 if (op)
584 return_type = TREE_TYPE (op); /* This is the default case. */
585 if (TREE_CODE (op) == CALL_EXPR)
586 if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (op)))
588 fn_arg = CALL_EXPR_ARG (op, 0);
589 if (fn_arg)
590 return_type = TREE_TYPE (fn_arg);
593 return return_type;
596 /* Extracts all the array notation triplet information from LIST and stores
597 them in the following fields of the 2-D array NODE(size x rank):
598 START, LENGTH and STRIDE, holding the starting index, length, and stride,
599 respectively. In addition, it also sets two bool fields, IS_VECTOR and
600 COUNT_DOWN, in NODE indicating whether a certain value at a certain field
601 is a vector and if the array is accessed from high to low. */
603 void
604 cilkplus_extract_an_triplets (vec<tree, va_gc> *list, size_t size, size_t rank,
605 vec<vec<struct cilkplus_an_parts> > *node)
607 vec<vec<tree> > array_exprs = vNULL;
609 node->safe_grow_cleared (size);
610 array_exprs.safe_grow_cleared (size);
612 if (rank > 0)
613 for (size_t ii = 0; ii < size; ii++)
615 (*node)[ii].safe_grow_cleared (rank);
616 array_exprs[ii].safe_grow_cleared (rank);
618 for (size_t ii = 0; ii < size; ii++)
620 size_t jj = 0;
621 tree ii_tree = (*list)[ii];
622 while (ii_tree)
624 if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
626 array_exprs[ii][jj] = ii_tree;
627 jj++;
628 ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
630 else if (TREE_CODE (ii_tree) == ARRAY_REF)
631 ii_tree = TREE_OPERAND (ii_tree, 0);
632 else
633 break;
636 for (size_t ii = 0; ii < size; ii++)
637 if (TREE_CODE ((*list)[ii]) == ARRAY_NOTATION_REF)
638 for (size_t jj = 0; jj < rank; jj++)
640 tree ii_tree = array_exprs[ii][jj];
641 (*node)[ii][jj].is_vector = true;
642 (*node)[ii][jj].value = ARRAY_NOTATION_ARRAY (ii_tree);
643 (*node)[ii][jj].start = ARRAY_NOTATION_START (ii_tree);
644 (*node)[ii][jj].length =
645 fold_build1 (CONVERT_EXPR, integer_type_node,
646 ARRAY_NOTATION_LENGTH (ii_tree));
647 (*node)[ii][jj].stride =
648 fold_build1 (CONVERT_EXPR, integer_type_node,
649 ARRAY_NOTATION_STRIDE (ii_tree));
653 /* Replaces all the __sec_implicit_arg functions in LIST with the induction
654 variable stored in VAR at the appropriate location pointed by the
655 __sec_implicit_arg's first parameter. Emits an error if the parameter is
656 not between 0 and RANK. */
658 vec <tree, va_gc> *
659 fix_sec_implicit_args (location_t loc, vec <tree, va_gc> *list,
660 vec<an_loop_parts> an_loop_info, size_t rank,
661 tree orig_stmt)
663 vec <tree, va_gc> *array_operand = NULL;
664 for (size_t ii = 0; ii < vec_safe_length (list); ii++)
665 if (TREE_CODE ((*list)[ii]) == CALL_EXPR
666 && is_sec_implicit_index_fn (CALL_EXPR_FN ((*list)[ii])))
668 int idx = extract_sec_implicit_index_arg (loc, (*list)[ii]);
669 if (idx < 0)
670 /* In this case, the returning function would have emitted an
671 error thus it is not necessary to do so again. */
672 return NULL;
673 else if (idx < (int) rank)
674 vec_safe_push (array_operand, an_loop_info[idx].var);
675 else
677 error_at (loc, "__sec_implicit_index argument %d must be "
678 "less than the rank of %qE", idx, orig_stmt);
679 return NULL;
682 else
683 /* Save the existing value into the array operand. */
684 vec_safe_push (array_operand, (*list)[ii]);
685 return array_operand;