LCOV - code coverage report
Current view: top level - gcc/c-family - c-omp.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.6 % 2588 2397
Test Date: 2026-07-11 15:47:05 Functions: 100.0 % 60 60
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* This file contains routines to construct OpenACC and OpenMP constructs,
       2              :    called from parsing in the C and C++ front ends.
       3              : 
       4              :    Copyright (C) 2005-2026 Free Software Foundation, Inc.
       5              :    Contributed by Richard Henderson <rth@redhat.com>,
       6              :                   Diego Novillo <dnovillo@redhat.com>.
       7              : 
       8              : This file is part of GCC.
       9              : 
      10              : GCC is free software; you can redistribute it and/or modify it under
      11              : the terms of the GNU General Public License as published by the Free
      12              : Software Foundation; either version 3, or (at your option) any later
      13              : version.
      14              : 
      15              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      16              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      17              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      18              : for more details.
      19              : 
      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/>.  */
      23              : 
      24              : #include "config.h"
      25              : #include "system.h"
      26              : #include "coretypes.h"
      27              : #include "options.h"
      28              : #include "c-common.h"
      29              : #include "gimple-expr.h"
      30              : #include "c-pragma.h"
      31              : #include "stringpool.h"
      32              : #include "omp-general.h"
      33              : #include "gomp-constants.h"
      34              : #include "memmodel.h"
      35              : #include "attribs.h"
      36              : #include "gimplify.h"
      37              : #include "langhooks.h"
      38              : #include "bitmap.h"
      39              : #include "tree-iterator.h"
      40              : 
      41              : 
      42              : /* Complete a #pragma oacc wait construct.  LOC is the location of
      43              :    the #pragma.  */
      44              : 
      45              : tree
      46          241 : c_finish_oacc_wait (location_t loc, tree parms, tree clauses)
      47              : {
      48          241 :   const int nparms = list_length (parms);
      49          241 :   tree stmt, t;
      50          241 :   vec<tree, va_gc> *args;
      51              : 
      52          241 :   vec_alloc (args, nparms + 2);
      53          241 :   stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT);
      54              : 
      55          241 :   if ((t = omp_find_clause (clauses, OMP_CLAUSE_ASYNC)))
      56           47 :     t = OMP_CLAUSE_ASYNC_EXPR (t);
      57              :   else
      58          194 :     t = build_int_cst (integer_type_node, GOMP_ASYNC_SYNC);
      59              : 
      60          241 :   args->quick_push (t);
      61          241 :   args->quick_push (build_int_cst (integer_type_node, nparms));
      62              : 
      63          380 :   for (t = parms; t; t = TREE_CHAIN (t))
      64              :     {
      65          139 :       if (TREE_CODE (OMP_CLAUSE_WAIT_EXPR (t)) == INTEGER_CST)
      66           42 :         args->quick_push (build_int_cst (integer_type_node,
      67           42 :                         TREE_INT_CST_LOW (OMP_CLAUSE_WAIT_EXPR (t))));
      68              :       else
      69           97 :         args->quick_push (OMP_CLAUSE_WAIT_EXPR (t));
      70              :     }
      71              : 
      72          241 :   stmt = build_call_expr_loc_vec (loc, stmt, args);
      73              : 
      74          241 :   t = omp_find_clause (clauses, OMP_CLAUSE_IF);
      75          241 :   if (t)
      76           24 :     stmt = build3_loc (input_location, COND_EXPR, void_type_node,
      77           24 :                        OMP_CLAUSE_IF_EXPR (t), stmt, NULL_TREE);
      78              : 
      79          241 :   vec_free (args);
      80              : 
      81          241 :   return stmt;
      82              : }
      83              : 
      84              : /* Complete a #pragma omp master construct.  STMT is the structured-block
      85              :    that follows the pragma.  LOC is the location of the #pragma.  */
      86              : 
      87              : tree
      88          718 : c_finish_omp_master (location_t loc, tree stmt)
      89              : {
      90          718 :   tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
      91          718 :   SET_EXPR_LOCATION (t, loc);
      92          718 :   return t;
      93              : }
      94              : 
      95              : /* Complete a #pragma omp masked construct.  BODY is the structured-block
      96              :    that follows the pragma.  LOC is the location of the #pragma.  */
      97              : 
      98              : tree
      99          421 : c_finish_omp_masked (location_t loc, tree body, tree clauses)
     100              : {
     101          421 :   tree stmt = make_node (OMP_MASKED);
     102          421 :   TREE_TYPE (stmt) = void_type_node;
     103          421 :   OMP_MASKED_BODY (stmt) = body;
     104          421 :   OMP_MASKED_CLAUSES (stmt) = clauses;
     105          421 :   SET_EXPR_LOCATION (stmt, loc);
     106          421 :   return add_stmt (stmt);
     107              : }
     108              : 
     109              : /* Complete a #pragma omp taskgroup construct.  BODY is the structured-block
     110              :    that follows the pragma.  LOC is the location of the #pragma.  */
     111              : 
     112              : tree
     113          430 : c_finish_omp_taskgroup (location_t loc, tree body, tree clauses)
     114              : {
     115          430 :   tree stmt = make_node (OMP_TASKGROUP);
     116          430 :   TREE_TYPE (stmt) = void_type_node;
     117          430 :   OMP_TASKGROUP_BODY (stmt) = body;
     118          430 :   OMP_TASKGROUP_CLAUSES (stmt) = clauses;
     119          430 :   SET_EXPR_LOCATION (stmt, loc);
     120          430 :   return add_stmt (stmt);
     121              : }
     122              : 
     123              : /* Complete a #pragma omp critical construct.  BODY is the structured-block
     124              :    that follows the pragma, NAME is the identifier in the pragma, or null
     125              :    if it was omitted.  LOC is the location of the #pragma.  */
     126              : 
     127              : tree
     128          411 : c_finish_omp_critical (location_t loc, tree body, tree name, tree clauses)
     129              : {
     130          492 :   gcc_assert (!clauses || OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_HINT);
     131          411 :   if (name == NULL_TREE
     132          411 :       && clauses != NULL_TREE
     133          411 :       && integer_nonzerop (OMP_CLAUSE_HINT_EXPR (clauses)))
     134              :     {
     135            2 :       error_at (OMP_CLAUSE_LOCATION (clauses),
     136              :                 "%<#pragma omp critical%> with %<hint%> clause requires "
     137              :                 "a name, except when %<omp_sync_hint_none%> is used");
     138            2 :       return error_mark_node;
     139              :     }
     140              : 
     141          409 :   tree stmt = make_node (OMP_CRITICAL);
     142          409 :   TREE_TYPE (stmt) = void_type_node;
     143          409 :   OMP_CRITICAL_BODY (stmt) = body;
     144          409 :   OMP_CRITICAL_NAME (stmt) = name;
     145          409 :   OMP_CRITICAL_CLAUSES (stmt) = clauses;
     146          409 :   SET_EXPR_LOCATION (stmt, loc);
     147          409 :   return add_stmt (stmt);
     148              : }
     149              : 
     150              : /* Complete a #pragma omp ordered construct.  STMT is the structured-block
     151              :    that follows the pragma.  LOC is the location of the #pragma.  */
     152              : 
     153              : tree
     154         1566 : c_finish_omp_ordered (location_t loc, tree clauses, tree stmt)
     155              : {
     156         1566 :   tree t = make_node (OMP_ORDERED);
     157         1566 :   TREE_TYPE (t) = void_type_node;
     158         1566 :   OMP_ORDERED_BODY (t) = stmt;
     159         1566 :   if (!flag_openmp      /* flag_openmp_simd */
     160         1606 :       && (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_SIMD
     161           40 :           || OMP_CLAUSE_CHAIN (clauses)))
     162            4 :     clauses = build_omp_clause (loc, OMP_CLAUSE_SIMD);
     163         1566 :   OMP_ORDERED_CLAUSES (t) = clauses;
     164         1566 :   SET_EXPR_LOCATION (t, loc);
     165         1566 :   return add_stmt (t);
     166              : }
     167              : 
     168              : 
     169              : /* Complete a #pragma omp barrier construct.  LOC is the location of
     170              :    the #pragma.  */
     171              : 
     172              : void
     173          346 : c_finish_omp_barrier (location_t loc)
     174              : {
     175          346 :   tree x;
     176              : 
     177          346 :   x = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
     178          346 :   x = build_call_expr_loc (loc, x, 1,
     179              :                            build_int_cst (integer_type_node,
     180              :                                           GOMP_BARRIER_EXPLICIT));
     181          346 :   add_stmt (x);
     182          346 : }
     183              : 
     184              : 
     185              : /* Complete a #pragma omp taskwait construct.  LOC is the location of the
     186              :    pragma.  */
     187              : 
     188              : void
     189           72 : c_finish_omp_taskwait (location_t loc)
     190              : {
     191           72 :   tree x;
     192              : 
     193           72 :   x = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
     194           72 :   x = build_call_expr_loc (loc, x, 0);
     195           72 :   add_stmt (x);
     196           72 : }
     197              : 
     198              : 
     199              : /* Complete a #pragma omp taskyield construct.  LOC is the location of the
     200              :    pragma.  */
     201              : 
     202              : void
     203            6 : c_finish_omp_taskyield (location_t loc)
     204              : {
     205            6 :   tree x;
     206              : 
     207            6 :   x = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
     208            6 :   x = build_call_expr_loc (loc, x, 0);
     209            6 :   add_stmt (x);
     210            6 : }
     211              : 
     212              : 
     213              : /* Complete a #pragma omp atomic construct.  For CODE OMP_ATOMIC
     214              :    the expression to be implemented atomically is LHS opcode= RHS.
     215              :    For OMP_ATOMIC_READ V = LHS, for OMP_ATOMIC_CAPTURE_{NEW,OLD} LHS
     216              :    opcode= RHS with the new or old content of LHS returned.
     217              :    LOC is the location of the atomic statement.  The value returned
     218              :    is either error_mark_node (if the construct was erroneous) or an
     219              :    OMP_ATOMIC* node which should be added to the current statement
     220              :    tree with add_stmt.  If TEST is set, avoid calling save_expr
     221              :    or create_tmp_var*.  */
     222              : 
     223              : tree
     224         4592 : c_finish_omp_atomic (location_t loc, enum tree_code code,
     225              :                      enum tree_code opcode, tree lhs, tree rhs,
     226              :                      tree v, tree lhs1, tree rhs1, tree r, bool swapped,
     227              :                      enum omp_memory_order memory_order, bool weak,
     228              :                      bool test)
     229              : {
     230         4592 :   tree x, type, addr, pre = NULL_TREE, rtmp = NULL_TREE, vtmp = NULL_TREE;
     231         4592 :   HOST_WIDE_INT bitpos = 0, bitsize = 0;
     232         4592 :   enum tree_code orig_opcode = opcode;
     233              : 
     234         4592 :   if (lhs == error_mark_node || rhs == error_mark_node
     235         4592 :       || v == error_mark_node || lhs1 == error_mark_node
     236         4592 :       || rhs1 == error_mark_node || r == error_mark_node)
     237              :     return error_mark_node;
     238              : 
     239              :   /* ??? According to one reading of the OpenMP spec, complex type are
     240              :      supported, but there are no atomic stores for any architecture.
     241              :      But at least icc 9.0 doesn't support complex types here either.
     242              :      And lets not even talk about vector types...  */
     243         4592 :   type = TREE_TYPE (lhs);
     244         4592 :   if (!INTEGRAL_TYPE_P (type)
     245          882 :       && !POINTER_TYPE_P (type)
     246          872 :       && !SCALAR_FLOAT_TYPE_P (type))
     247              :     {
     248            7 :       error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
     249            7 :       return error_mark_node;
     250              :     }
     251         4585 :   if (TYPE_ATOMIC (type))
     252              :     {
     253            8 :       error_at (loc, "%<_Atomic%> expression in %<#pragma omp atomic%>");
     254            8 :       return error_mark_node;
     255              :     }
     256         4577 :   if (r && r != void_list_node && !INTEGRAL_TYPE_P (TREE_TYPE (r)))
     257              :     {
     258            4 :       error_at (loc, "%<#pragma omp atomic compare capture%> with non-integral "
     259              :                      "comparison result");
     260            4 :       return error_mark_node;
     261              :     }
     262              : 
     263         4573 :   if (opcode == RDIV_EXPR)
     264            0 :     opcode = TRUNC_DIV_EXPR;
     265              : 
     266              :   /* ??? Validate that rhs does not overlap lhs.  */
     267         4573 :   tree blhs = NULL;
     268         4573 :   if (TREE_CODE (lhs) == COMPONENT_REF
     269           69 :       && TREE_CODE (TREE_OPERAND (lhs, 1)) == FIELD_DECL
     270           69 :       && DECL_C_BIT_FIELD (TREE_OPERAND (lhs, 1))
     271         4623 :       && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (lhs, 1)))
     272              :     {
     273           50 :       tree field = TREE_OPERAND (lhs, 1);
     274           50 :       tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
     275           50 :       if (tree_fits_uhwi_p (DECL_FIELD_OFFSET (field))
     276          100 :           && tree_fits_uhwi_p (DECL_FIELD_OFFSET (repr)))
     277           50 :         bitpos = (tree_to_uhwi (DECL_FIELD_OFFSET (field))
     278           50 :                   - tree_to_uhwi (DECL_FIELD_OFFSET (repr))) * BITS_PER_UNIT;
     279              :       else
     280              :         bitpos = 0;
     281           50 :       bitpos += (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
     282           50 :                  - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
     283           50 :       gcc_assert (tree_fits_shwi_p (DECL_SIZE (field)));
     284           50 :       bitsize = tree_to_shwi (DECL_SIZE (field));
     285           50 :       blhs = lhs;
     286           50 :       type = TREE_TYPE (repr);
     287           50 :       lhs = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (lhs, 0),
     288           50 :                     repr, TREE_OPERAND (lhs, 2));
     289              :     }
     290              : 
     291              :   /* Take and save the address of the lhs.  From then on we'll reference it
     292              :      via indirection.  */
     293         4573 :   addr = build_unary_op (loc, ADDR_EXPR, lhs, false);
     294         4573 :   if (addr == error_mark_node)
     295              :     return error_mark_node;
     296         4564 :   if (!test)
     297         4351 :     addr = save_expr (addr);
     298         4351 :   if (!test
     299         4351 :       && TREE_CODE (addr) != SAVE_EXPR
     300         3756 :       && (TREE_CODE (addr) != ADDR_EXPR
     301         3577 :           || !VAR_P (TREE_OPERAND (addr, 0))))
     302              :     {
     303              :       /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
     304              :          it even after unsharing function body.  */
     305          368 :       tree var = create_tmp_var_raw (TREE_TYPE (addr));
     306          368 :       DECL_CONTEXT (var) = current_function_decl;
     307          368 :       addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
     308              :     }
     309         4564 :   tree orig_lhs = lhs;
     310         4564 :   lhs = build_indirect_ref (loc, addr, RO_NULL);
     311         4564 :   tree new_lhs = lhs;
     312              : 
     313         4564 :   if (code == OMP_ATOMIC_READ)
     314              :     {
     315          750 :       x = build1 (OMP_ATOMIC_READ, type, addr);
     316          750 :       SET_EXPR_LOCATION (x, loc);
     317          750 :       OMP_ATOMIC_MEMORY_ORDER (x) = memory_order;
     318          750 :       gcc_assert (!weak);
     319          750 :       if (blhs)
     320            2 :         x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
     321            2 :                         bitsize_int (bitsize), bitsize_int (bitpos));
     322          750 :       return build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
     323          750 :                                 loc, x, NULL_TREE);
     324              :     }
     325              : 
     326              :   /* There are lots of warnings, errors, and conversions that need to happen
     327              :      in the course of interpreting a statement.  Use the normal mechanisms
     328              :      to do this, and then take it apart again.  */
     329         3814 :   if (blhs)
     330              :     {
     331           48 :       lhs = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), lhs,
     332           48 :                         bitsize_int (bitsize), bitsize_int (bitpos));
     333           48 :       if (opcode == COND_EXPR)
     334              :         {
     335           16 :           bool save = in_late_binary_op;
     336           16 :           in_late_binary_op = true;
     337           16 :           std::swap (rhs, rhs1);
     338           16 :           rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true);
     339           16 :           in_late_binary_op = save;
     340              :         }
     341           32 :       else if (swapped)
     342            0 :         rhs = build_binary_op (loc, opcode, rhs, lhs, true);
     343           32 :       else if (opcode != NOP_EXPR)
     344           26 :         rhs = build_binary_op (loc, opcode, lhs, rhs, true);
     345              :       opcode = NOP_EXPR;
     346              :     }
     347         3766 :   else if (opcode == COND_EXPR)
     348              :     {
     349          334 :       bool save = in_late_binary_op;
     350          334 :       in_late_binary_op = true;
     351          334 :       std::swap (rhs, rhs1);
     352          334 :       rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true);
     353          334 :       in_late_binary_op = save;
     354          334 :       opcode = NOP_EXPR;
     355              :     }
     356         3432 :   else if (swapped)
     357              :     {
     358          124 :       rhs = build_binary_op (loc, opcode, rhs, lhs, true);
     359          124 :       opcode = NOP_EXPR;
     360              :     }
     361         3814 :   bool save = in_late_binary_op;
     362         3814 :   in_late_binary_op = true;
     363         3814 :   if ((opcode == MIN_EXPR || opcode == MAX_EXPR)
     364         4102 :       && build_binary_op (loc, LT_EXPR, blhs ? blhs : lhs, rhs,
     365          288 :                           true) == error_mark_node)
     366              :     x = error_mark_node;
     367              :   else
     368         7572 :     x = build_modify_expr (loc, blhs ? blhs : lhs, NULL_TREE, opcode,
     369              :                            loc, rhs, NULL_TREE);
     370         3814 :   in_late_binary_op = save;
     371         3814 :   if (x == error_mark_node)
     372              :     return error_mark_node;
     373         3794 :   if (TREE_CODE (x) == COMPOUND_EXPR)
     374              :     {
     375           14 :       pre = TREE_OPERAND (x, 0);
     376           14 :       gcc_assert (TREE_CODE (pre) == SAVE_EXPR || tree_invariant_p (pre));
     377           14 :       x = TREE_OPERAND (x, 1);
     378              :     }
     379         3794 :   gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
     380         3794 :   rhs = TREE_OPERAND (x, 1);
     381              : 
     382         3794 :   if (blhs)
     383           48 :     rhs = build3_loc (loc, BIT_INSERT_EXPR, type, new_lhs,
     384           48 :                       rhs, bitsize_int (bitpos));
     385         3794 :   if (orig_opcode == COND_EXPR)
     386              :     {
     387          350 :       if (error_operand_p (rhs1))
     388            0 :         return error_mark_node;
     389          350 :       gcc_assert (TREE_CODE (rhs1) == EQ_EXPR);
     390          350 :       tree cmptype = TREE_TYPE (TREE_OPERAND (rhs1, 0));
     391          350 :       if (SCALAR_FLOAT_TYPE_P (cmptype) && !test)
     392              :         {
     393          114 :           bool clear_padding = false;
     394          114 :           HOST_WIDE_INT non_padding_start = 0;
     395          114 :           HOST_WIDE_INT non_padding_end = 0;
     396          114 :           if (BITS_PER_UNIT == 8
     397              :               && CHAR_BIT == 8
     398          114 :               && clear_padding_type_may_have_padding_p (cmptype))
     399              :             {
     400           30 :               HOST_WIDE_INT sz = int_size_in_bytes (cmptype), i;
     401           30 :               gcc_assert (sz > 0);
     402           30 :               unsigned char *buf = XALLOCAVEC (unsigned char, sz);
     403           30 :               memset (buf, ~0, sz);
     404           30 :               clear_type_padding_in_mask (cmptype, buf);
     405          360 :               for (i = 0; i < sz; i++)
     406          330 :                 if (buf[i] != (unsigned char) ~0)
     407              :                   {
     408              :                     clear_padding = true;
     409              :                     break;
     410              :                   }
     411           30 :               if (clear_padding && buf[i] == 0)
     412              :                 {
     413              :                   /* Try to optimize.  In the common case where
     414              :                      non-padding bits are all continuous and start
     415              :                      and end at a byte boundary, we can just adjust
     416              :                      the memcmp call arguments and don't need to
     417              :                      emit __builtin_clear_padding calls.  */
     418           30 :                   if (i == 0)
     419              :                     {
     420            0 :                       for (i = 0; i < sz; i++)
     421            0 :                         if (buf[i] != 0)
     422              :                           break;
     423            0 :                       if (i < sz && buf[i] == (unsigned char) ~0)
     424              :                         {
     425            0 :                           non_padding_start = i;
     426            0 :                           for (; i < sz; i++)
     427            0 :                             if (buf[i] != (unsigned char) ~0)
     428              :                               break;
     429              :                         }
     430              :                       else
     431              :                         i = 0;
     432              :                     }
     433           30 :                   if (i != 0)
     434              :                     {
     435          210 :                       non_padding_end = i;
     436          210 :                       for (; i < sz; i++)
     437          180 :                         if (buf[i] != 0)
     438              :                           {
     439              :                             non_padding_start = 0;
     440              :                             non_padding_end = 0;
     441              :                             break;
     442              :                           }
     443              :                     }
     444              :                 }
     445              :             }
     446           84 :           tree inttype = NULL_TREE;
     447           84 :           if (!clear_padding && tree_fits_uhwi_p (TYPE_SIZE (cmptype)))
     448              :             {
     449           84 :               HOST_WIDE_INT prec = tree_to_uhwi (TYPE_SIZE (cmptype));
     450           84 :               inttype = c_common_type_for_size (prec, 1);
     451           84 :               if (inttype
     452          168 :                   && (!tree_int_cst_equal (TYPE_SIZE (cmptype),
     453           84 :                                            TYPE_SIZE (inttype))
     454           84 :                       || TYPE_PRECISION (inttype) != prec))
     455              :                 inttype = NULL_TREE;
     456              :             }
     457           84 :           if (inttype)
     458              :             {
     459           84 :               TREE_OPERAND (rhs1, 0)
     460           84 :                 = build1_loc (loc, VIEW_CONVERT_EXPR, inttype,
     461           84 :                               TREE_OPERAND (rhs1, 0));
     462           84 :               TREE_OPERAND (rhs1, 1)
     463          168 :                 = build1_loc (loc, VIEW_CONVERT_EXPR, inttype,
     464           84 :                               TREE_OPERAND (rhs1, 1));
     465              :             }
     466              :           else
     467              :             {
     468           30 :               tree pcmptype = build_pointer_type (cmptype);
     469           30 :               tree tmp1 = create_tmp_var_raw (cmptype);
     470           30 :               TREE_ADDRESSABLE (tmp1) = 1;
     471           30 :               DECL_CONTEXT (tmp1) = current_function_decl;
     472           30 :               tmp1 = build4 (TARGET_EXPR, cmptype, tmp1,
     473           30 :                              TREE_OPERAND (rhs1, 0), NULL, NULL);
     474           30 :               tmp1 = build1 (ADDR_EXPR, pcmptype, tmp1);
     475           30 :               tree tmp2 = create_tmp_var_raw (cmptype);
     476           30 :               TREE_ADDRESSABLE (tmp2) = 1;
     477           30 :               DECL_CONTEXT (tmp2) = current_function_decl;
     478           30 :               tmp2 = build4 (TARGET_EXPR, cmptype, tmp2,
     479           30 :                              TREE_OPERAND (rhs1, 1), NULL, NULL);
     480           30 :               tmp2 = build1 (ADDR_EXPR, pcmptype, tmp2);
     481           30 :               if (non_padding_start)
     482              :                 {
     483            0 :                   tmp1 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp1,
     484            0 :                                  size_int (non_padding_start));
     485            0 :                   tmp2 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp2,
     486            0 :                                  size_int (non_padding_start));
     487              :                 }
     488           30 :               tree fndecl = builtin_decl_explicit (BUILT_IN_MEMCMP);
     489           60 :               rhs1 = build_call_expr_loc (loc, fndecl, 3, tmp1, tmp2,
     490              :                                           non_padding_end
     491           30 :                                           ? size_int (non_padding_end
     492              :                                                       - non_padding_start)
     493            0 :                                           : TYPE_SIZE_UNIT (cmptype));
     494           30 :               rhs1 = build2 (EQ_EXPR, boolean_type_node, rhs1,
     495              :                              integer_zero_node);
     496           30 :               if (clear_padding && non_padding_end == 0)
     497              :                 {
     498            0 :                   fndecl = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING);
     499            0 :                   tree cp1 = build_call_expr_loc (loc, fndecl, 1, tmp1);
     500            0 :                   tree cp2 = build_call_expr_loc (loc, fndecl, 1, tmp2);
     501            0 :                   rhs1 = omit_two_operands_loc (loc, boolean_type_node,
     502              :                                                 rhs1, cp2, cp1);
     503              :                 }
     504              :             }
     505              :         }
     506          350 :       if (r && test)
     507              :         rtmp = rhs1;
     508          325 :       else if (r)
     509              :         {
     510          118 :           tree var = create_tmp_var_raw (boolean_type_node);
     511          118 :           DECL_CONTEXT (var) = current_function_decl;
     512          118 :           rtmp = build4 (TARGET_EXPR, boolean_type_node, var,
     513              :                          boolean_false_node, NULL, NULL);
     514          118 :           save = in_late_binary_op;
     515          118 :           in_late_binary_op = true;
     516          118 :           x = build_modify_expr (loc, var, NULL_TREE, NOP_EXPR,
     517              :                                  loc, rhs1, NULL_TREE);
     518          118 :           in_late_binary_op = save;
     519          118 :           if (x == error_mark_node)
     520              :             return error_mark_node;
     521          118 :           gcc_assert (TREE_CODE (x) == MODIFY_EXPR
     522              :                       && TREE_OPERAND (x, 0) == var);
     523          118 :           TREE_OPERAND (x, 0) = rtmp;
     524          118 :           rhs1 = omit_one_operand_loc (loc, boolean_type_node, x, rtmp);
     525              :         }
     526          350 :       rhs = build3_loc (loc, COND_EXPR, type, rhs1, rhs, new_lhs);
     527          350 :       rhs1 = NULL_TREE;
     528              :     }
     529              : 
     530              :   /* Punt the actual generation of atomic operations to common code.  */
     531         3794 :   if (code == OMP_ATOMIC)
     532         2524 :     type = void_type_node;
     533         3794 :   x = build2 (code, type, addr, rhs);
     534         3794 :   SET_EXPR_LOCATION (x, loc);
     535         3794 :   OMP_ATOMIC_MEMORY_ORDER (x) = memory_order;
     536         3794 :   OMP_ATOMIC_WEAK (x) = weak;
     537              : 
     538              :   /* Generally it is hard to prove lhs1 and lhs are the same memory
     539              :      location, just diagnose different variables.  */
     540         3794 :   if (rhs1
     541         1031 :       && VAR_P (rhs1)
     542          439 :       && VAR_P (orig_lhs)
     543          439 :       && rhs1 != orig_lhs
     544            0 :       && !test)
     545              :     {
     546            0 :       if (code == OMP_ATOMIC)
     547            0 :         error_at (loc, "%<#pragma omp atomic update%> uses two different "
     548              :                        "variables for memory");
     549              :       else
     550            0 :         error_at (loc, "%<#pragma omp atomic capture%> uses two different "
     551              :                        "variables for memory");
     552            0 :       return error_mark_node;
     553              :     }
     554              : 
     555         3794 :   if (lhs1
     556         3794 :       && lhs1 != orig_lhs
     557          325 :       && TREE_CODE (lhs1) == COMPONENT_REF
     558           12 :       && TREE_CODE (TREE_OPERAND (lhs1, 1)) == FIELD_DECL
     559           12 :       && DECL_C_BIT_FIELD (TREE_OPERAND (lhs1, 1))
     560         3806 :       && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (lhs1, 1)))
     561              :     {
     562           12 :       tree field = TREE_OPERAND (lhs1, 1);
     563           12 :       tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
     564           12 :       lhs1 = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (lhs1, 0),
     565           12 :                      repr, TREE_OPERAND (lhs1, 2));
     566              :     }
     567         3794 :   if (rhs1
     568         1031 :       && rhs1 != orig_lhs
     569          592 :       && TREE_CODE (rhs1) == COMPONENT_REF
     570           16 :       && TREE_CODE (TREE_OPERAND (rhs1, 1)) == FIELD_DECL
     571           16 :       && DECL_C_BIT_FIELD (TREE_OPERAND (rhs1, 1))
     572         3810 :       && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (rhs1, 1)))
     573              :     {
     574           16 :       tree field = TREE_OPERAND (rhs1, 1);
     575           16 :       tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
     576           16 :       rhs1 = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (rhs1, 0),
     577           16 :                      repr, TREE_OPERAND (rhs1, 2));
     578              :     }
     579              : 
     580         3794 :   if (code != OMP_ATOMIC)
     581              :     {
     582              :       /* Generally it is hard to prove lhs1 and lhs are the same memory
     583              :          location, just diagnose different variables.  */
     584         1270 :       if (lhs1 && VAR_P (lhs1) && VAR_P (orig_lhs))
     585              :         {
     586          434 :           if (lhs1 != orig_lhs && !test)
     587              :             {
     588            0 :               error_at (loc, "%<#pragma omp atomic capture%> uses two "
     589              :                              "different variables for memory");
     590            0 :               return error_mark_node;
     591              :             }
     592              :         }
     593         1270 :       if (blhs)
     594           28 :         x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
     595           28 :                         bitsize_int (bitsize), bitsize_int (bitpos));
     596         1270 :       if (r && !test)
     597              :         {
     598           80 :           vtmp = create_tmp_var_raw (TREE_TYPE (x));
     599           80 :           DECL_CONTEXT (vtmp) = current_function_decl;
     600              :         }
     601              :       else
     602              :         vtmp = v;
     603         1270 :       x = build_modify_expr (loc, vtmp, NULL_TREE, NOP_EXPR,
     604              :                              loc, x, NULL_TREE);
     605         1270 :       if (x == error_mark_node)
     606              :         return error_mark_node;
     607         1266 :       type = TREE_TYPE (x);
     608         1266 :       if (r && !test)
     609              :         {
     610           80 :           vtmp = build4 (TARGET_EXPR, TREE_TYPE (vtmp), vtmp,
     611           80 :                          build_zero_cst (TREE_TYPE (vtmp)), NULL, NULL);
     612           80 :           gcc_assert (TREE_CODE (x) == MODIFY_EXPR
     613              :                       && TREE_OPERAND (x, 0) == TARGET_EXPR_SLOT (vtmp));
     614           80 :           TREE_OPERAND (x, 0) = vtmp;
     615              :         }
     616         1266 :       if (rhs1 && rhs1 != orig_lhs)
     617              :         {
     618          238 :           tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false);
     619          238 :           if (rhs1addr == error_mark_node)
     620              :             return error_mark_node;
     621          238 :           x = omit_one_operand_loc (loc, type, x, rhs1addr);
     622              :         }
     623         1266 :       if (lhs1 && lhs1 != orig_lhs)
     624              :         {
     625          325 :           tree lhs1addr = build_unary_op (loc, ADDR_EXPR, lhs1, false);
     626          325 :           if (lhs1addr == error_mark_node)
     627              :             return error_mark_node;
     628          324 :           if (code == OMP_ATOMIC_CAPTURE_OLD)
     629          205 :             x = omit_one_operand_loc (loc, type, x, lhs1addr);
     630              :           else
     631              :             {
     632          119 :               if (!test)
     633          103 :                 x = save_expr (x);
     634          119 :               x = omit_two_operands_loc (loc, type, x, x, lhs1addr);
     635              :             }
     636              :         }
     637              :     }
     638         2524 :   else if (rhs1 && rhs1 != orig_lhs)
     639              :     {
     640          354 :       tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false);
     641          354 :       if (rhs1addr == error_mark_node)
     642              :         return error_mark_node;
     643          354 :       x = omit_one_operand_loc (loc, type, x, rhs1addr);
     644              :     }
     645              : 
     646         3789 :   if (pre)
     647           14 :     x = omit_one_operand_loc (loc, type, x, pre);
     648         3789 :   if (r && r != void_list_node)
     649              :     {
     650           88 :       in_late_binary_op = true;
     651           88 :       tree x2 = build_modify_expr (loc, r, NULL_TREE, NOP_EXPR,
     652              :                                    loc, rtmp, NULL_TREE);
     653           88 :       in_late_binary_op = save;
     654           88 :       if (x2 == error_mark_node)
     655              :         return error_mark_node;
     656           88 :       x = omit_one_operand_loc (loc, TREE_TYPE (x2), x2, x);
     657              :     }
     658         3789 :   if (v && vtmp != v)
     659              :     {
     660           80 :       in_late_binary_op = true;
     661           80 :       tree x2 = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
     662              :                                    loc, vtmp, NULL_TREE);
     663           80 :       in_late_binary_op = save;
     664           80 :       if (x2 == error_mark_node)
     665              :         return error_mark_node;
     666           80 :       x2 = build3_loc (loc, COND_EXPR, void_type_node, rtmp,
     667              :                        void_node, x2);
     668           80 :       x = omit_one_operand_loc (loc, TREE_TYPE (x2), x2, x);
     669              :     }
     670              :   return x;
     671              : }
     672              : 
     673              : 
     674              : /* Return true if TYPE is the implementation's omp_interop_t.  */
     675              : 
     676              : bool
     677         1844 : c_omp_interop_t_p (tree type)
     678              : {
     679         1844 :   if (type == error_mark_node)
     680              :     return false;
     681         1820 :   type = TYPE_MAIN_VARIANT (type);
     682         1820 :   return (TREE_CODE (type) == ENUMERAL_TYPE
     683         1727 :           && TYPE_NAME (type)
     684         3454 :           && ((TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
     685         1727 :                ? DECL_NAME (TYPE_NAME (type)) : TYPE_NAME (type))
     686         1727 :               == get_identifier ("omp_interop_t"))
     687         1727 :           && TYPE_FILE_SCOPE_P (type)
     688         1727 :           && COMPLETE_TYPE_P (type)
     689         1727 :           && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
     690         3547 :           && !compare_tree_int (TYPE_SIZE (type),
     691         1727 :                                 tree_to_uhwi (TYPE_SIZE (ptr_type_node))));
     692              : }
     693              : 
     694              : /* Return true if TYPE is the implementation's omp_depend_t.  */
     695              : 
     696              : bool
     697         1214 : c_omp_depend_t_p (tree type)
     698              : {
     699         1214 :   type = TYPE_MAIN_VARIANT (type);
     700         1214 :   return (TREE_CODE (type) == RECORD_TYPE
     701          429 :           && TYPE_NAME (type)
     702          858 :           && ((TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
     703          429 :                ? DECL_NAME (TYPE_NAME (type)) : TYPE_NAME (type))
     704          429 :               == get_identifier ("omp_depend_t"))
     705          411 :           && TYPE_FILE_SCOPE_P (type)
     706          411 :           && COMPLETE_TYPE_P (type)
     707          411 :           && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
     708         1625 :           && !compare_tree_int (TYPE_SIZE (type),
     709          411 :                                 2 * tree_to_uhwi (TYPE_SIZE (ptr_type_node))));
     710              : }
     711              : 
     712              : 
     713              : /* Complete a #pragma omp depobj construct.  LOC is the location of the
     714              :    #pragma.  */
     715              : 
     716              : void
     717          355 : c_finish_omp_depobj (location_t loc, tree depobj,
     718              :                      enum omp_clause_depend_kind kind, tree clause)
     719              : {
     720          355 :   tree t = NULL_TREE;
     721          355 :   if (!error_operand_p (depobj))
     722              :     {
     723          344 :       if (!c_omp_depend_t_p (TREE_TYPE (depobj)))
     724              :         {
     725           42 :           error_at (EXPR_LOC_OR_LOC (depobj, loc),
     726              :                     "type of %<depobj%> expression is not %<omp_depend_t%>");
     727           21 :           depobj = error_mark_node;
     728              :         }
     729          323 :       else if (TYPE_READONLY (TREE_TYPE (depobj)))
     730              :         {
     731           14 :           error_at (EXPR_LOC_OR_LOC (depobj, loc),
     732              :                     "%<const%> qualified %<depobj%> expression");
     733            7 :           depobj = error_mark_node;
     734              :         }
     735              :     }
     736              :   else
     737           11 :     depobj = error_mark_node;
     738              : 
     739          355 :   if (clause == error_mark_node)
     740          355 :     return;
     741              : 
     742          317 :   if (clause)
     743              :     {
     744          169 :       gcc_assert (TREE_CODE (clause) == OMP_CLAUSE);
     745          169 :       if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DOACROSS)
     746              :         {
     747           42 :           error_at (OMP_CLAUSE_LOCATION (clause),
     748              :                     "%<depend(%s)%> is only allowed in %<omp ordered%>",
     749           14 :                     OMP_CLAUSE_DOACROSS_KIND (clause)
     750              :                     == OMP_CLAUSE_DOACROSS_SOURCE
     751              :                     ? "source" : "sink");
     752           14 :           return;
     753              :         }
     754          155 :       gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DEPEND);
     755          155 :       if (OMP_CLAUSE_CHAIN (clause))
     756            7 :         error_at (OMP_CLAUSE_LOCATION (clause),
     757              :                   "more than one locator in %<depend%> clause on %<depobj%> "
     758              :                   "construct");
     759          155 :       switch (OMP_CLAUSE_DEPEND_KIND (clause))
     760              :         {
     761            7 :         case OMP_CLAUSE_DEPEND_DEPOBJ:
     762            7 :           error_at (OMP_CLAUSE_LOCATION (clause),
     763              :                     "%<depobj%> dependence type specified in %<depend%> "
     764              :                     "clause on %<depobj%> construct");
     765            7 :           return;
     766          148 :         case OMP_CLAUSE_DEPEND_IN:
     767          148 :         case OMP_CLAUSE_DEPEND_OUT:
     768          148 :         case OMP_CLAUSE_DEPEND_INOUT:
     769          148 :         case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
     770          148 :         case OMP_CLAUSE_DEPEND_INOUTSET:
     771          148 :           kind = OMP_CLAUSE_DEPEND_KIND (clause);
     772          148 :           t = OMP_CLAUSE_DECL (clause);
     773          148 :           gcc_assert (t);
     774          148 :           if (OMP_ITERATOR_DECL_P (t))
     775              :             {
     776            7 :               error_at (OMP_CLAUSE_LOCATION (clause),
     777              :                         "%<iterator%> modifier may not be specified on "
     778              :                         "%<depobj%> construct");
     779            7 :               return;
     780              :             }
     781          141 :           if (TREE_CODE (t) == COMPOUND_EXPR)
     782              :             {
     783            0 :               tree t1 = build_fold_addr_expr (TREE_OPERAND (t, 1));
     784            0 :               t = build2 (COMPOUND_EXPR, TREE_TYPE (t1), TREE_OPERAND (t, 0),
     785              :                           t1);
     786              :             }
     787          141 :           else if (t != null_pointer_node)
     788          133 :             t = build_fold_addr_expr (t);
     789              :           break;
     790            0 :         default:
     791            0 :           gcc_unreachable ();
     792              :         }
     793              :     }
     794              :   else
     795          148 :     gcc_assert (kind != OMP_CLAUSE_DEPEND_INVALID);
     796              : 
     797          289 :   if (depobj == error_mark_node)
     798              :     return;
     799              : 
     800          483 :   depobj = build_fold_addr_expr_loc (EXPR_LOC_OR_LOC (depobj, loc), depobj);
     801          250 :   tree dtype
     802          250 :     = build_pointer_type_for_mode (ptr_type_node, TYPE_MODE (ptr_type_node),
     803              :                                    true);
     804          250 :   depobj = fold_convert (dtype, depobj);
     805          250 :   tree r;
     806          250 :   if (clause)
     807              :     {
     808          127 :       depobj = save_expr (depobj);
     809          127 :       r = build_indirect_ref (loc, depobj, RO_UNARY_STAR);
     810          127 :       add_stmt (build2 (MODIFY_EXPR, void_type_node, r, t));
     811              :     }
     812          250 :   int k;
     813          250 :   switch (kind)
     814              :     {
     815              :     case OMP_CLAUSE_DEPEND_IN:
     816              :       k = GOMP_DEPEND_IN;
     817              :       break;
     818           11 :     case OMP_CLAUSE_DEPEND_OUT:
     819           11 :       k = GOMP_DEPEND_OUT;
     820           11 :       break;
     821           45 :     case OMP_CLAUSE_DEPEND_INOUT:
     822           45 :       k = GOMP_DEPEND_INOUT;
     823           45 :       break;
     824           14 :     case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
     825           14 :       k = GOMP_DEPEND_MUTEXINOUTSET;
     826           14 :       break;
     827           12 :     case OMP_CLAUSE_DEPEND_INOUTSET:
     828           12 :       k = GOMP_DEPEND_INOUTSET;
     829           12 :       break;
     830           87 :     case OMP_CLAUSE_DEPEND_LAST:
     831           87 :       k = -1;
     832           87 :       break;
     833            0 :     default:
     834            0 :       gcc_unreachable ();
     835              :     }
     836          250 :   t = build_int_cst (ptr_type_node, k);
     837          250 :   depobj = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (depobj), depobj,
     838          250 :                        TYPE_SIZE_UNIT (ptr_type_node));
     839          250 :   r = build_indirect_ref (loc, depobj, RO_UNARY_STAR);
     840          250 :   add_stmt (build2 (MODIFY_EXPR, void_type_node, r, t));
     841              : }
     842              : 
     843              : 
     844              : /* Complete a #pragma omp flush construct.  We don't do anything with
     845              :    the variable list that the syntax allows.  LOC is the location of
     846              :    the #pragma.  */
     847              : 
     848              : void
     849           59 : c_finish_omp_flush (location_t loc, int mo)
     850              : {
     851           59 :   tree x;
     852              : 
     853           59 :   if (mo == MEMMODEL_LAST || mo == MEMMODEL_SEQ_CST)
     854              :     {
     855           41 :       x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
     856           41 :       x = build_call_expr_loc (loc, x, 0);
     857              :     }
     858              :   else
     859              :     {
     860           18 :       x = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE);
     861           18 :       x = build_call_expr_loc (loc, x, 1,
     862           18 :                                build_int_cst (integer_type_node, mo));
     863              :     }
     864           59 :   add_stmt (x);
     865           59 : }
     866              : 
     867              : 
     868              : /* Check and canonicalize OMP_FOR increment expression.
     869              :    Helper function for c_finish_omp_for.  */
     870              : 
     871              : static tree
     872          609 : check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
     873              : {
     874          694 :   tree t;
     875              : 
     876         1388 :   if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
     877         1388 :       || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
     878            0 :     return error_mark_node;
     879              : 
     880          694 :   if (exp == decl)
     881          171 :     return build_int_cst (TREE_TYPE (exp), 0);
     882              : 
     883          523 :   switch (TREE_CODE (exp))
     884              :     {
     885          197 :     CASE_CONVERT:
     886          197 :       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
     887          197 :       if (t != error_mark_node)
     888          165 :         return fold_convert_loc (loc, TREE_TYPE (exp), t);
     889              :       break;
     890           16 :     case MINUS_EXPR:
     891           16 :       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
     892           16 :       if (t != error_mark_node)
     893           16 :         return fold_build2_loc (loc, MINUS_EXPR,
     894           32 :                                 TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
     895              :       break;
     896          172 :     case PLUS_EXPR:
     897          172 :       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
     898          172 :       if (t != error_mark_node)
     899          131 :         return fold_build2_loc (loc, PLUS_EXPR,
     900          262 :                                 TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
     901           41 :       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl);
     902           41 :       if (t != error_mark_node)
     903           33 :         return fold_build2_loc (loc, PLUS_EXPR,
     904           66 :                                 TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
     905              :       break;
     906           85 :     case COMPOUND_EXPR:
     907           85 :       {
     908              :         /* cp_build_modify_expr forces preevaluation of the RHS to make
     909              :            sure that it is evaluated before the lvalue-rvalue conversion
     910              :            is applied to the LHS.  Reconstruct the original expression.  */
     911           85 :         tree op0 = TREE_OPERAND (exp, 0);
     912           85 :         if (TREE_CODE (op0) == TARGET_EXPR
     913           85 :             && !VOID_TYPE_P (TREE_TYPE (op0)))
     914              :           {
     915           85 :             tree op1 = TREE_OPERAND (exp, 1);
     916           85 :             tree temp = TARGET_EXPR_SLOT (op0);
     917           85 :             if (BINARY_CLASS_P (op1)
     918           85 :                 && TREE_OPERAND (op1, 1) == temp)
     919              :               {
     920           85 :                 op1 = copy_node (op1);
     921           85 :                 TREE_OPERAND (op1, 1) = TARGET_EXPR_INITIAL (op0);
     922           85 :                 return check_omp_for_incr_expr (loc, op1, decl);
     923              :               }
     924              :           }
     925              :         break;
     926              :       }
     927              :     default:
     928              :       break;
     929              :     }
     930              : 
     931           93 :   return error_mark_node;
     932              : }
     933              : 
     934              : /* If the OMP_FOR increment expression in INCR is of pointer type,
     935              :    canonicalize it into an expression handled by gimplify_omp_for()
     936              :    and return it.  DECL is the iteration variable.  */
     937              : 
     938              : static tree
     939        31984 : c_omp_for_incr_canonicalize_ptr (location_t loc, tree decl, tree incr)
     940              : {
     941        61961 :   if (POINTER_TYPE_P (TREE_TYPE (decl))
     942        31984 :       && TREE_OPERAND (incr, 1))
     943              :     {
     944         1997 :       tree t = fold_convert_loc (loc,
     945         1997 :                                  sizetype, TREE_OPERAND (incr, 1));
     946              : 
     947         1997 :       if (TREE_CODE (incr) == POSTDECREMENT_EXPR
     948         1954 :           || TREE_CODE (incr) == PREDECREMENT_EXPR)
     949          597 :         t = fold_build1_loc (loc, NEGATE_EXPR, sizetype, t);
     950         1997 :       t = fold_build_pointer_plus (decl, t);
     951         1997 :       incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
     952              :     }
     953        31984 :   return incr;
     954              : }
     955              : 
     956              : /* Validate and generate OMP_FOR.
     957              :    DECLV is a vector of iteration variables, for each collapsed loop.
     958              : 
     959              :    ORIG_DECLV, if non-NULL, is a vector with the original iteration
     960              :    variables (prior to any transformations, by say, C++ iterators).
     961              : 
     962              :    INITV, CONDV and INCRV are vectors containing initialization
     963              :    expressions, controlling predicates and increment expressions.
     964              :    BODY is the body of the loop and PRE_BODY statements that go before
     965              :    the loop.  */
     966              : 
     967              : tree
     968        31926 : c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
     969              :                   tree orig_declv, tree initv, tree condv, tree incrv,
     970              :                   tree body, tree pre_body, bool final_p)
     971              : {
     972        31926 :   location_t elocus;
     973        31926 :   bool fail = false;
     974        31926 :   int i;
     975              : 
     976        31926 :   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
     977        31926 :   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
     978        31926 :   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
     979        73875 :   for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
     980              :     {
     981        43327 :       tree decl = TREE_VEC_ELT (declv, i);
     982        43327 :       tree init = TREE_VEC_ELT (initv, i);
     983        43327 :       tree cond = TREE_VEC_ELT (condv, i);
     984        43327 :       tree incr = TREE_VEC_ELT (incrv, i);
     985              : 
     986        43327 :       if (init == NULL_TREE)
     987              :         {
     988         1378 :           gcc_assert (decl == NULL_TREE
     989              :                       && cond == NULL_TREE
     990              :                       && incr == NULL_TREE);
     991         1649 :           for (i++; i < TREE_VEC_LENGTH (declv); i++)
     992          271 :             gcc_assert (TREE_VEC_ELT (declv, i) == NULL_TREE
     993              :                         && TREE_VEC_ELT (initv, i) == NULL_TREE
     994              :                         && TREE_VEC_ELT (condv, i) == NULL_TREE
     995              :                         && TREE_VEC_ELT (incrv, i) == NULL_TREE);
     996              :           break;
     997              :         }
     998              : 
     999        41949 :       elocus = locus;
    1000        41949 :       if (EXPR_HAS_LOCATION (init))
    1001        37257 :         elocus = EXPR_LOCATION (init);
    1002              : 
    1003              :       /* Validate the iteration variable.  */
    1004        83898 :       if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
    1005        44823 :           && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
    1006              :         {
    1007            1 :           error_at (elocus, "invalid type for iteration variable %qE", decl);
    1008            1 :           fail = true;
    1009              :         }
    1010        41948 :       else if (TYPE_ATOMIC (TREE_TYPE (decl)))
    1011              :         {
    1012           16 :           error_at (elocus, "%<_Atomic%> iteration variable %qE", decl);
    1013           16 :           fail = true;
    1014              :           /* _Atomic iterator confuses stuff too much, so we risk ICE
    1015              :              trying to diagnose it further.  */
    1016           16 :           continue;
    1017              :         }
    1018              : 
    1019              :       /* In the case of "for (int i = 0...)", init will be a decl.  It should
    1020              :          have a DECL_INITIAL that we can turn into an assignment.  */
    1021        41933 :       if (init == decl)
    1022              :         {
    1023         4676 :           elocus = DECL_SOURCE_LOCATION (decl);
    1024              : 
    1025         4676 :           init = DECL_INITIAL (decl);
    1026         4676 :           if (init == NULL)
    1027              :             {
    1028            0 :               error_at (elocus, "%qE is not initialized", decl);
    1029            0 :               init = integer_zero_node;
    1030            0 :               fail = true;
    1031              :             }
    1032         4676 :           DECL_INITIAL (decl) = NULL_TREE;
    1033              : 
    1034         4676 :           init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR,
    1035              :                                     /* FIXME diagnostics: This should
    1036              :                                        be the location of the INIT.  */
    1037              :                                     elocus,
    1038              :                                     init,
    1039              :                                     NULL_TREE);
    1040              :         }
    1041        41933 :       if (init != error_mark_node)
    1042              :         {
    1043        41933 :           gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
    1044        41933 :           gcc_assert (TREE_OPERAND (init, 0) == decl);
    1045              :         }
    1046              : 
    1047        41933 :       if (cond == NULL_TREE)
    1048              :         {
    1049            2 :           error_at (elocus, "missing controlling predicate");
    1050            2 :           fail = true;
    1051              :         }
    1052              :       else
    1053              :         {
    1054        41931 :           bool cond_ok = false;
    1055              : 
    1056              :           /* E.g. C sizeof (vla) could add COMPOUND_EXPRs with
    1057              :              evaluation of the vla VAR_DECL.  We need to readd
    1058              :              them to the non-decl operand.  See PR45784.  */
    1059        41931 :           while (TREE_CODE (cond) == COMPOUND_EXPR)
    1060            0 :             cond = TREE_OPERAND (cond, 1);
    1061              : 
    1062        41931 :           if (EXPR_HAS_LOCATION (cond))
    1063        41803 :             elocus = EXPR_LOCATION (cond);
    1064              : 
    1065        41931 :           if (TREE_CODE (cond) == LT_EXPR
    1066              :               || TREE_CODE (cond) == LE_EXPR
    1067              :               || TREE_CODE (cond) == GT_EXPR
    1068        41931 :               || TREE_CODE (cond) == GE_EXPR
    1069         5587 :               || TREE_CODE (cond) == NE_EXPR
    1070           31 :               || TREE_CODE (cond) == EQ_EXPR)
    1071              :             {
    1072        41900 :               tree op0 = TREE_OPERAND (cond, 0);
    1073        41900 :               tree op1 = TREE_OPERAND (cond, 1);
    1074              : 
    1075              :               /* 2.5.1.  The comparison in the condition is computed in
    1076              :                  the type of DECL, otherwise the behavior is undefined.
    1077              : 
    1078              :                  For example:
    1079              :                  long n; int i;
    1080              :                  i < n;
    1081              : 
    1082              :                  according to ISO will be evaluated as:
    1083              :                  (long)i < n;
    1084              : 
    1085              :                  We want to force:
    1086              :                  i < (int)n;  */
    1087        41900 :               if (TREE_CODE (op0) == NOP_EXPR
    1088        41900 :                   && decl == TREE_OPERAND (op0, 0))
    1089              :                 {
    1090           58 :                   TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
    1091           58 :                   TREE_OPERAND (cond, 1)
    1092          116 :                     = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
    1093           58 :                                    TREE_OPERAND (cond, 1));
    1094              :                 }
    1095        41842 :               else if (TREE_CODE (op1) == NOP_EXPR
    1096        41842 :                        && decl == TREE_OPERAND (op1, 0))
    1097              :                 {
    1098            4 :                   TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
    1099            4 :                   TREE_OPERAND (cond, 0)
    1100            8 :                     = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
    1101            4 :                                    TREE_OPERAND (cond, 0));
    1102              :                 }
    1103              : 
    1104        41900 :               if (decl == TREE_OPERAND (cond, 0))
    1105              :                 cond_ok = true;
    1106          139 :               else if (decl == TREE_OPERAND (cond, 1))
    1107              :                 {
    1108          138 :                   TREE_SET_CODE (cond,
    1109              :                                  swap_tree_comparison (TREE_CODE (cond)));
    1110          138 :                   TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
    1111          138 :                   TREE_OPERAND (cond, 0) = decl;
    1112          138 :                   cond_ok = true;
    1113              :                 }
    1114              : 
    1115        41900 :               if (TREE_CODE (cond) == NE_EXPR
    1116        41900 :                   || TREE_CODE (cond) == EQ_EXPR)
    1117              :                 {
    1118         5556 :                   if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
    1119              :                     {
    1120          935 :                       if (code == OACC_LOOP || TREE_CODE (cond) == EQ_EXPR)
    1121              :                         cond_ok = false;
    1122              :                     }
    1123         4621 :                   else if (operand_equal_p (TREE_OPERAND (cond, 1),
    1124         4621 :                                             TYPE_MIN_VALUE (TREE_TYPE (decl)),
    1125              :                                             0))
    1126          221 :                     TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
    1127              :                                          ? GT_EXPR : LE_EXPR);
    1128         4400 :                   else if (operand_equal_p (TREE_OPERAND (cond, 1),
    1129         4400 :                                             TYPE_MAX_VALUE (TREE_TYPE (decl)),
    1130              :                                             0))
    1131            5 :                     TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
    1132              :                                          ? LT_EXPR : GE_EXPR);
    1133         4395 :                   else if (code == OACC_LOOP || TREE_CODE (cond) == EQ_EXPR)
    1134              :                     cond_ok = false;
    1135              :                 }
    1136              : 
    1137        41900 :               if (cond_ok && TREE_VEC_ELT (condv, i) != cond)
    1138              :                 {
    1139            0 :                   tree ce = NULL_TREE, *pce = &ce;
    1140            0 :                   tree type = TREE_TYPE (TREE_OPERAND (cond, 1));
    1141            0 :                   for (tree c = TREE_VEC_ELT (condv, i); c != cond;
    1142            0 :                        c = TREE_OPERAND (c, 1))
    1143              :                     {
    1144            0 :                       *pce = build2 (COMPOUND_EXPR, type, TREE_OPERAND (c, 0),
    1145            0 :                                      TREE_OPERAND (cond, 1));
    1146            0 :                       pce = &TREE_OPERAND (*pce, 1);
    1147              :                     }
    1148            0 :                   TREE_OPERAND (cond, 1) = ce;
    1149            0 :                   TREE_VEC_ELT (condv, i) = cond;
    1150              :                 }
    1151              :             }
    1152              : 
    1153        41900 :           if (!cond_ok)
    1154              :             {
    1155           32 :               error_at (elocus, "invalid controlling predicate");
    1156           32 :               fail = true;
    1157              :             }
    1158              :         }
    1159              : 
    1160        41933 :       if (incr == NULL_TREE)
    1161              :         {
    1162            0 :           error_at (elocus, "missing increment expression");
    1163            0 :           fail = true;
    1164              :         }
    1165              :       else
    1166              :         {
    1167        41933 :           bool incr_ok = false;
    1168              : 
    1169        41933 :           if (EXPR_HAS_LOCATION (incr))
    1170        41053 :             elocus = EXPR_LOCATION (incr);
    1171              : 
    1172              :           /* Check all the valid increment expressions: v++, v--, ++v, --v,
    1173              :              v = v + incr, v = incr + v and v = v - incr.  */
    1174        41933 :           switch (TREE_CODE (incr))
    1175              :             {
    1176        31990 :             case POSTINCREMENT_EXPR:
    1177        31990 :             case PREINCREMENT_EXPR:
    1178        31990 :             case POSTDECREMENT_EXPR:
    1179        31990 :             case PREDECREMENT_EXPR:
    1180        31990 :               if (TREE_OPERAND (incr, 0) != decl)
    1181              :                 break;
    1182              : 
    1183        31984 :               incr_ok = true;
    1184        31984 :               if (!fail
    1185        31959 :                   && TREE_CODE (cond) == NE_EXPR
    1186         3739 :                   && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
    1187          819 :                   && TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))
    1188        32803 :                   && (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))))
    1189              :                       != INTEGER_CST))
    1190              :                 {
    1191              :                   /* For pointer to VLA, transform != into < or >
    1192              :                      depending on whether incr is increment or decrement.  */
    1193            4 :                   if (TREE_CODE (incr) == PREINCREMENT_EXPR
    1194            4 :                       || TREE_CODE (incr) == POSTINCREMENT_EXPR)
    1195            2 :                     TREE_SET_CODE (cond, LT_EXPR);
    1196              :                   else
    1197            2 :                     TREE_SET_CODE (cond, GT_EXPR);
    1198              :                 }
    1199        31984 :               incr = c_omp_for_incr_canonicalize_ptr (elocus, decl, incr);
    1200        31984 :               break;
    1201              : 
    1202          202 :             case COMPOUND_EXPR:
    1203          202 :               if ((TREE_CODE (TREE_OPERAND (incr, 0)) != SAVE_EXPR
    1204            6 :                    && TREE_CODE (TREE_OPERAND (incr, 0)) != TARGET_EXPR)
    1205          203 :                   || TREE_CODE (TREE_OPERAND (incr, 1)) != MODIFY_EXPR)
    1206              :                 break;
    1207          197 :               incr = TREE_OPERAND (incr, 1);
    1208              :               /* FALLTHRU */
    1209         9927 :             case MODIFY_EXPR:
    1210         9927 :               if (TREE_OPERAND (incr, 0) != decl)
    1211              :                 break;
    1212         9927 :               if (TREE_OPERAND (incr, 1) == decl)
    1213              :                 break;
    1214         9927 :               if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
    1215         9927 :                   && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
    1216          286 :                       || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
    1217              :                 incr_ok = true;
    1218         2072 :               else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
    1219         1045 :                         || (TREE_CODE (TREE_OPERAND (incr, 1))
    1220              :                             == POINTER_PLUS_EXPR))
    1221         2937 :                        && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
    1222              :                 incr_ok = true;
    1223              :               else
    1224              :                 {
    1225          183 :                   tree t = check_omp_for_incr_expr (elocus,
    1226          183 :                                                     TREE_OPERAND (incr, 1),
    1227              :                                                     decl);
    1228          183 :                   if (t != error_mark_node)
    1229              :                     {
    1230          171 :                       incr_ok = true;
    1231          171 :                       t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
    1232          171 :                       incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
    1233              :                     }
    1234              :                 }
    1235         9927 :               if (!fail
    1236         9927 :                   && incr_ok
    1237         9909 :                   && TREE_CODE (cond) == NE_EXPR)
    1238              :                 {
    1239         1591 :                   tree i = TREE_OPERAND (incr, 1);
    1240         1591 :                   i = TREE_OPERAND (i, TREE_OPERAND (i, 0) == decl);
    1241         1591 :                   i = c_fully_fold (i, false, NULL);
    1242         1591 :                   if (!final_p
    1243            4 :                       && TREE_CODE (i) != INTEGER_CST)
    1244              :                     ;
    1245         1591 :                   else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
    1246              :                     {
    1247          116 :                       tree unit
    1248          116 :                         = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
    1249          116 :                       if (unit)
    1250              :                         {
    1251          116 :                           enum tree_code ccode = GT_EXPR;
    1252          116 :                           unit = c_fully_fold (unit, false, NULL);
    1253          116 :                           i = fold_convert (TREE_TYPE (unit), i);
    1254          116 :                           if (operand_equal_p (unit, i, 0))
    1255              :                             ccode = LT_EXPR;
    1256           90 :                           if (ccode == GT_EXPR)
    1257              :                             {
    1258           90 :                               i = fold_unary (NEGATE_EXPR, TREE_TYPE (i), i);
    1259           90 :                               if (i == NULL_TREE
    1260           90 :                                   || !operand_equal_p (unit, i, 0))
    1261              :                                 {
    1262           72 :                                   error_at (elocus,
    1263              :                                             "increment is not constant 1 or "
    1264              :                                             "-1 for %<!=%> condition");
    1265           72 :                                   fail = true;
    1266              :                                 }
    1267              :                             }
    1268          116 :                           if (TREE_CODE (unit) != INTEGER_CST)
    1269              :                             /* For pointer to VLA, transform != into < or >
    1270              :                                depending on whether the pointer is
    1271              :                                incremented or decremented in each
    1272              :                                iteration.  */
    1273           60 :                             TREE_SET_CODE (cond, ccode);
    1274              :                         }
    1275              :                     }
    1276              :                   else
    1277              :                     {
    1278         1475 :                       if (!integer_onep (i) && !integer_minus_onep (i))
    1279              :                         {
    1280          132 :                           error_at (elocus,
    1281              :                                     "increment is not constant 1 or -1 for"
    1282              :                                     " %<!=%> condition");
    1283          132 :                           fail = true;
    1284              :                         }
    1285              :                     }
    1286              :                 }
    1287              :               break;
    1288              : 
    1289              :             default:
    1290              :               break;
    1291              :             }
    1292        41911 :           if (!incr_ok)
    1293              :             {
    1294           34 :               error_at (elocus, "invalid increment expression");
    1295           34 :               fail = true;
    1296              :             }
    1297              :         }
    1298              : 
    1299        41933 :       TREE_VEC_ELT (initv, i) = init;
    1300        41933 :       TREE_VEC_ELT (incrv, i) = incr;
    1301              :     }
    1302              : 
    1303        31926 :   if (fail)
    1304              :     return NULL;
    1305              :   else
    1306              :     {
    1307        31641 :       tree t = make_node (code);
    1308              : 
    1309        31641 :       TREE_TYPE (t) = void_type_node;
    1310        31641 :       OMP_FOR_INIT (t) = initv;
    1311        31641 :       OMP_FOR_COND (t) = condv;
    1312        31641 :       OMP_FOR_INCR (t) = incrv;
    1313        31641 :       OMP_FOR_BODY (t) = body;
    1314        31641 :       OMP_FOR_PRE_BODY (t) = pre_body;
    1315        31641 :       OMP_FOR_ORIG_DECLS (t) = orig_declv;
    1316              : 
    1317        31641 :       SET_EXPR_LOCATION (t, locus);
    1318        31641 :       return t;
    1319              :     }
    1320              : }
    1321              : 
    1322              : /* Type for passing data in between c_omp_check_loop_iv and
    1323              :    c_omp_check_loop_iv_r.  */
    1324              : 
    1325              : struct c_omp_check_loop_iv_data
    1326              : {
    1327              :   tree declv;
    1328              :   bool fail;
    1329              :   bool maybe_nonrect;
    1330              :   location_t stmt_loc;
    1331              :   location_t expr_loc;
    1332              :   int kind;
    1333              :   int idx;
    1334              :   walk_tree_lh lh;
    1335              :   hash_set<tree> *ppset;
    1336              : };
    1337              : 
    1338              : /* Return -1 if DECL is not a loop iterator in loop nest D, otherwise
    1339              :    return the index of the loop in which it is an iterator.
    1340              :    Return TREE_VEC_LENGTH (d->declv) if it is a C++ range for iterator.  */
    1341              : 
    1342              : static int
    1343        42142 : c_omp_is_loop_iterator (tree decl, struct c_omp_check_loop_iv_data *d)
    1344              : {
    1345       133421 :   for (int i = 0; i < TREE_VEC_LENGTH (d->declv); i++)
    1346       105815 :     if (TREE_VEC_ELT (d->declv, i) == NULL_TREE)
    1347          253 :       continue;
    1348       105562 :     else if (decl == TREE_VEC_ELT (d->declv, i)
    1349       105562 :              || (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
    1350         2292 :                  && decl == TREE_PURPOSE (TREE_VEC_ELT (d->declv, i))))
    1351              :       return i;
    1352        91107 :     else if (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
    1353         2223 :              && TREE_CHAIN (TREE_VEC_ELT (d->declv, i))
    1354        92146 :              && (TREE_CODE (TREE_CHAIN (TREE_VEC_ELT (d->declv, i)))
    1355              :                  == TREE_VEC))
    1356         1461 :       for (int j = 2;
    1357         2500 :            j < TREE_VEC_LENGTH (TREE_CHAIN (TREE_VEC_ELT (d->declv, i))); j++)
    1358         1542 :         if (decl == TREE_VEC_ELT (TREE_CHAIN (TREE_VEC_ELT (d->declv, i)), j))
    1359              :           return TREE_VEC_LENGTH (d->declv);
    1360              :   return -1;
    1361              : }
    1362              : 
    1363              : /* Helper function called via walk_tree, to diagnose uses
    1364              :    of associated loop IVs inside of lb, b and incr expressions
    1365              :    of OpenMP loops.  */
    1366              : 
    1367              : static tree
    1368       169995 : c_omp_check_loop_iv_r (tree *tp, int *walk_subtrees, void *data)
    1369              : {
    1370       169995 :   struct c_omp_check_loop_iv_data *d
    1371              :     = (struct c_omp_check_loop_iv_data *) data;
    1372       169995 :   if (DECL_P (*tp))
    1373              :     {
    1374        28643 :       int idx = c_omp_is_loop_iterator (*tp, d);
    1375        28643 :       if (idx == -1)
    1376              :         return NULL_TREE;
    1377              : 
    1378         1441 :       if ((d->kind & 4) && idx < d->idx)
    1379              :         {
    1380          787 :           d->maybe_nonrect = true;
    1381          787 :           return NULL_TREE;
    1382              :         }
    1383              : 
    1384          654 :       if (d->ppset->add (*tp))
    1385              :         return NULL_TREE;
    1386              : 
    1387          636 :       location_t loc = d->expr_loc;
    1388          636 :       if (loc == UNKNOWN_LOCATION)
    1389          181 :         loc = d->stmt_loc;
    1390              : 
    1391          636 :       switch (d->kind & 3)
    1392              :         {
    1393          206 :         case 0:
    1394          206 :           error_at (loc, "initializer expression refers to "
    1395              :                          "iteration variable %qD", *tp);
    1396          206 :           break;
    1397          201 :         case 1:
    1398          201 :           error_at (loc, "condition expression refers to "
    1399              :                          "iteration variable %qD", *tp);
    1400          201 :           break;
    1401          229 :         case 2:
    1402          229 :           error_at (loc, "increment expression refers to "
    1403              :                          "iteration variable %qD", *tp);
    1404          229 :           break;
    1405              :         }
    1406          636 :       d->fail = true;
    1407              :     }
    1408       141352 :   else if ((d->kind & 4)
    1409              :            && TREE_CODE (*tp) != TREE_VEC
    1410              :            && TREE_CODE (*tp) != PLUS_EXPR
    1411              :            && TREE_CODE (*tp) != MINUS_EXPR
    1412              :            && TREE_CODE (*tp) != MULT_EXPR
    1413              :            && TREE_CODE (*tp) != POINTER_PLUS_EXPR
    1414              :            && !CONVERT_EXPR_P (*tp))
    1415              :     {
    1416        17170 :       *walk_subtrees = 0;
    1417        17170 :       d->kind &= 3;
    1418        17170 :       walk_tree_1 (tp, c_omp_check_loop_iv_r, data, NULL, d->lh);
    1419        17170 :       d->kind |= 4;
    1420        17170 :       return NULL_TREE;
    1421              :     }
    1422       124182 :   else if (d->ppset->add (*tp))
    1423        17893 :     *walk_subtrees = 0;
    1424              :   /* Don't walk dtors added by C++ wrap_cleanups_r.  */
    1425       106289 :   else if (TREE_CODE (*tp) == TRY_CATCH_EXPR
    1426       106289 :            && TRY_CATCH_IS_CLEANUP (*tp))
    1427              :     {
    1428            0 :       *walk_subtrees = 0;
    1429            0 :       return walk_tree_1 (&TREE_OPERAND (*tp, 0), c_omp_check_loop_iv_r, data,
    1430            0 :                           NULL, d->lh);
    1431              :     }
    1432              : 
    1433              :   return NULL_TREE;
    1434              : }
    1435              : 
    1436              : /* Check the allowed expressions for non-rectangular loop nest lb and b
    1437              :    expressions.  Return the outer var decl referenced in the expression.  */
    1438              : 
    1439              : static tree
    1440          744 : c_omp_check_nonrect_loop_iv (tree *tp, struct c_omp_check_loop_iv_data *d,
    1441              :                              walk_tree_lh lh)
    1442              : {
    1443          744 :   d->maybe_nonrect = false;
    1444          744 :   if (d->fail)
    1445              :     return NULL_TREE;
    1446              : 
    1447          728 :   hash_set<tree> pset;
    1448          728 :   hash_set<tree> *ppset = d->ppset;
    1449          728 :   d->ppset = &pset;
    1450              : 
    1451          728 :   tree t = *tp;
    1452          728 :   if (TREE_CODE (t) == TREE_VEC
    1453           24 :       && TREE_VEC_LENGTH (t) == 3
    1454           24 :       && DECL_P (TREE_VEC_ELT (t, 0))
    1455          752 :       && c_omp_is_loop_iterator (TREE_VEC_ELT (t, 0), d) >= 0)
    1456              :     {
    1457           24 :       d->kind &= 3;
    1458           24 :       walk_tree_1 (&TREE_VEC_ELT (t, 1), c_omp_check_loop_iv_r, d, NULL, lh);
    1459           24 :       walk_tree_1 (&TREE_VEC_ELT (t, 1), c_omp_check_loop_iv_r, d, NULL, lh);
    1460           24 :       d->ppset = ppset;
    1461           24 :       return d->fail ? NULL_TREE : TREE_VEC_ELT (t, 0);
    1462              :     }
    1463              : 
    1464          716 :   while (CONVERT_EXPR_P (t))
    1465           12 :     t = TREE_OPERAND (t, 0);
    1466              : 
    1467          704 :   tree a1 = t, a2 = integer_zero_node;
    1468          704 :   bool neg_a1 = false, neg_a2 = false;
    1469          704 :   switch (TREE_CODE (t))
    1470              :     {
    1471          298 :     case PLUS_EXPR:
    1472          298 :     case MINUS_EXPR:
    1473          298 :       a1 = TREE_OPERAND (t, 0);
    1474          298 :       a2 = TREE_OPERAND (t, 1);
    1475          350 :       while (CONVERT_EXPR_P (a1))
    1476           52 :         a1 = TREE_OPERAND (a1, 0);
    1477          386 :       while (CONVERT_EXPR_P (a2))
    1478           88 :         a2 = TREE_OPERAND (a2, 0);
    1479          298 :       if (DECL_P (a1) && c_omp_is_loop_iterator (a1, d) >= 0)
    1480              :         {
    1481           64 :           a2 = TREE_OPERAND (t, 1);
    1482           64 :           if (TREE_CODE (t) == MINUS_EXPR)
    1483           19 :             neg_a2 = true;
    1484           64 :           t = a1;
    1485           64 :           break;
    1486              :         }
    1487          234 :       if (DECL_P (a2) && c_omp_is_loop_iterator (a2, d) >= 0)
    1488              :         {
    1489            0 :           a1 = TREE_OPERAND (t, 0);
    1490            0 :           if (TREE_CODE (t) == MINUS_EXPR)
    1491            0 :             neg_a1 = true;
    1492            0 :           t = a2;
    1493            0 :           a2 = a1;
    1494            0 :           break;
    1495              :         }
    1496          234 :       if (TREE_CODE (a1) == MULT_EXPR && TREE_CODE (a2) == MULT_EXPR)
    1497              :         {
    1498            0 :           tree o1 = TREE_OPERAND (a1, 0);
    1499            0 :           tree o2 = TREE_OPERAND (a1, 1);
    1500            0 :           while (CONVERT_EXPR_P (o1))
    1501            0 :             o1 = TREE_OPERAND (o1, 0);
    1502            0 :           while (CONVERT_EXPR_P (o2))
    1503            0 :             o2 = TREE_OPERAND (o2, 0);
    1504            0 :           if ((DECL_P (o1) && c_omp_is_loop_iterator (o1, d) >= 0)
    1505            0 :               || (DECL_P (o2) && c_omp_is_loop_iterator (o2, d) >= 0))
    1506              :             {
    1507            0 :               a2 = TREE_OPERAND (t, 1);
    1508            0 :               if (TREE_CODE (t) == MINUS_EXPR)
    1509            0 :                 neg_a2 = true;
    1510            0 :               t = a1;
    1511            0 :               break;
    1512              :             }
    1513              :         }
    1514          234 :       if (TREE_CODE (a2) == MULT_EXPR)
    1515              :         {
    1516           60 :           a1 = TREE_OPERAND (t, 0);
    1517           60 :           if (TREE_CODE (t) == MINUS_EXPR)
    1518            0 :             neg_a1 = true;
    1519           60 :           t = a2;
    1520           60 :           a2 = a1;
    1521           60 :           break;
    1522              :         }
    1523          174 :       if (TREE_CODE (a1) == MULT_EXPR)
    1524              :         {
    1525          174 :           a2 = TREE_OPERAND (t, 1);
    1526          174 :           if (TREE_CODE (t) == MINUS_EXPR)
    1527           32 :             neg_a2 = true;
    1528          174 :           t = a1;
    1529          174 :           break;
    1530              :         }
    1531            0 :       a2 = integer_zero_node;
    1532            0 :       break;
    1533           75 :     case POINTER_PLUS_EXPR:
    1534           75 :       a1 = TREE_OPERAND (t, 0);
    1535           75 :       a2 = TREE_OPERAND (t, 1);
    1536           79 :       while (CONVERT_EXPR_P (a1))
    1537            4 :         a1 = TREE_OPERAND (a1, 0);
    1538           75 :       if (DECL_P (a1) && c_omp_is_loop_iterator (a1, d) >= 0)
    1539              :         {
    1540           71 :           a2 = TREE_OPERAND (t, 1);
    1541           71 :           t = a1;
    1542           71 :           break;
    1543              :         }
    1544              :       break;
    1545              :     default:
    1546              :       break;
    1547              :     }
    1548              : 
    1549          704 :   a1 = integer_one_node;
    1550          704 :   if (TREE_CODE (t) == MULT_EXPR)
    1551              :     {
    1552          367 :       tree o1 = TREE_OPERAND (t, 0);
    1553          367 :       tree o2 = TREE_OPERAND (t, 1);
    1554          448 :       while (CONVERT_EXPR_P (o1))
    1555           81 :         o1 = TREE_OPERAND (o1, 0);
    1556          435 :       while (CONVERT_EXPR_P (o2))
    1557           68 :         o2 = TREE_OPERAND (o2, 0);
    1558          367 :       if (DECL_P (o1) && c_omp_is_loop_iterator (o1, d) >= 0)
    1559              :         {
    1560          118 :           a1 = TREE_OPERAND (t, 1);
    1561          118 :           t = o1;
    1562              :         }
    1563          249 :       else if (DECL_P (o2) && c_omp_is_loop_iterator (o2, d) >= 0)
    1564              :         {
    1565          240 :           a1 = TREE_OPERAND (t, 0);
    1566          240 :           t = o2;
    1567              :         }
    1568              :     }
    1569              : 
    1570          704 :   d->kind &= 3;
    1571          704 :   tree ret = NULL_TREE;
    1572          704 :   if (DECL_P (t) && c_omp_is_loop_iterator (t, d) >= 0)
    1573              :     {
    1574          691 :       location_t loc = d->expr_loc;
    1575          691 :       if (loc == UNKNOWN_LOCATION)
    1576           93 :         loc = d->stmt_loc;
    1577          691 :       if (!lang_hooks.types_compatible_p (TREE_TYPE (*tp), TREE_TYPE (t)))
    1578              :         {
    1579           16 :           if (d->kind == 0)
    1580           12 :             error_at (loc, "outer iteration variable %qD used in initializer"
    1581              :                            " expression has type other than %qT",
    1582           12 :                       t, TREE_TYPE (*tp));
    1583              :           else
    1584            4 :             error_at (loc, "outer iteration variable %qD used in condition"
    1585              :                            " expression has type other than %qT",
    1586            4 :                       t, TREE_TYPE (*tp));
    1587           16 :           d->fail = true;
    1588              :         }
    1589          675 :       else if (!INTEGRAL_TYPE_P (TREE_TYPE (a1)))
    1590              :         {
    1591            0 :           error_at (loc, "outer iteration variable %qD multiplier expression"
    1592              :                          " %qE is not integral", t, a1);
    1593            0 :           d->fail = true;
    1594              :         }
    1595          675 :       else if (!INTEGRAL_TYPE_P (TREE_TYPE (a2)))
    1596              :         {
    1597            0 :           error_at (loc, "outer iteration variable %qD addend expression"
    1598              :                          " %qE is not integral", t, a2);
    1599            0 :           d->fail = true;
    1600              :         }
    1601              :       else
    1602              :         {
    1603          675 :           walk_tree_1 (&a1, c_omp_check_loop_iv_r, d, NULL, lh);
    1604          675 :           walk_tree_1 (&a2, c_omp_check_loop_iv_r, d, NULL, lh);
    1605              :         }
    1606          691 :       if (!d->fail)
    1607              :         {
    1608          660 :           a1 = fold_convert (TREE_TYPE (*tp), a1);
    1609          660 :           a2 = fold_convert (TREE_TYPE (*tp), a2);
    1610          660 :           if (neg_a1)
    1611            0 :             a1 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a1), a1);
    1612          660 :           if (neg_a2)
    1613           51 :             a2 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a2), a2);
    1614          660 :           ret = t;
    1615          660 :           *tp = make_tree_vec (3);
    1616          660 :           TREE_VEC_ELT (*tp, 0) = t;
    1617          660 :           TREE_VEC_ELT (*tp, 1) = a1;
    1618          660 :           TREE_VEC_ELT (*tp, 2) = a2;
    1619              :         }
    1620              :     }
    1621              :   else
    1622           13 :     walk_tree_1 (&t, c_omp_check_loop_iv_r, d, NULL, lh);
    1623              : 
    1624          704 :   d->ppset = ppset;
    1625          704 :   return ret;
    1626          728 : }
    1627              : 
    1628              : /* Callback for walk_tree to find nested loop transforming construct.  */
    1629              : 
    1630              : static tree
    1631        10110 : c_find_nested_loop_xform_r (tree *tp, int *walk_subtrees, void *)
    1632              : {
    1633        10110 :   *walk_subtrees = 0;
    1634        10110 :   switch (TREE_CODE (*tp))
    1635              :     {
    1636              :     case OMP_TILE:
    1637              :     case OMP_UNROLL:
    1638              :       return *tp;
    1639         2867 :     case BIND_EXPR:
    1640         2867 :       *walk_subtrees = 1;
    1641         2867 :       break;
    1642           41 :     case STATEMENT_LIST:
    1643           41 :       *walk_subtrees = 1;
    1644           41 :       break;
    1645           46 :     case TRY_FINALLY_EXPR:
    1646           46 :     case CLEANUP_POINT_EXPR:
    1647           46 :       *walk_subtrees = 1;
    1648           46 :       break;
    1649              :     default:
    1650              :       break;
    1651              :     }
    1652              :   return NULL;
    1653              : }
    1654              : 
    1655              : /* Find Jth loop among generated loops of STMT.  */
    1656              : 
    1657              : int
    1658         1659 : c_omp_find_generated_loop (tree &stmt, int j, walk_tree_lh lh)
    1659              : {
    1660         2498 :   stmt = walk_tree_1 (&stmt, c_find_nested_loop_xform_r,
    1661              :                       NULL, NULL, lh);
    1662         2498 :   gcc_assert (stmt);
    1663         2498 :   switch (TREE_CODE (stmt))
    1664              :     {
    1665          726 :     case OMP_UNROLL:
    1666          726 :       gcc_assert (omp_find_clause (OMP_FOR_CLAUSES (stmt),
    1667              :                                    OMP_CLAUSE_PARTIAL));
    1668              :       /* FALLTHRU */
    1669              :     case OMP_TILE:
    1670              :       int k;
    1671              :       k = 0;
    1672         2859 :       for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); ++i)
    1673         2859 :         if (i == j)
    1674              :           {
    1675         2498 :             if (TREE_VEC_ELT (OMP_FOR_INIT (stmt), i) == NULL_TREE)
    1676              :               {
    1677          839 :                 stmt = OMP_FOR_BODY (stmt);
    1678          839 :                 return c_omp_find_generated_loop (stmt, k, lh);
    1679              :               }
    1680              :             else
    1681         1659 :               return i;
    1682              :           }
    1683          361 :         else if (TREE_VEC_ELT (OMP_FOR_INIT (stmt), i) == NULL_TREE)
    1684           56 :           ++k;
    1685            0 :       gcc_unreachable ();
    1686            0 :     default:
    1687            0 :       gcc_unreachable ();
    1688              :     }
    1689              : }
    1690              : 
    1691              : /* Diagnose invalid references to loop iterators in lb, b and incr
    1692              :    expressions.  */
    1693              : 
    1694              : bool
    1695        31641 : c_omp_check_loop_iv (tree stmt, tree declv, walk_tree_lh lh)
    1696              : {
    1697        31641 :   hash_set<tree> pset;
    1698        31641 :   struct c_omp_check_loop_iv_data data;
    1699        31641 :   int i, k = 0;
    1700              : 
    1701        31641 :   data.declv = declv;
    1702        31641 :   data.fail = false;
    1703        31641 :   data.maybe_nonrect = false;
    1704        31641 :   data.stmt_loc = EXPR_LOCATION (stmt);
    1705        31641 :   data.lh = lh;
    1706        31641 :   data.ppset = &pset;
    1707        74950 :   for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
    1708              :     {
    1709        43309 :       tree this_stmt = stmt;
    1710        43309 :       int j = i;
    1711        43309 :       tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
    1712        43309 :       if (init == NULL_TREE)
    1713              :         {
    1714         1649 :           if (k == 0)
    1715         1378 :             data.declv = copy_node (declv);
    1716         1649 :           this_stmt = OMP_FOR_BODY (stmt);
    1717         1649 :           j = c_omp_find_generated_loop (this_stmt, k++, lh);
    1718         1649 :           init = TREE_VEC_ELT (OMP_FOR_INIT (this_stmt), j);
    1719         1649 :           TREE_VEC_ELT (data.declv, i) = TREE_OPERAND (init, 0);
    1720              :         }
    1721        43309 :       gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
    1722        43309 :       tree decl = TREE_OPERAND (init, 0);
    1723        43309 :       tree cond = TREE_VEC_ELT (OMP_FOR_COND (this_stmt), j);
    1724        43309 :       gcc_assert (COMPARISON_CLASS_P (cond));
    1725        43309 :       gcc_assert (TREE_OPERAND (cond, 0) == decl);
    1726        43309 :       tree incr = TREE_VEC_ELT (OMP_FOR_INCR (this_stmt), j);
    1727        43309 :       data.expr_loc = EXPR_LOCATION (TREE_OPERAND (init, 1));
    1728        43309 :       tree vec_outer1 = NULL_TREE, vec_outer2 = NULL_TREE;
    1729        43309 :       int kind = 0;
    1730        43309 :       if (i > 0
    1731        43309 :           && (unsigned) c_omp_is_loop_iterator (decl, &data) < (unsigned) i)
    1732              :         {
    1733           24 :           location_t loc = data.expr_loc;
    1734           24 :           if (loc == UNKNOWN_LOCATION)
    1735           24 :             loc = data.stmt_loc;
    1736           24 :           error_at (loc, "the same loop iteration variables %qD used in "
    1737              :                          "multiple associated loops", decl);
    1738           24 :           data.fail = true;
    1739              :         }
    1740              :       /* Handle non-rectangular loop nests.  */
    1741        43309 :       if (TREE_CODE (stmt) != OACC_LOOP && i > 0)
    1742        43309 :         kind = 4;
    1743        43309 :       data.kind = kind;
    1744        43309 :       data.idx = i;
    1745        43309 :       walk_tree_1 (&TREE_OPERAND (init, 1),
    1746              :                    c_omp_check_loop_iv_r, &data, NULL, lh);
    1747        43309 :       if (data.maybe_nonrect)
    1748          357 :         vec_outer1 = c_omp_check_nonrect_loop_iv (&TREE_OPERAND (init, 1),
    1749              :                                                   &data, lh);
    1750              :       /* Don't warn for C++ random access iterators here, the
    1751              :          expression then involves the subtraction and always refers
    1752              :          to the original value.  The C++ FE needs to warn on those
    1753              :          earlier.  */
    1754        43309 :       if (decl == TREE_VEC_ELT (data.declv, i)
    1755        43309 :           || (TREE_CODE (TREE_VEC_ELT (data.declv, i)) == TREE_LIST
    1756          933 :               && decl == TREE_PURPOSE (TREE_VEC_ELT (data.declv, i))))
    1757              :         {
    1758        42376 :           data.expr_loc = EXPR_LOCATION (cond);
    1759        42376 :           data.kind = kind | 1;
    1760        42376 :           walk_tree_1 (&TREE_OPERAND (cond, 1),
    1761              :                        c_omp_check_loop_iv_r, &data, NULL, lh);
    1762        42376 :           if (data.maybe_nonrect)
    1763          387 :             vec_outer2 = c_omp_check_nonrect_loop_iv (&TREE_OPERAND (cond, 1),
    1764              :                                                       &data, lh);
    1765              :         }
    1766        43309 :       if (vec_outer1 && vec_outer2 && vec_outer1 != vec_outer2)
    1767              :         {
    1768            8 :           location_t loc = data.expr_loc;
    1769            8 :           if (loc == UNKNOWN_LOCATION)
    1770            0 :             loc = data.stmt_loc;
    1771            8 :           error_at (loc, "two different outer iteration variables %qD and %qD"
    1772              :                          " used in a single loop", vec_outer1, vec_outer2);
    1773            8 :           data.fail = true;
    1774            8 :         }
    1775        43301 :       else if ((vec_outer1 || vec_outer2) && this_stmt != stmt)
    1776              :         {
    1777           16 :           location_t loc = data.expr_loc;
    1778           16 :           if (loc == UNKNOWN_LOCATION)
    1779            0 :             loc = data.stmt_loc;
    1780           16 :           sorry_at (loc, "non-rectangular loops from generated loops "
    1781              :                          "unsupported");
    1782           16 :           data.fail = true;
    1783              :         }
    1784        43309 :       if (vec_outer1 || vec_outer2)
    1785          474 :         OMP_FOR_NON_RECTANGULAR (stmt) = 1;
    1786        43309 :       if (TREE_CODE (incr) == MODIFY_EXPR)
    1787              :         {
    1788        11758 :           gcc_assert (TREE_OPERAND (incr, 0) == decl);
    1789        11758 :           incr = TREE_OPERAND (incr, 1);
    1790        11758 :           data.kind = 2;
    1791        11758 :           if (TREE_CODE (incr) == PLUS_EXPR
    1792        11758 :               && TREE_OPERAND (incr, 1) == decl)
    1793              :             {
    1794          299 :               data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 0));
    1795          299 :               walk_tree_1 (&TREE_OPERAND (incr, 0),
    1796              :                            c_omp_check_loop_iv_r, &data, NULL, lh);
    1797              :             }
    1798              :           else
    1799              :             {
    1800        11459 :               data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 1));
    1801        11459 :               walk_tree_1 (&TREE_OPERAND (incr, 1),
    1802              :                            c_omp_check_loop_iv_r, &data, NULL, lh);
    1803              :             }
    1804              :         }
    1805              :     }
    1806        31641 :   return !data.fail;
    1807        31641 : }
    1808              : 
    1809              : /* Similar, but allows to check the init or cond expressions individually.  */
    1810              : 
    1811              : bool
    1812         1971 : c_omp_check_loop_iv_exprs (location_t stmt_loc, enum tree_code code,
    1813              :                            tree declv, int i, tree decl, tree init, tree cond,
    1814              :                            walk_tree_lh lh)
    1815              : {
    1816         1971 :   hash_set<tree> pset;
    1817         1971 :   struct c_omp_check_loop_iv_data data;
    1818         1971 :   int kind = (code != OACC_LOOP && i > 0) ? 4 : 0;
    1819              : 
    1820         1971 :   data.declv = declv;
    1821         1971 :   data.fail = false;
    1822         1971 :   data.maybe_nonrect = false;
    1823         1971 :   data.stmt_loc = stmt_loc;
    1824         1971 :   data.lh = lh;
    1825         1971 :   data.ppset = &pset;
    1826         1971 :   data.idx = i;
    1827         1971 :   if (i > 0
    1828         1971 :       && (unsigned) c_omp_is_loop_iterator (decl, &data) < (unsigned) i)
    1829              :     {
    1830            6 :       error_at (stmt_loc, "the same loop iteration variables %qD used in "
    1831              :                           "multiple associated loops", decl);
    1832            6 :       data.fail = true;
    1833              :     }
    1834         1971 :   if (init)
    1835              :     {
    1836         1164 :       data.expr_loc = EXPR_LOCATION (init);
    1837         1164 :       data.kind = kind;
    1838         1164 :       walk_tree_1 (&init,
    1839              :                    c_omp_check_loop_iv_r, &data, NULL, lh);
    1840              :     }
    1841         1971 :   if (cond)
    1842              :     {
    1843          807 :       gcc_assert (COMPARISON_CLASS_P (cond));
    1844          807 :       data.expr_loc = EXPR_LOCATION (init);
    1845          807 :       data.kind = kind | 1;
    1846          807 :       if (TREE_OPERAND (cond, 0) == decl)
    1847          807 :         walk_tree_1 (&TREE_OPERAND (cond, 1),
    1848              :                      c_omp_check_loop_iv_r, &data, NULL, lh);
    1849              :       else
    1850            0 :         walk_tree_1 (&TREE_OPERAND (cond, 0),
    1851              :                      c_omp_check_loop_iv_r, &data, NULL, lh);
    1852              :     }
    1853         1971 :   return !data.fail;
    1854         1971 : }
    1855              : 
    1856              : 
    1857              : /* Helper function for c_omp_check_loop_binding_exprs: look for a binding
    1858              :    of DECL in BODY.  Only traverse things that might be containers for
    1859              :    intervening code in an OMP loop.  Returns the BIND_EXPR or DECL_EXPR
    1860              :    if found, otherwise null.  */
    1861              : 
    1862              : static tree
    1863         3987 : find_binding_in_body (tree decl, tree body)
    1864              : {
    1865         5543 :   if (!body)
    1866              :     return NULL_TREE;
    1867              : 
    1868         5543 :   switch (TREE_CODE (body))
    1869              :     {
    1870          447 :     case BIND_EXPR:
    1871          584 :       for (tree b = BIND_EXPR_VARS (body); b; b = DECL_CHAIN (b))
    1872          165 :         if (b == decl)
    1873              :           return body;
    1874          419 :       return find_binding_in_body (decl, BIND_EXPR_BODY (body));
    1875              : 
    1876          257 :     case DECL_EXPR:
    1877          257 :       if (DECL_EXPR_DECL (body) == decl)
    1878              :         return body;
    1879              :       return NULL_TREE;
    1880              : 
    1881         1042 :     case STATEMENT_LIST:
    1882         4587 :       for (tree_stmt_iterator si = tsi_start (body); !tsi_end_p (si);
    1883         3545 :            tsi_next (&si))
    1884              :         {
    1885         3573 :           tree b = find_binding_in_body (decl, tsi_stmt (si));
    1886         3573 :           if (b)
    1887           28 :             return b;
    1888              :         }
    1889         1014 :       return NULL_TREE;
    1890              : 
    1891         1137 :     case OMP_STRUCTURED_BLOCK:
    1892         1137 :       return find_binding_in_body (decl, OMP_BODY (body));
    1893              : 
    1894              :     default:
    1895              :       return NULL_TREE;
    1896              :     }
    1897              : }
    1898              : 
    1899              : /* Traversal function for check_loop_binding_expr, to diagnose
    1900              :    errors when a binding made in intervening code is referenced outside
    1901              :    of the loop.  Returns non-null if such a reference is found.  DATA points
    1902              :    to the tree containing the loop body.  */
    1903              : 
    1904              : static tree
    1905          859 : check_loop_binding_expr_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
    1906              :                            void *data)
    1907              : {
    1908          859 :   tree body = *(tree *)data;
    1909              : 
    1910          859 :   if (DECL_P (*tp) && find_binding_in_body (*tp, body))
    1911           49 :     return *tp;
    1912              :   return NULL_TREE;
    1913              : }
    1914              : 
    1915              : /* Helper macro used below.  */
    1916              : 
    1917              : #define LOCATION_OR(loc1, loc2) \
    1918              :   ((loc1) != UNKNOWN_LOCATION ? (loc1) : (loc2))
    1919              : 
    1920              : enum check_loop_binding_expr_ctx {
    1921              :   CHECK_LOOP_BINDING_EXPR_CTX_LOOP_VAR,
    1922              :   CHECK_LOOP_BINDING_EXPR_CTX_IN_INIT,
    1923              :   CHECK_LOOP_BINDING_EXPR_CTX_END_TEST,
    1924              :   CHECK_LOOP_BINDING_EXPR_CTX_INCR
    1925              : };
    1926              : 
    1927              : /* Check a single expression EXPR for references to variables bound in
    1928              :    intervening code in BODY.  Return true if ok, otherwise give an error
    1929              :    referencing CONTEXT and return false.  Use LOC for the error message
    1930              :    if EXPR doesn't have one.  */
    1931              : static bool
    1932          673 : check_loop_binding_expr (tree expr, tree body, location_t loc,
    1933              :                          check_loop_binding_expr_ctx ctx)
    1934              : {
    1935          673 :   tree bad = walk_tree (&expr, check_loop_binding_expr_r, (void *)&body, NULL);
    1936              : 
    1937          673 :   if (bad)
    1938              :     {
    1939           49 :       location_t eloc = EXPR_LOCATION (expr);
    1940           49 :       eloc = LOCATION_OR (eloc, loc);
    1941           49 :       switch (ctx)
    1942              :         {
    1943           14 :         case CHECK_LOOP_BINDING_EXPR_CTX_LOOP_VAR:
    1944           14 :           error_at (eloc, "variable %qD used as loop variable is bound "
    1945              :                     "in intervening code", bad);
    1946           14 :           break;
    1947           21 :         case CHECK_LOOP_BINDING_EXPR_CTX_IN_INIT:
    1948           21 :           error_at (eloc, "variable %qD used in initializer is bound "
    1949              :                     "in intervening code", bad);
    1950           21 :           break;
    1951            7 :         case CHECK_LOOP_BINDING_EXPR_CTX_END_TEST:
    1952            7 :           error_at (eloc, "variable %qD used in end test is bound "
    1953              :                     "in intervening code", bad);
    1954            7 :           break;
    1955            7 :         case CHECK_LOOP_BINDING_EXPR_CTX_INCR:
    1956            7 :           error_at (eloc, "variable %qD used in increment expression is bound "
    1957              :                     "in intervening code", bad);
    1958            7 :           break;
    1959              :         }
    1960           49 :       return false;
    1961              :     }
    1962              :   return true;
    1963              : }
    1964              : 
    1965              : /* STMT is an OMP_FOR construct.  Check all of the iteration variable,
    1966              :    initializer, end condition, and increment for bindings inside the
    1967              :    loop body.  If ORIG_INITS is provided, check those elements too.
    1968              :    Return true if OK, false otherwise.  */
    1969              : bool
    1970          190 : c_omp_check_loop_binding_exprs (tree stmt, vec<tree> *orig_inits)
    1971              : {
    1972          190 :   bool ok = true;
    1973          190 :   location_t loc = EXPR_LOCATION (stmt);
    1974          190 :   tree body = OMP_FOR_BODY (stmt);
    1975          338 :   int orig_init_length = orig_inits ? orig_inits->length () : 0;
    1976              : 
    1977          410 :   for (int i = 1; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
    1978              :     {
    1979          220 :       tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
    1980          220 :       if (init == NULL_TREE)
    1981              :         {
    1982           16 :           sorry_at (loc, "imperfectly nested loop using generated loops");
    1983           16 :           ok = false;
    1984           16 :           continue;
    1985              :         }
    1986          204 :       tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
    1987          204 :       tree incr = TREE_VEC_ELT (OMP_FOR_INCR (stmt), i);
    1988          204 :       gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
    1989          204 :       tree decl = TREE_OPERAND (init, 0);
    1990          204 :       tree orig_init = i < orig_init_length ? (*orig_inits)[i] : NULL_TREE;
    1991          204 :       tree e;
    1992          204 :       location_t eloc;
    1993              : 
    1994          204 :       e = TREE_OPERAND (init, 1);
    1995          204 :       eloc = LOCATION_OR (EXPR_LOCATION (init), loc);
    1996          204 :       if (!check_loop_binding_expr (decl, body, eloc,
    1997              :                                     CHECK_LOOP_BINDING_EXPR_CTX_LOOP_VAR))
    1998           14 :         ok = false;
    1999          204 :       if (!check_loop_binding_expr (e, body, eloc,
    2000              :                                     CHECK_LOOP_BINDING_EXPR_CTX_IN_INIT))
    2001           15 :         ok = false;
    2002          204 :       if (orig_init
    2003          204 :           && !check_loop_binding_expr (orig_init, body, eloc,
    2004              :                                        CHECK_LOOP_BINDING_EXPR_CTX_IN_INIT))
    2005              :         ok = false;
    2006              : 
    2007              :       /* INCR and/or COND may be null if this is a template with a
    2008              :          class iterator.  */
    2009          204 :       if (cond)
    2010              :         {
    2011          204 :           eloc = LOCATION_OR (EXPR_LOCATION (cond), loc);
    2012          204 :           if (COMPARISON_CLASS_P (cond) && TREE_OPERAND (cond, 0) == decl)
    2013          202 :             e = TREE_OPERAND (cond, 1);
    2014            2 :           else if (COMPARISON_CLASS_P (cond) && TREE_OPERAND (cond, 1) == decl)
    2015            0 :             e = TREE_OPERAND (cond, 0);
    2016              :           else
    2017              :             e = cond;
    2018          204 :           if (!check_loop_binding_expr (e, body, eloc,
    2019              :                                         CHECK_LOOP_BINDING_EXPR_CTX_END_TEST))
    2020          204 :             ok = false;
    2021              :         }
    2022              : 
    2023          204 :       if (incr)
    2024              :         {
    2025          202 :           eloc = LOCATION_OR (EXPR_LOCATION (incr), loc);
    2026              :           /* INCR should be either a MODIFY_EXPR or pre/post
    2027              :              increment/decrement.  We don't have to check the latter
    2028              :              since there are no operands besides the iteration variable.  */
    2029          202 :           if (TREE_CODE (incr) == MODIFY_EXPR
    2030          202 :               && !check_loop_binding_expr (TREE_OPERAND (incr, 1), body, eloc,
    2031              :                                            CHECK_LOOP_BINDING_EXPR_CTX_INCR))
    2032              :             ok = false;
    2033              :         }
    2034              :     }
    2035              : 
    2036          190 :   return ok;
    2037              : }
    2038              : 
    2039              : /* This function splits clauses for OpenACC combined loop
    2040              :    constructs.  OpenACC combined loop constructs are:
    2041              :    #pragma acc kernels loop
    2042              :    #pragma acc parallel loop  */
    2043              : 
    2044              : tree
    2045         1830 : c_oacc_split_loop_clauses (tree clauses, tree *not_loop_clauses,
    2046              :                            bool is_parallel)
    2047              : {
    2048         1830 :   tree next, loop_clauses, nc;
    2049              : 
    2050         1830 :   loop_clauses = *not_loop_clauses = NULL_TREE;
    2051         3613 :   for (; clauses ; clauses = next)
    2052              :     {
    2053         1783 :       next = OMP_CLAUSE_CHAIN (clauses);
    2054              : 
    2055         1783 :       switch (OMP_CLAUSE_CODE (clauses))
    2056              :         {
    2057              :           /* Loop clauses.  */
    2058         1174 :         case OMP_CLAUSE_COLLAPSE:
    2059         1174 :         case OMP_CLAUSE_TILE:
    2060         1174 :         case OMP_CLAUSE_GANG:
    2061         1174 :         case OMP_CLAUSE_WORKER:
    2062         1174 :         case OMP_CLAUSE_VECTOR:
    2063         1174 :         case OMP_CLAUSE_AUTO:
    2064         1174 :         case OMP_CLAUSE_SEQ:
    2065         1174 :         case OMP_CLAUSE_INDEPENDENT:
    2066         1174 :         case OMP_CLAUSE_PRIVATE:
    2067         1174 :           OMP_CLAUSE_CHAIN (clauses) = loop_clauses;
    2068         1174 :           loop_clauses = clauses;
    2069         1174 :           break;
    2070              : 
    2071              :           /* Reductions must be duplicated on both constructs.  */
    2072          114 :         case OMP_CLAUSE_REDUCTION:
    2073          114 :           if (is_parallel)
    2074              :             {
    2075           83 :               nc = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2076              :                                      OMP_CLAUSE_REDUCTION);
    2077           83 :               OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (clauses);
    2078          166 :               OMP_CLAUSE_REDUCTION_CODE (nc)
    2079           83 :                 = OMP_CLAUSE_REDUCTION_CODE (clauses);
    2080           83 :               OMP_CLAUSE_CHAIN (nc) = *not_loop_clauses;
    2081           83 :               *not_loop_clauses = nc;
    2082              :             }
    2083              : 
    2084          114 :           OMP_CLAUSE_CHAIN (clauses) = loop_clauses;
    2085          114 :           loop_clauses = clauses;
    2086          114 :           break;
    2087              : 
    2088              :           /* Parallel/kernels clauses.  */
    2089          495 :         default:
    2090          495 :           OMP_CLAUSE_CHAIN (clauses) = *not_loop_clauses;
    2091          495 :           *not_loop_clauses = clauses;
    2092          495 :           break;
    2093              :         }
    2094              :     }
    2095              : 
    2096         1830 :   return loop_clauses;
    2097              : }
    2098              : 
    2099              : /* This function attempts to split or duplicate clauses for OpenMP
    2100              :    combined/composite constructs.  Right now there are 30 different
    2101              :    constructs.  CODE is the innermost construct in the combined construct,
    2102              :    and MASK allows to determine which constructs are combined together,
    2103              :    as every construct has at least one clause that no other construct
    2104              :    has (except for OMP_SECTIONS, but that can be only combined with parallel,
    2105              :    and OMP_MASTER, which doesn't have any clauses at all).
    2106              :    OpenMP combined/composite constructs are:
    2107              :    #pragma omp distribute parallel for
    2108              :    #pragma omp distribute parallel for simd
    2109              :    #pragma omp distribute simd
    2110              :    #pragma omp for simd
    2111              :    #pragma omp masked taskloop
    2112              :    #pragma omp masked taskloop simd
    2113              :    #pragma omp master taskloop
    2114              :    #pragma omp master taskloop simd
    2115              :    #pragma omp parallel for
    2116              :    #pragma omp parallel for simd
    2117              :    #pragma omp parallel loop
    2118              :    #pragma omp parallel masked
    2119              :    #pragma omp parallel masked taskloop
    2120              :    #pragma omp parallel masked taskloop simd
    2121              :    #pragma omp parallel master
    2122              :    #pragma omp parallel master taskloop
    2123              :    #pragma omp parallel master taskloop simd
    2124              :    #pragma omp parallel sections
    2125              :    #pragma omp target parallel
    2126              :    #pragma omp target parallel for
    2127              :    #pragma omp target parallel for simd
    2128              :    #pragma omp target parallel loop
    2129              :    #pragma omp target teams
    2130              :    #pragma omp target teams distribute
    2131              :    #pragma omp target teams distribute parallel for
    2132              :    #pragma omp target teams distribute parallel for simd
    2133              :    #pragma omp target teams distribute simd
    2134              :    #pragma omp target teams loop
    2135              :    #pragma omp target simd
    2136              :    #pragma omp taskloop simd
    2137              :    #pragma omp teams distribute
    2138              :    #pragma omp teams distribute parallel for
    2139              :    #pragma omp teams distribute parallel for simd
    2140              :    #pragma omp teams distribute simd
    2141              :    #pragma omp teams loop  */
    2142              : 
    2143              : void
    2144        15819 : c_omp_split_clauses (location_t loc, enum tree_code code,
    2145              :                      omp_clause_mask mask, tree clauses, tree *cclauses)
    2146              : {
    2147        15819 :   tree next, c;
    2148        15819 :   enum c_omp_clause_split s;
    2149        15819 :   int i;
    2150        15819 :   bool has_dup_allocate = false;
    2151              : 
    2152       110733 :   for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
    2153        94914 :     cclauses[i] = NULL;
    2154              :   /* Add implicit nowait clause on
    2155              :      #pragma omp parallel {for,for simd,sections}.  */
    2156        15819 :   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
    2157        10915 :     switch (code)
    2158              :       {
    2159        10255 :       case OMP_FOR:
    2160        10255 :       case OMP_SIMD:
    2161        25892 :         if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
    2162        10073 :           cclauses[C_OMP_CLAUSE_SPLIT_FOR]
    2163        10073 :             = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
    2164              :         break;
    2165          155 :       case OMP_SECTIONS:
    2166          155 :         cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS]
    2167          155 :           = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
    2168          155 :         break;
    2169              :       default:
    2170              :         break;
    2171              :       }
    2172              : 
    2173        55734 :   for (; clauses ; clauses = next)
    2174              :     {
    2175        39915 :       next = OMP_CLAUSE_CHAIN (clauses);
    2176              : 
    2177        39915 :       switch (OMP_CLAUSE_CODE (clauses))
    2178              :         {
    2179              :         /* First the clauses that are unique to some constructs.  */
    2180              :         case OMP_CLAUSE_DEVICE:
    2181              :         case OMP_CLAUSE_DEVICE_TYPE:
    2182              :         case OMP_CLAUSE_DEFAULTMAP:
    2183              :         case OMP_CLAUSE_DEPEND:
    2184              :         case OMP_CLAUSE_DYN_GROUPPRIVATE:
    2185              :         case OMP_CLAUSE_IS_DEVICE_PTR:
    2186              :         case OMP_CLAUSE_HAS_DEVICE_ADDR:
    2187              :         case OMP_CLAUSE_MAP:
    2188              :         case OMP_CLAUSE_USES_ALLOCATORS:
    2189              :           s = C_OMP_CLAUSE_SPLIT_TARGET;
    2190              :           break;
    2191            4 :         case OMP_CLAUSE_DOACROSS:
    2192              :           /* This can happen with invalid depend(source) or
    2193              :              depend(sink:vec) on target combined with other constructs.  */
    2194            4 :           gcc_assert (OMP_CLAUSE_DOACROSS_DEPEND (clauses));
    2195              :           s = C_OMP_CLAUSE_SPLIT_TARGET;
    2196              :           break;
    2197              :         case OMP_CLAUSE_NUM_TEAMS:
    2198         2454 :           s = C_OMP_CLAUSE_SPLIT_TEAMS;
    2199              :           break;
    2200              :         case OMP_CLAUSE_DIST_SCHEDULE:
    2201         6933 :           s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
    2202              :           break;
    2203              :         case OMP_CLAUSE_COPYIN:
    2204              :         case OMP_CLAUSE_NUM_THREADS:
    2205              :         case OMP_CLAUSE_PROC_BIND:
    2206         7710 :           s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2207              :           break;
    2208              :         case OMP_CLAUSE_ORDERED:
    2209        13148 :           s = C_OMP_CLAUSE_SPLIT_FOR;
    2210              :           break;
    2211         6079 :         case OMP_CLAUSE_SCHEDULE:
    2212         6079 :           s = C_OMP_CLAUSE_SPLIT_FOR;
    2213         6079 :           if (code != OMP_SIMD)
    2214         3080 :             OMP_CLAUSE_SCHEDULE_SIMD (clauses) = 0;
    2215              :           break;
    2216              :         case OMP_CLAUSE_SAFELEN:
    2217              :         case OMP_CLAUSE_SIMDLEN:
    2218              :         case OMP_CLAUSE_ALIGNED:
    2219              :         case OMP_CLAUSE_NONTEMPORAL:
    2220         5337 :           s = C_OMP_CLAUSE_SPLIT_SIMD;
    2221              :           break;
    2222              :         case OMP_CLAUSE_GRAINSIZE:
    2223              :         case OMP_CLAUSE_NUM_TASKS:
    2224              :         case OMP_CLAUSE_FINAL:
    2225              :         case OMP_CLAUSE_UNTIED:
    2226              :         case OMP_CLAUSE_MERGEABLE:
    2227              :         case OMP_CLAUSE_NOGROUP:
    2228              :         case OMP_CLAUSE_PRIORITY:
    2229        13148 :           s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
    2230              :           break;
    2231              :         case OMP_CLAUSE_BIND:
    2232        13148 :           s = C_OMP_CLAUSE_SPLIT_LOOP;
    2233              :           break;
    2234              :         case OMP_CLAUSE_FILTER:
    2235         6933 :           s = C_OMP_CLAUSE_SPLIT_MASKED;
    2236              :           break;
    2237              :         /* Duplicate this to all of taskloop, distribute, for, simd and
    2238              :            loop.  */
    2239         5077 :         case OMP_CLAUSE_COLLAPSE:
    2240         5077 :           if (code == OMP_SIMD)
    2241              :             {
    2242         2579 :               if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
    2243         2579 :                            | (OMP_CLAUSE_MASK_1
    2244         2579 :                               << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
    2245         2579 :                            | (OMP_CLAUSE_MASK_1
    2246         2579 :                               << PRAGMA_OMP_CLAUSE_NOGROUP))) != 0)
    2247              :                 {
    2248         2531 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2249              :                                         OMP_CLAUSE_COLLAPSE);
    2250         2531 :                   OMP_CLAUSE_COLLAPSE_EXPR (c)
    2251         2531 :                     = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
    2252         2531 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
    2253         2531 :                   cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
    2254              :                 }
    2255              :               else
    2256              :                 {
    2257              :                   /* This must be #pragma omp target simd */
    2258              :                   s = C_OMP_CLAUSE_SPLIT_SIMD;
    2259              :                   break;
    2260              :                 }
    2261              :             }
    2262         5029 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
    2263              :             {
    2264         3925 :               if ((mask & (OMP_CLAUSE_MASK_1
    2265         3925 :                            << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
    2266              :                 {
    2267         2625 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2268              :                                         OMP_CLAUSE_COLLAPSE);
    2269         2625 :                   OMP_CLAUSE_COLLAPSE_EXPR (c)
    2270         2625 :                     = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
    2271         2625 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
    2272         2625 :                   cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
    2273         2625 :                   s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
    2274              :                 }
    2275              :               else
    2276              :                 s = C_OMP_CLAUSE_SPLIT_FOR;
    2277              :             }
    2278         1104 :           else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
    2279        13834 :                    != 0)
    2280              :             s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
    2281          686 :           else if (code == OMP_LOOP)
    2282              :             s = C_OMP_CLAUSE_SPLIT_LOOP;
    2283              :           else
    2284         6933 :             s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
    2285              :           break;
    2286              :         /* Private clause is supported on all constructs but master/masked,
    2287              :            it is enough to put it on the innermost one other than
    2288              :            master/masked.  For #pragma omp {for,sections} put it on parallel
    2289              :            though, as that's what we did for OpenMP 3.1.  */
    2290         1301 :         case OMP_CLAUSE_PRIVATE:
    2291         1301 :           switch (code)
    2292              :             {
    2293              :             case OMP_SIMD: s = C_OMP_CLAUSE_SPLIT_SIMD; break;
    2294              :             case OMP_FOR: case OMP_SECTIONS:
    2295         7710 :             case OMP_PARALLEL: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
    2296         6933 :             case OMP_DISTRIBUTE: s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break;
    2297         2454 :             case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break;
    2298         7710 :             case OMP_MASTER: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
    2299         7710 :             case OMP_MASKED: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
    2300        13148 :             case OMP_TASKLOOP: s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break;
    2301        13148 :             case OMP_LOOP: s = C_OMP_CLAUSE_SPLIT_LOOP; break;
    2302            0 :             default: gcc_unreachable ();
    2303              :             }
    2304              :           break;
    2305              :         /* Firstprivate clause is supported on all constructs but
    2306              :            simd, master, masked and loop.  Put it on the outermost of those
    2307              :            and duplicate on teams and parallel.  */
    2308         1743 :         case OMP_CLAUSE_FIRSTPRIVATE:
    2309         1743 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
    2310         2103 :               != 0)
    2311              :             {
    2312          388 :               if (code == OMP_SIMD
    2313          388 :                   && (mask & ((OMP_CLAUSE_MASK_1
    2314          134 :                                << PRAGMA_OMP_CLAUSE_NUM_THREADS)
    2315          134 :                               | (OMP_CLAUSE_MASK_1
    2316          134 :                                  << PRAGMA_OMP_CLAUSE_NUM_TEAMS))) == 0)
    2317              :                 {
    2318              :                   /* This must be #pragma omp target simd.  */
    2319           28 :                   s = C_OMP_CLAUSE_SPLIT_TARGET;
    2320           28 :                   OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clauses) = 1;
    2321           28 :                   OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (clauses) = 1;
    2322           28 :                   break;
    2323              :                 }
    2324          360 :               c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2325              :                                     OMP_CLAUSE_FIRSTPRIVATE);
    2326              :               /* firstprivate should not be applied to target if it is
    2327              :                  also lastprivate or on the combined/composite construct,
    2328              :                  or if it is mentioned in map clause.  OMP_CLAUSE_DECLs
    2329              :                  may need to go through FE handling though (instantiation,
    2330              :                  C++ non-static data members, array section lowering), so
    2331              :                  add the clause with OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT and
    2332              :                  let *finish_omp_clauses and the gimplifier handle it
    2333              :                  right.  */
    2334          360 :               OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 1;
    2335          360 :               OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2336          360 :               OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
    2337          360 :               cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
    2338              :             }
    2339         1715 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
    2340         1715 :               != 0)
    2341              :             {
    2342         1103 :               if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)
    2343         1103 :                            | (OMP_CLAUSE_MASK_1
    2344         1103 :                               << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE))) != 0)
    2345              :                 {
    2346          463 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2347              :                                         OMP_CLAUSE_FIRSTPRIVATE);
    2348          463 :                   OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2349          463 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
    2350          463 :                   cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
    2351          463 :                   if ((mask & (OMP_CLAUSE_MASK_1
    2352          463 :                                << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0)
    2353              :                     s = C_OMP_CLAUSE_SPLIT_TEAMS;
    2354              :                   else
    2355         6933 :                     s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
    2356              :                 }
    2357          640 :               else if ((mask & (OMP_CLAUSE_MASK_1
    2358          640 :                                 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
    2359              :                 /* This must be
    2360              :                    #pragma omp parallel mas{ked,ter} taskloop{, simd}.  */
    2361              :                 s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
    2362              :               else
    2363              :                 /* This must be
    2364              :                    #pragma omp parallel{, for{, simd}, sections,loop}
    2365              :                    or
    2366              :                    #pragma omp target parallel.  */
    2367         7710 :                 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2368              :             }
    2369          612 :           else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
    2370          612 :                    != 0)
    2371              :             {
    2372              :               /* This must be one of
    2373              :                  #pragma omp {,target }teams {distribute,loop}
    2374              :                  #pragma omp target teams
    2375              :                  #pragma omp {,target }teams distribute simd.  */
    2376          276 :               gcc_assert (code == OMP_DISTRIBUTE
    2377              :                           || code == OMP_LOOP
    2378              :                           || code == OMP_TEAMS
    2379              :                           || code == OMP_SIMD);
    2380              :               s = C_OMP_CLAUSE_SPLIT_TEAMS;
    2381              :             }
    2382          336 :           else if ((mask & (OMP_CLAUSE_MASK_1
    2383          336 :                             << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
    2384              :             {
    2385              :               /* This must be #pragma omp distribute simd.  */
    2386           76 :               gcc_assert (code == OMP_SIMD);
    2387              :               s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
    2388              :             }
    2389          260 :           else if ((mask & (OMP_CLAUSE_MASK_1
    2390          260 :                             << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
    2391              :             {
    2392              :               /* This must be
    2393              :                  #pragma omp {,{,parallel }mas{ked,ter} }taskloop simd
    2394              :                  or
    2395              :                  #pragma omp {,parallel }mas{ked,ter} taskloop.  */
    2396          232 :               gcc_assert (code == OMP_SIMD || code == OMP_TASKLOOP);
    2397              :               s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
    2398              :             }
    2399              :           else
    2400              :             {
    2401              :               /* This must be #pragma omp for simd.  */
    2402           28 :               gcc_assert (code == OMP_SIMD);
    2403              :               s = C_OMP_CLAUSE_SPLIT_FOR;
    2404              :             }
    2405              :           break;
    2406              :         /* Lastprivate is allowed on distribute, for, sections, taskloop, loop
    2407              :            and simd.  In parallel {for{, simd},sections} we actually want to
    2408              :            put it on parallel rather than for or sections.  */
    2409         1959 :         case OMP_CLAUSE_LASTPRIVATE:
    2410         1959 :           if (code == OMP_DISTRIBUTE)
    2411              :             {
    2412              :               s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
    2413              :               break;
    2414              :             }
    2415         1951 :           if ((mask & (OMP_CLAUSE_MASK_1
    2416         1951 :                        << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
    2417              :             {
    2418          548 :               c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2419              :                                     OMP_CLAUSE_LASTPRIVATE);
    2420          548 :               OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2421          548 :               OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
    2422         1096 :               OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
    2423          548 :                 = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
    2424          548 :               cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
    2425              :             }
    2426         1951 :           if (code == OMP_FOR || code == OMP_SECTIONS)
    2427              :             {
    2428          823 :               if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
    2429        20858 :                   != 0)
    2430              :                 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2431              :               else
    2432        13148 :                 s = C_OMP_CLAUSE_SPLIT_FOR;
    2433              :               break;
    2434              :             }
    2435              :           if (code == OMP_TASKLOOP)
    2436              :             {
    2437              :               s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
    2438              :               break;
    2439              :             }
    2440              :           if (code == OMP_LOOP)
    2441              :             {
    2442              :               s = C_OMP_CLAUSE_SPLIT_LOOP;
    2443              :               break;
    2444              :             }
    2445            0 :           gcc_assert (code == OMP_SIMD);
    2446          812 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
    2447              :             {
    2448          423 :               c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2449              :                                     OMP_CLAUSE_LASTPRIVATE);
    2450          423 :               OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2451          846 :               OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
    2452          423 :                 = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
    2453          423 :               if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
    2454          498 :                   != 0)
    2455              :                 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2456              :               else
    2457           75 :                 s = C_OMP_CLAUSE_SPLIT_FOR;
    2458          423 :               OMP_CLAUSE_CHAIN (c) = cclauses[s];
    2459          423 :               cclauses[s] = c;
    2460              :             }
    2461          812 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
    2462              :             {
    2463          253 :               c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2464              :                                     OMP_CLAUSE_LASTPRIVATE);
    2465          253 :               OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2466          506 :               OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
    2467          253 :                 = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
    2468          253 :               OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
    2469          253 :               cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
    2470              :             }
    2471              :           s = C_OMP_CLAUSE_SPLIT_SIMD;
    2472              :           break;
    2473              :         /* Shared and default clauses are allowed on parallel, teams and
    2474              :            taskloop.  */
    2475         3567 :         case OMP_CLAUSE_SHARED:
    2476         3567 :         case OMP_CLAUSE_DEFAULT:
    2477         3567 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
    2478         3567 :               != 0)
    2479              :             {
    2480          898 :               if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
    2481        13504 :                   != 0)
    2482              :                 {
    2483          712 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2484          356 :                                         OMP_CLAUSE_CODE (clauses));
    2485          356 :                   if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED)
    2486          128 :                     OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2487              :                   else
    2488          456 :                     OMP_CLAUSE_DEFAULT_KIND (c)
    2489          228 :                       = OMP_CLAUSE_DEFAULT_KIND (clauses);
    2490          356 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
    2491          356 :                   cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
    2492              :                 }
    2493              :               s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
    2494              :               break;
    2495              :             }
    2496         2669 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
    2497         9005 :               != 0)
    2498              :             {
    2499         1295 :               if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
    2500         3062 :                   == 0)
    2501              :                 {
    2502              :                   s = C_OMP_CLAUSE_SPLIT_TEAMS;
    2503              :                   break;
    2504              :                 }
    2505         1216 :               c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2506          608 :                                     OMP_CLAUSE_CODE (clauses));
    2507          608 :               if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED)
    2508          284 :                 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2509              :               else
    2510          648 :                 OMP_CLAUSE_DEFAULT_KIND (c)
    2511          324 :                   = OMP_CLAUSE_DEFAULT_KIND (clauses);
    2512          608 :               OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
    2513          608 :               cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
    2514              :             }
    2515              :           s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2516              :           break;
    2517              :         /* order clauses are allowed on distribute, for, simd and loop.  */
    2518          880 :         case OMP_CLAUSE_ORDER:
    2519          880 :           if ((mask & (OMP_CLAUSE_MASK_1
    2520          880 :                        << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
    2521              :             {
    2522          332 :               if (code == OMP_DISTRIBUTE)
    2523              :                 {
    2524              :                   s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
    2525              :                   break;
    2526              :                 }
    2527          288 :               c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2528              :                                     OMP_CLAUSE_ORDER);
    2529          576 :               OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
    2530          288 :                 = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
    2531          576 :               OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
    2532          288 :                 = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
    2533          288 :               OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
    2534          288 :               cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
    2535              :             }
    2536          836 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
    2537              :             {
    2538          465 :               if (code == OMP_SIMD)
    2539              :                 {
    2540          317 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2541              :                                         OMP_CLAUSE_ORDER);
    2542          634 :                   OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
    2543          317 :                     = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
    2544          634 :                   OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
    2545          317 :                     = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
    2546          317 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
    2547          317 :                   cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
    2548          317 :                   s = C_OMP_CLAUSE_SPLIT_SIMD;
    2549              :                 }
    2550              :               else
    2551              :                 s = C_OMP_CLAUSE_SPLIT_FOR;
    2552              :             }
    2553          371 :           else if (code == OMP_LOOP)
    2554              :             s = C_OMP_CLAUSE_SPLIT_LOOP;
    2555              :           else
    2556         5337 :             s = C_OMP_CLAUSE_SPLIT_SIMD;
    2557              :           break;
    2558              :         /* Reduction is allowed on simd, for, parallel, sections, taskloop,
    2559              :            teams and loop.  Duplicate it on all of them, but omit on for or
    2560              :            sections if parallel is present (unless inscan, in that case
    2561              :            omit on parallel).  If taskloop or loop is combined with
    2562              :            parallel, omit it on parallel.  */
    2563         2883 :         case OMP_CLAUSE_REDUCTION:
    2564         2883 :           if (OMP_CLAUSE_REDUCTION_TASK (clauses))
    2565              :             {
    2566           56 :               if (code == OMP_SIMD || code == OMP_LOOP)
    2567              :                 {
    2568           16 :                   error_at (OMP_CLAUSE_LOCATION (clauses),
    2569              :                             "invalid %<task%> reduction modifier on construct "
    2570              :                             "combined with %<simd%> or %<loop%>");
    2571           16 :                   OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
    2572              :                 }
    2573           40 :               else if (code != OMP_SECTIONS
    2574           34 :                        && (mask & (OMP_CLAUSE_MASK_1
    2575           34 :                                    << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0
    2576           40 :                        && (mask & (OMP_CLAUSE_MASK_1
    2577            4 :                                    << PRAGMA_OMP_CLAUSE_SCHEDULE)) == 0)
    2578              :                 {
    2579            4 :                   error_at (OMP_CLAUSE_LOCATION (clauses),
    2580              :                             "invalid %<task%> reduction modifier on construct "
    2581              :                             "not combined with %<parallel%>, %<for%> or "
    2582              :                             "%<sections%>");
    2583            4 :                   OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
    2584              :                 }
    2585              :             }
    2586         2883 :           if (OMP_CLAUSE_REDUCTION_INSCAN (clauses)
    2587         2883 :               && ((mask & ((OMP_CLAUSE_MASK_1
    2588          196 :                             << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
    2589          196 :                            | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)))
    2590         2895 :                   != 0))
    2591              :             {
    2592           12 :               error_at (OMP_CLAUSE_LOCATION (clauses),
    2593              :                         "%<inscan%> %<reduction%> clause on construct other "
    2594              :                         "than %<for%>, %<simd%>, %<for simd%>, "
    2595              :                         "%<parallel for%>, %<parallel for simd%>");
    2596           12 :               OMP_CLAUSE_REDUCTION_INSCAN (clauses) = 0;
    2597              :             }
    2598         2883 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
    2599              :             {
    2600          567 :               c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2601              :                                     OMP_CLAUSE_MAP);
    2602          567 :               OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2603          567 :               OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
    2604          567 :               OMP_CLAUSE_MAP_IMPLICIT (c) = 1;
    2605          567 :               OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
    2606          567 :               cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
    2607              :             }
    2608         2883 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
    2609              :             {
    2610         1722 :               if (code == OMP_SIMD)
    2611              :                 {
    2612          561 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2613              :                                         OMP_CLAUSE_REDUCTION);
    2614          561 :                   OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2615         1122 :                   OMP_CLAUSE_REDUCTION_CODE (c)
    2616          561 :                     = OMP_CLAUSE_REDUCTION_CODE (clauses);
    2617          561 :                   OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
    2618          561 :                     = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
    2619          561 :                   OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
    2620          561 :                     = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
    2621         1122 :                   OMP_CLAUSE_REDUCTION_INSCAN (c)
    2622          561 :                     = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
    2623          561 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
    2624          561 :                   cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
    2625              :                 }
    2626         1722 :               if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
    2627         1722 :                   != 0)
    2628              :                 {
    2629          431 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2630              :                                         OMP_CLAUSE_REDUCTION);
    2631          431 :                   OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2632          862 :                   OMP_CLAUSE_REDUCTION_CODE (c)
    2633          431 :                     = OMP_CLAUSE_REDUCTION_CODE (clauses);
    2634          431 :                   OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
    2635          431 :                     = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
    2636          431 :                   OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
    2637          431 :                     = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
    2638          862 :                   OMP_CLAUSE_REDUCTION_INSCAN (c)
    2639          431 :                     = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
    2640          431 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
    2641          431 :                   cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
    2642          431 :                   s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2643              :                 }
    2644         1291 :               else if ((mask & (OMP_CLAUSE_MASK_1
    2645         1291 :                                 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0
    2646         1202 :                        && !OMP_CLAUSE_REDUCTION_INSCAN (clauses))
    2647              :                 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2648              :               else
    2649        13148 :                 s = C_OMP_CLAUSE_SPLIT_FOR;
    2650              :             }
    2651         1161 :           else if (code == OMP_SECTIONS
    2652         1161 :                    || code == OMP_PARALLEL
    2653              :                    || code == OMP_MASTER
    2654              :                    || code == OMP_MASKED)
    2655              :             s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2656              :           else if (code == OMP_TASKLOOP)
    2657              :             s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
    2658              :           else if (code == OMP_LOOP)
    2659              :             s = C_OMP_CLAUSE_SPLIT_LOOP;
    2660              :           else if (code == OMP_SIMD)
    2661              :             {
    2662          437 :               if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
    2663          437 :                   != 0)
    2664              :                 {
    2665          247 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2666              :                                         OMP_CLAUSE_REDUCTION);
    2667          247 :                   OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2668          494 :                   OMP_CLAUSE_REDUCTION_CODE (c)
    2669          247 :                     = OMP_CLAUSE_REDUCTION_CODE (clauses);
    2670          247 :                   OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
    2671          247 :                     = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
    2672          247 :                   OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
    2673          247 :                     = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
    2674          494 :                   OMP_CLAUSE_REDUCTION_INSCAN (c)
    2675          247 :                     = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
    2676          247 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
    2677          247 :                   cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
    2678              :                 }
    2679          190 :               else if ((mask & (OMP_CLAUSE_MASK_1
    2680          190 :                                 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0)
    2681              :                 {
    2682           90 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2683              :                                         OMP_CLAUSE_REDUCTION);
    2684           90 :                   OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2685          180 :                   OMP_CLAUSE_REDUCTION_CODE (c)
    2686           90 :                     = OMP_CLAUSE_REDUCTION_CODE (clauses);
    2687           90 :                   OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
    2688           90 :                     = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
    2689           90 :                   OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
    2690           90 :                     = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
    2691          180 :                   OMP_CLAUSE_REDUCTION_INSCAN (c)
    2692           90 :                     = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
    2693           90 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
    2694           90 :                   cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
    2695              :                 }
    2696              :               s = C_OMP_CLAUSE_SPLIT_SIMD;
    2697              :             }
    2698              :           else
    2699              :             s = C_OMP_CLAUSE_SPLIT_TEAMS;
    2700              :           break;
    2701          400 :         case OMP_CLAUSE_IN_REDUCTION:
    2702          400 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
    2703              :             {
    2704              :               /* When on target, map(always, tofrom: item) is added as
    2705              :                  well.  For non-combined target it is added in the FEs.  */
    2706          228 :               c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2707              :                                     OMP_CLAUSE_MAP);
    2708          228 :               OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2709          228 :               OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_TOFROM);
    2710          228 :               OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
    2711          228 :               cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
    2712          228 :               s = C_OMP_CLAUSE_SPLIT_TARGET;
    2713          228 :               break;
    2714              :             }
    2715              :           /* in_reduction on taskloop simd becomes reduction on the simd
    2716              :              and keeps being in_reduction on taskloop.  */
    2717          172 :           if (code == OMP_SIMD)
    2718              :             {
    2719          108 :               c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2720              :                                     OMP_CLAUSE_REDUCTION);
    2721          108 :               OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2722          216 :               OMP_CLAUSE_REDUCTION_CODE (c)
    2723          108 :                 = OMP_CLAUSE_REDUCTION_CODE (clauses);
    2724          108 :               OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
    2725          108 :                 = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
    2726          108 :               OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
    2727          108 :                 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
    2728          108 :               OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
    2729          108 :               cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
    2730              :             }
    2731              :           s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
    2732              :           break;
    2733         1617 :         case OMP_CLAUSE_IF:
    2734         1617 :           if (OMP_CLAUSE_IF_MODIFIER (clauses) != ERROR_MARK)
    2735              :             {
    2736         1188 :               s = C_OMP_CLAUSE_SPLIT_COUNT;
    2737         1188 :               switch (OMP_CLAUSE_IF_MODIFIER (clauses))
    2738              :                 {
    2739          510 :                 case OMP_PARALLEL:
    2740          510 :                   if ((mask & (OMP_CLAUSE_MASK_1
    2741          510 :                                << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
    2742              :                     s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2743              :                   break;
    2744          280 :                 case OMP_SIMD:
    2745          280 :                   if (code == OMP_SIMD)
    2746              :                     s = C_OMP_CLAUSE_SPLIT_SIMD;
    2747              :                   break;
    2748          168 :                 case OMP_TASKLOOP:
    2749          168 :                   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
    2750        13156 :                       != 0)
    2751              :                     s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
    2752              :                   break;
    2753          222 :                 case OMP_TARGET:
    2754          222 :                   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
    2755         3218 :                       != 0)
    2756              :                     s = C_OMP_CLAUSE_SPLIT_TARGET;
    2757              :                   break;
    2758              :                 default:
    2759              :                   break;
    2760              :                 }
    2761              :               if (s != C_OMP_CLAUSE_SPLIT_COUNT)
    2762              :                 break;
    2763              :               /* Error-recovery here, invalid if-modifier specified, add the
    2764              :                  clause to just one construct.  */
    2765            8 :               if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
    2766              :                 s = C_OMP_CLAUSE_SPLIT_TARGET;
    2767            4 :               else if ((mask & (OMP_CLAUSE_MASK_1
    2768            4 :                                 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
    2769              :                 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2770            0 :               else if ((mask & (OMP_CLAUSE_MASK_1
    2771            0 :                                 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
    2772              :                 s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
    2773            0 :               else if (code == OMP_SIMD)
    2774              :                 s = C_OMP_CLAUSE_SPLIT_SIMD;
    2775              :               else
    2776            0 :                 gcc_unreachable ();
    2777              :               break;
    2778              :             }
    2779              :           /* Otherwise, duplicate if clause to all constructs.  */
    2780          429 :           if (code == OMP_SIMD)
    2781              :             {
    2782          266 :               if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)
    2783          266 :                            | (OMP_CLAUSE_MASK_1
    2784          266 :                               << PRAGMA_OMP_CLAUSE_NUM_THREADS)
    2785          266 :                            | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)))
    2786         5337 :                   != 0)
    2787              :                 {
    2788          176 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2789              :                                         OMP_CLAUSE_IF);
    2790          352 :                   OMP_CLAUSE_IF_MODIFIER (c)
    2791          176 :                     = OMP_CLAUSE_IF_MODIFIER (clauses);
    2792          176 :                   OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
    2793          176 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
    2794          176 :                   cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
    2795              :                 }
    2796              :               else
    2797              :                 {
    2798              :                   s = C_OMP_CLAUSE_SPLIT_SIMD;
    2799              :                   break;
    2800              :                 }
    2801              :             }
    2802          339 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
    2803          339 :               != 0)
    2804              :             {
    2805          148 :               if ((mask & (OMP_CLAUSE_MASK_1
    2806          148 :                            << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
    2807              :                 {
    2808           64 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2809              :                                         OMP_CLAUSE_IF);
    2810          128 :                   OMP_CLAUSE_IF_MODIFIER (c)
    2811           64 :                     = OMP_CLAUSE_IF_MODIFIER (clauses);
    2812           64 :                   OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
    2813           64 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
    2814           64 :                   cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
    2815           64 :                   s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2816              :                 }
    2817              :               else
    2818              :                 s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
    2819              :             }
    2820          191 :           else if ((mask & (OMP_CLAUSE_MASK_1
    2821          191 :                             << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
    2822              :             {
    2823          119 :               if ((mask & (OMP_CLAUSE_MASK_1
    2824         7730 :                            << PRAGMA_OMP_CLAUSE_MAP)) != 0)
    2825              :                 {
    2826           20 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2827              :                                         OMP_CLAUSE_IF);
    2828           40 :                   OMP_CLAUSE_IF_MODIFIER (c)
    2829           20 :                     = OMP_CLAUSE_IF_MODIFIER (clauses);
    2830           20 :                   OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
    2831           20 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
    2832           20 :                   cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
    2833           20 :                   s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2834              :                 }
    2835              :               else
    2836              :                 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2837              :             }
    2838              :           else
    2839              :             s = C_OMP_CLAUSE_SPLIT_TARGET;
    2840              :           break;
    2841          800 :         case OMP_CLAUSE_LINEAR:
    2842              :           /* Linear clause is allowed on simd and for.  Put it on the
    2843              :              innermost construct.  */
    2844          800 :           if (code == OMP_SIMD)
    2845              :             s = C_OMP_CLAUSE_SPLIT_SIMD;
    2846              :           else
    2847        13148 :             s = C_OMP_CLAUSE_SPLIT_FOR;
    2848              :           break;
    2849          247 :         case OMP_CLAUSE_NOWAIT:
    2850              :           /* Nowait clause is allowed on target, for and sections, but
    2851              :              is not allowed on parallel for or parallel sections.  Therefore,
    2852              :              put it on target construct if present, because that can only
    2853              :              be combined with parallel for{, simd} and not with for{, simd},
    2854              :              otherwise to the worksharing construct.  */
    2855          247 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
    2856        16358 :               != 0)
    2857              :             s = C_OMP_CLAUSE_SPLIT_TARGET;
    2858              :           else
    2859        13148 :             s = C_OMP_CLAUSE_SPLIT_FOR;
    2860              :           break;
    2861              :           /* thread_limit is allowed on target and teams.  Distribute it
    2862              :              to all.  */
    2863          444 :         case OMP_CLAUSE_THREAD_LIMIT:
    2864          444 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
    2865         2454 :               != 0)
    2866              :             {
    2867          232 :               if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
    2868         3210 :                   != 0)
    2869              :                 {
    2870          230 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2871              :                                         OMP_CLAUSE_THREAD_LIMIT);
    2872          230 :                   OMP_CLAUSE_THREAD_LIMIT_EXPR (c)
    2873          230 :                     = OMP_CLAUSE_THREAD_LIMIT_EXPR (clauses);
    2874          230 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
    2875          230 :                   cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
    2876              :                 }
    2877              :               else
    2878              :                 {
    2879              :                   s = C_OMP_CLAUSE_SPLIT_TARGET;
    2880              :                   break;
    2881              :                 }
    2882              :             }
    2883              :           s = C_OMP_CLAUSE_SPLIT_TEAMS;
    2884              :           break;
    2885              :         /* Allocate clause is allowed on target, teams, distribute, parallel,
    2886              :            for, sections and taskloop.  Distribute it to all.  */
    2887              :         case OMP_CLAUSE_ALLOCATE:
    2888              :           s = C_OMP_CLAUSE_SPLIT_COUNT;
    2889         7861 :           for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
    2890              :             {
    2891         6738 :               switch (i)
    2892              :                 {
    2893         1123 :                 case C_OMP_CLAUSE_SPLIT_TARGET:
    2894         1986 :                   if ((mask & (OMP_CLAUSE_MASK_1
    2895         1123 :                                << PRAGMA_OMP_CLAUSE_MAP)) == 0)
    2896          863 :                     continue;
    2897              :                   break;
    2898         1123 :                 case C_OMP_CLAUSE_SPLIT_TEAMS:
    2899         1842 :                   if ((mask & (OMP_CLAUSE_MASK_1
    2900         1123 :                                << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
    2901          719 :                     continue;
    2902              :                   break;
    2903         1123 :                 case C_OMP_CLAUSE_SPLIT_DISTRIBUTE:
    2904         1794 :                   if ((mask & (OMP_CLAUSE_MASK_1
    2905         1123 :                                << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
    2906          671 :                     continue;
    2907              :                   break;
    2908         1123 :                 case C_OMP_CLAUSE_SPLIT_PARALLEL:
    2909         1495 :                   if ((mask & (OMP_CLAUSE_MASK_1
    2910         1123 :                                << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
    2911          372 :                     continue;
    2912              :                   break;
    2913         1123 :                 case C_OMP_CLAUSE_SPLIT_FOR:
    2914         1123 :                   STATIC_ASSERT (C_OMP_CLAUSE_SPLIT_SECTIONS
    2915              :                                  == C_OMP_CLAUSE_SPLIT_FOR
    2916              :                                  && (C_OMP_CLAUSE_SPLIT_TASKLOOP
    2917              :                                      == C_OMP_CLAUSE_SPLIT_FOR)
    2918              :                                  && (C_OMP_CLAUSE_SPLIT_LOOP
    2919              :                                      == C_OMP_CLAUSE_SPLIT_FOR));
    2920         1123 :                   if (code == OMP_SECTIONS)
    2921              :                     break;
    2922         1107 :                   if ((mask & (OMP_CLAUSE_MASK_1
    2923         1107 :                                << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
    2924              :                     break;
    2925          602 :                   if ((mask & (OMP_CLAUSE_MASK_1
    2926          602 :                                << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
    2927              :                     break;
    2928          322 :                   continue;
    2929         1123 :                 case C_OMP_CLAUSE_SPLIT_SIMD:
    2930         1123 :                   continue;
    2931              :                 default:
    2932              :                   gcc_unreachable ();
    2933              :                 }
    2934         2668 :               if (s != C_OMP_CLAUSE_SPLIT_COUNT)
    2935              :                 {
    2936         1545 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2937              :                                         OMP_CLAUSE_ALLOCATE);
    2938         3090 :                   OMP_CLAUSE_DECL (c)
    2939         1545 :                     = OMP_CLAUSE_DECL (clauses);
    2940         1545 :                   OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
    2941         1545 :                     = OMP_CLAUSE_ALLOCATE_ALLOCATOR (clauses);
    2942         1545 :                   OMP_CLAUSE_ALLOCATE_ALIGN (c)
    2943         1545 :                     = OMP_CLAUSE_ALLOCATE_ALIGN (clauses);
    2944         1545 :                   OMP_CLAUSE_CHAIN (c) = cclauses[s];
    2945         1545 :                   cclauses[s] = c;
    2946         1545 :                   has_dup_allocate = true;
    2947              :                 }
    2948         2668 :               s = (enum c_omp_clause_split) i;
    2949              :             }
    2950         1123 :           gcc_assert (s != C_OMP_CLAUSE_SPLIT_COUNT);
    2951              :           break;
    2952            0 :         default:
    2953            0 :           gcc_unreachable ();
    2954              :         }
    2955        39915 :       OMP_CLAUSE_CHAIN (clauses) = cclauses[s];
    2956        39915 :       cclauses[s] = clauses;
    2957              :     }
    2958              : 
    2959        15819 :   if (has_dup_allocate)
    2960              :     {
    2961          753 :       bool need_prune = false;
    2962          753 :       bitmap_obstack_initialize (NULL);
    2963         8588 :       for (i = 0; i < C_OMP_CLAUSE_SPLIT_SIMD - (code == OMP_LOOP); i++)
    2964         3701 :         if (cclauses[i])
    2965              :           {
    2966         2230 :             bitmap_head allocate_head;
    2967         2230 :             bitmap_initialize (&allocate_head, &bitmap_default_obstack);
    2968        17416 :             for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
    2969        15186 :               if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
    2970        15186 :                   && DECL_P (OMP_CLAUSE_DECL (c)))
    2971         4716 :                 bitmap_set_bit (&allocate_head,
    2972         2358 :                                 DECL_UID (OMP_CLAUSE_DECL (c)));
    2973        17416 :             for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
    2974        15186 :               switch (OMP_CLAUSE_CODE (c))
    2975              :                 {
    2976         1103 :                 case OMP_CLAUSE_REDUCTION:
    2977         1103 :                 case OMP_CLAUSE_IN_REDUCTION:
    2978         1103 :                 case OMP_CLAUSE_TASK_REDUCTION:
    2979         1103 :                   if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
    2980              :                     {
    2981            0 :                       tree t = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
    2982            0 :                       if (TREE_CODE (t) == POINTER_PLUS_EXPR)
    2983            0 :                         t = TREE_OPERAND (t, 0);
    2984            0 :                       if (TREE_CODE (t) == ADDR_EXPR
    2985            0 :                           || INDIRECT_REF_P (t))
    2986            0 :                         t = TREE_OPERAND (t, 0);
    2987            0 :                       if (DECL_P (t))
    2988            0 :                         bitmap_clear_bit (&allocate_head, DECL_UID (t));
    2989              :                       break;
    2990              :                     }
    2991         1103 :                   else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST)
    2992              :                     {
    2993              :                       /* TODO: This can go away once we transition all uses of
    2994              :                          TREE_LIST for representing OMP array sections to
    2995              :                          OMP_ARRAY_SECTION.  */
    2996            0 :                       tree t;
    2997            0 :                       for (t = OMP_CLAUSE_DECL (c);
    2998            0 :                            TREE_CODE (t) == TREE_LIST; t = TREE_CHAIN (t))
    2999              :                         ;
    3000            0 :                       if (DECL_P (t))
    3001            0 :                         bitmap_clear_bit (&allocate_head, DECL_UID (t));
    3002              :                       break;
    3003              :                     }
    3004         1103 :                   else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == OMP_ARRAY_SECTION)
    3005              :                     {
    3006          112 :                       tree t;
    3007          112 :                       for (t = OMP_CLAUSE_DECL (c);
    3008          224 :                            TREE_CODE (t) == OMP_ARRAY_SECTION;
    3009          112 :                            t = TREE_OPERAND (t, 0))
    3010              :                         ;
    3011          112 :                       if (DECL_P (t))
    3012          112 :                         bitmap_clear_bit (&allocate_head, DECL_UID (t));
    3013              :                       break;
    3014              :                     }
    3015              :                   /* FALLTHRU */
    3016         3241 :                 case OMP_CLAUSE_PRIVATE:
    3017         3241 :                 case OMP_CLAUSE_FIRSTPRIVATE:
    3018         3241 :                 case OMP_CLAUSE_LASTPRIVATE:
    3019         3241 :                 case OMP_CLAUSE_LINEAR:
    3020         3241 :                   if (DECL_P (OMP_CLAUSE_DECL (c)))
    3021         6482 :                     bitmap_clear_bit (&allocate_head,
    3022         3241 :                                       DECL_UID (OMP_CLAUSE_DECL (c)));
    3023              :                   break;
    3024              :                 default:
    3025              :                   break;
    3026              :                 }
    3027        17416 :             for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
    3028        15186 :               if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
    3029         2358 :                   && DECL_P (OMP_CLAUSE_DECL (c))
    3030        17544 :                   && bitmap_bit_p (&allocate_head,
    3031         2358 :                                    DECL_UID (OMP_CLAUSE_DECL (c))))
    3032              :                 {
    3033              :                   /* Mark allocate clauses which don't have corresponding
    3034              :                      explicit data sharing clause.  */
    3035         1029 :                   OMP_CLAUSE_ALLOCATE_COMBINED (c) = 1;
    3036         1029 :                   need_prune = true;
    3037              :                 }
    3038              :           }
    3039          753 :       bitmap_obstack_release (NULL);
    3040          753 :       if (need_prune)
    3041              :         {
    3042              :           /* At least one allocate clause has been marked.  Walk all the
    3043              :              duplicated allocate clauses in sync.  If it is marked in all
    3044              :              constituent constructs, diagnose it as invalid and remove
    3045              :              them.  Otherwise, remove all marked inner clauses inside
    3046              :              a construct that doesn't have them marked.  Keep the outer
    3047              :              marked ones, because some clause duplication is done only
    3048              :              during gimplification.  */
    3049              :           tree *p[C_OMP_CLAUSE_SPLIT_COUNT];
    3050         4599 :           for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
    3051         3942 :             if (cclauses[i] == NULL_TREE
    3052         2298 :                 || i == C_OMP_CLAUSE_SPLIT_SIMD
    3053         2038 :                 || (i == C_OMP_CLAUSE_SPLIT_LOOP && code == OMP_LOOP))
    3054         1904 :               p[i] = NULL;
    3055              :             else
    3056         2038 :               p[i] = &cclauses[i];
    3057         1310 :           do
    3058              :             {
    3059         1310 :               int j = -1;
    3060         1310 :               tree seen = NULL_TREE;
    3061         6173 :               for (i = C_OMP_CLAUSE_SPLIT_COUNT - 1; i >= 0; i--)
    3062         5520 :                 if (p[i])
    3063              :                   {
    3064        13457 :                     while (*p[i]
    3065        13457 :                            && OMP_CLAUSE_CODE (*p[i]) != OMP_CLAUSE_ALLOCATE)
    3066        10634 :                       p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
    3067         2823 :                     if (*p[i] == NULL_TREE)
    3068              :                       {
    3069              :                         i = C_OMP_CLAUSE_SPLIT_COUNT;
    3070              :                         break;
    3071              :                       }
    3072         2166 :                     if (!OMP_CLAUSE_ALLOCATE_COMBINED (*p[i]) && j == -1)
    3073         4863 :                       j = i;
    3074              :                     seen = *p[i];
    3075              :                   }
    3076         1310 :               if (i == C_OMP_CLAUSE_SPLIT_COUNT)
    3077              :                 break;
    3078          653 :               if (j == -1)
    3079            8 :                 error_at (OMP_CLAUSE_LOCATION (seen),
    3080              :                           "%qD specified in %<allocate%> clause but not in "
    3081              :                           "an explicit privatization clause",
    3082            4 :                           OMP_CLAUSE_DECL (seen));
    3083         4571 :               for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
    3084         3918 :                 if (p[i])
    3085              :                   {
    3086         2038 :                     if (i > j)
    3087              :                       /* Remove.  */
    3088          580 :                       *p[i] = OMP_CLAUSE_CHAIN (*p[i]);
    3089              :                     else
    3090              :                       /* Keep.  */
    3091         1458 :                       p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
    3092              :                   }
    3093              :             }
    3094              :           while (1);
    3095              :         }
    3096              :     }
    3097              : 
    3098        15819 :   if (!flag_checking)
    3099              :     return;
    3100              : 
    3101        15819 :   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
    3102        10634 :     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TARGET] == NULL_TREE);
    3103        15819 :   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
    3104         8979 :     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] == NULL_TREE);
    3105        15819 :   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0
    3106         8553 :       && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)) == 0)
    3107         8303 :     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] == NULL_TREE);
    3108        15819 :   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
    3109         4904 :     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] == NULL_TREE);
    3110        15819 :   if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
    3111        15819 :                | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))) == 0
    3112         4117 :       && code != OMP_SECTIONS
    3113         4117 :       && code != OMP_LOOP)
    3114         3667 :     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_FOR] == NULL_TREE);
    3115        15819 :   if (code != OMP_SIMD)
    3116         9308 :     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_SIMD] == NULL_TREE);
    3117              : }
    3118              : 
    3119              : 
    3120              : /* qsort callback to compare #pragma omp declare simd clauses.  */
    3121              : 
    3122              : static int
    3123        12200 : c_omp_declare_simd_clause_cmp (const void *p, const void *q)
    3124              : {
    3125        12200 :   tree a = *(const tree *) p;
    3126        12200 :   tree b = *(const tree *) q;
    3127        12200 :   if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_CODE (b))
    3128              :     {
    3129        10725 :       if (OMP_CLAUSE_CODE (a) > OMP_CLAUSE_CODE (b))
    3130              :         return -1;
    3131         4480 :       return 1;
    3132              :     }
    3133         1475 :   if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_SIMDLEN
    3134              :       && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_INBRANCH
    3135              :       && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_NOTINBRANCH)
    3136              :     {
    3137         1451 :       int c = tree_to_shwi (OMP_CLAUSE_DECL (a));
    3138         1451 :       int d = tree_to_shwi (OMP_CLAUSE_DECL (b));
    3139         1451 :       if (c < d)
    3140              :         return 1;
    3141          670 :       if (c > d)
    3142          670 :         return -1;
    3143              :     }
    3144              :   return 0;
    3145              : }
    3146              : 
    3147              : /* Change PARM_DECLs in OMP_CLAUSE_DECL of #pragma omp declare simd
    3148              :    CLAUSES on FNDECL into argument indexes and sort them.  */
    3149              : 
    3150              : tree
    3151         1427 : c_omp_declare_simd_clauses_to_numbers (tree parms, tree clauses)
    3152              : {
    3153         1427 :   tree c;
    3154         1427 :   vec<tree> clvec = vNULL;
    3155              : 
    3156         4507 :   for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
    3157              :     {
    3158         3080 :       if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
    3159              :           && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
    3160              :           && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
    3161              :         {
    3162         1712 :           tree decl = OMP_CLAUSE_DECL (c);
    3163         1712 :           tree arg;
    3164         1712 :           int idx;
    3165         3815 :           for (arg = parms, idx = 0; arg;
    3166         2103 :                arg = TREE_CHAIN (arg), idx++)
    3167         3815 :             if (arg == decl)
    3168              :               break;
    3169         1712 :           if (arg == NULL_TREE)
    3170              :             {
    3171            0 :               error_at (OMP_CLAUSE_LOCATION (c),
    3172              :                         "%qD is not a function argument", decl);
    3173         3080 :               continue;
    3174              :             }
    3175         1712 :           OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, idx);
    3176         1712 :           if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
    3177         1712 :               && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
    3178              :             {
    3179           43 :               decl = OMP_CLAUSE_LINEAR_STEP (c);
    3180          121 :               for (arg = parms, idx = 0; arg;
    3181           78 :                    arg = TREE_CHAIN (arg), idx++)
    3182          121 :                 if (arg == decl)
    3183              :                   break;
    3184           43 :               if (arg == NULL_TREE)
    3185              :                 {
    3186            0 :                   error_at (OMP_CLAUSE_LOCATION (c),
    3187              :                             "%qD is not a function argument", decl);
    3188            0 :                   continue;
    3189              :                 }
    3190           43 :               OMP_CLAUSE_LINEAR_STEP (c)
    3191           86 :                 = build_int_cst (integer_type_node, idx);
    3192              :             }
    3193              :         }
    3194         3080 :       clvec.safe_push (c);
    3195              :     }
    3196         1427 :   if (!clvec.is_empty ())
    3197              :     {
    3198         1314 :       unsigned int len = clvec.length (), i;
    3199         1314 :       clvec.qsort (c_omp_declare_simd_clause_cmp);
    3200         1314 :       clauses = clvec[0];
    3201         4394 :       for (i = 0; i < len; i++)
    3202         3080 :         OMP_CLAUSE_CHAIN (clvec[i]) = (i < len - 1) ? clvec[i + 1] : NULL_TREE;
    3203              :     }
    3204              :   else
    3205              :     clauses = NULL_TREE;
    3206         1427 :   clvec.release ();
    3207         1427 :   return clauses;
    3208              : }
    3209              : 
    3210              : /* Change argument indexes in CLAUSES of FNDECL back to PARM_DECLs.  */
    3211              : 
    3212              : void
    3213          105 : c_omp_declare_simd_clauses_to_decls (tree fndecl, tree clauses)
    3214              : {
    3215          105 :   tree c;
    3216              : 
    3217          393 :   for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
    3218          288 :     if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
    3219              :         && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
    3220              :         && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
    3221              :       {
    3222          189 :         int idx = tree_to_shwi (OMP_CLAUSE_DECL (c)), i;
    3223          189 :         tree arg;
    3224          369 :         for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
    3225          180 :              arg = TREE_CHAIN (arg), i++)
    3226          369 :           if (i == idx)
    3227              :             break;
    3228            0 :         gcc_assert (arg);
    3229          189 :         OMP_CLAUSE_DECL (c) = arg;
    3230          189 :         if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
    3231          189 :             && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
    3232              :           {
    3233            0 :             idx = tree_to_shwi (OMP_CLAUSE_LINEAR_STEP (c));
    3234            0 :             for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
    3235            0 :                  arg = TREE_CHAIN (arg), i++)
    3236            0 :               if (i == idx)
    3237              :                 break;
    3238            0 :             gcc_assert (arg);
    3239            0 :             OMP_CLAUSE_LINEAR_STEP (c) = arg;
    3240              :           }
    3241              :       }
    3242          105 : }
    3243              : 
    3244              : /* Return true for __func__ and similar function-local predefined
    3245              :    variables (which are in OpenMP predetermined shared, allowed in
    3246              :    shared/firstprivate clauses).  */
    3247              : 
    3248              : bool
    3249        65281 : c_omp_predefined_variable (tree decl)
    3250              : {
    3251        65281 :   if (VAR_P (decl)
    3252        34324 :       && DECL_ARTIFICIAL (decl)
    3253          309 :       && TREE_STATIC (decl)
    3254        65575 :       && DECL_NAME (decl))
    3255              :     {
    3256          294 :       if (TREE_READONLY (decl)
    3257          294 :           && (DECL_NAME (decl) == ridpointers[RID_C99_FUNCTION_NAME]
    3258          226 :               || DECL_NAME (decl) == ridpointers[RID_FUNCTION_NAME]
    3259          182 :               || DECL_NAME (decl) == ridpointers[RID_PRETTY_FUNCTION_NAME]))
    3260              :         return true;
    3261              :       /* For UBSan handle the same also ubsan_create_data created
    3262              :          variables.  There is no magic flag for those, but user variables
    3263              :          shouldn't be DECL_ARTIFICIAL or have TYPE_ARTIFICIAL type with
    3264              :          such names.  */
    3265          142 :       if ((flag_sanitize & (SANITIZE_UNDEFINED
    3266              :                             | SANITIZE_UNDEFINED_NONDEFAULT)) != 0
    3267           39 :           && DECL_IGNORED_P (decl)
    3268           39 :           && !TREE_READONLY (decl)
    3269           30 :           && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE
    3270           30 :           && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
    3271           30 :           && TYPE_ARTIFICIAL (TREE_TYPE (decl))
    3272           30 :           && TYPE_NAME (TREE_TYPE (decl))
    3273           30 :           && TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) == TYPE_DECL
    3274           30 :           && DECL_NAME (TYPE_NAME (TREE_TYPE (decl)))
    3275          172 :           && (TREE_CODE (DECL_NAME (TYPE_NAME (TREE_TYPE (decl))))
    3276              :               == IDENTIFIER_NODE))
    3277              :         {
    3278           30 :           tree id1 = DECL_NAME (decl);
    3279           30 :           tree id2 = DECL_NAME (TYPE_NAME (TREE_TYPE (decl)));
    3280           30 :           if (IDENTIFIER_LENGTH (id1) >= sizeof ("ubsan_data") - 1
    3281           30 :               && IDENTIFIER_LENGTH (id2) >= sizeof ("__ubsan__data")
    3282           30 :               && !memcmp (IDENTIFIER_POINTER (id2), "__ubsan_",
    3283              :                           sizeof ("__ubsan_") - 1)
    3284           30 :               && !memcmp (IDENTIFIER_POINTER (id2) + IDENTIFIER_LENGTH (id2)
    3285           30 :                           - sizeof ("_data") + 1, "_data",
    3286              :                           sizeof ("_data") - 1)
    3287           60 :               && strstr (IDENTIFIER_POINTER (id1), "ubsan_data"))
    3288           30 :             return true;
    3289              :         }
    3290              :     }
    3291              :   return false;
    3292              : }
    3293              : 
    3294              : /* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute of DECL
    3295              :    is predetermined.  */
    3296              : 
    3297              : enum omp_clause_default_kind
    3298        28029 : c_omp_predetermined_sharing (tree decl)
    3299              : {
    3300              :   /* Predetermine artificial variables holding integral values, those
    3301              :      are usually result of gimplify_one_sizepos or SAVE_EXPR
    3302              :      gimplification.  */
    3303        28029 :   if (VAR_P (decl)
    3304        17249 :       && DECL_ARTIFICIAL (decl)
    3305        28668 :       && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
    3306              :     return OMP_CLAUSE_DEFAULT_SHARED;
    3307              : 
    3308        27481 :   if (c_omp_predefined_variable (decl))
    3309              :     return OMP_CLAUSE_DEFAULT_SHARED;
    3310              : 
    3311              :   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
    3312              : }
    3313              : 
    3314              : /* OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED unless OpenMP mapping attribute
    3315              :    of DECL is predetermined.  */
    3316              : 
    3317              : enum omp_clause_defaultmap_kind
    3318         5150 : c_omp_predetermined_mapping (tree decl)
    3319              : {
    3320              :   /* Predetermine artificial variables holding integral values, those
    3321              :      are usually result of gimplify_one_sizepos or SAVE_EXPR
    3322              :      gimplification.  */
    3323         5150 :   if (VAR_P (decl)
    3324          939 :       && DECL_ARTIFICIAL (decl)
    3325         5182 :       && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
    3326              :     return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
    3327              : 
    3328         5122 :   if (c_omp_predefined_variable (decl))
    3329            2 :     return OMP_CLAUSE_DEFAULTMAP_TO;
    3330              : 
    3331              :   return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
    3332              : }
    3333              : 
    3334              : 
    3335              : /* Used to merge map clause information in c_omp_adjust_map_clauses.  */
    3336              : struct map_clause
    3337              : {
    3338              :   tree clause;
    3339              :   bool firstprivate_ptr_p;
    3340              :   bool decl_mapped;
    3341              :   bool omp_declare_target;
    3342         3552 :   map_clause (void) : clause (NULL_TREE), firstprivate_ptr_p (false),
    3343         3552 :     decl_mapped (false), omp_declare_target (false) { }
    3344              : };
    3345              : 
    3346              : /* Adjust map clauses after normal clause parsing, mainly to mark specific
    3347              :    base-pointer map cases addressable that may be turned into attach/detach
    3348              :    operations during gimplification.  */
    3349              : void
    3350        12771 : c_omp_adjust_map_clauses (tree clauses, bool is_target)
    3351              : {
    3352        12771 :   if (!is_target)
    3353              :     {
    3354              :       /* If this is not a target construct, just turn firstprivate pointers
    3355              :          into attach/detach, the runtime will check and do the rest.  */
    3356              : 
    3357         4506 :       for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
    3358         3056 :         if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
    3359         2579 :             && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
    3360            0 :             && DECL_P (OMP_CLAUSE_DECL (c))
    3361         3056 :             && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
    3362              :           {
    3363            0 :             tree ptr = OMP_CLAUSE_DECL (c);
    3364            0 :             c_common_mark_addressable_vec (ptr);
    3365              :           }
    3366         1450 :       return;
    3367              :     }
    3368              : 
    3369        11321 :   hash_map<tree, map_clause> maps;
    3370              : 
    3371        24617 :   for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
    3372        13296 :     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
    3373        13296 :         && DECL_P (OMP_CLAUSE_DECL (c)))
    3374              :       {
    3375              :         /* If this is for a target construct, the firstprivate pointer
    3376              :            is marked addressable if either is true:
    3377              :            (1) the base-pointer is mapped in this same construct, or
    3378              :            (2) the base-pointer is a variable place on the device by
    3379              :                "declare target" directives.
    3380              : 
    3381              :            Here we iterate through all map clauses collecting these cases,
    3382              :            and merge them with a hash_map to process below.  */
    3383              : 
    3384         4192 :         if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
    3385         4192 :             && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
    3386              :           {
    3387          341 :             tree ptr = OMP_CLAUSE_DECL (c);
    3388          341 :             map_clause &mc = maps.get_or_insert (ptr);
    3389          341 :             if (mc.clause == NULL_TREE)
    3390          341 :               mc.clause = c;
    3391          341 :             mc.firstprivate_ptr_p = true;
    3392              : 
    3393          341 :             if (is_global_var (ptr)
    3394          389 :                 && lookup_attribute ("omp declare target",
    3395           48 :                                      DECL_ATTRIBUTES (ptr)))
    3396            0 :               mc.omp_declare_target = true;
    3397              :           }
    3398         3851 :         else if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALLOC
    3399         3764 :                  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO
    3400         3261 :                  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
    3401         2259 :                  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TOFROM
    3402         1049 :                  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
    3403          979 :                  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
    3404         4821 :                  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM)
    3405              :           {
    3406         3242 :             map_clause &mc = maps.get_or_insert (OMP_CLAUSE_DECL (c));
    3407         3242 :             mc.decl_mapped = true;
    3408              :           }
    3409              :       }
    3410              : 
    3411        14873 :   for (hash_map<tree, map_clause>::iterator i = maps.begin ();
    3412        29746 :        i != maps.end (); ++i)
    3413              :     {
    3414         3552 :       map_clause &mc = (*i).second;
    3415              : 
    3416         3552 :       if (mc.firstprivate_ptr_p
    3417          341 :           && (mc.decl_mapped || mc.omp_declare_target))
    3418           23 :         c_common_mark_addressable_vec (OMP_CLAUSE_DECL (mc.clause));
    3419              :     }
    3420        11321 : }
    3421              : 
    3422              : /* Maybe strip off an indirection from a "converted" reference, then find the
    3423              :    origin of a pointer (i.e. without any offset).  */
    3424              : 
    3425              : tree
    3426        70919 : c_omp_address_inspector::unconverted_ref_origin ()
    3427              : {
    3428        70919 :   tree t = orig;
    3429              : 
    3430              :   /* We may have a reference-typed component access at the outermost level
    3431              :      that has had convert_from_reference called on it.  Get the un-dereferenced
    3432              :      reference itself.  */
    3433        70919 :   t = maybe_unconvert_ref (t);
    3434              : 
    3435              :   /* Find base pointer for POINTER_PLUS_EXPR, etc.  */
    3436        70919 :   t = get_origin (t);
    3437              : 
    3438        70919 :   return t;
    3439              : }
    3440              : 
    3441              : /* Return TRUE if the address is a component access.  */
    3442              : 
    3443              : bool
    3444        12245 : c_omp_address_inspector::component_access_p ()
    3445              : {
    3446        12245 :   tree t = maybe_unconvert_ref (orig);
    3447              : 
    3448        12245 :   t = get_origin (t);
    3449              : 
    3450        12245 :   return TREE_CODE (t) == COMPONENT_REF;
    3451              : }
    3452              : 
    3453              : /* Perform various checks on the address, as described by clause CLAUSE (we
    3454              :    only use its code and location here).  */
    3455              : 
    3456              : bool
    3457        33153 : c_omp_address_inspector::check_clause (tree clause)
    3458              : {
    3459        33153 :   tree t = unconverted_ref_origin ();
    3460              : 
    3461        33153 :   if (TREE_CODE (t) != COMPONENT_REF)
    3462              :     return true;
    3463              : 
    3464         4869 :   if (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL
    3465         4869 :       && DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
    3466              :     {
    3467           24 :       error_at (OMP_CLAUSE_LOCATION (clause),
    3468              :                 "bit-field %qE in %qs clause",
    3469           24 :                 t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
    3470           24 :       return false;
    3471              :     }
    3472         4845 :   else if (!processing_template_decl_p ()
    3473         4845 :            && !omp_mappable_type (TREE_TYPE (t)))
    3474              :     {
    3475            0 :       error_at (OMP_CLAUSE_LOCATION (clause),
    3476              :                 "%qE does not have a mappable type in %qs clause",
    3477            0 :                 t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
    3478            0 :       emit_unmappable_type_notes (TREE_TYPE (t));
    3479            0 :       return false;
    3480              :     }
    3481         4845 :   else if (TREE_TYPE (t) && TYPE_ATOMIC (TREE_TYPE (t)))
    3482              :     {
    3483            2 :       error_at (OMP_CLAUSE_LOCATION (clause),
    3484              :                 "%<_Atomic%> %qE in %qs clause", t,
    3485            2 :                 omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
    3486            2 :       return false;
    3487              :     }
    3488              : 
    3489              :   return true;
    3490              : }
    3491              : 
    3492              : /* Find the "root term" for the address.  This is the innermost decl, etc.
    3493              :    of the access.  */
    3494              : 
    3495              : tree
    3496         1691 : c_omp_address_inspector::get_root_term (bool checking)
    3497              : {
    3498         1691 :   if (root_term && !checking)
    3499              :     return root_term;
    3500              : 
    3501         1691 :   tree t = unconverted_ref_origin ();
    3502              : 
    3503         5737 :   while (TREE_CODE (t) == COMPONENT_REF)
    3504              :     {
    3505         2355 :       if (checking
    3506         2355 :           && TREE_TYPE (TREE_OPERAND (t, 0))
    3507         4522 :           && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE)
    3508              :         {
    3509            0 :           error_at (loc, "%qE is a member of a union", t);
    3510            0 :           return error_mark_node;
    3511              :         }
    3512         2355 :       t = TREE_OPERAND (t, 0);
    3513         2355 :       while (TREE_CODE (t) == MEM_REF
    3514         3774 :              || TREE_CODE (t) == INDIRECT_REF
    3515         3774 :              || TREE_CODE (t) == ARRAY_REF)
    3516              :         {
    3517         1419 :           if (TREE_CODE (t) == MEM_REF
    3518              :               || TREE_CODE (t) == INDIRECT_REF)
    3519         1275 :             indirections = true;
    3520         1419 :           t = TREE_OPERAND (t, 0);
    3521         1419 :           STRIP_NOPS (t);
    3522         1419 :           if (TREE_CODE (t) == POINTER_PLUS_EXPR)
    3523          102 :             t = TREE_OPERAND (t, 0);
    3524              :         }
    3525              :     }
    3526              : 
    3527         1691 :   root_term = t;
    3528              : 
    3529         1691 :   return t;
    3530              : }
    3531              : 
    3532              : /* Return TRUE if the address is supported in mapping clauses.  At present,
    3533              :    this means that the innermost expression is a DECL_P, but could be extended
    3534              :    to other types of expression in the future.  */
    3535              : 
    3536              : bool
    3537        25521 : c_omp_address_inspector::map_supported_p ()
    3538              : {
    3539              :   /* If we've already decided if the mapped address is supported, return
    3540              :      that.  */
    3541        25521 :   if (map_supported != -1)
    3542            0 :     return map_supported;
    3543              : 
    3544        25521 :   tree t = unconverted_ref_origin ();
    3545              : 
    3546        25521 :   STRIP_NOPS (t);
    3547              : 
    3548        25521 :   while (TREE_CODE (t) == INDIRECT_REF
    3549        41622 :          || TREE_CODE (t) == MEM_REF
    3550              :          || TREE_CODE (t) == ARRAY_REF
    3551              :          || TREE_CODE (t) == COMPONENT_REF
    3552              :          || TREE_CODE (t) == COMPOUND_EXPR
    3553              :          || TREE_CODE (t) == SAVE_EXPR
    3554              :          || TREE_CODE (t) == POINTER_PLUS_EXPR
    3555              :          || TREE_CODE (t) == NON_LVALUE_EXPR
    3556              :          || TREE_CODE (t) == OMP_ARRAY_SECTION
    3557        41622 :          || TREE_CODE (t) == NOP_EXPR)
    3558        16101 :     if (TREE_CODE (t) == COMPOUND_EXPR)
    3559           27 :       t = TREE_OPERAND (t, 1);
    3560              :     else
    3561        16074 :       t = TREE_OPERAND (t, 0);
    3562              : 
    3563        25521 :   STRIP_NOPS (t);
    3564              : 
    3565        25521 :   map_supported = DECL_P (t);
    3566              : 
    3567        25521 :   return map_supported;
    3568              : }
    3569              : 
    3570              : /* Get the origin of an address T, stripping off offsets and some other
    3571              :    bits.  */
    3572              : 
    3573              : tree
    3574        83164 : c_omp_address_inspector::get_origin (tree t)
    3575              : {
    3576        83713 :   while (1)
    3577              :     {
    3578        83713 :       if (TREE_CODE (t) == COMPOUND_EXPR)
    3579              :         {
    3580           10 :           t = TREE_OPERAND (t, 1);
    3581           10 :           STRIP_NOPS (t);
    3582              :         }
    3583        83703 :       else if (TREE_CODE (t) == POINTER_PLUS_EXPR
    3584        83703 :                || TREE_CODE (t) == SAVE_EXPR)
    3585          512 :         t = TREE_OPERAND (t, 0);
    3586        83191 :       else if (!processing_template_decl_p ()
    3587        76444 :                && TREE_CODE (t) == INDIRECT_REF
    3588        85790 :                && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE)
    3589           27 :         t = TREE_OPERAND (t, 0);
    3590              :       else
    3591              :         break;
    3592              :     }
    3593        83164 :   STRIP_NOPS (t);
    3594        83164 :   return t;
    3595              : }
    3596              : 
    3597              : /* For an address T that might be a reference that has had
    3598              :    "convert_from_reference" called on it, return the actual reference without
    3599              :    any indirection.  */
    3600              : 
    3601              : tree
    3602        92437 : c_omp_address_inspector::maybe_unconvert_ref (tree t)
    3603              : {
    3604              :   /* Be careful not to dereference the type if we're processing a
    3605              :      template decl, else it might be NULL.  */
    3606        92437 :   if (!processing_template_decl_p ()
    3607        83694 :       && TREE_CODE (t) == INDIRECT_REF
    3608        95557 :       && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE)
    3609          587 :     return TREE_OPERAND (t, 0);
    3610              : 
    3611              :   return t;
    3612              : }
    3613              : 
    3614              : /* Return TRUE if CLAUSE might describe a zero-length array section.  */
    3615              : 
    3616              : bool
    3617         5452 : c_omp_address_inspector::maybe_zero_length_array_section (tree clause)
    3618              : {
    3619         5452 :   switch (OMP_CLAUSE_MAP_KIND (clause))
    3620              :     {
    3621              :     case GOMP_MAP_ALLOC:
    3622              :     case GOMP_MAP_IF_PRESENT:
    3623              :     case GOMP_MAP_TO:
    3624              :     case GOMP_MAP_FROM:
    3625              :     case GOMP_MAP_TOFROM:
    3626              :     case GOMP_MAP_ALWAYS_TO:
    3627              :     case GOMP_MAP_ALWAYS_FROM:
    3628              :     case GOMP_MAP_ALWAYS_TOFROM:
    3629              :     case GOMP_MAP_PRESENT_ALLOC:
    3630              :     case GOMP_MAP_PRESENT_TO:
    3631              :     case GOMP_MAP_PRESENT_FROM:
    3632              :     case GOMP_MAP_PRESENT_TOFROM:
    3633              :     case GOMP_MAP_ALWAYS_PRESENT_TO:
    3634              :     case GOMP_MAP_ALWAYS_PRESENT_FROM:
    3635              :     case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
    3636              :     case GOMP_MAP_RELEASE:
    3637              :     case GOMP_MAP_DELETE:
    3638              :     case GOMP_MAP_FORCE_TO:
    3639              :     case GOMP_MAP_FORCE_FROM:
    3640              :     case GOMP_MAP_FORCE_TOFROM:
    3641              :     case GOMP_MAP_FORCE_PRESENT:
    3642              :       return true;
    3643           28 :     default:
    3644           28 :       return false;
    3645              :     }
    3646              : }
    3647              : 
    3648              : /* Expand a chained access.  We only expect to see a quite limited range of
    3649              :    expression types here, because e.g. you can't have an array of
    3650              :    references.  */
    3651              : 
    3652              : static tree
    3653           75 : omp_expand_access_chain (tree c, tree expr, vec<omp_addr_token *> &addr_tokens,
    3654              :                          unsigned *idx, c_omp_region_type ort)
    3655              : {
    3656           83 :   using namespace omp_addr_tokenizer;
    3657           83 :   location_t loc = OMP_CLAUSE_LOCATION (c);
    3658           83 :   unsigned i = *idx;
    3659           83 :   tree c2 = NULL_TREE;
    3660           83 :   gomp_map_kind kind;
    3661              : 
    3662           83 :   if ((ort & C_ORT_EXIT_DATA) != 0
    3663           71 :       || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM
    3664          154 :       || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
    3665           71 :           && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
    3666           71 :               || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DELETE
    3667           71 :               || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_RELEASE
    3668           71 :               || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
    3669           71 :               || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_FROM
    3670           71 :               || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PRESENT_FROM
    3671           71 :               || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_FROM)))
    3672              :     kind = GOMP_MAP_DETACH;
    3673              :   else
    3674              :     kind = GOMP_MAP_ATTACH;
    3675              : 
    3676           83 :   switch (addr_tokens[i]->u.access_kind)
    3677              :     {
    3678           83 :     case ACCESS_POINTER:
    3679           83 :     case ACCESS_POINTER_OFFSET:
    3680           83 :       {
    3681           83 :         tree virtual_origin
    3682           83 :           = fold_convert_loc (loc, ptrdiff_type_node, addr_tokens[i]->expr);
    3683           83 :         tree data_addr = omp_accessed_addr (addr_tokens, i, expr);
    3684           83 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    3685           83 :         OMP_CLAUSE_SET_MAP_KIND (c2, kind);
    3686           83 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i]->expr;
    3687           83 :         OMP_CLAUSE_SIZE (c2)
    3688           83 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    3689              :                              fold_convert_loc (loc, ptrdiff_type_node,
    3690              :                                                data_addr),
    3691              :                              virtual_origin);
    3692              :       }
    3693           83 :       break;
    3694              : 
    3695              :     case ACCESS_INDEXED_ARRAY:
    3696              :       break;
    3697              : 
    3698            0 :     default:
    3699            0 :       return error_mark_node;
    3700              :     }
    3701              : 
    3702           83 :   if (c2)
    3703              :     {
    3704           83 :       OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
    3705           83 :       OMP_CLAUSE_CHAIN (c) = c2;
    3706           83 :       c = c2;
    3707              :     }
    3708              : 
    3709           83 :   *idx = ++i;
    3710              : 
    3711           83 :   if (i < addr_tokens.length ()
    3712           91 :       && addr_tokens[i]->type == ACCESS_METHOD)
    3713              :     return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
    3714              : 
    3715              :   return c;
    3716              : }
    3717              : 
    3718              : /* Translate "array_base_decl access_method" to OMP mapping clauses.  */
    3719              : 
    3720              : tree
    3721        18237 : c_omp_address_inspector::expand_array_base (tree c,
    3722              :                                             vec<omp_addr_token *> &addr_tokens,
    3723              :                                             tree expr, unsigned *idx,
    3724              :                                             c_omp_region_type ort)
    3725              : {
    3726        18237 :   using namespace omp_addr_tokenizer;
    3727        18237 :   location_t loc = OMP_CLAUSE_LOCATION (c);
    3728        18237 :   int i = *idx;
    3729        18237 :   tree decl = addr_tokens[i + 1]->expr;
    3730        18237 :   bool decl_p = DECL_P (decl);
    3731        18237 :   bool declare_target_p = (decl_p
    3732        18228 :                            && is_global_var (decl)
    3733        25736 :                            && lookup_attribute ("omp declare target",
    3734         7499 :                                                 DECL_ATTRIBUTES (decl)));
    3735        18237 :   bool map_p = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP;
    3736        18237 :   bool implicit_p = map_p && OMP_CLAUSE_MAP_IMPLICIT (c);
    3737        18237 :   bool chain_p = omp_access_chain_p (addr_tokens, i + 1);
    3738        18237 :   tree c2 = NULL_TREE, c3 = NULL_TREE;
    3739        18237 :   unsigned consume_tokens = 2;
    3740        18237 :   bool target_p = (ort & C_ORT_TARGET) != 0;
    3741        18237 :   bool openmp_p = (ort & C_ORT_OMP) != 0;
    3742              : 
    3743        18237 :   gcc_assert (i == 0);
    3744              : 
    3745        18237 :   if (!openmp_p
    3746        18237 :       && map_p
    3747        18237 :       && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
    3748         6745 :           || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH))
    3749              :     {
    3750           28 :       i += 2;
    3751           28 :       *idx = i;
    3752           28 :       return c;
    3753              :     }
    3754              : 
    3755        18209 :   switch (addr_tokens[i + 1]->u.access_kind)
    3756              :     {
    3757        13938 :     case ACCESS_DIRECT:
    3758        13938 :       if (decl_p && !target_p)
    3759         8630 :         c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3760              :       break;
    3761              : 
    3762          154 :     case ACCESS_REF:
    3763          154 :       {
    3764              :         /* Copy the referenced object.  Note that we do this even for !MAP_P
    3765              :            clauses.  */
    3766          154 :         tree obj = convert_from_reference (addr_tokens[i + 1]->expr);
    3767          154 :         if (TREE_CODE (TREE_TYPE (obj)) == ARRAY_TYPE)
    3768              :           /* We have a ref to array: add a [0] element as the ME expects.  */
    3769           47 :           OMP_CLAUSE_DECL (c) = build_array_ref (loc, obj, integer_zero_node);
    3770              :         else
    3771          107 :           OMP_CLAUSE_DECL (c) = obj;
    3772          154 :         OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (obj));
    3773              : 
    3774          154 :         if (!map_p)
    3775              :           {
    3776            6 :             if (decl_p)
    3777            6 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3778              :             break;
    3779              :           }
    3780              : 
    3781          148 :         if (!target_p)
    3782              :           break;
    3783              : 
    3784              :         /* If we have a reference to a pointer, avoid using
    3785              :            FIRSTPRIVATE_REFERENCE here in case the pointer is modified in the
    3786              :            offload region (we can only do that if the pointer does not point
    3787              :            to a mapped block).  We could avoid doing this if we don't have a
    3788              :            FROM mapping...  */
    3789           88 :         bool ref_to_ptr = TREE_CODE (TREE_TYPE (obj)) == POINTER_TYPE;
    3790              : 
    3791           88 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    3792           88 :         if (!ref_to_ptr
    3793           88 :             && !declare_target_p
    3794           54 :             && decl_p)
    3795           54 :           OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
    3796              :         else
    3797              :           {
    3798           34 :             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    3799           34 :             if (decl_p)
    3800           34 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3801              :           }
    3802           88 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    3803           88 :         OMP_CLAUSE_SIZE (c2) = size_zero_node;
    3804              : 
    3805           88 :         if (ref_to_ptr)
    3806              :           {
    3807           34 :             c3 = c2;
    3808           34 :             c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    3809           34 :             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALLOC);
    3810           34 :             OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    3811           68 :             OMP_CLAUSE_SIZE (c2)
    3812           34 :               = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (c2)));
    3813              :           }
    3814              :       }
    3815              :       break;
    3816              : 
    3817           83 :     case ACCESS_INDEXED_REF_TO_ARRAY:
    3818           83 :       {
    3819           83 :         if (!map_p)
    3820              :           {
    3821            0 :             if (decl_p)
    3822            0 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3823              :             break;
    3824              :           }
    3825              : 
    3826           83 :         if (!target_p)
    3827              :           break;
    3828              : 
    3829           64 :         tree virtual_origin
    3830           64 :           = convert_from_reference (addr_tokens[i + 1]->expr);
    3831           64 :         virtual_origin = build_fold_addr_expr (virtual_origin);
    3832           64 :         virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    3833              :                                            virtual_origin);
    3834           64 :         tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
    3835           64 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    3836           64 :         if (decl_p && target_p && !declare_target_p)
    3837              :           {
    3838              :             /* It appears that omp-low.cc mishandles cases where we have a
    3839              :                [reference to an] array of pointers such as:
    3840              : 
    3841              :                  int *arr[N];   (or "int *(&arr)[N] = ...")
    3842              :                  #pragma omp target map(arr[a][b:c])
    3843              :                  { ... }
    3844              : 
    3845              :                in such cases chain_p will be true.  For now, fall back to
    3846              :                GOMP_MAP_POINTER.  */
    3847           61 :             enum gomp_map_kind k = chain_p ? GOMP_MAP_POINTER
    3848              :                                            : GOMP_MAP_FIRSTPRIVATE_REFERENCE;
    3849           61 :             OMP_CLAUSE_SET_MAP_KIND (c2, k);
    3850           61 :           }
    3851              :         else
    3852              :           {
    3853            3 :             if (decl_p)
    3854            0 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3855            3 :             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    3856              :           }
    3857           64 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    3858           64 :         OMP_CLAUSE_SIZE (c2)
    3859           64 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    3860              :                              fold_convert_loc (loc, ptrdiff_type_node,
    3861              :                                                data_addr),
    3862              :                              virtual_origin);
    3863              :       }
    3864           64 :       break;
    3865              : 
    3866         1328 :     case ACCESS_INDEXED_ARRAY:
    3867         1328 :       {
    3868         1328 :         if (!map_p)
    3869              :           {
    3870            0 :             if (decl_p)
    3871            0 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3872              :             break;
    3873              :           }
    3874              : 
    3875              :         /* The code handling "firstprivatize_array_bases" in gimplify.cc is
    3876              :            relevant here.  What do we need to create for arrays at this
    3877              :            stage?  (This condition doesn't feel quite right.  FIXME?)  */
    3878         1328 :         if (!target_p
    3879         1328 :             && (TREE_CODE (TREE_TYPE (addr_tokens[i + 1]->expr))
    3880              :                 == ARRAY_TYPE))
    3881              :           break;
    3882              : 
    3883          683 :         tree virtual_origin
    3884          683 :           = build_fold_addr_expr (addr_tokens[i + 1]->expr);
    3885          683 :         virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    3886              :                                            virtual_origin);
    3887          683 :         tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
    3888          683 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    3889          683 :         if (decl_p && target_p)
    3890              :           {
    3891              :             /* See comment for ACCESS_INDEXED_REF_TO_ARRAY above.  */
    3892          683 :             enum gomp_map_kind k = chain_p ? GOMP_MAP_POINTER
    3893              :                                            : GOMP_MAP_FIRSTPRIVATE_POINTER;
    3894          683 :             OMP_CLAUSE_SET_MAP_KIND (c2, k);
    3895              :           }
    3896              :         else
    3897              :           {
    3898            0 :             if (decl_p)
    3899            0 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3900            0 :             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    3901              :           }
    3902          683 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    3903          683 :         OMP_CLAUSE_SIZE (c2)
    3904          683 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    3905              :                              fold_convert_loc (loc, ptrdiff_type_node,
    3906              :                                                data_addr),
    3907              :                              virtual_origin);
    3908              :       }
    3909          683 :       break;
    3910              : 
    3911         2632 :     case ACCESS_POINTER:
    3912         2632 :     case ACCESS_POINTER_OFFSET:
    3913         2632 :       {
    3914         2632 :         if (!map_p)
    3915              :           {
    3916            0 :             if (decl_p)
    3917            0 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3918              :             break;
    3919              :           }
    3920              : 
    3921         2632 :         unsigned last_access = i + 1;
    3922         2632 :         tree virtual_origin;
    3923              : 
    3924         2632 :         if (chain_p
    3925          149 :             && addr_tokens[i + 2]->type == ACCESS_METHOD
    3926         2781 :             && addr_tokens[i + 2]->u.access_kind == ACCESS_INDEXED_ARRAY)
    3927              :           {
    3928              :             /* !!! This seems wrong for ACCESS_POINTER_OFFSET.  */
    3929          115 :             consume_tokens = 3;
    3930          115 :             chain_p = omp_access_chain_p (addr_tokens, i + 2);
    3931          115 :             last_access = i + 2;
    3932          115 :             virtual_origin
    3933          115 :               = build_array_ref (loc, addr_tokens[last_access]->expr,
    3934              :                                  integer_zero_node);
    3935          115 :             virtual_origin = build_fold_addr_expr (virtual_origin);
    3936          115 :             virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    3937              :                                                virtual_origin);
    3938              :           }
    3939              :         else
    3940         2517 :           virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    3941         2517 :                                              addr_tokens[last_access]->expr);
    3942         2632 :         tree data_addr = omp_accessed_addr (addr_tokens, last_access, expr);
    3943         2632 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    3944              :         /* For OpenACC, use FIRSTPRIVATE_POINTER for decls even on non-compute
    3945              :            regions (e.g. "acc data" constructs).  It'll be removed anyway in
    3946              :            gimplify.cc, but doing it this way maintains diagnostic
    3947              :            behaviour.  */
    3948         2632 :         if (decl_p && (target_p || !openmp_p) && !chain_p && !declare_target_p)
    3949         2434 :           OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
    3950              :         else
    3951              :           {
    3952          195 :             if (decl_p)
    3953          195 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3954          198 :             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    3955              :           }
    3956         2632 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    3957         2632 :         OMP_CLAUSE_SIZE (c2)
    3958         2632 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    3959              :                              fold_convert_loc (loc, ptrdiff_type_node,
    3960              :                                                data_addr),
    3961              :                              virtual_origin);
    3962              :       }
    3963         2632 :       break;
    3964              : 
    3965           74 :     case ACCESS_REF_TO_POINTER:
    3966           74 :     case ACCESS_REF_TO_POINTER_OFFSET:
    3967           74 :       {
    3968           74 :         if (!map_p)
    3969              :           {
    3970            0 :             if (decl_p)
    3971            0 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3972              :             break;
    3973              :           }
    3974              : 
    3975           74 :         unsigned last_access = i + 1;
    3976           74 :         tree virtual_origin;
    3977              : 
    3978           74 :         if (chain_p
    3979            6 :             && addr_tokens[i + 2]->type == ACCESS_METHOD
    3980           80 :             && addr_tokens[i + 2]->u.access_kind == ACCESS_INDEXED_ARRAY)
    3981              :           {
    3982              :             /* !!! This seems wrong for ACCESS_POINTER_OFFSET.  */
    3983            2 :             consume_tokens = 3;
    3984            2 :             chain_p = omp_access_chain_p (addr_tokens, i + 2);
    3985            2 :             last_access = i + 2;
    3986            2 :             virtual_origin
    3987            2 :               = build_array_ref (loc, addr_tokens[last_access]->expr,
    3988              :                                  integer_zero_node);
    3989            2 :             virtual_origin = build_fold_addr_expr (virtual_origin);
    3990            2 :             virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    3991              :                                                virtual_origin);
    3992              :           }
    3993              :         else
    3994              :           {
    3995           72 :             virtual_origin
    3996           72 :               = convert_from_reference (addr_tokens[last_access]->expr);
    3997           72 :             virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    3998              :                                                virtual_origin);
    3999              :           }
    4000              : 
    4001           74 :         tree data_addr = omp_accessed_addr (addr_tokens, last_access, expr);
    4002           74 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    4003           74 :         if (decl_p && target_p && !chain_p && !declare_target_p)
    4004              :           {
    4005           58 :             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
    4006           58 :             OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    4007              :           }
    4008              :         else
    4009              :           {
    4010           16 :             if (decl_p)
    4011           16 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    4012           16 :             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    4013           16 :             OMP_CLAUSE_DECL (c2)
    4014           32 :               = convert_from_reference (addr_tokens[i + 1]->expr);
    4015              :           }
    4016           74 :         OMP_CLAUSE_SIZE (c2)
    4017           74 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    4018              :                              fold_convert_loc (loc, ptrdiff_type_node,
    4019              :                                                data_addr),
    4020              :                              virtual_origin);
    4021              :       }
    4022           74 :       break;
    4023              : 
    4024            0 :     default:
    4025            0 :       *idx = i + consume_tokens;
    4026            0 :       return error_mark_node;
    4027              :     }
    4028              : 
    4029        12089 :   if (c3)
    4030              :     {
    4031           34 :       OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c);
    4032           34 :       OMP_CLAUSE_CHAIN (c2) = c3;
    4033           34 :       OMP_CLAUSE_CHAIN (c) = c2;
    4034           34 :       if (implicit_p)
    4035              :         {
    4036            0 :           OMP_CLAUSE_MAP_IMPLICIT (c2) = 1;
    4037            0 :           OMP_CLAUSE_MAP_IMPLICIT (c3) = 1;
    4038              :         }
    4039              :       c = c3;
    4040              :     }
    4041        18175 :   else if (c2)
    4042              :     {
    4043         3507 :       OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
    4044         3507 :       OMP_CLAUSE_CHAIN (c) = c2;
    4045         3507 :       if (implicit_p)
    4046          116 :         OMP_CLAUSE_MAP_IMPLICIT (c2) = 1;
    4047              :       c = c2;
    4048              :     }
    4049              : 
    4050        18209 :   i += consume_tokens;
    4051        18209 :   *idx = i;
    4052              : 
    4053        18209 :   if (chain_p && map_p)
    4054           53 :     return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
    4055              : 
    4056              :   return c;
    4057              : }
    4058              : 
    4059              : /* Translate "component_selector access_method" to OMP mapping clauses.  */
    4060              : 
    4061              : tree
    4062         3226 : c_omp_address_inspector::expand_component_selector (tree c,
    4063              :                                                     vec<omp_addr_token *>
    4064              :                                                       &addr_tokens,
    4065              :                                                     tree expr, unsigned *idx,
    4066              :                                                     c_omp_region_type ort)
    4067              : {
    4068         3226 :   using namespace omp_addr_tokenizer;
    4069         3226 :   location_t loc = OMP_CLAUSE_LOCATION (c);
    4070         3226 :   unsigned i = *idx;
    4071         3226 :   tree c2 = NULL_TREE, c3 = NULL_TREE;
    4072         3226 :   bool chain_p = omp_access_chain_p (addr_tokens, i + 1);
    4073         3226 :   bool map_p = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP;
    4074              : 
    4075         3226 :   switch (addr_tokens[i + 1]->u.access_kind)
    4076              :     {
    4077              :     case ACCESS_DIRECT:
    4078              :     case ACCESS_INDEXED_ARRAY:
    4079              :       break;
    4080              : 
    4081          479 :     case ACCESS_REF:
    4082          479 :       {
    4083              :         /* Copy the referenced object.  Note that we also do this for !MAP_P
    4084              :            clauses.  */
    4085          479 :         tree obj = convert_from_reference (addr_tokens[i + 1]->expr);
    4086          479 :         OMP_CLAUSE_DECL (c) = obj;
    4087          479 :         OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (obj));
    4088              : 
    4089          479 :         if (!map_p)
    4090              :           break;
    4091              : 
    4092          461 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    4093          461 :         OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    4094          461 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    4095          461 :         OMP_CLAUSE_SIZE (c2) = size_zero_node;
    4096              :       }
    4097          461 :       break;
    4098              : 
    4099           92 :     case ACCESS_INDEXED_REF_TO_ARRAY:
    4100           92 :       {
    4101           92 :         if (!map_p)
    4102              :           break;
    4103              : 
    4104           92 :         tree virtual_origin
    4105           92 :           = convert_from_reference (addr_tokens[i + 1]->expr);
    4106           92 :         virtual_origin = build_fold_addr_expr (virtual_origin);
    4107           92 :         virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    4108              :                                            virtual_origin);
    4109           92 :         tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
    4110              : 
    4111           92 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    4112           92 :         OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    4113           92 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    4114           92 :         OMP_CLAUSE_SIZE (c2)
    4115           92 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    4116              :                              fold_convert_loc (loc, ptrdiff_type_node,
    4117              :                                                data_addr),
    4118              :                              virtual_origin);
    4119              :       }
    4120           92 :       break;
    4121              : 
    4122          778 :     case ACCESS_POINTER:
    4123          778 :     case ACCESS_POINTER_OFFSET:
    4124          778 :       {
    4125          778 :         if (!map_p)
    4126              :           break;
    4127              : 
    4128          778 :         tree virtual_origin
    4129         1556 :           = fold_convert_loc (loc, ptrdiff_type_node,
    4130          778 :                               addr_tokens[i + 1]->expr);
    4131          778 :         tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
    4132              : 
    4133          778 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    4134          778 :         OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    4135          778 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    4136          778 :         OMP_CLAUSE_SIZE (c2)
    4137          778 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    4138              :                              fold_convert_loc (loc, ptrdiff_type_node,
    4139              :                                                data_addr),
    4140              :                              virtual_origin);
    4141              :       }
    4142          778 :       break;
    4143              : 
    4144          185 :     case ACCESS_REF_TO_POINTER:
    4145          185 :     case ACCESS_REF_TO_POINTER_OFFSET:
    4146          185 :       {
    4147          185 :         if (!map_p)
    4148              :           break;
    4149              : 
    4150          185 :         tree ptr = convert_from_reference (addr_tokens[i + 1]->expr);
    4151          185 :         tree virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    4152              :                                                 ptr);
    4153          185 :         tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
    4154              : 
    4155              :         /* Attach the pointer...  */
    4156          185 :         c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
    4157          185 :         OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    4158          185 :         OMP_CLAUSE_DECL (c2) = ptr;
    4159          185 :         OMP_CLAUSE_SIZE (c2)
    4160          185 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    4161              :                              fold_convert_loc (loc, ptrdiff_type_node,
    4162              :                                                data_addr),
    4163              :                              virtual_origin);
    4164              : 
    4165              :         /* ...and also the reference.  */
    4166          185 :         c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
    4167          185 :         OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_ATTACH_DETACH);
    4168          185 :         OMP_CLAUSE_DECL (c3) = addr_tokens[i + 1]->expr;
    4169          185 :         OMP_CLAUSE_SIZE (c3) = size_zero_node;
    4170              :       }
    4171          185 :       break;
    4172              : 
    4173            0 :     default:
    4174            0 :       *idx = i + 2;
    4175            0 :       return error_mark_node;
    4176              :     }
    4177              : 
    4178         1331 :   if (c3)
    4179              :     {
    4180          185 :       OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c);
    4181          185 :       OMP_CLAUSE_CHAIN (c2) = c3;
    4182          185 :       OMP_CLAUSE_CHAIN (c) = c2;
    4183          185 :       c = c3;
    4184              :     }
    4185         3041 :   else if (c2)
    4186              :     {
    4187         1331 :       OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
    4188         1331 :       OMP_CLAUSE_CHAIN (c) = c2;
    4189         1331 :       c = c2;
    4190              :     }
    4191              : 
    4192         3226 :   i += 2;
    4193         3226 :   *idx = i;
    4194              : 
    4195         3226 :   if (chain_p && map_p)
    4196           22 :     return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
    4197              : 
    4198              :   return c;
    4199              : }
    4200              : 
    4201              : /* Expand a map clause into a group of mapping clauses, creating nodes to
    4202              :    attach/detach pointers and so forth as necessary.  */
    4203              : 
    4204              : tree
    4205        21463 : c_omp_address_inspector::expand_map_clause (tree c, tree expr,
    4206              :                                             vec<omp_addr_token *> &addr_tokens,
    4207              :                                             c_omp_region_type ort)
    4208              : {
    4209        21463 :   using namespace omp_addr_tokenizer;
    4210        21463 :   unsigned i, length = addr_tokens.length ();
    4211              : 
    4212        46847 :   for (i = 0; i < length;)
    4213              :     {
    4214        25384 :       int remaining = length - i;
    4215              : 
    4216        25384 :       if (remaining >= 2
    4217        25384 :           && addr_tokens[i]->type == ARRAY_BASE
    4218        18237 :           && addr_tokens[i]->u.structure_base_kind == BASE_DECL
    4219        43612 :           && addr_tokens[i + 1]->type == ACCESS_METHOD)
    4220              :         {
    4221        18228 :           c = expand_array_base (c, addr_tokens, expr, &i, ort);
    4222        18228 :           if (c == error_mark_node)
    4223              :             return error_mark_node;
    4224              :         }
    4225         7156 :       else if (remaining >= 2
    4226         7156 :                && addr_tokens[i]->type == ARRAY_BASE
    4227            9 :                && addr_tokens[i]->u.structure_base_kind == BASE_ARBITRARY_EXPR
    4228         7165 :                && addr_tokens[i + 1]->type == ACCESS_METHOD)
    4229              :         {
    4230            9 :           c = expand_array_base (c, addr_tokens, expr, &i, ort);
    4231            9 :           if (c == error_mark_node)
    4232              :             return error_mark_node;
    4233              :         }
    4234         7147 :       else if (remaining >= 2
    4235         7147 :                && addr_tokens[i]->type == STRUCTURE_BASE
    4236         3226 :                && addr_tokens[i]->u.structure_base_kind == BASE_DECL
    4237        10370 :                && addr_tokens[i + 1]->type == ACCESS_METHOD)
    4238              :         {
    4239         3223 :           if (addr_tokens[i + 1]->u.access_kind == ACCESS_DIRECT)
    4240         1754 :             c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    4241         3223 :           i += 2;
    4242         3383 :           while (addr_tokens[i]->type == ACCESS_METHOD)
    4243          160 :             i++;
    4244              :         }
    4245         3924 :       else if (remaining >= 2
    4246         3924 :                && addr_tokens[i]->type == STRUCTURE_BASE
    4247            3 :                && addr_tokens[i]->u.structure_base_kind == BASE_ARBITRARY_EXPR
    4248         3927 :                && addr_tokens[i + 1]->type == ACCESS_METHOD)
    4249              :         {
    4250            3 :           switch (addr_tokens[i + 1]->u.access_kind)
    4251              :             {
    4252            3 :             case ACCESS_DIRECT:
    4253            3 :             case ACCESS_POINTER:
    4254            3 :               i += 2;
    4255            3 :               while (addr_tokens[i]->type == ACCESS_METHOD)
    4256            0 :                 i++;
    4257              :               break;
    4258            0 :             default:
    4259            0 :               return error_mark_node;
    4260              :             }
    4261              :         }
    4262         3921 :       else if (remaining >= 2
    4263         3921 :                && addr_tokens[i]->type == COMPONENT_SELECTOR
    4264         7842 :                && addr_tokens[i + 1]->type == ACCESS_METHOD)
    4265              :         {
    4266         3226 :           c = expand_component_selector (c, addr_tokens, expr, &i, ort);
    4267              :           /* We used 'expr', so these must have been the last tokens.  */
    4268         3226 :           gcc_assert (i == length);
    4269         3226 :           if (c == error_mark_node)
    4270              :             return error_mark_node;
    4271              :         }
    4272          695 :       else if (remaining >= 3
    4273          695 :                && addr_tokens[i]->type == COMPONENT_SELECTOR
    4274          695 :                && addr_tokens[i + 1]->type == STRUCTURE_BASE
    4275          695 :                && (addr_tokens[i + 1]->u.structure_base_kind
    4276              :                    == BASE_COMPONENT_EXPR)
    4277         1390 :                && addr_tokens[i + 2]->type == ACCESS_METHOD)
    4278              :         {
    4279          695 :           i += 3;
    4280          719 :           while (addr_tokens[i]->type == ACCESS_METHOD)
    4281           24 :             i++;
    4282              :         }
    4283              :       else
    4284              :         break;
    4285              :     }
    4286              : 
    4287        21463 :   if (i == length)
    4288              :     return c;
    4289              : 
    4290            0 :   return error_mark_node;
    4291              : }
    4292              : 
    4293              : /* Given a mapper function MAPPER_FN, recursively scan through the map clauses
    4294              :    for that mapper, and if any of those should use a (named or unnamed) mapper
    4295              :    themselves, add it to MLIST.  */
    4296              : 
    4297              : void
    4298          140 : c_omp_find_nested_mappers (omp_mapper_list<tree> *mlist, tree mapper_fn)
    4299              : {
    4300          140 :   tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
    4301          140 :   tree mapper_name = NULL_TREE;
    4302              : 
    4303          140 :   if (mapper == error_mark_node)
    4304              :     return;
    4305              : 
    4306          140 :   gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER);
    4307              : 
    4308          454 :   for (tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper);
    4309          454 :        clause;
    4310          314 :        clause = OMP_CLAUSE_CHAIN (clause))
    4311              :     {
    4312          314 :       tree expr = OMP_CLAUSE_DECL (clause);
    4313          314 :       enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (clause);
    4314          314 :       tree elem_type;
    4315              : 
    4316          314 :       if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
    4317              :         {
    4318            0 :           mapper_name = expr;
    4319            0 :           continue;
    4320              :         }
    4321          314 :       else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
    4322              :         {
    4323            0 :           mapper_name = NULL_TREE;
    4324            0 :           continue;
    4325              :         }
    4326              : 
    4327          314 :       gcc_assert (TREE_CODE (expr) != TREE_LIST);
    4328          314 :       if (TREE_CODE (expr) == OMP_ARRAY_SECTION)
    4329              :         {
    4330          220 :           while (TREE_CODE (expr) == OMP_ARRAY_SECTION)
    4331          110 :             expr = TREE_OPERAND (expr, 0);
    4332              : 
    4333          110 :           elem_type = TREE_TYPE (expr);
    4334              :         }
    4335              :       else
    4336          204 :         elem_type = TREE_TYPE (expr);
    4337              : 
    4338              :       /* This might be too much... or not enough?  */
    4339          512 :       while (TREE_CODE (elem_type) == ARRAY_TYPE
    4340          506 :              || TREE_CODE (elem_type) == POINTER_TYPE
    4341          826 :              || TREE_CODE (elem_type) == REFERENCE_TYPE)
    4342          198 :         elem_type = TREE_TYPE (elem_type);
    4343              : 
    4344          314 :       elem_type = TYPE_MAIN_VARIANT (elem_type);
    4345              : 
    4346          314 :       if (RECORD_OR_UNION_TYPE_P (elem_type)
    4347          314 :           && !mlist->contains (mapper_name, elem_type))
    4348              :         {
    4349            5 :           tree nested_mapper_fn
    4350            5 :             = lang_hooks.decls.omp_mapper_lookup (mapper_name, elem_type);
    4351              : 
    4352            5 :           if (nested_mapper_fn)
    4353              :             {
    4354            5 :               mlist->add_mapper (mapper_name, elem_type, nested_mapper_fn);
    4355            5 :               c_omp_find_nested_mappers (mlist, nested_mapper_fn);
    4356              :             }
    4357            0 :           else if (mapper_name)
    4358              :             {
    4359            0 :               error ("mapper %qE not found for type %qT", mapper_name,
    4360              :                      elem_type);
    4361            0 :               continue;
    4362              :             }
    4363              :         }
    4364              :     }
    4365              : }
    4366              : 
    4367              : struct remap_mapper_decl_info
    4368              : {
    4369              :   tree dummy_var;
    4370              :   tree expr;
    4371              : };
    4372              : 
    4373              : /* Helper for rewriting DUMMY_VAR into EXPR in a map clause decl.  */
    4374              : 
    4375              : static tree
    4376         4044 : remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data)
    4377              : {
    4378         4044 :   remap_mapper_decl_info *map_info = (remap_mapper_decl_info *) data;
    4379              : 
    4380         4044 :   if (operand_equal_p (*tp, map_info->dummy_var))
    4381              :     {
    4382         1001 :       *tp = map_info->expr;
    4383         1001 :       *walk_subtrees = 0;
    4384              :     }
    4385              : 
    4386         4044 :   return NULL_TREE;
    4387              : }
    4388              : 
    4389              : static enum gomp_map_kind
    4390          946 : omp_split_map_kind (enum gomp_map_kind op, bool *force_p, bool *always_p,
    4391              :                     bool *present_p)
    4392              : {
    4393          946 :   *force_p = *always_p = *present_p = false;
    4394              : 
    4395          946 :   switch (op)
    4396              :     {
    4397            0 :     case GOMP_MAP_FORCE_ALLOC:
    4398            0 :     case GOMP_MAP_FORCE_TO:
    4399            0 :     case GOMP_MAP_FORCE_FROM:
    4400            0 :     case GOMP_MAP_FORCE_TOFROM:
    4401            0 :     case GOMP_MAP_FORCE_PRESENT:
    4402            0 :       *force_p = true;
    4403            0 :       break;
    4404           54 :     case GOMP_MAP_ALWAYS_TO:
    4405           54 :     case GOMP_MAP_ALWAYS_FROM:
    4406           54 :     case GOMP_MAP_ALWAYS_TOFROM:
    4407           54 :       *always_p = true;
    4408           54 :       break;
    4409           32 :     case GOMP_MAP_ALWAYS_PRESENT_TO:
    4410           32 :     case GOMP_MAP_ALWAYS_PRESENT_FROM:
    4411           32 :     case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
    4412           32 :       *always_p = true;
    4413              :       /* Fallthrough.  */
    4414          132 :     case GOMP_MAP_PRESENT_ALLOC:
    4415          132 :     case GOMP_MAP_PRESENT_TO:
    4416          132 :     case GOMP_MAP_PRESENT_FROM:
    4417          132 :     case GOMP_MAP_PRESENT_TOFROM:
    4418          132 :       *present_p = true;
    4419          132 :       break;
    4420          946 :     default:
    4421          946 :       ;
    4422              :     }
    4423              : 
    4424          946 :   switch (op)
    4425              :     {
    4426              :     case GOMP_MAP_ALLOC:
    4427              :     case GOMP_MAP_FORCE_ALLOC:
    4428              :     case GOMP_MAP_PRESENT_ALLOC:
    4429              :       return GOMP_MAP_ALLOC;
    4430          283 :     case GOMP_MAP_TO:
    4431          283 :     case GOMP_MAP_FORCE_TO:
    4432          283 :     case GOMP_MAP_ALWAYS_TO:
    4433          283 :     case GOMP_MAP_PRESENT_TO:
    4434          283 :     case GOMP_MAP_ALWAYS_PRESENT_TO:
    4435          283 :       return GOMP_MAP_TO;
    4436          212 :     case GOMP_MAP_FROM:
    4437          212 :     case GOMP_MAP_FORCE_FROM:
    4438          212 :     case GOMP_MAP_ALWAYS_FROM:
    4439          212 :     case GOMP_MAP_PRESENT_FROM:
    4440          212 :     case GOMP_MAP_ALWAYS_PRESENT_FROM:
    4441          212 :       return GOMP_MAP_FROM;
    4442          210 :     case GOMP_MAP_TOFROM:
    4443          210 :     case GOMP_MAP_FORCE_TOFROM:
    4444          210 :     case GOMP_MAP_ALWAYS_TOFROM:
    4445          210 :     case GOMP_MAP_PRESENT_TOFROM:
    4446          210 :     case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
    4447          210 :       return GOMP_MAP_TOFROM;
    4448          128 :     default:
    4449          128 :       ;
    4450              :     }
    4451              : 
    4452          128 :   return op;
    4453              : }
    4454              : 
    4455              : static enum gomp_map_kind
    4456          416 : omp_join_map_kind (enum gomp_map_kind op, bool force_p, bool always_p,
    4457              :                    bool present_p)
    4458              : {
    4459          416 :   gcc_assert (!force_p || !(always_p || present_p));
    4460              : 
    4461          416 :   switch (op)
    4462              :     {
    4463           89 :     case GOMP_MAP_ALLOC:
    4464           89 :       if (force_p)
    4465              :         return GOMP_MAP_FORCE_ALLOC;
    4466           89 :       else if (present_p)
    4467           16 :         return GOMP_MAP_PRESENT_ALLOC;
    4468              :       break;
    4469              : 
    4470          127 :     case GOMP_MAP_TO:
    4471          127 :       if (force_p)
    4472              :         return GOMP_MAP_FORCE_TO;
    4473          127 :       else if (always_p && present_p)
    4474              :         return GOMP_MAP_ALWAYS_PRESENT_TO;
    4475          115 :       else if (always_p)
    4476              :         return GOMP_MAP_ALWAYS_TO;
    4477           93 :       else if (present_p)
    4478           24 :         return GOMP_MAP_PRESENT_TO;
    4479              :       break;
    4480              : 
    4481           76 :     case GOMP_MAP_FROM:
    4482           76 :       if (force_p)
    4483              :         return GOMP_MAP_FORCE_FROM;
    4484           76 :       else if (always_p && present_p)
    4485              :         return GOMP_MAP_ALWAYS_PRESENT_FROM;
    4486           68 :       else if (always_p)
    4487              :         return GOMP_MAP_ALWAYS_FROM;
    4488           60 :       else if (present_p)
    4489           24 :         return GOMP_MAP_PRESENT_FROM;
    4490              :       break;
    4491              : 
    4492           80 :     case GOMP_MAP_TOFROM:
    4493           80 :       if (force_p)
    4494              :         return GOMP_MAP_FORCE_TOFROM;
    4495           80 :       else if (always_p && present_p)
    4496              :         return GOMP_MAP_ALWAYS_PRESENT_TOFROM;
    4497           80 :       else if (always_p)
    4498              :         return GOMP_MAP_ALWAYS_TOFROM;
    4499           80 :       else if (present_p)
    4500            0 :         return GOMP_MAP_PRESENT_TOFROM;
    4501              :       break;
    4502              : 
    4503              :     default:
    4504              :       ;
    4505              :     }
    4506              : 
    4507              :   return op;
    4508              : }
    4509              : 
    4510              : /* Map kind decay (OpenMP 5.2, 5.8.8 "declare mapper Directive").  Return the
    4511              :    map kind to use given MAPPER_KIND specified in the mapper and INVOKED_AS
    4512              :    specified on the clause that invokes the mapper.  See also
    4513              :    fortran/trans-openmp.cc:omp_map_decayed_kind.  */
    4514              : 
    4515              : static enum gomp_map_kind
    4516          432 : omp_map_decayed_kind (enum gomp_map_kind mapper_kind,
    4517              :                       enum gomp_map_kind invoked_as, bool exit_p)
    4518              : {
    4519          432 :   if (invoked_as == GOMP_MAP_RELEASE || invoked_as == GOMP_MAP_DELETE)
    4520              :     return invoked_as;
    4521              : 
    4522          416 :   bool m_force_p, m_always_p, m_present_p;
    4523          416 :   bool force_p, always_p, present_p;
    4524              : 
    4525          416 :   mapper_kind = omp_split_map_kind (mapper_kind, &m_force_p, &m_always_p, &m_present_p);
    4526          416 :   invoked_as = omp_split_map_kind (invoked_as, &force_p, &always_p, &present_p);
    4527          416 :   gomp_map_kind decay_to;
    4528              : 
    4529          416 :   switch (mapper_kind)
    4530              :     {
    4531           53 :     case GOMP_MAP_ALLOC:
    4532           53 :       if (exit_p && invoked_as == GOMP_MAP_FROM)
    4533              :         decay_to = GOMP_MAP_RELEASE;
    4534              :       else
    4535           77 :         decay_to = GOMP_MAP_ALLOC;
    4536              :       break;
    4537              : 
    4538          115 :     case GOMP_MAP_TO:
    4539          115 :       if (invoked_as == GOMP_MAP_FROM)
    4540          101 :         decay_to = exit_p ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
    4541           91 :       else if (invoked_as == GOMP_MAP_ALLOC)
    4542              :         decay_to = GOMP_MAP_ALLOC;
    4543              :       else
    4544          416 :         decay_to = GOMP_MAP_TO;
    4545              :       break;
    4546              : 
    4547           52 :     case GOMP_MAP_FROM:
    4548           52 :       if (invoked_as == GOMP_MAP_ALLOC || invoked_as == GOMP_MAP_TO)
    4549              :         decay_to = GOMP_MAP_ALLOC;
    4550              :       else
    4551          416 :         decay_to = GOMP_MAP_FROM;
    4552              :       break;
    4553              : 
    4554              :     case GOMP_MAP_TOFROM:
    4555              :     case GOMP_MAP_UNSET:
    4556              :       decay_to = invoked_as;
    4557              :       break;
    4558              : 
    4559            0 :     default:
    4560            0 :       gcc_unreachable ();
    4561              :     }
    4562              : 
    4563          416 :   return omp_join_map_kind (decay_to, m_force_p | force_p,
    4564          416 :                             m_always_p | always_p, m_present_p | present_p);
    4565              : }
    4566              : 
    4567              : /* Return a name to use for a "basic" map kind, e.g. as output from
    4568              :    omp_split_map_kind above.  */
    4569              : 
    4570              : static const char *
    4571           16 : omp_basic_map_kind_name (enum gomp_map_kind kind)
    4572              : {
    4573           16 :   switch (kind)
    4574              :     {
    4575              :     case GOMP_MAP_ALLOC:
    4576              :       return "alloc";
    4577            4 :     case GOMP_MAP_TO:
    4578            4 :       return "to";
    4579            4 :     case GOMP_MAP_FROM:
    4580            4 :       return "from";
    4581            0 :     case GOMP_MAP_TOFROM:
    4582            0 :       return "tofrom";
    4583            0 :     case GOMP_MAP_RELEASE:
    4584            0 :       return "release";
    4585            0 :     case GOMP_MAP_DELETE:
    4586            0 :       return "delete";
    4587            0 :     default:
    4588            0 :       gcc_unreachable ();
    4589              :     }
    4590              : }
    4591              : 
    4592              : /* Instantiate a mapper MAPPER for expression EXPR at location LOC,
    4593              :    adding new clauses to OUTLIST.  OUTER_KIND is the mapping kind
    4594              :    to use if not already specified in the mapper declaration; ORT
    4595              :    denotes the directive that uses the mapper.
    4596              :    The resulting OUTLIST is also returned by the function.  */
    4597              : 
    4598              : static tree *
    4599          142 : omp_instantiate_mapper (location_t loc, tree *outlist, tree mapper, tree expr,
    4600              :                         enum gomp_map_kind outer_kind,
    4601              :                         enum c_omp_region_type ort)
    4602              : {
    4603          142 :   tree clauses = OMP_DECLARE_MAPPER_CLAUSES (mapper);
    4604          142 :   tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper);
    4605          142 :   tree mapper_name = NULL_TREE;
    4606              : 
    4607          142 :   remap_mapper_decl_info map_info;
    4608          142 :   map_info.dummy_var = dummy_var;
    4609          142 :   map_info.expr = expr;
    4610              : 
    4611          574 :   for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
    4612              :     {
    4613          432 :       tree unshared = unshare_expr (c);
    4614          432 :       enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (c);
    4615          432 :       tree t = OMP_CLAUSE_DECL (unshared);
    4616          432 :       tree type = NULL_TREE;
    4617          432 :       bool nonunit_array_with_mapper = false;
    4618              : 
    4619          432 :       if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
    4620              :         {
    4621            0 :           mapper_name = t;
    4622            2 :           continue;
    4623              :         }
    4624          432 :       else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
    4625              :         {
    4626            0 :           mapper_name = NULL_TREE;
    4627            0 :           continue;
    4628              :         }
    4629              : 
    4630          432 :       if (TREE_CODE (t) == OMP_ARRAY_SECTION)
    4631              :         {
    4632           43 :           tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
    4633              : 
    4634           43 :           if (t2 == t)
    4635              :             {
    4636           42 :               nonunit_array_with_mapper = true;
    4637              :               /* We'd want use the mapper for the element type if this worked:
    4638              :                  look that one up.  */
    4639           42 :               type = TREE_TYPE (TREE_TYPE (t));
    4640              :             }
    4641              :           else
    4642              :             {
    4643            1 :               t = t2;
    4644            1 :               type = TREE_TYPE (t);
    4645              :             }
    4646              :         }
    4647              :       else
    4648          389 :         type = TREE_TYPE (t);
    4649              : 
    4650          432 :       gcc_assert (type);
    4651              : 
    4652          432 :       if (type == error_mark_node)
    4653            0 :         continue;
    4654              : 
    4655          432 :       walk_tree (&unshared, remap_mapper_decl_1, &map_info, NULL);
    4656              : 
    4657          432 :       OMP_CLAUSE_LOCATION (unshared) = loc;
    4658              : 
    4659          432 :       enum gomp_map_kind decayed_kind
    4660          432 :         = omp_map_decayed_kind (clause_kind, outer_kind,
    4661              :                                 (ort & C_ORT_EXIT_DATA) != 0
    4662          432 :                                 || (outer_kind == GOMP_MAP_FROM
    4663           32 :                                     && (ort & C_ORT_UPDATE) != 0));
    4664          432 :       OMP_CLAUSE_SET_MAP_KIND (unshared, decayed_kind);
    4665              : 
    4666          432 :       type = TYPE_MAIN_VARIANT (type);
    4667              : 
    4668          432 :       tree mapper_fn = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
    4669              : 
    4670          432 :       if (mapper_fn && nonunit_array_with_mapper)
    4671              :         {
    4672            0 :           sorry ("user-defined mapper with non-unit length array section");
    4673            0 :           continue;
    4674              :         }
    4675          432 :       else if (mapper_fn)
    4676              :         {
    4677           27 :           tree nested_mapper
    4678           27 :             = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
    4679           27 :           if (nested_mapper != mapper)
    4680              :             {
    4681            2 :               outlist = omp_instantiate_mapper (loc, outlist, nested_mapper,
    4682              :                                                 t, outer_kind, ort);
    4683            2 :               continue;
    4684              :             }
    4685              :         }
    4686          405 :       else if (mapper_name)
    4687              :         {
    4688            0 :           error ("mapper %qE not found for type %qT", mapper_name, type);
    4689            0 :           continue;
    4690              :         }
    4691              : 
    4692          430 :       if (ort & C_ORT_UPDATE)
    4693              :         {
    4694           98 :           bool force_p, always_p, present_p;
    4695           98 :           decayed_kind
    4696           98 :             = omp_split_map_kind (decayed_kind, &force_p, &always_p,
    4697              :                                   &present_p);
    4698              :           /* We don't expect to see these flags here.  */
    4699           98 :           gcc_assert (!force_p && !always_p);
    4700              :           /* For a "target update" operation, we want to turn the map node
    4701              :              expanded from the mapper back into a OMP_CLAUSE_TO or
    4702              :              OMP_CLAUSE_FROM node.  If we can do neither, emit a warning and
    4703              :              drop the clause.  */
    4704           98 :           switch (decayed_kind)
    4705              :             {
    4706           82 :             case GOMP_MAP_TO:
    4707           82 :             case GOMP_MAP_FROM:
    4708           82 :               {
    4709           82 :                 tree xfer
    4710          122 :                   = build_omp_clause (loc, (decayed_kind == GOMP_MAP_TO
    4711              :                                             ? OMP_CLAUSE_TO : OMP_CLAUSE_FROM));
    4712           82 :                 OMP_CLAUSE_DECL (xfer) = OMP_CLAUSE_DECL (unshared);
    4713           82 :                 OMP_CLAUSE_SIZE (xfer) = OMP_CLAUSE_SIZE (unshared);
    4714              :                 /* For FROM/TO clauses, "present" is represented by a flag.
    4715              :                    Set it for the expanded clause here.  */
    4716           82 :                 if (present_p)
    4717           32 :                   OMP_CLAUSE_MOTION_PRESENT (xfer) = 1;
    4718           82 :                 *outlist = xfer;
    4719           82 :                 outlist = &OMP_CLAUSE_CHAIN (xfer);
    4720              :               }
    4721           82 :               break;
    4722           16 :             default:
    4723           16 :               clause_kind
    4724           16 :                 = omp_split_map_kind (clause_kind, &force_p, &always_p,
    4725              :                                       &present_p);
    4726           16 :               warning_at (loc, OPT_Wopenmp,
    4727              :                           "dropping %qs clause during mapper expansion "
    4728              :                           "in %<#pragma omp target update%>",
    4729              :                           omp_basic_map_kind_name (clause_kind));
    4730           16 :               inform (OMP_CLAUSE_LOCATION (c), "for map clause here");
    4731              :             }
    4732              :         }
    4733              :       else
    4734              :         {
    4735          332 :           *outlist = unshared;
    4736          332 :           outlist = &OMP_CLAUSE_CHAIN (unshared);
    4737              :         }
    4738              :     }
    4739              : 
    4740          142 :   return outlist;
    4741              : }
    4742              : 
    4743              : /* Given a list of CLAUSES, scan each clause and invoke a user-defined mapper
    4744              :    appropriate to the type of the data in that clause, if such a mapper is
    4745              :    visible in the current parsing context.  */
    4746              : 
    4747              : tree
    4748        16513 : c_omp_instantiate_mappers (tree clauses, enum c_omp_region_type ort)
    4749              : {
    4750        16513 :   tree c, *pc, mapper_name = NULL_TREE;
    4751              : 
    4752        35965 :   for (pc = &clauses, c = clauses; c; c = *pc)
    4753              :     {
    4754        19452 :       bool using_mapper = false;
    4755        19452 :       bool update_p = false, update_present_p = false;
    4756              : 
    4757        19452 :       switch (OMP_CLAUSE_CODE (c))
    4758              :         {
    4759         5987 :         case OMP_CLAUSE_TO:
    4760         5987 :         case OMP_CLAUSE_FROM:
    4761         5987 :           update_p = true;
    4762         5987 :           if (OMP_CLAUSE_MOTION_PRESENT (c))
    4763           58 :             update_present_p = true;
    4764              :           /* Fallthrough.  */
    4765        13128 :         case OMP_CLAUSE_MAP:
    4766        13128 :           {
    4767        13128 :             tree t = OMP_CLAUSE_DECL (c);
    4768        13128 :             tree type = NULL_TREE;
    4769        13128 :             bool nonunit_array_with_mapper = false;
    4770              : 
    4771        13202 :             if (!update_p
    4772        13128 :                 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME
    4773         7104 :                     || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POP_MAPPER_NAME))
    4774              :               {
    4775           74 :                 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME)
    4776           37 :                   mapper_name = OMP_CLAUSE_DECL (c);
    4777              :                 else
    4778              :                   mapper_name = NULL_TREE;
    4779           74 :                 pc = &OMP_CLAUSE_CHAIN (c);
    4780           74 :                 continue;
    4781              :               }
    4782              : 
    4783        13054 :             if (TREE_CODE (t) == OMP_ARRAY_SECTION)
    4784              :               {
    4785         2376 :                 location_t loc = OMP_CLAUSE_LOCATION (c);
    4786         2376 :                 tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
    4787              : 
    4788         2376 :                 if (t2 == t)
    4789              :                   {
    4790              :                     /* !!! Array sections of size >1 with mappers for elements
    4791              :                        are hard to support.  Do something here.  */
    4792         1999 :                     nonunit_array_with_mapper = true;
    4793         1999 :                     type = TREE_TYPE (TREE_TYPE (t));
    4794              :                   }
    4795              :                 else
    4796              :                   {
    4797          377 :                     t = t2;
    4798          377 :                     type = TREE_TYPE (t);
    4799              :                   }
    4800              :               }
    4801              :             else
    4802        10678 :               type = TREE_TYPE (t);
    4803              : 
    4804        13054 :             if (type == NULL_TREE || type == error_mark_node)
    4805              :               {
    4806           58 :                 pc = &OMP_CLAUSE_CHAIN (c);
    4807           58 :                 continue;
    4808              :               }
    4809              : 
    4810        12996 :             enum gomp_map_kind kind;
    4811        12996 :             if (update_p)
    4812              :               {
    4813         5987 :                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO)
    4814          983 :                   kind = update_present_p ? GOMP_MAP_PRESENT_TO
    4815              :                                           : GOMP_MAP_TO;
    4816              :                 else
    4817         5004 :                   kind = update_present_p ? GOMP_MAP_PRESENT_FROM
    4818              :                                           : GOMP_MAP_FROM;
    4819              :               }
    4820              :             else
    4821              :               {
    4822         7009 :                 kind = OMP_CLAUSE_MAP_KIND (c);
    4823         7009 :                 if (kind == GOMP_MAP_UNSET)
    4824            0 :                   kind = GOMP_MAP_TOFROM;
    4825              :               }
    4826              : 
    4827        12996 :             type = TYPE_MAIN_VARIANT (type);
    4828              : 
    4829        12996 :             tree mapper_fn
    4830        12996 :               = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
    4831              : 
    4832        12996 :             if (mapper_fn && nonunit_array_with_mapper)
    4833              :               {
    4834            0 :                 sorry ("user-defined mapper with non-unit length "
    4835              :                        "array section");
    4836            0 :                 using_mapper = true;
    4837              :               }
    4838        12996 :             else if (mapper_fn)
    4839              :               {
    4840          140 :                 tree mapper
    4841          140 :                   = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
    4842          140 :                 pc = omp_instantiate_mapper (OMP_CLAUSE_LOCATION (c),
    4843              :                                              pc, mapper, t, kind, ort);
    4844          140 :                 using_mapper = true;
    4845              :               }
    4846        12856 :             else if (mapper_name)
    4847              :               {
    4848            0 :                 error ("mapper %qE not found for type %qT", mapper_name, type);
    4849            0 :                 using_mapper = true;
    4850              :               }
    4851              :           }
    4852              :           break;
    4853              : 
    4854          140 :         default:
    4855          140 :           ;
    4856              :         }
    4857              : 
    4858          140 :       if (using_mapper)
    4859          140 :         *pc = OMP_CLAUSE_CHAIN (c);
    4860              :       else
    4861        19180 :         pc = &OMP_CLAUSE_CHAIN (c);
    4862              :     }
    4863              : 
    4864        16513 :   return clauses;
    4865              : }
    4866              : 
    4867              : const struct c_omp_directive c_omp_directives[] = {
    4868              :   /* Keep this alphabetically sorted by the first word.  Non-null second/third
    4869              :      if any should precede null ones.  */
    4870              :   { "allocate", nullptr, nullptr, PRAGMA_OMP_ALLOCATE,
    4871              :     C_OMP_DIR_DECLARATIVE, false },
    4872              :   { "assume", nullptr, nullptr, PRAGMA_OMP_ASSUME,
    4873              :     C_OMP_DIR_INFORMATIONAL, false },
    4874              :   { "assumes", nullptr, nullptr, PRAGMA_OMP_ASSUMES,
    4875              :     C_OMP_DIR_INFORMATIONAL, false },
    4876              :   { "atomic", nullptr, nullptr, PRAGMA_OMP_ATOMIC,
    4877              :     C_OMP_DIR_CONSTRUCT, false },
    4878              :   { "barrier", nullptr, nullptr, PRAGMA_OMP_BARRIER,
    4879              :     C_OMP_DIR_STANDALONE, false },
    4880              :   { "begin", "assumes", nullptr, PRAGMA_OMP_BEGIN,
    4881              :     C_OMP_DIR_INFORMATIONAL, false },
    4882              :   { "begin", "declare", "target", PRAGMA_OMP_BEGIN,
    4883              :     C_OMP_DIR_DECLARATIVE, false },
    4884              :   { "begin", "declare", "variant", PRAGMA_OMP_BEGIN,
    4885              :     C_OMP_DIR_DECLARATIVE, false },
    4886              :   /* 'begin metadirective' is not yet implemented; however,
    4887              :      it is only applicable if an end-directive exists, but
    4888              :      metadirectives are of limited use for declarative directives.  */
    4889              :   /* { "begin", "metadirective", nullptr, PRAGMA_OMP_BEGIN,
    4890              :     C_OMP_DIR_META, false },  */
    4891              :   { "cancel", nullptr, nullptr, PRAGMA_OMP_CANCEL,
    4892              :     C_OMP_DIR_STANDALONE, false },
    4893              :   { "cancellation", "point", nullptr, PRAGMA_OMP_CANCELLATION_POINT,
    4894              :     C_OMP_DIR_STANDALONE, false },
    4895              :   { "critical", nullptr, nullptr, PRAGMA_OMP_CRITICAL,
    4896              :     C_OMP_DIR_CONSTRUCT, false },
    4897              :   /* { "declare", "induction", nullptr, PRAGMA_OMP_DECLARE,
    4898              :     C_OMP_DIR_DECLARATIVE, true }, */
    4899              :   { "declare", "mapper", nullptr, PRAGMA_OMP_DECLARE,
    4900              :     C_OMP_DIR_DECLARATIVE, false },
    4901              :   { "declare", "reduction", nullptr, PRAGMA_OMP_DECLARE,
    4902              :     C_OMP_DIR_DECLARATIVE, true },
    4903              :   { "declare", "simd", nullptr, PRAGMA_OMP_DECLARE,
    4904              :     C_OMP_DIR_DECLARATIVE, true },
    4905              :   { "declare", "target", nullptr, PRAGMA_OMP_DECLARE,
    4906              :     C_OMP_DIR_DECLARATIVE, false },
    4907              :   { "declare", "variant", nullptr, PRAGMA_OMP_DECLARE,
    4908              :     C_OMP_DIR_DECLARATIVE, false },
    4909              :   { "depobj", nullptr, nullptr, PRAGMA_OMP_DEPOBJ,
    4910              :     C_OMP_DIR_STANDALONE, false },
    4911              :   { "dispatch", nullptr, nullptr, PRAGMA_OMP_DISPATCH,
    4912              :     C_OMP_DIR_DECLARATIVE, false },
    4913              :   { "distribute", nullptr, nullptr, PRAGMA_OMP_DISTRIBUTE,
    4914              :     C_OMP_DIR_CONSTRUCT, true },
    4915              :   { "end", "assumes", nullptr, PRAGMA_OMP_END,
    4916              :     C_OMP_DIR_INFORMATIONAL, false },
    4917              :   { "end", "declare", "target", PRAGMA_OMP_END,
    4918              :     C_OMP_DIR_DECLARATIVE, false },
    4919              :   { "end", "declare", "variant", PRAGMA_OMP_END,
    4920              :     C_OMP_DIR_DECLARATIVE, false },
    4921              :   /* { "end", "metadirective", nullptr, PRAGMA_OMP_END,
    4922              :     C_OMP_DIR_META, false },  */
    4923              :   /* error with at(execution) is C_OMP_DIR_STANDALONE.  */
    4924              :   { "error", nullptr, nullptr, PRAGMA_OMP_ERROR,
    4925              :     C_OMP_DIR_UTILITY, false },
    4926              :   /* { "flatten", nullptr, nullptr, PRAGMA_OMP_FLATTEN,
    4927              :     C_OMP_DIR_CONSTRUCT, true },  */
    4928              :   { "flush", nullptr, nullptr, PRAGMA_OMP_FLUSH,
    4929              :     C_OMP_DIR_STANDALONE, false },
    4930              :   { "for", nullptr, nullptr, PRAGMA_OMP_FOR,
    4931              :     C_OMP_DIR_CONSTRUCT, true },
    4932              :   /* { "fuse", nullptr, nullptr, PRAGMA_OMP_FUSE,
    4933              :     C_OMP_DIR_CONSTRUCT, true },  */
    4934              :   { "groupprivate", nullptr, nullptr, PRAGMA_OMP_GROUPPRIVATE,
    4935              :     C_OMP_DIR_DECLARATIVE, false },
    4936              :   /* { "interchange", nullptr, nullptr, PRAGMA_OMP_INTERCHANGE,
    4937              :     C_OMP_DIR_CONSTRUCT, true },  */
    4938              :   { "interop", nullptr, nullptr, PRAGMA_OMP_INTEROP,
    4939              :     C_OMP_DIR_STANDALONE, false },
    4940              :   { "loop", nullptr, nullptr, PRAGMA_OMP_LOOP,
    4941              :     C_OMP_DIR_CONSTRUCT, true },
    4942              :   { "masked", nullptr, nullptr, PRAGMA_OMP_MASKED,
    4943              :     C_OMP_DIR_CONSTRUCT, true },
    4944              :   { "master", nullptr, nullptr, PRAGMA_OMP_MASTER,
    4945              :     C_OMP_DIR_CONSTRUCT, true },
    4946              :   { "metadirective", nullptr, nullptr, PRAGMA_OMP_METADIRECTIVE,
    4947              :     C_OMP_DIR_META, false },
    4948              :   { "nothing", nullptr, nullptr, PRAGMA_OMP_NOTHING,
    4949              :     C_OMP_DIR_UTILITY, false },
    4950              :   /* ordered with depend clause is C_OMP_DIR_STANDALONE.  */
    4951              :   { "ordered", nullptr, nullptr, PRAGMA_OMP_ORDERED,
    4952              :     C_OMP_DIR_CONSTRUCT, true },
    4953              :   { "parallel", nullptr, nullptr, PRAGMA_OMP_PARALLEL,
    4954              :     C_OMP_DIR_CONSTRUCT, true },
    4955              :   { "requires", nullptr, nullptr, PRAGMA_OMP_REQUIRES,
    4956              :     C_OMP_DIR_INFORMATIONAL, false },
    4957              :   { "scan", nullptr, nullptr, PRAGMA_OMP_SCAN,
    4958              :     C_OMP_DIR_CONSTRUCT, true },
    4959              :   { "scope", nullptr, nullptr, PRAGMA_OMP_SCOPE,
    4960              :     C_OMP_DIR_CONSTRUCT, false },
    4961              :   { "section", nullptr, nullptr, PRAGMA_OMP_SECTION,
    4962              :     C_OMP_DIR_CONSTRUCT, false },
    4963              :   { "sections", nullptr, nullptr, PRAGMA_OMP_SECTIONS,
    4964              :     C_OMP_DIR_CONSTRUCT, false },
    4965              :   { "simd", nullptr, nullptr, PRAGMA_OMP_SIMD,
    4966              :     C_OMP_DIR_CONSTRUCT, true },
    4967              :   { "single", nullptr, nullptr, PRAGMA_OMP_SINGLE,
    4968              :     C_OMP_DIR_CONSTRUCT, false },
    4969              :   /* { "split", nullptr, nullptr, PRAGMA_OMP_SPLIT,
    4970              :     C_OMP_DIR_CONSTRUCT, true },  */
    4971              :   /* { "stripe", nullptr, nullptr, PRAGMA_OMP_STRIPE,
    4972              :     C_OMP_DIR_CONSTRUCT, true },  */
    4973              :   { "target", "data", nullptr, PRAGMA_OMP_TARGET,
    4974              :     C_OMP_DIR_CONSTRUCT, false },
    4975              :   { "target", "enter", "data", PRAGMA_OMP_TARGET,
    4976              :     C_OMP_DIR_STANDALONE, false },
    4977              :   { "target", "exit", "data", PRAGMA_OMP_TARGET,
    4978              :     C_OMP_DIR_STANDALONE, false },
    4979              :   { "target", "update", nullptr, PRAGMA_OMP_TARGET,
    4980              :     C_OMP_DIR_STANDALONE, false },
    4981              :   { "target", nullptr, nullptr, PRAGMA_OMP_TARGET,
    4982              :     C_OMP_DIR_CONSTRUCT, true },
    4983              :   { "task", nullptr, nullptr, PRAGMA_OMP_TASK,
    4984              :     C_OMP_DIR_CONSTRUCT, false },
    4985              :   /* { "task", "iteration", nullptr, PRAGMA_OMP_TASK_ITERATION,
    4986              :     C_OMP_DIR_STANDALONE, false },  */
    4987              :   /* { "taskgraph", nullptr, nullptr, PRAGMA_OMP_TASKGRAPH,
    4988              :     C_OMP_DIR_CONSTRUCT, false },  */
    4989              :   { "taskgroup", nullptr, nullptr, PRAGMA_OMP_TASKGROUP,
    4990              :     C_OMP_DIR_CONSTRUCT, false },
    4991              :   { "taskloop", nullptr, nullptr, PRAGMA_OMP_TASKLOOP,
    4992              :     C_OMP_DIR_CONSTRUCT, true },
    4993              :   { "taskwait", nullptr, nullptr, PRAGMA_OMP_TASKWAIT,
    4994              :     C_OMP_DIR_STANDALONE, false },
    4995              :   { "taskyield", nullptr, nullptr, PRAGMA_OMP_TASKYIELD,
    4996              :     C_OMP_DIR_STANDALONE, false },
    4997              :   { "tile", nullptr, nullptr, PRAGMA_OMP_TILE,
    4998              :     C_OMP_DIR_CONSTRUCT, false },
    4999              :   { "teams", nullptr, nullptr, PRAGMA_OMP_TEAMS,
    5000              :     C_OMP_DIR_CONSTRUCT, true },
    5001              :   { "threadprivate", nullptr, nullptr, PRAGMA_OMP_THREADPRIVATE,
    5002              :     C_OMP_DIR_DECLARATIVE, false },
    5003              :   { "unroll", nullptr, nullptr, PRAGMA_OMP_UNROLL,
    5004              :     C_OMP_DIR_CONSTRUCT, false },
    5005              : };
    5006              : 
    5007              : /* Find (non-combined/composite) OpenMP directive (if any) which starts
    5008              :    with FIRST keyword and for multi-word directives has SECOND and
    5009              :    THIRD keyword after it.  */
    5010              : 
    5011              : const struct c_omp_directive *
    5012         6628 : c_omp_categorize_directive (const char *first, const char *second,
    5013              :                             const char *third)
    5014              : {
    5015         6628 :   const size_t n_omp_directives = ARRAY_SIZE (c_omp_directives);
    5016       211255 :   for (size_t i = 0; i < n_omp_directives; i++)
    5017              :     {
    5018       395586 :       if ((unsigned char) c_omp_directives[i].first[0]
    5019       211255 :           < (unsigned char) first[0])
    5020       184331 :         continue;
    5021        26924 :       if ((unsigned char) c_omp_directives[i].first[0]
    5022              :           > (unsigned char) first[0])
    5023              :         break;
    5024        26837 :       if (strcmp (c_omp_directives[i].first, first))
    5025        16103 :         continue;
    5026        10734 :       if (!c_omp_directives[i].second)
    5027         5138 :         return &c_omp_directives[i];
    5028         5596 :       if (!second || strcmp (c_omp_directives[i].second, second))
    5029         4157 :         continue;
    5030         1439 :       if (!c_omp_directives[i].third)
    5031         1103 :         return &c_omp_directives[i];
    5032          336 :       if (!third || strcmp (c_omp_directives[i].third, third))
    5033           36 :         continue;
    5034          300 :       return &c_omp_directives[i];
    5035              :     }
    5036              :   return NULL;
    5037              : }
    5038              : 
    5039              : /* Auxiliary helper function for c_omp_expand_variant_construct.  */
    5040              : 
    5041              : static tree
    5042          388 : c_omp_expand_variant_construct_r (vec<struct omp_variant> &candidates,
    5043              :                               hash_map<tree, tree> &body_labels,
    5044              :                               unsigned index)
    5045              : {
    5046          388 :   struct omp_variant &candidate = candidates[index];
    5047          388 :   tree if_block = push_stmt_list ();
    5048          388 :   if (candidate.alternative != NULL_TREE)
    5049          388 :     add_stmt (candidate.alternative);
    5050          388 :   if (candidate.body != NULL_TREE)
    5051              :     {
    5052          118 :       tree *label = body_labels.get (candidate.body);
    5053          118 :       if (label != NULL)
    5054            0 :         add_stmt (build1 (GOTO_EXPR, void_type_node, *label));
    5055              :       else
    5056              :         {
    5057          118 :           tree body_label = create_artificial_label (UNKNOWN_LOCATION);
    5058          118 :           add_stmt (build1 (LABEL_EXPR, void_type_node, body_label));
    5059          118 :           add_stmt (candidate.body);
    5060          118 :           body_labels.put (candidate.body, body_label);
    5061              :         }
    5062              :     }
    5063          388 :   if_block = pop_stmt_list (if_block);
    5064              : 
    5065          776 :   if (index == candidates.length () - 1)
    5066              :     return if_block;
    5067              : 
    5068          154 :   tree cond = omp_dynamic_cond (candidate.selector, NULL_TREE);
    5069          154 :   gcc_assert (cond != NULL_TREE);
    5070              : 
    5071          154 :   tree else_block = c_omp_expand_variant_construct_r (candidates, body_labels,
    5072              :                                                       index + 1);
    5073          154 :   tree ret = push_stmt_list ();
    5074          154 :   tree stmt = build3 (COND_EXPR, void_type_node, cond, if_block, else_block);
    5075          154 :   add_stmt (stmt);
    5076          154 :   ret = pop_stmt_list (ret);
    5077              : 
    5078          154 :   return ret;
    5079              : }
    5080              : 
    5081              : /* Resolve the vector of metadirective variant CANDIDATES to a parse tree
    5082              :    structure.  */
    5083              : 
    5084              : tree
    5085          234 : c_omp_expand_variant_construct (vec<struct omp_variant> &candidates)
    5086              : {
    5087          234 :   hash_map<tree, tree> body_labels;
    5088          234 :   return c_omp_expand_variant_construct_r (candidates, body_labels, 0);
    5089          234 : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.