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 % 2594 2403
Test Date: 2026-10-17 16:30:31 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           21 :           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            7 :           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          250 :   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        32116 : c_omp_for_incr_canonicalize_ptr (location_t loc, tree decl, tree incr)
     940              : {
     941        62225 :   if (POINTER_TYPE_P (TREE_TYPE (decl))
     942        32116 :       && 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        32116 :   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        32058 : 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        32058 :   location_t elocus;
     973        32058 :   bool fail = false;
     974        32058 :   int i;
     975              : 
     976        32058 :   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
     977        32058 :   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
     978        32058 :   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
     979        74139 :   for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
     980              :     {
     981        43459 :       tree decl = TREE_VEC_ELT (declv, i);
     982        43459 :       tree init = TREE_VEC_ELT (initv, i);
     983        43459 :       tree cond = TREE_VEC_ELT (condv, i);
     984        43459 :       tree incr = TREE_VEC_ELT (incrv, i);
     985              : 
     986        43459 :       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        42081 :       elocus = locus;
    1000        42081 :       if (EXPR_HAS_LOCATION (init))
    1001        37373 :         elocus = EXPR_LOCATION (init);
    1002              : 
    1003              :       /* Validate the iteration variable.  */
    1004        84162 :       if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
    1005        44955 :           && 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        42080 :       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        42065 :       if (init == decl)
    1022              :         {
    1023         4692 :           elocus = DECL_SOURCE_LOCATION (decl);
    1024              : 
    1025         4692 :           init = DECL_INITIAL (decl);
    1026         4692 :           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         4692 :           DECL_INITIAL (decl) = NULL_TREE;
    1033              : 
    1034         4692 :           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        42065 :       if (init != error_mark_node)
    1042              :         {
    1043        42065 :           gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
    1044        42065 :           gcc_assert (TREE_OPERAND (init, 0) == decl);
    1045              :         }
    1046              : 
    1047        42065 :       if (cond == NULL_TREE)
    1048              :         {
    1049            2 :           error_at (elocus, "missing controlling predicate");
    1050            2 :           fail = true;
    1051              :         }
    1052              :       else
    1053              :         {
    1054        42063 :           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        42063 :           while (TREE_CODE (cond) == COMPOUND_EXPR)
    1060            0 :             cond = TREE_OPERAND (cond, 1);
    1061              : 
    1062        42063 :           if (EXPR_HAS_LOCATION (cond))
    1063        41935 :             elocus = EXPR_LOCATION (cond);
    1064              : 
    1065        42063 :           if (TREE_CODE (cond) == LT_EXPR
    1066              :               || TREE_CODE (cond) == LE_EXPR
    1067              :               || TREE_CODE (cond) == GT_EXPR
    1068        42063 :               || TREE_CODE (cond) == GE_EXPR
    1069         5587 :               || TREE_CODE (cond) == NE_EXPR
    1070           31 :               || TREE_CODE (cond) == EQ_EXPR)
    1071              :             {
    1072        42032 :               tree op0 = TREE_OPERAND (cond, 0);
    1073        42032 :               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        42032 :               if (TREE_CODE (op0) == NOP_EXPR
    1088        42032 :                   && 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        41974 :               else if (TREE_CODE (op1) == NOP_EXPR
    1096        41974 :                        && 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        42032 :               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        42032 :               if (TREE_CODE (cond) == NE_EXPR
    1116        42032 :                   || 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        42032 :               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        42032 :           if (!cond_ok)
    1154              :             {
    1155           32 :               error_at (elocus, "invalid controlling predicate");
    1156           32 :               fail = true;
    1157              :             }
    1158              :         }
    1159              : 
    1160        42065 :       if (incr == NULL_TREE)
    1161              :         {
    1162            0 :           error_at (elocus, "missing increment expression");
    1163            0 :           fail = true;
    1164              :         }
    1165              :       else
    1166              :         {
    1167        42065 :           bool incr_ok = false;
    1168              : 
    1169        42065 :           if (EXPR_HAS_LOCATION (incr))
    1170        41163 :             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        42065 :           switch (TREE_CODE (incr))
    1175              :             {
    1176        32122 :             case POSTINCREMENT_EXPR:
    1177        32122 :             case PREINCREMENT_EXPR:
    1178        32122 :             case POSTDECREMENT_EXPR:
    1179        32122 :             case PREDECREMENT_EXPR:
    1180        32122 :               if (TREE_OPERAND (incr, 0) != decl)
    1181              :                 break;
    1182              : 
    1183        32116 :               incr_ok = true;
    1184        32116 :               if (!fail
    1185        32091 :                   && 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        32935 :                   && (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        32116 :               incr = c_omp_for_incr_canonicalize_ptr (elocus, decl, incr);
    1200        32116 :               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        42043 :           if (!incr_ok)
    1293              :             {
    1294           34 :               error_at (elocus, "invalid increment expression");
    1295           34 :               fail = true;
    1296              :             }
    1297              :         }
    1298              : 
    1299        42065 :       TREE_VEC_ELT (initv, i) = init;
    1300        42065 :       TREE_VEC_ELT (incrv, i) = incr;
    1301              :     }
    1302              : 
    1303        32058 :   if (fail)
    1304              :     return NULL;
    1305              :   else
    1306              :     {
    1307        31773 :       tree t = make_node (code);
    1308              : 
    1309        31773 :       TREE_TYPE (t) = void_type_node;
    1310        31773 :       OMP_FOR_INIT (t) = initv;
    1311        31773 :       OMP_FOR_COND (t) = condv;
    1312        31773 :       OMP_FOR_INCR (t) = incrv;
    1313        31773 :       OMP_FOR_BODY (t) = body;
    1314        31773 :       OMP_FOR_PRE_BODY (t) = pre_body;
    1315        31773 :       OMP_FOR_ORIG_DECLS (t) = orig_declv;
    1316              : 
    1317        31773 :       SET_EXPR_LOCATION (t, locus);
    1318        31773 :       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        42198 : c_omp_is_loop_iterator (tree decl, struct c_omp_check_loop_iv_data *d)
    1344              : {
    1345       133533 :   for (int i = 0; i < TREE_VEC_LENGTH (d->declv); i++)
    1346       105871 :     if (TREE_VEC_ELT (d->declv, i) == NULL_TREE)
    1347          253 :       continue;
    1348       105618 :     else if (decl == TREE_VEC_ELT (d->declv, i)
    1349       105618 :              || (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        91163 :     else if (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
    1353         2223 :              && TREE_CHAIN (TREE_VEC_ELT (d->declv, i))
    1354        92202 :              && (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       170259 : c_omp_check_loop_iv_r (tree *tp, int *walk_subtrees, void *data)
    1369              : {
    1370       170259 :   struct c_omp_check_loop_iv_data *d
    1371              :     = (struct c_omp_check_loop_iv_data *) data;
    1372       170259 :   if (DECL_P (*tp))
    1373              :     {
    1374        28699 :       int idx = c_omp_is_loop_iterator (*tp, d);
    1375        28699 :       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       141560 :   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       124390 :   else if (d->ppset->add (*tp))
    1423        17893 :     *walk_subtrees = 0;
    1424              :   /* Don't walk dtors added by C++ wrap_cleanups_r.  */
    1425       106497 :   else if (TREE_CODE (*tp) == TRY_CATCH_EXPR
    1426       106497 :            && 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         2498 :     case OMP_TILE:
    1670         2498 :       int k;
    1671         2498 :       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        31773 : c_omp_check_loop_iv (tree stmt, tree declv, walk_tree_lh lh)
    1696              : {
    1697        31773 :   hash_set<tree> pset;
    1698        31773 :   struct c_omp_check_loop_iv_data data;
    1699        31773 :   int i, k = 0;
    1700              : 
    1701        31773 :   data.declv = declv;
    1702        31773 :   data.fail = false;
    1703        31773 :   data.maybe_nonrect = false;
    1704        31773 :   data.stmt_loc = EXPR_LOCATION (stmt);
    1705        31773 :   data.lh = lh;
    1706        31773 :   data.ppset = &pset;
    1707        75214 :   for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
    1708              :     {
    1709        43441 :       tree this_stmt = stmt;
    1710        43441 :       int j = i;
    1711        43441 :       tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
    1712        43441 :       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        43441 :       gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
    1722        43441 :       tree decl = TREE_OPERAND (init, 0);
    1723        43441 :       tree cond = TREE_VEC_ELT (OMP_FOR_COND (this_stmt), j);
    1724        43441 :       gcc_assert (COMPARISON_CLASS_P (cond));
    1725        43441 :       gcc_assert (TREE_OPERAND (cond, 0) == decl);
    1726        43441 :       tree incr = TREE_VEC_ELT (OMP_FOR_INCR (this_stmt), j);
    1727        43441 :       data.expr_loc = EXPR_LOCATION (TREE_OPERAND (init, 1));
    1728        43441 :       tree vec_outer1 = NULL_TREE, vec_outer2 = NULL_TREE;
    1729        43441 :       int kind = 0;
    1730        43441 :       if (i > 0
    1731        43441 :           && (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        43441 :       if (TREE_CODE (stmt) != OACC_LOOP && i > 0)
    1742        43441 :         kind = 4;
    1743        43441 :       data.kind = kind;
    1744        43441 :       data.idx = i;
    1745        43441 :       walk_tree_1 (&TREE_OPERAND (init, 1),
    1746              :                    c_omp_check_loop_iv_r, &data, NULL, lh);
    1747        43441 :       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        43441 :       if (decl == TREE_VEC_ELT (data.declv, i)
    1755        43441 :           || (TREE_CODE (TREE_VEC_ELT (data.declv, i)) == TREE_LIST
    1756          933 :               && decl == TREE_PURPOSE (TREE_VEC_ELT (data.declv, i))))
    1757              :         {
    1758        42508 :           data.expr_loc = EXPR_LOCATION (cond);
    1759        42508 :           data.kind = kind | 1;
    1760        42508 :           walk_tree_1 (&TREE_OPERAND (cond, 1),
    1761              :                        c_omp_check_loop_iv_r, &data, NULL, lh);
    1762        42508 :           if (data.maybe_nonrect)
    1763          387 :             vec_outer2 = c_omp_check_nonrect_loop_iv (&TREE_OPERAND (cond, 1),
    1764              :                                                       &data, lh);
    1765              :         }
    1766        43441 :       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        43433 :       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        43441 :       if (vec_outer1 || vec_outer2)
    1785          474 :         OMP_FOR_NON_RECTANGULAR (stmt) = 1;
    1786        43441 :       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        31773 :   return !data.fail;
    1807        31773 : }
    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           21 :         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              :       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        15861 : c_omp_split_clauses (location_t loc, enum tree_code code,
    2145              :                      omp_clause_mask mask, tree clauses, tree *cclauses)
    2146              : {
    2147        15861 :   tree next, c;
    2148        15861 :   enum c_omp_clause_split s;
    2149        15861 :   int i;
    2150        15861 :   bool has_dup_allocate = false;
    2151              : 
    2152       111027 :   for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
    2153        95166 :     cclauses[i] = NULL;
    2154              :   /* Add implicit nowait clause on
    2155              :      #pragma omp parallel {for,for simd,sections}.  */
    2156        15861 :   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
    2157        10957 :     switch (code)
    2158              :       {
    2159        10293 :       case OMP_FOR:
    2160        10293 :       case OMP_SIMD:
    2161        25972 :         if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
    2162        10111 :           cclauses[C_OMP_CLAUSE_SPLIT_FOR]
    2163        10111 :             = 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        55856 :   for (; clauses ; clauses = next)
    2174              :     {
    2175        39995 :       next = OMP_CLAUSE_CHAIN (clauses);
    2176              : 
    2177        39995 :       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         2456 :           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         7742 :           s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2207              :           break;
    2208              :         case OMP_CLAUSE_ORDERED:
    2209        13156 :           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        13156 :           s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
    2230              :           break;
    2231              :         case OMP_CLAUSE_BIND:
    2232        13156 :           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        13842 :                    != 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         1305 :         case OMP_CLAUSE_PRIVATE:
    2291         1305 :           switch (code)
    2292              :             {
    2293              :             case OMP_SIMD: s = C_OMP_CLAUSE_SPLIT_SIMD; break;
    2294              :             case OMP_FOR: case OMP_SECTIONS:
    2295         7742 :             case OMP_PARALLEL: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
    2296         6933 :             case OMP_DISTRIBUTE: s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break;
    2297         2456 :             case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break;
    2298         7742 :             case OMP_MASTER: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
    2299         7742 :             case OMP_MASKED: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
    2300        13156 :             case OMP_TASKLOOP: s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break;
    2301        13156 :             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         1745 :         case OMP_CLAUSE_FIRSTPRIVATE:
    2309         1745 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
    2310         2105 :               != 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         1717 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
    2340         1717 :               != 0)
    2341              :             {
    2342         1105 :               if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)
    2343         1105 :                            | (OMP_CLAUSE_MASK_1
    2344         1105 :                               << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE))) != 0)
    2345              :                 {
    2346          465 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2347              :                                         OMP_CLAUSE_FIRSTPRIVATE);
    2348          465 :                   OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2349          465 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
    2350          465 :                   cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
    2351          465 :                   if ((mask & (OMP_CLAUSE_MASK_1
    2352          465 :                                << 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         7742 :                 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        20898 :                   != 0)
    2430              :                 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2431              :               else
    2432        13156 :                 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        13512 :                   != 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         9037 :               != 0)
    2498              :             {
    2499         1295 :               if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
    2500         3064 :                   == 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         2919 :         case OMP_CLAUSE_REDUCTION:
    2564         2919 :           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         2919 :           if (OMP_CLAUSE_REDUCTION_INSCAN (clauses)
    2587         2919 :               && ((mask & ((OMP_CLAUSE_MASK_1
    2588          204 :                             << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
    2589          204 :                            | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)))
    2590         2931 :                   != 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         2919 :           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         2919 :           if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
    2609              :             {
    2610         1758 :               if (code == OMP_SIMD)
    2611              :                 {
    2612          569 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2613              :                                         OMP_CLAUSE_REDUCTION);
    2614          569 :                   OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2615         1138 :                   OMP_CLAUSE_REDUCTION_CODE (c)
    2616          569 :                     = OMP_CLAUSE_REDUCTION_CODE (clauses);
    2617          569 :                   OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
    2618          569 :                     = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
    2619          569 :                   OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
    2620          569 :                     = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
    2621         1138 :                   OMP_CLAUSE_REDUCTION_INSCAN (c)
    2622          569 :                     = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
    2623          569 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
    2624          569 :                   cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
    2625              :                 }
    2626         1758 :               if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
    2627         1758 :                   != 0)
    2628              :                 {
    2629          459 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2630              :                                         OMP_CLAUSE_REDUCTION);
    2631          459 :                   OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
    2632          918 :                   OMP_CLAUSE_REDUCTION_CODE (c)
    2633          459 :                     = OMP_CLAUSE_REDUCTION_CODE (clauses);
    2634          459 :                   OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
    2635          459 :                     = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
    2636          459 :                   OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
    2637          459 :                     = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
    2638          918 :                   OMP_CLAUSE_REDUCTION_INSCAN (c)
    2639          459 :                     = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
    2640          459 :                   OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
    2641          459 :                   cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
    2642          459 :                   s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2643              :                 }
    2644         1299 :               else if ((mask & (OMP_CLAUSE_MASK_1
    2645         1299 :                                 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0
    2646         1210 :                        && !OMP_CLAUSE_REDUCTION_INSCAN (clauses))
    2647              :                 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
    2648              :               else
    2649        13156 :                 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        13164 :                       != 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        40003 :                       != 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         7762 :                            << 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        13156 :             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        53151 :               != 0)
    2857              :             s = C_OMP_CLAUSE_SPLIT_TARGET;
    2858              :           else
    2859        13156 :             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         2456 :               != 0)
    2866              :             {
    2867          232 :               if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
    2868        40225 :                   != 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         8099 :           for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
    2890              :             {
    2891         6942 :               switch (i)
    2892              :                 {
    2893         1157 :                 case C_OMP_CLAUSE_SPLIT_TARGET:
    2894         2050 :                   if ((mask & (OMP_CLAUSE_MASK_1
    2895         1157 :                                << PRAGMA_OMP_CLAUSE_MAP)) == 0)
    2896          893 :                     continue;
    2897              :                   break;
    2898         1157 :                 case C_OMP_CLAUSE_SPLIT_TEAMS:
    2899         1880 :                   if ((mask & (OMP_CLAUSE_MASK_1
    2900         1157 :                                << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
    2901          723 :                     continue;
    2902              :                   break;
    2903         1157 :                 case C_OMP_CLAUSE_SPLIT_DISTRIBUTE:
    2904         1832 :                   if ((mask & (OMP_CLAUSE_MASK_1
    2905         1157 :                                << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
    2906          675 :                     continue;
    2907              :                   break;
    2908         1157 :                 case C_OMP_CLAUSE_SPLIT_PARALLEL:
    2909         1529 :                   if ((mask & (OMP_CLAUSE_MASK_1
    2910         1157 :                                << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
    2911          372 :                     continue;
    2912              :                   break;
    2913         1157 :                 case C_OMP_CLAUSE_SPLIT_FOR:
    2914         1157 :                   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         1157 :                   if (code == OMP_SECTIONS)
    2921              :                     break;
    2922         1141 :                   if ((mask & (OMP_CLAUSE_MASK_1
    2923         1141 :                                << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
    2924              :                     break;
    2925          606 :                   if ((mask & (OMP_CLAUSE_MASK_1
    2926          606 :                                << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
    2927              :                     break;
    2928          326 :                   continue;
    2929         1157 :                 case C_OMP_CLAUSE_SPLIT_SIMD:
    2930         1157 :                   continue;
    2931              :                 default:
    2932              :                   gcc_unreachable ();
    2933              :                 }
    2934         2796 :               if (s != C_OMP_CLAUSE_SPLIT_COUNT)
    2935              :                 {
    2936         1639 :                   c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
    2937              :                                         OMP_CLAUSE_ALLOCATE);
    2938         3278 :                   OMP_CLAUSE_DECL (c)
    2939         1639 :                     = OMP_CLAUSE_DECL (clauses);
    2940         1639 :                   OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
    2941         1639 :                     = OMP_CLAUSE_ALLOCATE_ALLOCATOR (clauses);
    2942         1639 :                   OMP_CLAUSE_ALLOCATE_ALIGN (c)
    2943         1639 :                     = OMP_CLAUSE_ALLOCATE_ALIGN (clauses);
    2944         1639 :                   OMP_CLAUSE_CHAIN (c) = cclauses[s];
    2945         1639 :                   cclauses[s] = c;
    2946         1639 :                   has_dup_allocate = true;
    2947              :                 }
    2948         2796 :               s = (enum c_omp_clause_split) i;
    2949              :             }
    2950         1157 :           gcc_assert (s != C_OMP_CLAUSE_SPLIT_COUNT);
    2951              :           break;
    2952            0 :         default:
    2953            0 :           gcc_unreachable ();
    2954              :         }
    2955        39995 :       OMP_CLAUSE_CHAIN (clauses) = cclauses[s];
    2956        39995 :       cclauses[s] = clauses;
    2957              :     }
    2958              : 
    2959        15861 :   if (has_dup_allocate)
    2960              :     {
    2961          787 :       bool need_prune = false;
    2962          787 :       bitmap_obstack_initialize (NULL);
    2963         9783 :       for (i = 0; i < C_OMP_CLAUSE_SPLIT_SIMD - (code == OMP_LOOP); i++)
    2964         3871 :         if (cclauses[i])
    2965              :           {
    2966         2358 :             bitmap_head allocate_head;
    2967         2358 :             bitmap_initialize (&allocate_head, &bitmap_default_obstack);
    2968        17770 :             for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
    2969        15412 :               if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
    2970        15412 :                   && DECL_P (OMP_CLAUSE_DECL (c)))
    2971         4972 :                 bitmap_set_bit (&allocate_head,
    2972         2486 :                                 DECL_UID (OMP_CLAUSE_DECL (c)));
    2973        17770 :             for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
    2974        15412 :               switch (OMP_CLAUSE_CODE (c))
    2975              :                 {
    2976         1159 :                 case OMP_CLAUSE_REDUCTION:
    2977         1159 :                 case OMP_CLAUSE_IN_REDUCTION:
    2978         1159 :                 case OMP_CLAUSE_TASK_REDUCTION:
    2979         1159 :                   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         1159 :                   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         1159 :                   else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == OMP_ARRAY_SECTION)
    3005              :                     {
    3006          152 :                       tree t;
    3007          152 :                       for (t = OMP_CLAUSE_DECL (c);
    3008          304 :                            TREE_CODE (t) == OMP_ARRAY_SECTION;
    3009          152 :                            t = TREE_OPERAND (t, 0))
    3010              :                         ;
    3011          152 :                       if (DECL_P (t))
    3012          152 :                         bitmap_clear_bit (&allocate_head, DECL_UID (t));
    3013              :                       break;
    3014              :                     }
    3015              :                   /* FALLTHRU */
    3016         3265 :                 case OMP_CLAUSE_PRIVATE:
    3017         3265 :                 case OMP_CLAUSE_FIRSTPRIVATE:
    3018         3265 :                 case OMP_CLAUSE_LASTPRIVATE:
    3019         3265 :                 case OMP_CLAUSE_LINEAR:
    3020         3265 :                   if (DECL_P (OMP_CLAUSE_DECL (c)))
    3021         6530 :                     bitmap_clear_bit (&allocate_head,
    3022         3265 :                                       DECL_UID (OMP_CLAUSE_DECL (c)));
    3023              :                   break;
    3024              :                 default:
    3025              :                   break;
    3026              :                 }
    3027        17770 :             for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
    3028        15412 :               if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
    3029         2486 :                   && DECL_P (OMP_CLAUSE_DECL (c))
    3030        17898 :                   && bitmap_bit_p (&allocate_head,
    3031         2486 :                                    DECL_UID (OMP_CLAUSE_DECL (c))))
    3032              :                 {
    3033              :                   /* Mark allocate clauses which don't have corresponding
    3034              :                      explicit data sharing clause.  */
    3035         1093 :                   OMP_CLAUSE_ALLOCATE_COMBINED (c) = 1;
    3036         1093 :                   need_prune = true;
    3037              :                 }
    3038              :           }
    3039          787 :       bitmap_obstack_release (NULL);
    3040          787 :       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         4837 :           for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
    3051         4146 :             if (cclauses[i] == NULL_TREE
    3052         2426 :                 || i == C_OMP_CLAUSE_SPLIT_SIMD
    3053         2166 :                 || (i == C_OMP_CLAUSE_SPLIT_LOOP && code == OMP_LOOP))
    3054         1980 :               p[i] = NULL;
    3055              :             else
    3056         2166 :               p[i] = &cclauses[i];
    3057         1378 :           do
    3058              :             {
    3059         1378 :               int j = -1;
    3060         1378 :               tree seen = NULL_TREE;
    3061         6483 :               for (i = C_OMP_CLAUSE_SPLIT_COUNT - 1; i >= 0; i--)
    3062         5796 :                 if (p[i])
    3063              :                   {
    3064        13717 :                     while (*p[i]
    3065        13717 :                            && OMP_CLAUSE_CODE (*p[i]) != OMP_CLAUSE_ALLOCATE)
    3066        10732 :                       p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
    3067         2985 :                     if (*p[i] == NULL_TREE)
    3068              :                       {
    3069              :                         i = C_OMP_CLAUSE_SPLIT_COUNT;
    3070              :                         break;
    3071              :                       }
    3072         2294 :                     if (!OMP_CLAUSE_ALLOCATE_COMBINED (*p[i]) && j == -1)
    3073         5105 :                       j = i;
    3074              :                     seen = *p[i];
    3075              :                   }
    3076         1378 :               if (i == C_OMP_CLAUSE_SPLIT_COUNT)
    3077              :                 break;
    3078          687 :               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         4809 :               for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
    3084         4122 :                 if (p[i])
    3085              :                   {
    3086         2166 :                     if (i > j)
    3087              :                       /* Remove.  */
    3088          610 :                       *p[i] = OMP_CLAUSE_CHAIN (*p[i]);
    3089              :                     else
    3090              :                       /* Keep.  */
    3091         1556 :                       p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
    3092              :                   }
    3093              :             }
    3094              :           while (1);
    3095              :         }
    3096              :     }
    3097              : 
    3098        15861 :   if (!flag_checking)
    3099              :     return;
    3100              : 
    3101        15861 :   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
    3102        10672 :     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TARGET] == NULL_TREE);
    3103        15861 :   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
    3104         8991 :     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] == NULL_TREE);
    3105        15861 :   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0
    3106         8565 :       && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)) == 0)
    3107         8315 :     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] == NULL_TREE);
    3108        15861 :   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        15861 :   if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
    3111        15861 :                | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))) == 0
    3112         4121 :       && code != OMP_SECTIONS
    3113         4121 :       && code != OMP_LOOP)
    3114         3671 :     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_FOR] == NULL_TREE);
    3115        15861 :   if (code != OMP_SIMD)
    3116         9342 :     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        12204 : c_omp_declare_simd_clause_cmp (const void *p, const void *q)
    3124              : {
    3125        12204 :   tree a = *(const tree *) p;
    3126        12204 :   tree b = *(const tree *) q;
    3127        12204 :   if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_CODE (b))
    3128              :     {
    3129        10729 :       if (OMP_CLAUSE_CODE (a) > OMP_CLAUSE_CODE (b))
    3130              :         return -1;
    3131         4482 :       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         1493 : c_omp_declare_simd_clauses_to_numbers (tree parms, tree clauses)
    3152              : {
    3153         1493 :   tree c;
    3154         1493 :   vec<tree> clvec = vNULL;
    3155              : 
    3156         4640 :   for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
    3157              :     {
    3158         3147 :       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMDLEN
    3159         3147 :           && OMP_CLAUSE_SIMDLEN_TYPE (c))
    3160           59 :         sorry_at (OMP_CLAUSE_LOCATION (c),
    3161              :                   "%<simdlen%> clause with %<scaled%> modifier");
    3162         3147 :       if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
    3163              :           && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
    3164              :           && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
    3165              :         {
    3166         1712 :           tree decl = OMP_CLAUSE_DECL (c);
    3167         1712 :           tree arg;
    3168         1712 :           int idx;
    3169         3815 :           for (arg = parms, idx = 0; arg;
    3170         2103 :                arg = TREE_CHAIN (arg), idx++)
    3171         3815 :             if (arg == decl)
    3172              :               break;
    3173         1712 :           if (arg == NULL_TREE)
    3174              :             {
    3175            0 :               error_at (OMP_CLAUSE_LOCATION (c),
    3176              :                         "%qD is not a function argument", decl);
    3177         3147 :               continue;
    3178              :             }
    3179         1712 :           OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, idx);
    3180         1712 :           if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
    3181         1712 :               && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
    3182              :             {
    3183           43 :               decl = OMP_CLAUSE_LINEAR_STEP (c);
    3184          121 :               for (arg = parms, idx = 0; arg;
    3185           78 :                    arg = TREE_CHAIN (arg), idx++)
    3186          121 :                 if (arg == decl)
    3187              :                   break;
    3188           43 :               if (arg == NULL_TREE)
    3189              :                 {
    3190            0 :                   error_at (OMP_CLAUSE_LOCATION (c),
    3191              :                             "%qD is not a function argument", decl);
    3192            0 :                   continue;
    3193              :                 }
    3194           43 :               OMP_CLAUSE_LINEAR_STEP (c)
    3195           86 :                 = build_int_cst (integer_type_node, idx);
    3196              :             }
    3197              :         }
    3198         3147 :       clvec.safe_push (c);
    3199              :     }
    3200         1493 :   if (!clvec.is_empty ())
    3201              :     {
    3202         1380 :       unsigned int len = clvec.length (), i;
    3203         1380 :       clvec.qsort (c_omp_declare_simd_clause_cmp);
    3204         1380 :       clauses = clvec[0];
    3205         4527 :       for (i = 0; i < len; i++)
    3206         3147 :         OMP_CLAUSE_CHAIN (clvec[i]) = (i < len - 1) ? clvec[i + 1] : NULL_TREE;
    3207              :     }
    3208              :   else
    3209              :     clauses = NULL_TREE;
    3210         1493 :   clvec.release ();
    3211         1493 :   return clauses;
    3212              : }
    3213              : 
    3214              : /* Change argument indexes in CLAUSES of FNDECL back to PARM_DECLs.  */
    3215              : 
    3216              : void
    3217          123 : c_omp_declare_simd_clauses_to_decls (tree fndecl, tree clauses)
    3218              : {
    3219          123 :   tree c;
    3220              : 
    3221          429 :   for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
    3222          306 :     if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
    3223              :         && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
    3224              :         && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
    3225              :       {
    3226          189 :         int idx = tree_to_shwi (OMP_CLAUSE_DECL (c)), i;
    3227          189 :         tree arg;
    3228          369 :         for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
    3229          180 :              arg = TREE_CHAIN (arg), i++)
    3230          369 :           if (i == idx)
    3231              :             break;
    3232            0 :         gcc_assert (arg);
    3233          189 :         OMP_CLAUSE_DECL (c) = arg;
    3234          189 :         if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
    3235          189 :             && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
    3236              :           {
    3237            0 :             idx = tree_to_shwi (OMP_CLAUSE_LINEAR_STEP (c));
    3238            0 :             for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
    3239            0 :                  arg = TREE_CHAIN (arg), i++)
    3240            0 :               if (i == idx)
    3241              :                 break;
    3242            0 :             gcc_assert (arg);
    3243            0 :             OMP_CLAUSE_LINEAR_STEP (c) = arg;
    3244              :           }
    3245              :       }
    3246          123 : }
    3247              : 
    3248              : /* Return true for __func__ and similar function-local predefined
    3249              :    variables (which are in OpenMP predetermined shared, allowed in
    3250              :    shared/firstprivate clauses).  */
    3251              : 
    3252              : bool
    3253        65329 : c_omp_predefined_variable (tree decl)
    3254              : {
    3255        65329 :   if (VAR_P (decl)
    3256        34371 :       && DECL_ARTIFICIAL (decl)
    3257          309 :       && TREE_STATIC (decl)
    3258        65623 :       && DECL_NAME (decl))
    3259              :     {
    3260          294 :       if (TREE_READONLY (decl)
    3261          294 :           && (DECL_NAME (decl) == ridpointers[RID_C99_FUNCTION_NAME]
    3262          226 :               || DECL_NAME (decl) == ridpointers[RID_FUNCTION_NAME]
    3263          182 :               || DECL_NAME (decl) == ridpointers[RID_PRETTY_FUNCTION_NAME]))
    3264              :         return true;
    3265              :       /* For UBSan handle the same also ubsan_create_data created
    3266              :          variables.  There is no magic flag for those, but user variables
    3267              :          shouldn't be DECL_ARTIFICIAL or have TYPE_ARTIFICIAL type with
    3268              :          such names.  */
    3269          142 :       if ((flag_sanitize & (SANITIZE_UNDEFINED
    3270              :                             | SANITIZE_UNDEFINED_NONDEFAULT)) != 0
    3271           39 :           && DECL_IGNORED_P (decl)
    3272           39 :           && !TREE_READONLY (decl)
    3273           30 :           && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE
    3274           30 :           && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
    3275           30 :           && TYPE_ARTIFICIAL (TREE_TYPE (decl))
    3276           30 :           && TYPE_NAME (TREE_TYPE (decl))
    3277           30 :           && TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) == TYPE_DECL
    3278           30 :           && DECL_NAME (TYPE_NAME (TREE_TYPE (decl)))
    3279          172 :           && (TREE_CODE (DECL_NAME (TYPE_NAME (TREE_TYPE (decl))))
    3280              :               == IDENTIFIER_NODE))
    3281              :         {
    3282           30 :           tree id1 = DECL_NAME (decl);
    3283           30 :           tree id2 = DECL_NAME (TYPE_NAME (TREE_TYPE (decl)));
    3284           30 :           if (IDENTIFIER_LENGTH (id1) >= sizeof ("ubsan_data") - 1
    3285           30 :               && IDENTIFIER_LENGTH (id2) >= sizeof ("__ubsan__data")
    3286           30 :               && !memcmp (IDENTIFIER_POINTER (id2), "__ubsan_",
    3287              :                           sizeof ("__ubsan_") - 1)
    3288           30 :               && !memcmp (IDENTIFIER_POINTER (id2) + IDENTIFIER_LENGTH (id2)
    3289           30 :                           - sizeof ("_data") + 1, "_data",
    3290              :                           sizeof ("_data") - 1)
    3291           60 :               && strstr (IDENTIFIER_POINTER (id1), "ubsan_data"))
    3292           30 :             return true;
    3293              :         }
    3294              :     }
    3295              :   return false;
    3296              : }
    3297              : 
    3298              : /* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute of DECL
    3299              :    is predetermined.  */
    3300              : 
    3301              : enum omp_clause_default_kind
    3302        28056 : c_omp_predetermined_sharing (tree decl)
    3303              : {
    3304              :   /* Predetermine artificial variables holding integral values, those
    3305              :      are usually result of gimplify_one_sizepos or SAVE_EXPR
    3306              :      gimplification.  */
    3307        28056 :   if (VAR_P (decl)
    3308        17274 :       && DECL_ARTIFICIAL (decl)
    3309        28695 :       && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
    3310              :     return OMP_CLAUSE_DEFAULT_SHARED;
    3311              : 
    3312        27508 :   if (c_omp_predefined_variable (decl))
    3313           91 :     return OMP_CLAUSE_DEFAULT_SHARED;
    3314              : 
    3315              :   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
    3316              : }
    3317              : 
    3318              : /* OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED unless OpenMP mapping attribute
    3319              :    of DECL is predetermined.  */
    3320              : 
    3321              : enum omp_clause_defaultmap_kind
    3322         5175 : c_omp_predetermined_mapping (tree decl)
    3323              : {
    3324              :   /* Predetermine artificial variables holding integral values, those
    3325              :      are usually result of gimplify_one_sizepos or SAVE_EXPR
    3326              :      gimplification.  */
    3327         5175 :   if (VAR_P (decl)
    3328          944 :       && DECL_ARTIFICIAL (decl)
    3329         5207 :       && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
    3330              :     return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
    3331              : 
    3332         5147 :   if (c_omp_predefined_variable (decl))
    3333            2 :     return OMP_CLAUSE_DEFAULTMAP_TO;
    3334              : 
    3335              :   return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
    3336              : }
    3337              : 
    3338              : 
    3339              : /* Used to merge map clause information in c_omp_adjust_map_clauses.  */
    3340              : struct map_clause
    3341              : {
    3342              :   tree clause;
    3343              :   bool firstprivate_ptr_p;
    3344              :   bool decl_mapped;
    3345              :   bool omp_declare_target;
    3346         3617 :   map_clause (void) : clause (NULL_TREE), firstprivate_ptr_p (false),
    3347         3617 :     decl_mapped (false), omp_declare_target (false) { }
    3348              : };
    3349              : 
    3350              : /* Adjust map clauses after normal clause parsing, mainly to mark specific
    3351              :    base-pointer map cases addressable that may be turned into attach/detach
    3352              :    operations during gimplification.  */
    3353              : void
    3354        12903 : c_omp_adjust_map_clauses (tree clauses, bool is_target)
    3355              : {
    3356        12903 :   if (!is_target)
    3357              :     {
    3358              :       /* If this is not a target construct, just turn firstprivate pointers
    3359              :          into attach/detach, the runtime will check and do the rest.  */
    3360              : 
    3361         4651 :       for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
    3362         3143 :         if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
    3363         2666 :             && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
    3364            0 :             && DECL_P (OMP_CLAUSE_DECL (c))
    3365         3143 :             && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
    3366              :           {
    3367            0 :             tree ptr = OMP_CLAUSE_DECL (c);
    3368            0 :             c_common_mark_addressable_vec (ptr);
    3369              :           }
    3370         1508 :       return;
    3371              :     }
    3372              : 
    3373        11395 :   hash_map<tree, map_clause> maps;
    3374              : 
    3375        36264 :   for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
    3376        13474 :     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
    3377        13474 :         && DECL_P (OMP_CLAUSE_DECL (c)))
    3378              :       {
    3379              :         /* If this is for a target construct, the firstprivate pointer
    3380              :            is marked addressable if either is true:
    3381              :            (1) the base-pointer is mapped in this same construct, or
    3382              :            (2) the base-pointer is a variable place on the device by
    3383              :                "declare target" directives.
    3384              : 
    3385              :            Here we iterate through all map clauses collecting these cases,
    3386              :            and merge them with a hash_map to process below.  */
    3387              : 
    3388         4283 :         if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
    3389         4283 :             && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
    3390              :           {
    3391          343 :             tree ptr = OMP_CLAUSE_DECL (c);
    3392          343 :             map_clause &mc = maps.get_or_insert (ptr);
    3393          343 :             if (mc.clause == NULL_TREE)
    3394          343 :               mc.clause = c;
    3395          343 :             mc.firstprivate_ptr_p = true;
    3396              : 
    3397          343 :             if (is_global_var (ptr)
    3398          391 :                 && lookup_attribute ("omp declare target",
    3399           48 :                                      DECL_ATTRIBUTES (ptr)))
    3400            0 :               mc.omp_declare_target = true;
    3401              :           }
    3402         3940 :         else if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALLOC
    3403         3853 :                  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO
    3404         3339 :                  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
    3405         2288 :                  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TOFROM
    3406         1077 :                  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
    3407         1007 :                  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
    3408         4938 :                  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM)
    3409              :           {
    3410         3305 :             map_clause &mc = maps.get_or_insert (OMP_CLAUSE_DECL (c));
    3411         3305 :             mc.decl_mapped = true;
    3412              :           }
    3413              :       }
    3414              : 
    3415        15012 :   for (hash_map<tree, map_clause>::iterator i = maps.begin ();
    3416        26407 :        i != maps.end (); ++i)
    3417              :     {
    3418         3617 :       map_clause &mc = (*i).second;
    3419              : 
    3420         3617 :       if (mc.firstprivate_ptr_p
    3421          343 :           && (mc.decl_mapped || mc.omp_declare_target))
    3422           23 :         c_common_mark_addressable_vec (OMP_CLAUSE_DECL (mc.clause));
    3423              :     }
    3424        11395 : }
    3425              : 
    3426              : /* Maybe strip off an indirection from a "converted" reference, then find the
    3427              :    origin of a pointer (i.e. without any offset).  */
    3428              : 
    3429              : tree
    3430        72247 : c_omp_address_inspector::unconverted_ref_origin ()
    3431              : {
    3432        72247 :   tree t = orig;
    3433              : 
    3434              :   /* We may have a reference-typed component access at the outermost level
    3435              :      that has had convert_from_reference called on it.  Get the un-dereferenced
    3436              :      reference itself.  */
    3437        72247 :   t = maybe_unconvert_ref (t);
    3438              : 
    3439              :   /* Find base pointer for POINTER_PLUS_EXPR, etc.  */
    3440        72247 :   t = get_origin (t);
    3441              : 
    3442        72247 :   return t;
    3443              : }
    3444              : 
    3445              : /* Return TRUE if the address is a component access.  */
    3446              : 
    3447              : bool
    3448        12705 : c_omp_address_inspector::component_access_p ()
    3449              : {
    3450        12705 :   tree t = maybe_unconvert_ref (orig);
    3451              : 
    3452        12705 :   t = get_origin (t);
    3453              : 
    3454        12705 :   return TREE_CODE (t) == COMPONENT_REF;
    3455              : }
    3456              : 
    3457              : /* Perform various checks on the address, as described by clause CLAUSE (we
    3458              :    only use its code and location here).  */
    3459              : 
    3460              : bool
    3461        33775 : c_omp_address_inspector::check_clause (tree clause)
    3462              : {
    3463        33775 :   tree t = unconverted_ref_origin ();
    3464              : 
    3465        33775 :   if (TREE_CODE (t) != COMPONENT_REF)
    3466              :     return true;
    3467              : 
    3468         4875 :   if (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL
    3469         4875 :       && DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
    3470              :     {
    3471           24 :       error_at (OMP_CLAUSE_LOCATION (clause),
    3472              :                 "bit-field %qE in %qs clause",
    3473           24 :                 t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
    3474           24 :       return false;
    3475              :     }
    3476         4851 :   else if (!processing_template_decl_p ()
    3477         4851 :            && !omp_mappable_type (TREE_TYPE (t)))
    3478              :     {
    3479            0 :       error_at (OMP_CLAUSE_LOCATION (clause),
    3480              :                 "%qE does not have a mappable type in %qs clause",
    3481            0 :                 t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
    3482            0 :       emit_unmappable_type_notes (TREE_TYPE (t));
    3483            0 :       return false;
    3484              :     }
    3485         4851 :   else if (TREE_TYPE (t) && TYPE_ATOMIC (TREE_TYPE (t)))
    3486              :     {
    3487            2 :       error_at (OMP_CLAUSE_LOCATION (clause),
    3488              :                 "%<_Atomic%> %qE in %qs clause", t,
    3489            2 :                 omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
    3490            2 :       return false;
    3491              :     }
    3492              : 
    3493              :   return true;
    3494              : }
    3495              : 
    3496              : /* Find the "root term" for the address.  This is the innermost decl, etc.
    3497              :    of the access.  */
    3498              : 
    3499              : tree
    3500         1691 : c_omp_address_inspector::get_root_term (bool checking)
    3501              : {
    3502         1691 :   if (root_term && !checking)
    3503              :     return root_term;
    3504              : 
    3505         1691 :   tree t = unconverted_ref_origin ();
    3506              : 
    3507         5737 :   while (TREE_CODE (t) == COMPONENT_REF)
    3508              :     {
    3509         2355 :       if (checking
    3510         2355 :           && TREE_TYPE (TREE_OPERAND (t, 0))
    3511         4522 :           && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE)
    3512              :         {
    3513            0 :           error_at (loc, "%qE is a member of a union", t);
    3514            0 :           return error_mark_node;
    3515              :         }
    3516         2355 :       t = TREE_OPERAND (t, 0);
    3517         2355 :       while (TREE_CODE (t) == MEM_REF
    3518         3774 :              || TREE_CODE (t) == INDIRECT_REF
    3519         3774 :              || TREE_CODE (t) == ARRAY_REF)
    3520              :         {
    3521         1419 :           if (TREE_CODE (t) == MEM_REF
    3522              :               || TREE_CODE (t) == INDIRECT_REF)
    3523         1275 :             indirections = true;
    3524         1419 :           t = TREE_OPERAND (t, 0);
    3525         1419 :           STRIP_NOPS (t);
    3526         1419 :           if (TREE_CODE (t) == POINTER_PLUS_EXPR)
    3527          102 :             t = TREE_OPERAND (t, 0);
    3528              :         }
    3529              :     }
    3530              : 
    3531         1691 :   root_term = t;
    3532              : 
    3533         1691 :   return t;
    3534              : }
    3535              : 
    3536              : /* Return TRUE if the address is supported in mapping clauses.  At present,
    3537              :    this means that the innermost expression is a DECL_P, but could be extended
    3538              :    to other types of expression in the future.  */
    3539              : 
    3540              : bool
    3541        25767 : c_omp_address_inspector::map_supported_p ()
    3542              : {
    3543              :   /* If we've already decided if the mapped address is supported, return
    3544              :      that.  */
    3545        25767 :   if (map_supported != -1)
    3546            0 :     return map_supported;
    3547              : 
    3548        25767 :   tree t = unconverted_ref_origin ();
    3549              : 
    3550        25767 :   STRIP_NOPS (t);
    3551              : 
    3552        25767 :   while (TREE_CODE (t) == INDIRECT_REF
    3553        41922 :          || TREE_CODE (t) == MEM_REF
    3554              :          || TREE_CODE (t) == ARRAY_REF
    3555              :          || TREE_CODE (t) == COMPONENT_REF
    3556              :          || TREE_CODE (t) == COMPOUND_EXPR
    3557              :          || TREE_CODE (t) == SAVE_EXPR
    3558              :          || TREE_CODE (t) == POINTER_PLUS_EXPR
    3559              :          || TREE_CODE (t) == NON_LVALUE_EXPR
    3560              :          || TREE_CODE (t) == OMP_ARRAY_SECTION
    3561        41922 :          || TREE_CODE (t) == NOP_EXPR)
    3562        16155 :     if (TREE_CODE (t) == COMPOUND_EXPR)
    3563           27 :       t = TREE_OPERAND (t, 1);
    3564              :     else
    3565        16128 :       t = TREE_OPERAND (t, 0);
    3566              : 
    3567        25767 :   STRIP_NOPS (t);
    3568              : 
    3569        25767 :   map_supported = DECL_P (t);
    3570              : 
    3571        25767 :   return map_supported;
    3572              : }
    3573              : 
    3574              : /* Get the origin of an address T, stripping off offsets and some other
    3575              :    bits.  */
    3576              : 
    3577              : tree
    3578        84952 : c_omp_address_inspector::get_origin (tree t)
    3579              : {
    3580        85528 :   while (1)
    3581              :     {
    3582        85528 :       if (TREE_CODE (t) == COMPOUND_EXPR)
    3583              :         {
    3584           10 :           t = TREE_OPERAND (t, 1);
    3585           10 :           STRIP_NOPS (t);
    3586              :         }
    3587        85518 :       else if (TREE_CODE (t) == POINTER_PLUS_EXPR
    3588        85518 :                || TREE_CODE (t) == SAVE_EXPR)
    3589          539 :         t = TREE_OPERAND (t, 0);
    3590        84979 :       else if (!processing_template_decl_p ()
    3591        78024 :                && TREE_CODE (t) == INDIRECT_REF
    3592        87597 :                && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE)
    3593           27 :         t = TREE_OPERAND (t, 0);
    3594              :       else
    3595              :         break;
    3596              :     }
    3597        84952 :   STRIP_NOPS (t);
    3598        84952 :   return t;
    3599              : }
    3600              : 
    3601              : /* For an address T that might be a reference that has had
    3602              :    "convert_from_reference" called on it, return the actual reference without
    3603              :    any indirection.  */
    3604              : 
    3605              : tree
    3606        94664 : c_omp_address_inspector::maybe_unconvert_ref (tree t)
    3607              : {
    3608              :   /* Be careful not to dereference the type if we're processing a
    3609              :      template decl, else it might be NULL.  */
    3610        94664 :   if (!processing_template_decl_p ()
    3611        85647 :       && TREE_CODE (t) == INDIRECT_REF
    3612        97803 :       && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE)
    3613          587 :     return TREE_OPERAND (t, 0);
    3614              : 
    3615              :   return t;
    3616              : }
    3617              : 
    3618              : /* Return TRUE if CLAUSE might describe a zero-length array section.  */
    3619              : 
    3620              : bool
    3621         5517 : c_omp_address_inspector::maybe_zero_length_array_section (tree clause)
    3622              : {
    3623         5517 :   switch (OMP_CLAUSE_MAP_KIND (clause))
    3624              :     {
    3625              :     case GOMP_MAP_ALLOC:
    3626              :     case GOMP_MAP_IF_PRESENT:
    3627              :     case GOMP_MAP_TO:
    3628              :     case GOMP_MAP_FROM:
    3629              :     case GOMP_MAP_TOFROM:
    3630              :     case GOMP_MAP_ALWAYS_TO:
    3631              :     case GOMP_MAP_ALWAYS_FROM:
    3632              :     case GOMP_MAP_ALWAYS_TOFROM:
    3633              :     case GOMP_MAP_PRESENT_ALLOC:
    3634              :     case GOMP_MAP_PRESENT_TO:
    3635              :     case GOMP_MAP_PRESENT_FROM:
    3636              :     case GOMP_MAP_PRESENT_TOFROM:
    3637              :     case GOMP_MAP_ALWAYS_PRESENT_TO:
    3638              :     case GOMP_MAP_ALWAYS_PRESENT_FROM:
    3639              :     case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
    3640              :     case GOMP_MAP_RELEASE:
    3641              :     case GOMP_MAP_DELETE:
    3642              :     case GOMP_MAP_FORCE_TO:
    3643              :     case GOMP_MAP_FORCE_FROM:
    3644              :     case GOMP_MAP_FORCE_TOFROM:
    3645              :     case GOMP_MAP_FORCE_PRESENT:
    3646              :       return true;
    3647           28 :     default:
    3648           28 :       return false;
    3649              :     }
    3650              : }
    3651              : 
    3652              : /* Expand a chained access.  We only expect to see a quite limited range of
    3653              :    expression types here, because e.g. you can't have an array of
    3654              :    references.  */
    3655              : 
    3656              : static tree
    3657           79 : omp_expand_access_chain (tree c, tree expr, vec<omp_addr_token *> &addr_tokens,
    3658              :                          unsigned *idx, c_omp_region_type ort)
    3659              : {
    3660           87 :   using namespace omp_addr_tokenizer;
    3661           87 :   location_t loc = OMP_CLAUSE_LOCATION (c);
    3662           87 :   unsigned i = *idx;
    3663           87 :   tree c2 = NULL_TREE;
    3664           87 :   gomp_map_kind kind;
    3665              : 
    3666           87 :   if ((ort & C_ORT_EXIT_DATA) != 0
    3667           75 :       || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM
    3668          162 :       || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
    3669           75 :           && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
    3670           75 :               || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DELETE
    3671           75 :               || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_RELEASE
    3672           75 :               || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
    3673           75 :               || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_FROM
    3674           75 :               || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PRESENT_FROM
    3675           75 :               || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_FROM)))
    3676              :     kind = GOMP_MAP_DETACH;
    3677              :   else
    3678              :     kind = GOMP_MAP_ATTACH;
    3679              : 
    3680           87 :   switch (addr_tokens[i]->u.access_kind)
    3681              :     {
    3682           87 :     case ACCESS_POINTER:
    3683           87 :     case ACCESS_POINTER_OFFSET:
    3684           87 :       {
    3685           87 :         tree virtual_origin
    3686           87 :           = fold_convert_loc (loc, ptrdiff_type_node, addr_tokens[i]->expr);
    3687           87 :         tree data_addr = omp_accessed_addr (addr_tokens, i, expr);
    3688           87 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    3689           87 :         OMP_CLAUSE_SET_MAP_KIND (c2, kind);
    3690           87 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i]->expr;
    3691           87 :         OMP_CLAUSE_SIZE (c2)
    3692           87 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    3693              :                              fold_convert_loc (loc, ptrdiff_type_node,
    3694              :                                                data_addr),
    3695              :                              virtual_origin);
    3696              :       }
    3697           87 :       break;
    3698              : 
    3699              :     case ACCESS_INDEXED_ARRAY:
    3700              :       break;
    3701              : 
    3702            0 :     default:
    3703            0 :       return error_mark_node;
    3704              :     }
    3705              : 
    3706           87 :   if (c2)
    3707              :     {
    3708           87 :       OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
    3709           87 :       OMP_CLAUSE_CHAIN (c) = c2;
    3710           87 :       c = c2;
    3711              :     }
    3712              : 
    3713           87 :   *idx = ++i;
    3714              : 
    3715           87 :   if (i < addr_tokens.length ()
    3716           95 :       && addr_tokens[i]->type == ACCESS_METHOD)
    3717              :     return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
    3718              : 
    3719              :   return c;
    3720              : }
    3721              : 
    3722              : /* Translate "array_base_decl access_method" to OMP mapping clauses.  */
    3723              : 
    3724              : tree
    3725        18419 : c_omp_address_inspector::expand_array_base (tree c,
    3726              :                                             vec<omp_addr_token *> &addr_tokens,
    3727              :                                             tree expr, unsigned *idx,
    3728              :                                             c_omp_region_type ort)
    3729              : {
    3730        18419 :   using namespace omp_addr_tokenizer;
    3731        18419 :   location_t loc = OMP_CLAUSE_LOCATION (c);
    3732        18419 :   int i = *idx;
    3733        18419 :   tree decl = addr_tokens[i + 1]->expr;
    3734        18419 :   bool decl_p = DECL_P (decl);
    3735        18419 :   bool declare_target_p = (decl_p
    3736        18410 :                            && is_global_var (decl)
    3737        25954 :                            && lookup_attribute ("omp declare target",
    3738         7535 :                                                 DECL_ATTRIBUTES (decl)));
    3739        18419 :   bool map_p = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP;
    3740        18419 :   bool implicit_p = map_p && OMP_CLAUSE_MAP_IMPLICIT (c);
    3741        18419 :   bool chain_p = omp_access_chain_p (addr_tokens, i + 1);
    3742        18419 :   tree c2 = NULL_TREE, c3 = NULL_TREE;
    3743        18419 :   unsigned consume_tokens = 2;
    3744        18419 :   bool target_p = (ort & C_ORT_TARGET) != 0;
    3745        18419 :   bool openmp_p = (ort & C_ORT_OMP) != 0;
    3746              : 
    3747        18419 :   gcc_assert (i == 0);
    3748              : 
    3749        18419 :   if (!openmp_p
    3750        18419 :       && map_p
    3751        18419 :       && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
    3752         6749 :           || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH))
    3753              :     {
    3754           28 :       i += 2;
    3755           28 :       *idx = i;
    3756           28 :       return c;
    3757              :     }
    3758              : 
    3759        18391 :   switch (addr_tokens[i + 1]->u.access_kind)
    3760              :     {
    3761        14057 :     case ACCESS_DIRECT:
    3762        14057 :       if (decl_p && !target_p)
    3763         8684 :         c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3764              :       break;
    3765              : 
    3766          154 :     case ACCESS_REF:
    3767          154 :       {
    3768              :         /* Copy the referenced object.  Note that we do this even for !MAP_P
    3769              :            clauses.  */
    3770          154 :         tree obj = convert_from_reference (addr_tokens[i + 1]->expr);
    3771          154 :         if (TREE_CODE (TREE_TYPE (obj)) == ARRAY_TYPE)
    3772              :           /* We have a ref to array: add a [0] element as the ME expects.  */
    3773           47 :           OMP_CLAUSE_DECL (c) = build_array_ref (loc, obj, integer_zero_node);
    3774              :         else
    3775          107 :           OMP_CLAUSE_DECL (c) = obj;
    3776          154 :         OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (obj));
    3777              : 
    3778          154 :         if (!map_p)
    3779              :           {
    3780            6 :             if (decl_p)
    3781            6 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3782              :             break;
    3783              :           }
    3784              : 
    3785          148 :         if (!target_p)
    3786              :           break;
    3787              : 
    3788              :         /* If we have a reference to a pointer, avoid using
    3789              :            FIRSTPRIVATE_REFERENCE here in case the pointer is modified in the
    3790              :            offload region (we can only do that if the pointer does not point
    3791              :            to a mapped block).  We could avoid doing this if we don't have a
    3792              :            FROM mapping...  */
    3793           88 :         bool ref_to_ptr = TREE_CODE (TREE_TYPE (obj)) == POINTER_TYPE;
    3794              : 
    3795           88 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    3796           88 :         if (!ref_to_ptr
    3797           88 :             && !declare_target_p
    3798           54 :             && decl_p)
    3799           54 :           OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
    3800              :         else
    3801              :           {
    3802           34 :             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    3803           34 :             if (decl_p)
    3804           34 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3805              :           }
    3806           88 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    3807           88 :         OMP_CLAUSE_SIZE (c2) = size_zero_node;
    3808              : 
    3809           88 :         if (ref_to_ptr)
    3810              :           {
    3811           34 :             c3 = c2;
    3812           34 :             c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    3813           34 :             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALLOC);
    3814           34 :             OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    3815           68 :             OMP_CLAUSE_SIZE (c2)
    3816           34 :               = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (c2)));
    3817              :           }
    3818              :       }
    3819              :       break;
    3820              : 
    3821           83 :     case ACCESS_INDEXED_REF_TO_ARRAY:
    3822           83 :       {
    3823           83 :         if (!map_p)
    3824              :           {
    3825            0 :             if (decl_p)
    3826            0 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3827              :             break;
    3828              :           }
    3829              : 
    3830           83 :         if (!target_p)
    3831              :           break;
    3832              : 
    3833           64 :         tree virtual_origin
    3834           64 :           = convert_from_reference (addr_tokens[i + 1]->expr);
    3835           64 :         virtual_origin = build_fold_addr_expr (virtual_origin);
    3836           64 :         virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    3837              :                                            virtual_origin);
    3838           64 :         tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
    3839           64 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    3840           64 :         if (decl_p && target_p && !declare_target_p)
    3841              :           {
    3842              :             /* It appears that omp-low.cc mishandles cases where we have a
    3843              :                [reference to an] array of pointers such as:
    3844              : 
    3845              :                  int *arr[N];   (or "int *(&arr)[N] = ...")
    3846              :                  #pragma omp target map(arr[a][b:c])
    3847              :                  { ... }
    3848              : 
    3849              :                in such cases chain_p will be true.  For now, fall back to
    3850              :                GOMP_MAP_POINTER.  */
    3851           61 :             enum gomp_map_kind k = chain_p ? GOMP_MAP_POINTER
    3852              :                                            : GOMP_MAP_FIRSTPRIVATE_REFERENCE;
    3853           61 :             OMP_CLAUSE_SET_MAP_KIND (c2, k);
    3854           61 :           }
    3855              :         else
    3856              :           {
    3857            3 :             if (decl_p)
    3858            0 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3859            3 :             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    3860              :           }
    3861           64 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    3862           64 :         OMP_CLAUSE_SIZE (c2)
    3863           64 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    3864              :                              fold_convert_loc (loc, ptrdiff_type_node,
    3865              :                                                data_addr),
    3866              :                              virtual_origin);
    3867              :       }
    3868           64 :       break;
    3869              : 
    3870         1381 :     case ACCESS_INDEXED_ARRAY:
    3871         1381 :       {
    3872         1381 :         if (!map_p)
    3873              :           {
    3874            0 :             if (decl_p)
    3875            0 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3876              :             break;
    3877              :           }
    3878              : 
    3879              :         /* The code handling "firstprivatize_array_bases" in gimplify.cc is
    3880              :            relevant here.  What do we need to create for arrays at this
    3881              :            stage?  (This condition doesn't feel quite right.  FIXME?)  */
    3882         1381 :         if (!target_p
    3883         1381 :             && (TREE_CODE (TREE_TYPE (addr_tokens[i + 1]->expr))
    3884              :                 == ARRAY_TYPE))
    3885              :           break;
    3886              : 
    3887          707 :         tree virtual_origin
    3888          707 :           = build_fold_addr_expr (addr_tokens[i + 1]->expr);
    3889          707 :         virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    3890              :                                            virtual_origin);
    3891          707 :         tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
    3892          707 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    3893          707 :         if (decl_p && target_p)
    3894              :           {
    3895              :             /* See comment for ACCESS_INDEXED_REF_TO_ARRAY above.  */
    3896          707 :             enum gomp_map_kind k = chain_p ? GOMP_MAP_POINTER
    3897              :                                            : GOMP_MAP_FIRSTPRIVATE_POINTER;
    3898          707 :             OMP_CLAUSE_SET_MAP_KIND (c2, k);
    3899              :           }
    3900              :         else
    3901              :           {
    3902            0 :             if (decl_p)
    3903            0 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3904            0 :             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    3905              :           }
    3906          707 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    3907          707 :         OMP_CLAUSE_SIZE (c2)
    3908          707 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    3909              :                              fold_convert_loc (loc, ptrdiff_type_node,
    3910              :                                                data_addr),
    3911              :                              virtual_origin);
    3912              :       }
    3913          707 :       break;
    3914              : 
    3915         2642 :     case ACCESS_POINTER:
    3916         2642 :     case ACCESS_POINTER_OFFSET:
    3917         2642 :       {
    3918         2642 :         if (!map_p)
    3919              :           {
    3920            0 :             if (decl_p)
    3921            0 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3922              :             break;
    3923              :           }
    3924              : 
    3925         2642 :         unsigned last_access = i + 1;
    3926         2642 :         tree virtual_origin;
    3927              : 
    3928         2642 :         if (chain_p
    3929          151 :             && addr_tokens[i + 2]->type == ACCESS_METHOD
    3930         2793 :             && addr_tokens[i + 2]->u.access_kind == ACCESS_INDEXED_ARRAY)
    3931              :           {
    3932              :             /* !!! This seems wrong for ACCESS_POINTER_OFFSET.  */
    3933          117 :             consume_tokens = 3;
    3934          117 :             chain_p = omp_access_chain_p (addr_tokens, i + 2);
    3935          117 :             last_access = i + 2;
    3936          117 :             virtual_origin
    3937          117 :               = build_array_ref (loc, addr_tokens[last_access]->expr,
    3938              :                                  integer_zero_node);
    3939          117 :             virtual_origin = build_fold_addr_expr (virtual_origin);
    3940          117 :             virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    3941              :                                                virtual_origin);
    3942              :           }
    3943              :         else
    3944         2525 :           virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    3945         2525 :                                              addr_tokens[last_access]->expr);
    3946         2642 :         tree data_addr = omp_accessed_addr (addr_tokens, last_access, expr);
    3947         2642 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    3948              :         /* For OpenACC, use FIRSTPRIVATE_POINTER for decls even on non-compute
    3949              :            regions (e.g. "acc data" constructs).  It'll be removed anyway in
    3950              :            gimplify.cc, but doing it this way maintains diagnostic
    3951              :            behaviour.  */
    3952         2642 :         if (decl_p && (target_p || !openmp_p) && !chain_p && !declare_target_p)
    3953         2440 :           OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
    3954              :         else
    3955              :           {
    3956          199 :             if (decl_p)
    3957          199 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3958          202 :             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    3959              :           }
    3960         2642 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    3961         2642 :         OMP_CLAUSE_SIZE (c2)
    3962         2642 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    3963              :                              fold_convert_loc (loc, ptrdiff_type_node,
    3964              :                                                data_addr),
    3965              :                              virtual_origin);
    3966              :       }
    3967         2642 :       break;
    3968              : 
    3969           74 :     case ACCESS_REF_TO_POINTER:
    3970           74 :     case ACCESS_REF_TO_POINTER_OFFSET:
    3971           74 :       {
    3972           74 :         if (!map_p)
    3973              :           {
    3974            0 :             if (decl_p)
    3975            0 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    3976              :             break;
    3977              :           }
    3978              : 
    3979           74 :         unsigned last_access = i + 1;
    3980           74 :         tree virtual_origin;
    3981              : 
    3982           74 :         if (chain_p
    3983            6 :             && addr_tokens[i + 2]->type == ACCESS_METHOD
    3984           80 :             && addr_tokens[i + 2]->u.access_kind == ACCESS_INDEXED_ARRAY)
    3985              :           {
    3986              :             /* !!! This seems wrong for ACCESS_POINTER_OFFSET.  */
    3987            2 :             consume_tokens = 3;
    3988            2 :             chain_p = omp_access_chain_p (addr_tokens, i + 2);
    3989            2 :             last_access = i + 2;
    3990            2 :             virtual_origin
    3991            2 :               = build_array_ref (loc, addr_tokens[last_access]->expr,
    3992              :                                  integer_zero_node);
    3993            2 :             virtual_origin = build_fold_addr_expr (virtual_origin);
    3994            2 :             virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    3995              :                                                virtual_origin);
    3996              :           }
    3997              :         else
    3998              :           {
    3999           72 :             virtual_origin
    4000           72 :               = convert_from_reference (addr_tokens[last_access]->expr);
    4001           72 :             virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    4002              :                                                virtual_origin);
    4003              :           }
    4004              : 
    4005           74 :         tree data_addr = omp_accessed_addr (addr_tokens, last_access, expr);
    4006           74 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    4007           74 :         if (decl_p && target_p && !chain_p && !declare_target_p)
    4008              :           {
    4009           58 :             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
    4010           58 :             OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    4011              :           }
    4012              :         else
    4013              :           {
    4014           16 :             if (decl_p)
    4015           16 :               c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    4016           16 :             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    4017           16 :             OMP_CLAUSE_DECL (c2)
    4018           32 :               = convert_from_reference (addr_tokens[i + 1]->expr);
    4019              :           }
    4020           74 :         OMP_CLAUSE_SIZE (c2)
    4021           74 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    4022              :                              fold_convert_loc (loc, ptrdiff_type_node,
    4023              :                                                data_addr),
    4024              :                              virtual_origin);
    4025              :       }
    4026           74 :       break;
    4027              : 
    4028            0 :     default:
    4029            0 :       *idx = i + consume_tokens;
    4030            0 :       return error_mark_node;
    4031              :     }
    4032              : 
    4033        12177 :   if (c3)
    4034              :     {
    4035           34 :       OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c);
    4036           34 :       OMP_CLAUSE_CHAIN (c2) = c3;
    4037           34 :       OMP_CLAUSE_CHAIN (c) = c2;
    4038           34 :       if (implicit_p)
    4039              :         {
    4040            0 :           OMP_CLAUSE_MAP_IMPLICIT (c2) = 1;
    4041            0 :           OMP_CLAUSE_MAP_IMPLICIT (c3) = 1;
    4042              :         }
    4043              :       c = c3;
    4044              :     }
    4045        18357 :   else if (c2)
    4046              :     {
    4047         3541 :       OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
    4048         3541 :       OMP_CLAUSE_CHAIN (c) = c2;
    4049         3541 :       if (implicit_p)
    4050          116 :         OMP_CLAUSE_MAP_IMPLICIT (c2) = 1;
    4051              :       c = c2;
    4052              :     }
    4053              : 
    4054        18391 :   i += consume_tokens;
    4055        18391 :   *idx = i;
    4056              : 
    4057        18391 :   if (chain_p && map_p)
    4058           55 :     return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
    4059              : 
    4060              :   return c;
    4061              : }
    4062              : 
    4063              : /* Translate "component_selector access_method" to OMP mapping clauses.  */
    4064              : 
    4065              : tree
    4066         3234 : c_omp_address_inspector::expand_component_selector (tree c,
    4067              :                                                     vec<omp_addr_token *>
    4068              :                                                       &addr_tokens,
    4069              :                                                     tree expr, unsigned *idx,
    4070              :                                                     c_omp_region_type ort)
    4071              : {
    4072         3234 :   using namespace omp_addr_tokenizer;
    4073         3234 :   location_t loc = OMP_CLAUSE_LOCATION (c);
    4074         3234 :   unsigned i = *idx;
    4075         3234 :   tree c2 = NULL_TREE, c3 = NULL_TREE;
    4076         3234 :   bool chain_p = omp_access_chain_p (addr_tokens, i + 1);
    4077         3234 :   bool map_p = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP;
    4078              : 
    4079         3234 :   switch (addr_tokens[i + 1]->u.access_kind)
    4080              :     {
    4081              :     case ACCESS_DIRECT:
    4082              :     case ACCESS_INDEXED_ARRAY:
    4083              :       break;
    4084              : 
    4085          479 :     case ACCESS_REF:
    4086          479 :       {
    4087              :         /* Copy the referenced object.  Note that we also do this for !MAP_P
    4088              :            clauses.  */
    4089          479 :         tree obj = convert_from_reference (addr_tokens[i + 1]->expr);
    4090          479 :         OMP_CLAUSE_DECL (c) = obj;
    4091          479 :         OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (obj));
    4092              : 
    4093          479 :         if (!map_p)
    4094              :           break;
    4095              : 
    4096          461 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    4097          461 :         OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    4098          461 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    4099          461 :         OMP_CLAUSE_SIZE (c2) = size_zero_node;
    4100              :       }
    4101          461 :       break;
    4102              : 
    4103           92 :     case ACCESS_INDEXED_REF_TO_ARRAY:
    4104           92 :       {
    4105           92 :         if (!map_p)
    4106              :           break;
    4107              : 
    4108           92 :         tree virtual_origin
    4109           92 :           = convert_from_reference (addr_tokens[i + 1]->expr);
    4110           92 :         virtual_origin = build_fold_addr_expr (virtual_origin);
    4111           92 :         virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    4112              :                                            virtual_origin);
    4113           92 :         tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
    4114              : 
    4115           92 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    4116           92 :         OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    4117           92 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    4118           92 :         OMP_CLAUSE_SIZE (c2)
    4119           92 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    4120              :                              fold_convert_loc (loc, ptrdiff_type_node,
    4121              :                                                data_addr),
    4122              :                              virtual_origin);
    4123              :       }
    4124           92 :       break;
    4125              : 
    4126          778 :     case ACCESS_POINTER:
    4127          778 :     case ACCESS_POINTER_OFFSET:
    4128          778 :       {
    4129          778 :         if (!map_p)
    4130              :           break;
    4131              : 
    4132          778 :         tree virtual_origin
    4133         1556 :           = fold_convert_loc (loc, ptrdiff_type_node,
    4134          778 :                               addr_tokens[i + 1]->expr);
    4135          778 :         tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
    4136              : 
    4137          778 :         c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
    4138          778 :         OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    4139          778 :         OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
    4140          778 :         OMP_CLAUSE_SIZE (c2)
    4141          778 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    4142              :                              fold_convert_loc (loc, ptrdiff_type_node,
    4143              :                                                data_addr),
    4144              :                              virtual_origin);
    4145              :       }
    4146          778 :       break;
    4147              : 
    4148          185 :     case ACCESS_REF_TO_POINTER:
    4149          185 :     case ACCESS_REF_TO_POINTER_OFFSET:
    4150          185 :       {
    4151          185 :         if (!map_p)
    4152              :           break;
    4153              : 
    4154          185 :         tree ptr = convert_from_reference (addr_tokens[i + 1]->expr);
    4155          185 :         tree virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
    4156              :                                                 ptr);
    4157          185 :         tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
    4158              : 
    4159              :         /* Attach the pointer...  */
    4160          185 :         c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
    4161          185 :         OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
    4162          185 :         OMP_CLAUSE_DECL (c2) = ptr;
    4163          185 :         OMP_CLAUSE_SIZE (c2)
    4164          185 :           = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
    4165              :                              fold_convert_loc (loc, ptrdiff_type_node,
    4166              :                                                data_addr),
    4167              :                              virtual_origin);
    4168              : 
    4169              :         /* ...and also the reference.  */
    4170          185 :         c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
    4171          185 :         OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_ATTACH_DETACH);
    4172          185 :         OMP_CLAUSE_DECL (c3) = addr_tokens[i + 1]->expr;
    4173          185 :         OMP_CLAUSE_SIZE (c3) = size_zero_node;
    4174              :       }
    4175          185 :       break;
    4176              : 
    4177            0 :     default:
    4178            0 :       *idx = i + 2;
    4179            0 :       return error_mark_node;
    4180              :     }
    4181              : 
    4182         1331 :   if (c3)
    4183              :     {
    4184          185 :       OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c);
    4185          185 :       OMP_CLAUSE_CHAIN (c2) = c3;
    4186          185 :       OMP_CLAUSE_CHAIN (c) = c2;
    4187          185 :       c = c3;
    4188              :     }
    4189         3049 :   else if (c2)
    4190              :     {
    4191         1331 :       OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
    4192         1331 :       OMP_CLAUSE_CHAIN (c) = c2;
    4193         1331 :       c = c2;
    4194              :     }
    4195              : 
    4196         3234 :   i += 2;
    4197         3234 :   *idx = i;
    4198              : 
    4199         3234 :   if (chain_p && map_p)
    4200           24 :     return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
    4201              : 
    4202              :   return c;
    4203              : }
    4204              : 
    4205              : /* Expand a map clause into a group of mapping clauses, creating nodes to
    4206              :    attach/detach pointers and so forth as necessary.  */
    4207              : 
    4208              : tree
    4209        21653 : c_omp_address_inspector::expand_map_clause (tree c, tree expr,
    4210              :                                             vec<omp_addr_token *> &addr_tokens,
    4211              :                                             c_omp_region_type ort)
    4212              : {
    4213        21653 :   using namespace omp_addr_tokenizer;
    4214        21653 :   unsigned i, length = addr_tokens.length ();
    4215              : 
    4216        47235 :   for (i = 0; i < length;)
    4217              :     {
    4218        25582 :       int remaining = length - i;
    4219              : 
    4220        25582 :       if (remaining >= 2
    4221        25582 :           && addr_tokens[i]->type == ARRAY_BASE
    4222        18419 :           && addr_tokens[i]->u.structure_base_kind == BASE_DECL
    4223        43992 :           && addr_tokens[i + 1]->type == ACCESS_METHOD)
    4224              :         {
    4225        18410 :           c = expand_array_base (c, addr_tokens, expr, &i, ort);
    4226        18410 :           if (c == error_mark_node)
    4227              :             return error_mark_node;
    4228              :         }
    4229         7172 :       else if (remaining >= 2
    4230         7172 :                && addr_tokens[i]->type == ARRAY_BASE
    4231            9 :                && addr_tokens[i]->u.structure_base_kind == BASE_ARBITRARY_EXPR
    4232         7181 :                && addr_tokens[i + 1]->type == ACCESS_METHOD)
    4233              :         {
    4234            9 :           c = expand_array_base (c, addr_tokens, expr, &i, ort);
    4235            9 :           if (c == error_mark_node)
    4236              :             return error_mark_node;
    4237              :         }
    4238         7163 :       else if (remaining >= 2
    4239         7163 :                && addr_tokens[i]->type == STRUCTURE_BASE
    4240         3234 :                && addr_tokens[i]->u.structure_base_kind == BASE_DECL
    4241        10394 :                && addr_tokens[i + 1]->type == ACCESS_METHOD)
    4242              :         {
    4243         3231 :           if (addr_tokens[i + 1]->u.access_kind == ACCESS_DIRECT)
    4244         1762 :             c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
    4245         3231 :           i += 2;
    4246         3391 :           while (addr_tokens[i]->type == ACCESS_METHOD)
    4247          160 :             i++;
    4248              :         }
    4249         3932 :       else if (remaining >= 2
    4250         3932 :                && addr_tokens[i]->type == STRUCTURE_BASE
    4251            3 :                && addr_tokens[i]->u.structure_base_kind == BASE_ARBITRARY_EXPR
    4252         3935 :                && addr_tokens[i + 1]->type == ACCESS_METHOD)
    4253              :         {
    4254            3 :           switch (addr_tokens[i + 1]->u.access_kind)
    4255              :             {
    4256            3 :             case ACCESS_DIRECT:
    4257            3 :             case ACCESS_POINTER:
    4258            3 :               i += 2;
    4259            3 :               while (addr_tokens[i]->type == ACCESS_METHOD)
    4260            0 :                 i++;
    4261              :               break;
    4262            0 :             default:
    4263            0 :               return error_mark_node;
    4264              :             }
    4265              :         }
    4266         3929 :       else if (remaining >= 2
    4267         3929 :                && addr_tokens[i]->type == COMPONENT_SELECTOR
    4268         7858 :                && addr_tokens[i + 1]->type == ACCESS_METHOD)
    4269              :         {
    4270         3234 :           c = expand_component_selector (c, addr_tokens, expr, &i, ort);
    4271              :           /* We used 'expr', so these must have been the last tokens.  */
    4272         3234 :           gcc_assert (i == length);
    4273         3234 :           if (c == error_mark_node)
    4274              :             return error_mark_node;
    4275              :         }
    4276          695 :       else if (remaining >= 3
    4277          695 :                && addr_tokens[i]->type == COMPONENT_SELECTOR
    4278          695 :                && addr_tokens[i + 1]->type == STRUCTURE_BASE
    4279          695 :                && (addr_tokens[i + 1]->u.structure_base_kind
    4280              :                    == BASE_COMPONENT_EXPR)
    4281         1390 :                && addr_tokens[i + 2]->type == ACCESS_METHOD)
    4282              :         {
    4283          695 :           i += 3;
    4284          719 :           while (addr_tokens[i]->type == ACCESS_METHOD)
    4285           24 :             i++;
    4286              :         }
    4287              :       else
    4288              :         break;
    4289              :     }
    4290              : 
    4291        21653 :   if (i == length)
    4292              :     return c;
    4293              : 
    4294            0 :   return error_mark_node;
    4295              : }
    4296              : 
    4297              : /* Given a mapper function MAPPER_FN, recursively scan through the map clauses
    4298              :    for that mapper, and if any of those should use a (named or unnamed) mapper
    4299              :    themselves, add it to MLIST.  */
    4300              : 
    4301              : void
    4302          140 : c_omp_find_nested_mappers (omp_mapper_list<tree> *mlist, tree mapper_fn)
    4303              : {
    4304          140 :   tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
    4305          140 :   tree mapper_name = NULL_TREE;
    4306              : 
    4307          140 :   if (mapper == error_mark_node)
    4308              :     return;
    4309              : 
    4310          140 :   gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER);
    4311              : 
    4312          454 :   for (tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper);
    4313          454 :        clause;
    4314          314 :        clause = OMP_CLAUSE_CHAIN (clause))
    4315              :     {
    4316          314 :       tree expr = OMP_CLAUSE_DECL (clause);
    4317          314 :       enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (clause);
    4318          314 :       tree elem_type;
    4319              : 
    4320          314 :       if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
    4321              :         {
    4322            0 :           mapper_name = expr;
    4323            0 :           continue;
    4324              :         }
    4325          314 :       else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
    4326              :         {
    4327            0 :           mapper_name = NULL_TREE;
    4328            0 :           continue;
    4329              :         }
    4330              : 
    4331          314 :       gcc_assert (TREE_CODE (expr) != TREE_LIST);
    4332          314 :       if (TREE_CODE (expr) == OMP_ARRAY_SECTION)
    4333              :         {
    4334          220 :           while (TREE_CODE (expr) == OMP_ARRAY_SECTION)
    4335          110 :             expr = TREE_OPERAND (expr, 0);
    4336              : 
    4337          110 :           elem_type = TREE_TYPE (expr);
    4338              :         }
    4339              :       else
    4340          204 :         elem_type = TREE_TYPE (expr);
    4341              : 
    4342              :       /* This might be too much... or not enough?  */
    4343          512 :       while (TREE_CODE (elem_type) == ARRAY_TYPE
    4344          506 :              || TREE_CODE (elem_type) == POINTER_TYPE
    4345          826 :              || TREE_CODE (elem_type) == REFERENCE_TYPE)
    4346          198 :         elem_type = TREE_TYPE (elem_type);
    4347              : 
    4348          314 :       elem_type = TYPE_MAIN_VARIANT (elem_type);
    4349              : 
    4350          314 :       if (RECORD_OR_UNION_TYPE_P (elem_type)
    4351          314 :           && !mlist->contains (mapper_name, elem_type))
    4352              :         {
    4353            5 :           tree nested_mapper_fn
    4354            5 :             = lang_hooks.decls.omp_mapper_lookup (mapper_name, elem_type);
    4355              : 
    4356            5 :           if (nested_mapper_fn)
    4357              :             {
    4358            5 :               mlist->add_mapper (mapper_name, elem_type, nested_mapper_fn);
    4359            5 :               c_omp_find_nested_mappers (mlist, nested_mapper_fn);
    4360              :             }
    4361            0 :           else if (mapper_name)
    4362              :             {
    4363            0 :               error ("mapper %qE not found for type %qT", mapper_name,
    4364              :                      elem_type);
    4365            0 :               continue;
    4366              :             }
    4367              :         }
    4368              :     }
    4369              : }
    4370              : 
    4371              : struct remap_mapper_decl_info
    4372              : {
    4373              :   tree dummy_var;
    4374              :   tree expr;
    4375              : };
    4376              : 
    4377              : /* Helper for rewriting DUMMY_VAR into EXPR in a map clause decl.  */
    4378              : 
    4379              : static tree
    4380         4044 : remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data)
    4381              : {
    4382         4044 :   remap_mapper_decl_info *map_info = (remap_mapper_decl_info *) data;
    4383              : 
    4384         4044 :   if (operand_equal_p (*tp, map_info->dummy_var))
    4385              :     {
    4386         1001 :       *tp = map_info->expr;
    4387         1001 :       *walk_subtrees = 0;
    4388              :     }
    4389              : 
    4390         4044 :   return NULL_TREE;
    4391              : }
    4392              : 
    4393              : static enum gomp_map_kind
    4394          946 : omp_split_map_kind (enum gomp_map_kind op, bool *force_p, bool *always_p,
    4395              :                     bool *present_p)
    4396              : {
    4397          946 :   *force_p = *always_p = *present_p = false;
    4398              : 
    4399          946 :   switch (op)
    4400              :     {
    4401            0 :     case GOMP_MAP_FORCE_ALLOC:
    4402            0 :     case GOMP_MAP_FORCE_TO:
    4403            0 :     case GOMP_MAP_FORCE_FROM:
    4404            0 :     case GOMP_MAP_FORCE_TOFROM:
    4405            0 :     case GOMP_MAP_FORCE_PRESENT:
    4406            0 :       *force_p = true;
    4407            0 :       break;
    4408           54 :     case GOMP_MAP_ALWAYS_TO:
    4409           54 :     case GOMP_MAP_ALWAYS_FROM:
    4410           54 :     case GOMP_MAP_ALWAYS_TOFROM:
    4411           54 :       *always_p = true;
    4412           54 :       break;
    4413           32 :     case GOMP_MAP_ALWAYS_PRESENT_TO:
    4414           32 :     case GOMP_MAP_ALWAYS_PRESENT_FROM:
    4415           32 :     case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
    4416           32 :       *always_p = true;
    4417              :       /* Fallthrough.  */
    4418          132 :     case GOMP_MAP_PRESENT_ALLOC:
    4419          132 :     case GOMP_MAP_PRESENT_TO:
    4420          132 :     case GOMP_MAP_PRESENT_FROM:
    4421          132 :     case GOMP_MAP_PRESENT_TOFROM:
    4422          132 :       *present_p = true;
    4423          132 :       break;
    4424          946 :     default:
    4425          946 :       ;
    4426              :     }
    4427              : 
    4428          946 :   switch (op)
    4429              :     {
    4430              :     case GOMP_MAP_ALLOC:
    4431              :     case GOMP_MAP_FORCE_ALLOC:
    4432              :     case GOMP_MAP_PRESENT_ALLOC:
    4433              :       return GOMP_MAP_ALLOC;
    4434          283 :     case GOMP_MAP_TO:
    4435          283 :     case GOMP_MAP_FORCE_TO:
    4436          283 :     case GOMP_MAP_ALWAYS_TO:
    4437          283 :     case GOMP_MAP_PRESENT_TO:
    4438          283 :     case GOMP_MAP_ALWAYS_PRESENT_TO:
    4439          283 :       return GOMP_MAP_TO;
    4440          212 :     case GOMP_MAP_FROM:
    4441          212 :     case GOMP_MAP_FORCE_FROM:
    4442          212 :     case GOMP_MAP_ALWAYS_FROM:
    4443          212 :     case GOMP_MAP_PRESENT_FROM:
    4444          212 :     case GOMP_MAP_ALWAYS_PRESENT_FROM:
    4445          212 :       return GOMP_MAP_FROM;
    4446          210 :     case GOMP_MAP_TOFROM:
    4447          210 :     case GOMP_MAP_FORCE_TOFROM:
    4448          210 :     case GOMP_MAP_ALWAYS_TOFROM:
    4449          210 :     case GOMP_MAP_PRESENT_TOFROM:
    4450          210 :     case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
    4451          210 :       return GOMP_MAP_TOFROM;
    4452          128 :     default:
    4453          128 :       ;
    4454              :     }
    4455              : 
    4456          128 :   return op;
    4457              : }
    4458              : 
    4459              : static enum gomp_map_kind
    4460          416 : omp_join_map_kind (enum gomp_map_kind op, bool force_p, bool always_p,
    4461              :                    bool present_p)
    4462              : {
    4463          416 :   gcc_assert (!force_p || !(always_p || present_p));
    4464              : 
    4465          416 :   switch (op)
    4466              :     {
    4467           89 :     case GOMP_MAP_ALLOC:
    4468           89 :       if (force_p)
    4469              :         return GOMP_MAP_FORCE_ALLOC;
    4470           89 :       else if (present_p)
    4471           16 :         return GOMP_MAP_PRESENT_ALLOC;
    4472              :       break;
    4473              : 
    4474          127 :     case GOMP_MAP_TO:
    4475          127 :       if (force_p)
    4476              :         return GOMP_MAP_FORCE_TO;
    4477          127 :       else if (always_p && present_p)
    4478              :         return GOMP_MAP_ALWAYS_PRESENT_TO;
    4479          115 :       else if (always_p)
    4480              :         return GOMP_MAP_ALWAYS_TO;
    4481           93 :       else if (present_p)
    4482           24 :         return GOMP_MAP_PRESENT_TO;
    4483              :       break;
    4484              : 
    4485           76 :     case GOMP_MAP_FROM:
    4486           76 :       if (force_p)
    4487              :         return GOMP_MAP_FORCE_FROM;
    4488           76 :       else if (always_p && present_p)
    4489              :         return GOMP_MAP_ALWAYS_PRESENT_FROM;
    4490           68 :       else if (always_p)
    4491              :         return GOMP_MAP_ALWAYS_FROM;
    4492           60 :       else if (present_p)
    4493           24 :         return GOMP_MAP_PRESENT_FROM;
    4494              :       break;
    4495              : 
    4496           80 :     case GOMP_MAP_TOFROM:
    4497           80 :       if (force_p)
    4498              :         return GOMP_MAP_FORCE_TOFROM;
    4499           80 :       else if (always_p && present_p)
    4500              :         return GOMP_MAP_ALWAYS_PRESENT_TOFROM;
    4501           80 :       else if (always_p)
    4502              :         return GOMP_MAP_ALWAYS_TOFROM;
    4503           80 :       else if (present_p)
    4504            0 :         return GOMP_MAP_PRESENT_TOFROM;
    4505              :       break;
    4506              : 
    4507              :     default:
    4508              :       ;
    4509              :     }
    4510              : 
    4511              :   return op;
    4512              : }
    4513              : 
    4514              : /* Map kind decay (OpenMP 5.2, 5.8.8 "declare mapper Directive").  Return the
    4515              :    map kind to use given MAPPER_KIND specified in the mapper and INVOKED_AS
    4516              :    specified on the clause that invokes the mapper.  See also
    4517              :    fortran/trans-openmp.cc:omp_map_decayed_kind.  */
    4518              : 
    4519              : static enum gomp_map_kind
    4520          432 : omp_map_decayed_kind (enum gomp_map_kind mapper_kind,
    4521              :                       enum gomp_map_kind invoked_as, bool exit_p)
    4522              : {
    4523          432 :   if (invoked_as == GOMP_MAP_RELEASE || invoked_as == GOMP_MAP_DELETE)
    4524              :     return invoked_as;
    4525              : 
    4526          416 :   bool m_force_p, m_always_p, m_present_p;
    4527          416 :   bool force_p, always_p, present_p;
    4528              : 
    4529          416 :   mapper_kind = omp_split_map_kind (mapper_kind, &m_force_p, &m_always_p, &m_present_p);
    4530          416 :   invoked_as = omp_split_map_kind (invoked_as, &force_p, &always_p, &present_p);
    4531          416 :   gomp_map_kind decay_to;
    4532              : 
    4533          416 :   switch (mapper_kind)
    4534              :     {
    4535           53 :     case GOMP_MAP_ALLOC:
    4536           53 :       if (exit_p && invoked_as == GOMP_MAP_FROM)
    4537              :         decay_to = GOMP_MAP_RELEASE;
    4538              :       else
    4539           77 :         decay_to = GOMP_MAP_ALLOC;
    4540              :       break;
    4541              : 
    4542          115 :     case GOMP_MAP_TO:
    4543          115 :       if (invoked_as == GOMP_MAP_FROM)
    4544          101 :         decay_to = exit_p ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
    4545           91 :       else if (invoked_as == GOMP_MAP_ALLOC)
    4546              :         decay_to = GOMP_MAP_ALLOC;
    4547              :       else
    4548          416 :         decay_to = GOMP_MAP_TO;
    4549              :       break;
    4550              : 
    4551           52 :     case GOMP_MAP_FROM:
    4552           52 :       if (invoked_as == GOMP_MAP_ALLOC || invoked_as == GOMP_MAP_TO)
    4553              :         decay_to = GOMP_MAP_ALLOC;
    4554              :       else
    4555          416 :         decay_to = GOMP_MAP_FROM;
    4556              :       break;
    4557              : 
    4558              :     case GOMP_MAP_TOFROM:
    4559              :     case GOMP_MAP_UNSET:
    4560              :       decay_to = invoked_as;
    4561              :       break;
    4562              : 
    4563            0 :     default:
    4564            0 :       gcc_unreachable ();
    4565              :     }
    4566              : 
    4567          416 :   return omp_join_map_kind (decay_to, m_force_p | force_p,
    4568          416 :                             m_always_p | always_p, m_present_p | present_p);
    4569              : }
    4570              : 
    4571              : /* Return a name to use for a "basic" map kind, e.g. as output from
    4572              :    omp_split_map_kind above.  */
    4573              : 
    4574              : static const char *
    4575           16 : omp_basic_map_kind_name (enum gomp_map_kind kind)
    4576              : {
    4577           16 :   switch (kind)
    4578              :     {
    4579              :     case GOMP_MAP_ALLOC:
    4580              :       return "alloc";
    4581            4 :     case GOMP_MAP_TO:
    4582            4 :       return "to";
    4583            4 :     case GOMP_MAP_FROM:
    4584            4 :       return "from";
    4585            0 :     case GOMP_MAP_TOFROM:
    4586            0 :       return "tofrom";
    4587            0 :     case GOMP_MAP_RELEASE:
    4588            0 :       return "release";
    4589            0 :     case GOMP_MAP_DELETE:
    4590            0 :       return "delete";
    4591            0 :     default:
    4592            0 :       gcc_unreachable ();
    4593              :     }
    4594              : }
    4595              : 
    4596              : /* Instantiate a mapper MAPPER for expression EXPR at location LOC,
    4597              :    adding new clauses to OUTLIST.  OUTER_KIND is the mapping kind
    4598              :    to use if not already specified in the mapper declaration; ORT
    4599              :    denotes the directive that uses the mapper.
    4600              :    The resulting OUTLIST is also returned by the function.  */
    4601              : 
    4602              : static tree *
    4603          142 : omp_instantiate_mapper (location_t loc, tree *outlist, tree mapper, tree expr,
    4604              :                         enum gomp_map_kind outer_kind,
    4605              :                         enum c_omp_region_type ort)
    4606              : {
    4607          142 :   tree clauses = OMP_DECLARE_MAPPER_CLAUSES (mapper);
    4608          142 :   tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper);
    4609          142 :   tree mapper_name = NULL_TREE;
    4610              : 
    4611          142 :   remap_mapper_decl_info map_info;
    4612          142 :   map_info.dummy_var = dummy_var;
    4613          142 :   map_info.expr = expr;
    4614              : 
    4615          574 :   for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
    4616              :     {
    4617          432 :       tree unshared = unshare_expr (c);
    4618          432 :       enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (c);
    4619          432 :       tree t = OMP_CLAUSE_DECL (unshared);
    4620          432 :       tree type = NULL_TREE;
    4621          432 :       bool nonunit_array_with_mapper = false;
    4622              : 
    4623          432 :       if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
    4624              :         {
    4625            0 :           mapper_name = t;
    4626            2 :           continue;
    4627              :         }
    4628          432 :       else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
    4629              :         {
    4630            0 :           mapper_name = NULL_TREE;
    4631            0 :           continue;
    4632              :         }
    4633              : 
    4634          432 :       if (TREE_CODE (t) == OMP_ARRAY_SECTION)
    4635              :         {
    4636           43 :           tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
    4637              : 
    4638           43 :           if (t2 == t)
    4639              :             {
    4640           42 :               nonunit_array_with_mapper = true;
    4641              :               /* We'd want use the mapper for the element type if this worked:
    4642              :                  look that one up.  */
    4643           42 :               type = TREE_TYPE (TREE_TYPE (t));
    4644              :             }
    4645              :           else
    4646              :             {
    4647            1 :               t = t2;
    4648            1 :               type = TREE_TYPE (t);
    4649              :             }
    4650              :         }
    4651              :       else
    4652          389 :         type = TREE_TYPE (t);
    4653              : 
    4654          432 :       gcc_assert (type);
    4655              : 
    4656          432 :       if (type == error_mark_node)
    4657            0 :         continue;
    4658              : 
    4659          432 :       walk_tree (&unshared, remap_mapper_decl_1, &map_info, NULL);
    4660              : 
    4661          432 :       OMP_CLAUSE_LOCATION (unshared) = loc;
    4662              : 
    4663          432 :       enum gomp_map_kind decayed_kind
    4664          548 :         = omp_map_decayed_kind (clause_kind, outer_kind,
    4665              :                                 (ort & C_ORT_EXIT_DATA) != 0
    4666              :                                 || (outer_kind == GOMP_MAP_FROM
    4667           32 :                                     && (ort & C_ORT_UPDATE) != 0));
    4668          432 :       OMP_CLAUSE_SET_MAP_KIND (unshared, decayed_kind);
    4669              : 
    4670          432 :       type = TYPE_MAIN_VARIANT (type);
    4671              : 
    4672          432 :       tree mapper_fn = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
    4673              : 
    4674          432 :       if (mapper_fn && nonunit_array_with_mapper)
    4675              :         {
    4676            0 :           sorry ("user-defined mapper with non-unit length array section");
    4677            0 :           continue;
    4678              :         }
    4679          432 :       else if (mapper_fn)
    4680              :         {
    4681           27 :           tree nested_mapper
    4682           27 :             = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
    4683           27 :           if (nested_mapper != mapper)
    4684              :             {
    4685            2 :               outlist = omp_instantiate_mapper (loc, outlist, nested_mapper,
    4686              :                                                 t, outer_kind, ort);
    4687            2 :               continue;
    4688              :             }
    4689              :         }
    4690          405 :       else if (mapper_name)
    4691              :         {
    4692            0 :           error ("mapper %qE not found for type %qT", mapper_name, type);
    4693            0 :           continue;
    4694              :         }
    4695              : 
    4696          430 :       if (ort & C_ORT_UPDATE)
    4697              :         {
    4698           98 :           bool force_p, always_p, present_p;
    4699           98 :           decayed_kind
    4700           98 :             = omp_split_map_kind (decayed_kind, &force_p, &always_p,
    4701              :                                   &present_p);
    4702              :           /* We don't expect to see these flags here.  */
    4703           98 :           gcc_assert (!force_p && !always_p);
    4704              :           /* For a "target update" operation, we want to turn the map node
    4705              :              expanded from the mapper back into a OMP_CLAUSE_TO or
    4706              :              OMP_CLAUSE_FROM node.  If we can do neither, emit a warning and
    4707              :              drop the clause.  */
    4708           98 :           switch (decayed_kind)
    4709              :             {
    4710           82 :             case GOMP_MAP_TO:
    4711           82 :             case GOMP_MAP_FROM:
    4712           82 :               {
    4713           82 :                 tree xfer
    4714          122 :                   = build_omp_clause (loc, (decayed_kind == GOMP_MAP_TO
    4715              :                                             ? OMP_CLAUSE_TO : OMP_CLAUSE_FROM));
    4716           82 :                 OMP_CLAUSE_DECL (xfer) = OMP_CLAUSE_DECL (unshared);
    4717           82 :                 OMP_CLAUSE_SIZE (xfer) = OMP_CLAUSE_SIZE (unshared);
    4718              :                 /* For FROM/TO clauses, "present" is represented by a flag.
    4719              :                    Set it for the expanded clause here.  */
    4720           82 :                 if (present_p)
    4721           32 :                   OMP_CLAUSE_MOTION_PRESENT (xfer) = 1;
    4722           82 :                 *outlist = xfer;
    4723           82 :                 outlist = &OMP_CLAUSE_CHAIN (xfer);
    4724              :               }
    4725           82 :               break;
    4726           16 :             default:
    4727           16 :               clause_kind
    4728           16 :                 = omp_split_map_kind (clause_kind, &force_p, &always_p,
    4729              :                                       &present_p);
    4730           16 :               warning_at (loc, OPT_Wopenmp,
    4731              :                           "dropping %qs clause during mapper expansion "
    4732              :                           "in %<#pragma omp target update%>",
    4733              :                           omp_basic_map_kind_name (clause_kind));
    4734           16 :               inform (OMP_CLAUSE_LOCATION (c), "for map clause here");
    4735              :             }
    4736              :         }
    4737              :       else
    4738              :         {
    4739          332 :           *outlist = unshared;
    4740          332 :           outlist = &OMP_CLAUSE_CHAIN (unshared);
    4741              :         }
    4742              :     }
    4743              : 
    4744          142 :   return outlist;
    4745              : }
    4746              : 
    4747              : /* Given a list of CLAUSES, scan each clause and invoke a user-defined mapper
    4748              :    appropriate to the type of the data in that clause, if such a mapper is
    4749              :    visible in the current parsing context.  */
    4750              : 
    4751              : tree
    4752        16773 : c_omp_instantiate_mappers (tree clauses, enum c_omp_region_type ort)
    4753              : {
    4754        16773 :   tree c, *pc, mapper_name = NULL_TREE;
    4755              : 
    4756        36673 :   for (pc = &clauses, c = clauses; c; c = *pc)
    4757              :     {
    4758        19900 :       bool using_mapper = false;
    4759        19900 :       bool update_p = false, update_present_p = false;
    4760              : 
    4761        19900 :       switch (OMP_CLAUSE_CODE (c))
    4762              :         {
    4763         6017 :         case OMP_CLAUSE_TO:
    4764         6017 :         case OMP_CLAUSE_FROM:
    4765         6017 :           update_p = true;
    4766         6017 :           if (OMP_CLAUSE_MOTION_PRESENT (c))
    4767           58 :             update_present_p = true;
    4768              :           /* Fallthrough.  */
    4769        13343 :         case OMP_CLAUSE_MAP:
    4770        13343 :           {
    4771        13343 :             tree t = OMP_CLAUSE_DECL (c);
    4772        13343 :             tree type = NULL_TREE;
    4773        13343 :             bool nonunit_array_with_mapper = false;
    4774              : 
    4775        13417 :             if (!update_p
    4776        13343 :                 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME
    4777         7289 :                     || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POP_MAPPER_NAME))
    4778              :               {
    4779           74 :                 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME)
    4780           37 :                   mapper_name = OMP_CLAUSE_DECL (c);
    4781              :                 else
    4782              :                   mapper_name = NULL_TREE;
    4783           74 :                 pc = &OMP_CLAUSE_CHAIN (c);
    4784           74 :                 continue;
    4785              :               }
    4786              : 
    4787        13269 :             if (TREE_CODE (t) == OMP_ARRAY_SECTION)
    4788              :               {
    4789         2451 :                 location_t loc = OMP_CLAUSE_LOCATION (c);
    4790         2451 :                 tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
    4791              : 
    4792         2451 :                 if (t2 == t)
    4793              :                   {
    4794              :                     /* !!! Array sections of size >1 with mappers for elements
    4795              :                        are hard to support.  Do something here.  */
    4796         2037 :                     nonunit_array_with_mapper = true;
    4797         2037 :                     type = TREE_TYPE (TREE_TYPE (t));
    4798              :                   }
    4799              :                 else
    4800              :                   {
    4801          414 :                     t = t2;
    4802          414 :                     type = TREE_TYPE (t);
    4803              :                   }
    4804              :               }
    4805              :             else
    4806        10818 :               type = TREE_TYPE (t);
    4807              : 
    4808        13269 :             if (type == NULL_TREE || type == error_mark_node)
    4809              :               {
    4810           73 :                 pc = &OMP_CLAUSE_CHAIN (c);
    4811           73 :                 continue;
    4812              :               }
    4813              : 
    4814        13196 :             enum gomp_map_kind kind;
    4815        13196 :             if (update_p)
    4816              :               {
    4817         6017 :                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO)
    4818          999 :                   kind = update_present_p ? GOMP_MAP_PRESENT_TO
    4819              :                                           : GOMP_MAP_TO;
    4820              :                 else
    4821         5018 :                   kind = update_present_p ? GOMP_MAP_PRESENT_FROM
    4822              :                                           : GOMP_MAP_FROM;
    4823              :               }
    4824              :             else
    4825              :               {
    4826         7179 :                 kind = OMP_CLAUSE_MAP_KIND (c);
    4827         7179 :                 if (kind == GOMP_MAP_UNSET)
    4828            0 :                   kind = GOMP_MAP_TOFROM;
    4829              :               }
    4830              : 
    4831        13196 :             type = TYPE_MAIN_VARIANT (type);
    4832              : 
    4833        13196 :             tree mapper_fn
    4834        13196 :               = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
    4835              : 
    4836        13196 :             if (mapper_fn && nonunit_array_with_mapper)
    4837              :               {
    4838            0 :                 sorry ("user-defined mapper with non-unit length "
    4839              :                        "array section");
    4840            0 :                 using_mapper = true;
    4841              :               }
    4842        13196 :             else if (mapper_fn)
    4843              :               {
    4844          140 :                 tree mapper
    4845          140 :                   = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
    4846          140 :                 pc = omp_instantiate_mapper (OMP_CLAUSE_LOCATION (c),
    4847              :                                              pc, mapper, t, kind, ort);
    4848          140 :                 using_mapper = true;
    4849              :               }
    4850        13056 :             else if (mapper_name)
    4851              :               {
    4852            0 :                 error ("mapper %qE not found for type %qT", mapper_name, type);
    4853            0 :                 using_mapper = true;
    4854              :               }
    4855              :           }
    4856              :           break;
    4857              : 
    4858          140 :         default:
    4859          140 :           ;
    4860              :         }
    4861              : 
    4862          140 :       if (using_mapper)
    4863          140 :         *pc = OMP_CLAUSE_CHAIN (c);
    4864              :       else
    4865        19613 :         pc = &OMP_CLAUSE_CHAIN (c);
    4866              :     }
    4867              : 
    4868        16773 :   return clauses;
    4869              : }
    4870              : 
    4871              : const struct c_omp_directive c_omp_directives[] = {
    4872              :   /* Keep this alphabetically sorted by the first word.  Non-null second/third
    4873              :      if any should precede null ones.  */
    4874              :   { "allocate", nullptr, nullptr, PRAGMA_OMP_ALLOCATE,
    4875              :     C_OMP_DIR_DECLARATIVE, false },
    4876              :   { "assume", nullptr, nullptr, PRAGMA_OMP_ASSUME,
    4877              :     C_OMP_DIR_INFORMATIONAL, false },
    4878              :   { "assumes", nullptr, nullptr, PRAGMA_OMP_ASSUMES,
    4879              :     C_OMP_DIR_INFORMATIONAL, false },
    4880              :   { "atomic", nullptr, nullptr, PRAGMA_OMP_ATOMIC,
    4881              :     C_OMP_DIR_CONSTRUCT, false },
    4882              :   { "barrier", nullptr, nullptr, PRAGMA_OMP_BARRIER,
    4883              :     C_OMP_DIR_STANDALONE, false },
    4884              :   { "begin", "assumes", nullptr, PRAGMA_OMP_BEGIN,
    4885              :     C_OMP_DIR_INFORMATIONAL, false },
    4886              :   { "begin", "declare", "target", PRAGMA_OMP_BEGIN,
    4887              :     C_OMP_DIR_DECLARATIVE, false },
    4888              :   { "begin", "declare", "variant", PRAGMA_OMP_BEGIN,
    4889              :     C_OMP_DIR_DECLARATIVE, false },
    4890              :   /* 'begin metadirective' is not yet implemented; however,
    4891              :      it is only applicable if an end-directive exists, but
    4892              :      metadirectives are of limited use for declarative directives.  */
    4893              :   /* { "begin", "metadirective", nullptr, PRAGMA_OMP_BEGIN,
    4894              :     C_OMP_DIR_META, false },  */
    4895              :   { "cancel", nullptr, nullptr, PRAGMA_OMP_CANCEL,
    4896              :     C_OMP_DIR_STANDALONE, false },
    4897              :   { "cancellation", "point", nullptr, PRAGMA_OMP_CANCELLATION_POINT,
    4898              :     C_OMP_DIR_STANDALONE, false },
    4899              :   { "critical", nullptr, nullptr, PRAGMA_OMP_CRITICAL,
    4900              :     C_OMP_DIR_CONSTRUCT, false },
    4901              :   /* { "declare", "induction", nullptr, PRAGMA_OMP_DECLARE,
    4902              :     C_OMP_DIR_DECLARATIVE, true }, */
    4903              :   { "declare", "mapper", nullptr, PRAGMA_OMP_DECLARE,
    4904              :     C_OMP_DIR_DECLARATIVE, false },
    4905              :   { "declare", "reduction", nullptr, PRAGMA_OMP_DECLARE,
    4906              :     C_OMP_DIR_DECLARATIVE, true },
    4907              :   { "declare", "simd", nullptr, PRAGMA_OMP_DECLARE,
    4908              :     C_OMP_DIR_DECLARATIVE, true },
    4909              :   { "declare", "target", nullptr, PRAGMA_OMP_DECLARE,
    4910              :     C_OMP_DIR_DECLARATIVE, false },
    4911              :   { "declare", "variant", nullptr, PRAGMA_OMP_DECLARE,
    4912              :     C_OMP_DIR_DECLARATIVE, false },
    4913              :   { "depobj", nullptr, nullptr, PRAGMA_OMP_DEPOBJ,
    4914              :     C_OMP_DIR_STANDALONE, false },
    4915              :   { "dispatch", nullptr, nullptr, PRAGMA_OMP_DISPATCH,
    4916              :     C_OMP_DIR_DECLARATIVE, false },
    4917              :   { "distribute", nullptr, nullptr, PRAGMA_OMP_DISTRIBUTE,
    4918              :     C_OMP_DIR_CONSTRUCT, true },
    4919              :   { "end", "assumes", nullptr, PRAGMA_OMP_END,
    4920              :     C_OMP_DIR_INFORMATIONAL, false },
    4921              :   { "end", "declare", "target", PRAGMA_OMP_END,
    4922              :     C_OMP_DIR_DECLARATIVE, false },
    4923              :   { "end", "declare", "variant", PRAGMA_OMP_END,
    4924              :     C_OMP_DIR_DECLARATIVE, false },
    4925              :   /* { "end", "metadirective", nullptr, PRAGMA_OMP_END,
    4926              :     C_OMP_DIR_META, false },  */
    4927              :   /* error with at(execution) is C_OMP_DIR_STANDALONE.  */
    4928              :   { "error", nullptr, nullptr, PRAGMA_OMP_ERROR,
    4929              :     C_OMP_DIR_UTILITY, false },
    4930              :   /* { "flatten", nullptr, nullptr, PRAGMA_OMP_FLATTEN,
    4931              :     C_OMP_DIR_CONSTRUCT, true },  */
    4932              :   { "flush", nullptr, nullptr, PRAGMA_OMP_FLUSH,
    4933              :     C_OMP_DIR_STANDALONE, false },
    4934              :   { "for", nullptr, nullptr, PRAGMA_OMP_FOR,
    4935              :     C_OMP_DIR_CONSTRUCT, true },
    4936              :   /* { "fuse", nullptr, nullptr, PRAGMA_OMP_FUSE,
    4937              :     C_OMP_DIR_CONSTRUCT, true },  */
    4938              :   { "groupprivate", nullptr, nullptr, PRAGMA_OMP_GROUPPRIVATE,
    4939              :     C_OMP_DIR_DECLARATIVE, false },
    4940              :   /* { "interchange", nullptr, nullptr, PRAGMA_OMP_INTERCHANGE,
    4941              :     C_OMP_DIR_CONSTRUCT, true },  */
    4942              :   { "interop", nullptr, nullptr, PRAGMA_OMP_INTEROP,
    4943              :     C_OMP_DIR_STANDALONE, false },
    4944              :   { "loop", nullptr, nullptr, PRAGMA_OMP_LOOP,
    4945              :     C_OMP_DIR_CONSTRUCT, true },
    4946              :   { "masked", nullptr, nullptr, PRAGMA_OMP_MASKED,
    4947              :     C_OMP_DIR_CONSTRUCT, true },
    4948              :   { "master", nullptr, nullptr, PRAGMA_OMP_MASTER,
    4949              :     C_OMP_DIR_CONSTRUCT, true },
    4950              :   { "metadirective", nullptr, nullptr, PRAGMA_OMP_METADIRECTIVE,
    4951              :     C_OMP_DIR_META, false },
    4952              :   { "nothing", nullptr, nullptr, PRAGMA_OMP_NOTHING,
    4953              :     C_OMP_DIR_UTILITY, false },
    4954              :   /* ordered with depend clause is C_OMP_DIR_STANDALONE.  */
    4955              :   { "ordered", nullptr, nullptr, PRAGMA_OMP_ORDERED,
    4956              :     C_OMP_DIR_CONSTRUCT, true },
    4957              :   { "parallel", nullptr, nullptr, PRAGMA_OMP_PARALLEL,
    4958              :     C_OMP_DIR_CONSTRUCT, true },
    4959              :   { "requires", nullptr, nullptr, PRAGMA_OMP_REQUIRES,
    4960              :     C_OMP_DIR_INFORMATIONAL, false },
    4961              :   { "scan", nullptr, nullptr, PRAGMA_OMP_SCAN,
    4962              :     C_OMP_DIR_CONSTRUCT, true },
    4963              :   { "scope", nullptr, nullptr, PRAGMA_OMP_SCOPE,
    4964              :     C_OMP_DIR_CONSTRUCT, false },
    4965              :   { "section", nullptr, nullptr, PRAGMA_OMP_SECTION,
    4966              :     C_OMP_DIR_CONSTRUCT, false },
    4967              :   { "sections", nullptr, nullptr, PRAGMA_OMP_SECTIONS,
    4968              :     C_OMP_DIR_CONSTRUCT, false },
    4969              :   { "simd", nullptr, nullptr, PRAGMA_OMP_SIMD,
    4970              :     C_OMP_DIR_CONSTRUCT, true },
    4971              :   { "single", nullptr, nullptr, PRAGMA_OMP_SINGLE,
    4972              :     C_OMP_DIR_CONSTRUCT, false },
    4973              :   /* { "split", nullptr, nullptr, PRAGMA_OMP_SPLIT,
    4974              :     C_OMP_DIR_CONSTRUCT, true },  */
    4975              :   /* { "stripe", nullptr, nullptr, PRAGMA_OMP_STRIPE,
    4976              :     C_OMP_DIR_CONSTRUCT, true },  */
    4977              :   { "target", "data", nullptr, PRAGMA_OMP_TARGET,
    4978              :     C_OMP_DIR_CONSTRUCT, false },
    4979              :   { "target", "enter", "data", PRAGMA_OMP_TARGET,
    4980              :     C_OMP_DIR_STANDALONE, false },
    4981              :   { "target", "exit", "data", PRAGMA_OMP_TARGET,
    4982              :     C_OMP_DIR_STANDALONE, false },
    4983              :   { "target", "update", nullptr, PRAGMA_OMP_TARGET,
    4984              :     C_OMP_DIR_STANDALONE, false },
    4985              :   { "target", nullptr, nullptr, PRAGMA_OMP_TARGET,
    4986              :     C_OMP_DIR_CONSTRUCT, true },
    4987              :   { "task", nullptr, nullptr, PRAGMA_OMP_TASK,
    4988              :     C_OMP_DIR_CONSTRUCT, false },
    4989              :   /* { "task", "iteration", nullptr, PRAGMA_OMP_TASK_ITERATION,
    4990              :     C_OMP_DIR_STANDALONE, false },  */
    4991              :   /* { "taskgraph", nullptr, nullptr, PRAGMA_OMP_TASKGRAPH,
    4992              :     C_OMP_DIR_CONSTRUCT, false },  */
    4993              :   { "taskgroup", nullptr, nullptr, PRAGMA_OMP_TASKGROUP,
    4994              :     C_OMP_DIR_CONSTRUCT, false },
    4995              :   { "taskloop", nullptr, nullptr, PRAGMA_OMP_TASKLOOP,
    4996              :     C_OMP_DIR_CONSTRUCT, true },
    4997              :   { "taskwait", nullptr, nullptr, PRAGMA_OMP_TASKWAIT,
    4998              :     C_OMP_DIR_STANDALONE, false },
    4999              :   { "taskyield", nullptr, nullptr, PRAGMA_OMP_TASKYIELD,
    5000              :     C_OMP_DIR_STANDALONE, false },
    5001              :   { "tile", nullptr, nullptr, PRAGMA_OMP_TILE,
    5002              :     C_OMP_DIR_CONSTRUCT, false },
    5003              :   { "teams", nullptr, nullptr, PRAGMA_OMP_TEAMS,
    5004              :     C_OMP_DIR_CONSTRUCT, true },
    5005              :   { "threadprivate", nullptr, nullptr, PRAGMA_OMP_THREADPRIVATE,
    5006              :     C_OMP_DIR_DECLARATIVE, false },
    5007              :   { "unroll", nullptr, nullptr, PRAGMA_OMP_UNROLL,
    5008              :     C_OMP_DIR_CONSTRUCT, false },
    5009              : };
    5010              : 
    5011              : /* Find (non-combined/composite) OpenMP directive (if any) which starts
    5012              :    with FIRST keyword and for multi-word directives has SECOND and
    5013              :    THIRD keyword after it.  */
    5014              : 
    5015              : const struct c_omp_directive *
    5016         6652 : c_omp_categorize_directive (const char *first, const char *second,
    5017              :                             const char *third)
    5018              : {
    5019         6652 :   const size_t n_omp_directives = ARRAY_SIZE (c_omp_directives);
    5020       211591 :   for (size_t i = 0; i < n_omp_directives; i++)
    5021              :     {
    5022       396186 :       if ((unsigned char) c_omp_directives[i].first[0]
    5023       211591 :           < (unsigned char) first[0])
    5024       184595 :         continue;
    5025        26996 :       if ((unsigned char) c_omp_directives[i].first[0]
    5026              :           > (unsigned char) first[0])
    5027              :         break;
    5028        26909 :       if (strcmp (c_omp_directives[i].first, first))
    5029        16103 :         continue;
    5030        10806 :       if (!c_omp_directives[i].second)
    5031         5138 :         return &c_omp_directives[i];
    5032         5668 :       if (!second || strcmp (c_omp_directives[i].second, second))
    5033         4205 :         continue;
    5034         1463 :       if (!c_omp_directives[i].third)
    5035         1127 :         return &c_omp_directives[i];
    5036          336 :       if (!third || strcmp (c_omp_directives[i].third, third))
    5037           36 :         continue;
    5038          300 :       return &c_omp_directives[i];
    5039              :     }
    5040              :   return NULL;
    5041              : }
    5042              : 
    5043              : /* Auxiliary helper function for c_omp_expand_variant_construct.  */
    5044              : 
    5045              : static tree
    5046          388 : c_omp_expand_variant_construct_r (vec<struct omp_variant> &candidates,
    5047              :                               hash_map<tree, tree> &body_labels,
    5048              :                               unsigned index)
    5049              : {
    5050          388 :   struct omp_variant &candidate = candidates[index];
    5051          388 :   tree if_block = push_stmt_list ();
    5052          388 :   if (candidate.alternative != NULL_TREE)
    5053          388 :     add_stmt (candidate.alternative);
    5054          388 :   if (candidate.body != NULL_TREE)
    5055              :     {
    5056          118 :       tree *label = body_labels.get (candidate.body);
    5057          118 :       if (label != NULL)
    5058            0 :         add_stmt (build1 (GOTO_EXPR, void_type_node, *label));
    5059              :       else
    5060              :         {
    5061          118 :           tree body_label = create_artificial_label (UNKNOWN_LOCATION);
    5062          118 :           add_stmt (build1 (LABEL_EXPR, void_type_node, body_label));
    5063          118 :           add_stmt (candidate.body);
    5064          118 :           body_labels.put (candidate.body, body_label);
    5065              :         }
    5066              :     }
    5067          388 :   if_block = pop_stmt_list (if_block);
    5068              : 
    5069          776 :   if (index == candidates.length () - 1)
    5070              :     return if_block;
    5071              : 
    5072          154 :   tree cond = omp_dynamic_cond (candidate.selector, NULL_TREE);
    5073          154 :   gcc_assert (cond != NULL_TREE);
    5074              : 
    5075          154 :   tree else_block = c_omp_expand_variant_construct_r (candidates, body_labels,
    5076              :                                                       index + 1);
    5077          154 :   tree ret = push_stmt_list ();
    5078          154 :   tree stmt = build3 (COND_EXPR, void_type_node, cond, if_block, else_block);
    5079          154 :   add_stmt (stmt);
    5080          154 :   ret = pop_stmt_list (ret);
    5081              : 
    5082          154 :   return ret;
    5083              : }
    5084              : 
    5085              : /* Resolve the vector of metadirective variant CANDIDATES to a parse tree
    5086              :    structure.  */
    5087              : 
    5088              : tree
    5089          234 : c_omp_expand_variant_construct (vec<struct omp_variant> &candidates)
    5090              : {
    5091          234 :   hash_map<tree, tree> body_labels;
    5092          234 :   return c_omp_expand_variant_construct_r (candidates, body_labels, 0);
    5093          234 : }
        

Generated by: LCOV version 2.5.0-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.