xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/c-family/c-omp.c (revision d909946ca08dceb44d7d0f22ec9488679695d976)
1 /* This file contains routines to construct GNU OpenMP constructs,
2    called from parsing in the C and C++ front ends.
3 
4    Copyright (C) 2005-2013 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 "tree.h"
28 #include "c-common.h"
29 #include "gimple.h"		/* For create_tmp_var_raw.  */
30 #include "langhooks.h"
31 
32 
33 /* Complete a #pragma omp master construct.  STMT is the structured-block
34    that follows the pragma.  LOC is the l*/
35 
36 tree
37 c_finish_omp_master (location_t loc, tree stmt)
38 {
39   tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
40   SET_EXPR_LOCATION (t, loc);
41   return t;
42 }
43 
44 /* Complete a #pragma omp critical construct.  STMT is the structured-block
45    that follows the pragma, NAME is the identifier in the pragma, or null
46    if it was omitted.  LOC is the location of the #pragma.  */
47 
48 tree
49 c_finish_omp_critical (location_t loc, tree body, tree name)
50 {
51   tree stmt = make_node (OMP_CRITICAL);
52   TREE_TYPE (stmt) = void_type_node;
53   OMP_CRITICAL_BODY (stmt) = body;
54   OMP_CRITICAL_NAME (stmt) = name;
55   SET_EXPR_LOCATION (stmt, loc);
56   return add_stmt (stmt);
57 }
58 
59 /* Complete a #pragma omp ordered construct.  STMT is the structured-block
60    that follows the pragma.  LOC is the location of the #pragma.  */
61 
62 tree
63 c_finish_omp_ordered (location_t loc, tree stmt)
64 {
65   tree t = build1 (OMP_ORDERED, void_type_node, stmt);
66   SET_EXPR_LOCATION (t, loc);
67   return add_stmt (t);
68 }
69 
70 
71 /* Complete a #pragma omp barrier construct.  LOC is the location of
72    the #pragma.  */
73 
74 void
75 c_finish_omp_barrier (location_t loc)
76 {
77   tree x;
78 
79   x = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
80   x = build_call_expr_loc (loc, x, 0);
81   add_stmt (x);
82 }
83 
84 
85 /* Complete a #pragma omp taskwait construct.  LOC is the location of the
86    pragma.  */
87 
88 void
89 c_finish_omp_taskwait (location_t loc)
90 {
91   tree x;
92 
93   x = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
94   x = build_call_expr_loc (loc, x, 0);
95   add_stmt (x);
96 }
97 
98 
99 /* Complete a #pragma omp taskyield construct.  LOC is the location of the
100    pragma.  */
101 
102 void
103 c_finish_omp_taskyield (location_t loc)
104 {
105   tree x;
106 
107   x = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
108   x = build_call_expr_loc (loc, x, 0);
109   add_stmt (x);
110 }
111 
112 
113 /* Complete a #pragma omp atomic construct.  For CODE OMP_ATOMIC
114    the expression to be implemented atomically is LHS opcode= RHS.
115    For OMP_ATOMIC_READ V = LHS, for OMP_ATOMIC_CAPTURE_{NEW,OLD} LHS
116    opcode= RHS with the new or old content of LHS returned.
117    LOC is the location of the atomic statement.  The value returned
118    is either error_mark_node (if the construct was erroneous) or an
119    OMP_ATOMIC* node which should be added to the current statement
120    tree with add_stmt.  */
121 
122 tree
123 c_finish_omp_atomic (location_t loc, enum tree_code code,
124 		     enum tree_code opcode, tree lhs, tree rhs,
125 		     tree v, tree lhs1, tree rhs1)
126 {
127   tree x, type, addr;
128 
129   if (lhs == error_mark_node || rhs == error_mark_node
130       || v == error_mark_node || lhs1 == error_mark_node
131       || rhs1 == error_mark_node)
132     return error_mark_node;
133 
134   /* ??? According to one reading of the OpenMP spec, complex type are
135      supported, but there are no atomic stores for any architecture.
136      But at least icc 9.0 doesn't support complex types here either.
137      And lets not even talk about vector types...  */
138   type = TREE_TYPE (lhs);
139   if (!INTEGRAL_TYPE_P (type)
140       && !POINTER_TYPE_P (type)
141       && !SCALAR_FLOAT_TYPE_P (type))
142     {
143       error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
144       return error_mark_node;
145     }
146 
147   /* ??? Validate that rhs does not overlap lhs.  */
148 
149   /* Take and save the address of the lhs.  From then on we'll reference it
150      via indirection.  */
151   addr = build_unary_op (loc, ADDR_EXPR, lhs, 0);
152   if (addr == error_mark_node)
153     return error_mark_node;
154   addr = save_expr (addr);
155   if (TREE_CODE (addr) != SAVE_EXPR
156       && (TREE_CODE (addr) != ADDR_EXPR
157 	  || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL))
158     {
159       /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
160 	 it even after unsharing function body.  */
161       tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL);
162       DECL_CONTEXT (var) = current_function_decl;
163       addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
164     }
165   lhs = build_indirect_ref (loc, addr, RO_NULL);
166 
167   if (code == OMP_ATOMIC_READ)
168     {
169       x = build1 (OMP_ATOMIC_READ, type, addr);
170       SET_EXPR_LOCATION (x, loc);
171       return build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
172 				loc, x, NULL_TREE);
173       return x;
174     }
175 
176   /* There are lots of warnings, errors, and conversions that need to happen
177      in the course of interpreting a statement.  Use the normal mechanisms
178      to do this, and then take it apart again.  */
179   x = build_modify_expr (input_location, lhs, NULL_TREE, opcode,
180       			 input_location, rhs, NULL_TREE);
181   if (x == error_mark_node)
182     return error_mark_node;
183   gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
184   rhs = TREE_OPERAND (x, 1);
185 
186   /* Punt the actual generation of atomic operations to common code.  */
187   if (code == OMP_ATOMIC)
188     type = void_type_node;
189   x = build2 (code, type, addr, rhs);
190   SET_EXPR_LOCATION (x, loc);
191 
192   /* Generally it is hard to prove lhs1 and lhs are the same memory
193      location, just diagnose different variables.  */
194   if (rhs1
195       && TREE_CODE (rhs1) == VAR_DECL
196       && TREE_CODE (lhs) == VAR_DECL
197       && rhs1 != lhs)
198     {
199       if (code == OMP_ATOMIC)
200 	error_at (loc, "%<#pragma omp atomic update%> uses two different variables for memory");
201       else
202 	error_at (loc, "%<#pragma omp atomic capture%> uses two different variables for memory");
203       return error_mark_node;
204     }
205 
206   if (code != OMP_ATOMIC)
207     {
208       /* Generally it is hard to prove lhs1 and lhs are the same memory
209 	 location, just diagnose different variables.  */
210       if (lhs1 && TREE_CODE (lhs1) == VAR_DECL && TREE_CODE (lhs) == VAR_DECL)
211 	{
212 	  if (lhs1 != lhs)
213 	    {
214 	      error_at (loc, "%<#pragma omp atomic capture%> uses two different variables for memory");
215 	      return error_mark_node;
216 	    }
217 	}
218       x = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
219 			     loc, x, NULL_TREE);
220       if (rhs1 && rhs1 != lhs)
221 	{
222 	  tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, 0);
223 	  if (rhs1addr == error_mark_node)
224 	    return error_mark_node;
225 	  x = omit_one_operand_loc (loc, type, x, rhs1addr);
226 	}
227       if (lhs1 && lhs1 != lhs)
228 	{
229 	  tree lhs1addr = build_unary_op (loc, ADDR_EXPR, lhs1, 0);
230 	  if (lhs1addr == error_mark_node)
231 	    return error_mark_node;
232 	  if (code == OMP_ATOMIC_CAPTURE_OLD)
233 	    x = omit_one_operand_loc (loc, type, x, lhs1addr);
234 	  else
235 	    {
236 	      x = save_expr (x);
237 	      x = omit_two_operands_loc (loc, type, x, x, lhs1addr);
238 	    }
239 	}
240     }
241   else if (rhs1 && rhs1 != lhs)
242     {
243       tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, 0);
244       if (rhs1addr == error_mark_node)
245 	return error_mark_node;
246       x = omit_one_operand_loc (loc, type, x, rhs1addr);
247     }
248 
249   return x;
250 }
251 
252 
253 /* Complete a #pragma omp flush construct.  We don't do anything with
254    the variable list that the syntax allows.  LOC is the location of
255    the #pragma.  */
256 
257 void
258 c_finish_omp_flush (location_t loc)
259 {
260   tree x;
261 
262   x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
263   x = build_call_expr_loc (loc, x, 0);
264   add_stmt (x);
265 }
266 
267 
268 /* Check and canonicalize #pragma omp for increment expression.
269    Helper function for c_finish_omp_for.  */
270 
271 static tree
272 check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
273 {
274   tree t;
275 
276   if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
277       || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
278     return error_mark_node;
279 
280   if (exp == decl)
281     return build_int_cst (TREE_TYPE (exp), 0);
282 
283   switch (TREE_CODE (exp))
284     {
285     CASE_CONVERT:
286       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
287       if (t != error_mark_node)
288         return fold_convert_loc (loc, TREE_TYPE (exp), t);
289       break;
290     case MINUS_EXPR:
291       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
292       if (t != error_mark_node)
293         return fold_build2_loc (loc, MINUS_EXPR,
294 			    TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
295       break;
296     case PLUS_EXPR:
297       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
298       if (t != error_mark_node)
299         return fold_build2_loc (loc, PLUS_EXPR,
300 			    TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
301       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl);
302       if (t != error_mark_node)
303         return fold_build2_loc (loc, PLUS_EXPR,
304 			    TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
305       break;
306     case COMPOUND_EXPR:
307       {
308 	/* cp_build_modify_expr forces preevaluation of the RHS to make
309 	   sure that it is evaluated before the lvalue-rvalue conversion
310 	   is applied to the LHS.  Reconstruct the original expression.  */
311 	tree op0 = TREE_OPERAND (exp, 0);
312 	if (TREE_CODE (op0) == TARGET_EXPR
313 	    && !VOID_TYPE_P (TREE_TYPE (op0)))
314 	  {
315 	    tree op1 = TREE_OPERAND (exp, 1);
316 	    tree temp = TARGET_EXPR_SLOT (op0);
317 	    if (TREE_CODE_CLASS (TREE_CODE (op1)) == tcc_binary
318 		&& TREE_OPERAND (op1, 1) == temp)
319 	      {
320 		op1 = copy_node (op1);
321 		TREE_OPERAND (op1, 1) = TARGET_EXPR_INITIAL (op0);
322 		return check_omp_for_incr_expr (loc, op1, decl);
323 	      }
324 	  }
325 	break;
326       }
327     default:
328       break;
329     }
330 
331   return error_mark_node;
332 }
333 
334 /* Validate and emit code for the OpenMP directive #pragma omp for.
335    DECLV is a vector of iteration variables, for each collapsed loop.
336    INITV, CONDV and INCRV are vectors containing initialization
337    expressions, controlling predicates and increment expressions.
338    BODY is the body of the loop and PRE_BODY statements that go before
339    the loop.  */
340 
341 tree
342 c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
343 		  tree incrv, tree body, tree pre_body)
344 {
345   location_t elocus;
346   bool fail = false;
347   int i;
348 
349   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
350   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
351   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
352   for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
353     {
354       tree decl = TREE_VEC_ELT (declv, i);
355       tree init = TREE_VEC_ELT (initv, i);
356       tree cond = TREE_VEC_ELT (condv, i);
357       tree incr = TREE_VEC_ELT (incrv, i);
358 
359       elocus = locus;
360       if (EXPR_HAS_LOCATION (init))
361 	elocus = EXPR_LOCATION (init);
362 
363       /* Validate the iteration variable.  */
364       if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
365 	  && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
366 	{
367 	  error_at (elocus, "invalid type for iteration variable %qE", decl);
368 	  fail = true;
369 	}
370 
371       /* In the case of "for (int i = 0...)", init will be a decl.  It should
372 	 have a DECL_INITIAL that we can turn into an assignment.  */
373       if (init == decl)
374 	{
375 	  elocus = DECL_SOURCE_LOCATION (decl);
376 
377 	  init = DECL_INITIAL (decl);
378 	  if (init == NULL)
379 	    {
380 	      error_at (elocus, "%qE is not initialized", decl);
381 	      init = integer_zero_node;
382 	      fail = true;
383 	    }
384 
385 	  init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR,
386 	      			    /* FIXME diagnostics: This should
387 				       be the location of the INIT.  */
388 	      			    elocus,
389 				    init,
390 				    NULL_TREE);
391 	}
392       gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
393       gcc_assert (TREE_OPERAND (init, 0) == decl);
394 
395       if (cond == NULL_TREE)
396 	{
397 	  error_at (elocus, "missing controlling predicate");
398 	  fail = true;
399 	}
400       else
401 	{
402 	  bool cond_ok = false;
403 
404 	  if (EXPR_HAS_LOCATION (cond))
405 	    elocus = EXPR_LOCATION (cond);
406 
407 	  if (TREE_CODE (cond) == LT_EXPR
408 	      || TREE_CODE (cond) == LE_EXPR
409 	      || TREE_CODE (cond) == GT_EXPR
410 	      || TREE_CODE (cond) == GE_EXPR
411 	      || TREE_CODE (cond) == NE_EXPR
412 	      || TREE_CODE (cond) == EQ_EXPR)
413 	    {
414 	      tree op0 = TREE_OPERAND (cond, 0);
415 	      tree op1 = TREE_OPERAND (cond, 1);
416 
417 	      /* 2.5.1.  The comparison in the condition is computed in
418 		 the type of DECL, otherwise the behavior is undefined.
419 
420 		 For example:
421 		 long n; int i;
422 		 i < n;
423 
424 		 according to ISO will be evaluated as:
425 		 (long)i < n;
426 
427 		 We want to force:
428 		 i < (int)n;  */
429 	      if (TREE_CODE (op0) == NOP_EXPR
430 		  && decl == TREE_OPERAND (op0, 0))
431 		{
432 		  TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
433 		  TREE_OPERAND (cond, 1)
434 		    = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
435 				   TREE_OPERAND (cond, 1));
436 		}
437 	      else if (TREE_CODE (op1) == NOP_EXPR
438 		       && decl == TREE_OPERAND (op1, 0))
439 		{
440 		  TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
441 		  TREE_OPERAND (cond, 0)
442 		    = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
443 				   TREE_OPERAND (cond, 0));
444 		}
445 
446 	      if (decl == TREE_OPERAND (cond, 0))
447 		cond_ok = true;
448 	      else if (decl == TREE_OPERAND (cond, 1))
449 		{
450 		  TREE_SET_CODE (cond,
451 				 swap_tree_comparison (TREE_CODE (cond)));
452 		  TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
453 		  TREE_OPERAND (cond, 0) = decl;
454 		  cond_ok = true;
455 		}
456 
457 	      if (TREE_CODE (cond) == NE_EXPR
458 		  || TREE_CODE (cond) == EQ_EXPR)
459 		{
460 		  if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
461 		    cond_ok = false;
462 		  else if (operand_equal_p (TREE_OPERAND (cond, 1),
463 					    TYPE_MIN_VALUE (TREE_TYPE (decl)),
464 					    0))
465 		    TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
466 					 ? GT_EXPR : LE_EXPR);
467 		  else if (operand_equal_p (TREE_OPERAND (cond, 1),
468 					    TYPE_MAX_VALUE (TREE_TYPE (decl)),
469 					    0))
470 		    TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
471 					 ? LT_EXPR : GE_EXPR);
472 		  else
473 		    cond_ok = false;
474 		}
475 	    }
476 
477 	  if (!cond_ok)
478 	    {
479 	      error_at (elocus, "invalid controlling predicate");
480 	      fail = true;
481 	    }
482 	}
483 
484       if (incr == NULL_TREE)
485 	{
486 	  error_at (elocus, "missing increment expression");
487 	  fail = true;
488 	}
489       else
490 	{
491 	  bool incr_ok = false;
492 
493 	  if (EXPR_HAS_LOCATION (incr))
494 	    elocus = EXPR_LOCATION (incr);
495 
496 	  /* Check all the valid increment expressions: v++, v--, ++v, --v,
497 	     v = v + incr, v = incr + v and v = v - incr.  */
498 	  switch (TREE_CODE (incr))
499 	    {
500 	    case POSTINCREMENT_EXPR:
501 	    case PREINCREMENT_EXPR:
502 	    case POSTDECREMENT_EXPR:
503 	    case PREDECREMENT_EXPR:
504 	      if (TREE_OPERAND (incr, 0) != decl)
505 		break;
506 
507 	      incr_ok = true;
508 	      if (POINTER_TYPE_P (TREE_TYPE (decl))
509 		  && TREE_OPERAND (incr, 1))
510 		{
511 		  tree t = fold_convert_loc (elocus,
512 					     sizetype, TREE_OPERAND (incr, 1));
513 
514 		  if (TREE_CODE (incr) == POSTDECREMENT_EXPR
515 		      || TREE_CODE (incr) == PREDECREMENT_EXPR)
516 		    t = fold_build1_loc (elocus, NEGATE_EXPR, sizetype, t);
517 		  t = fold_build_pointer_plus (decl, t);
518 		  incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
519 		}
520 	      break;
521 
522 	    case MODIFY_EXPR:
523 	      if (TREE_OPERAND (incr, 0) != decl)
524 		break;
525 	      if (TREE_OPERAND (incr, 1) == decl)
526 		break;
527 	      if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
528 		  && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
529 		      || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
530 		incr_ok = true;
531 	      else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
532 			|| (TREE_CODE (TREE_OPERAND (incr, 1))
533 			    == POINTER_PLUS_EXPR))
534 		       && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
535 		incr_ok = true;
536 	      else
537 		{
538 		  tree t = check_omp_for_incr_expr (elocus,
539 						    TREE_OPERAND (incr, 1),
540 						    decl);
541 		  if (t != error_mark_node)
542 		    {
543 		      incr_ok = true;
544 		      t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
545 		      incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
546 		    }
547 		}
548 	      break;
549 
550 	    default:
551 	      break;
552 	    }
553 	  if (!incr_ok)
554 	    {
555 	      error_at (elocus, "invalid increment expression");
556 	      fail = true;
557 	    }
558 	}
559 
560       TREE_VEC_ELT (initv, i) = init;
561       TREE_VEC_ELT (incrv, i) = incr;
562     }
563 
564   if (fail)
565     return NULL;
566   else
567     {
568       tree t = make_node (OMP_FOR);
569 
570       TREE_TYPE (t) = void_type_node;
571       OMP_FOR_INIT (t) = initv;
572       OMP_FOR_COND (t) = condv;
573       OMP_FOR_INCR (t) = incrv;
574       OMP_FOR_BODY (t) = body;
575       OMP_FOR_PRE_BODY (t) = pre_body;
576 
577       SET_EXPR_LOCATION (t, locus);
578       return add_stmt (t);
579     }
580 }
581 
582 
583 /* Divide CLAUSES into two lists: those that apply to a parallel
584    construct, and those that apply to a work-sharing construct.  Place
585    the results in *PAR_CLAUSES and *WS_CLAUSES respectively.  In
586    addition, add a nowait clause to the work-sharing list.  LOC is the
587    location of the OMP_PARALLEL*.  */
588 
589 void
590 c_split_parallel_clauses (location_t loc, tree clauses,
591 			  tree *par_clauses, tree *ws_clauses)
592 {
593   tree next;
594 
595   *par_clauses = NULL;
596   *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
597 
598   for (; clauses ; clauses = next)
599     {
600       next = OMP_CLAUSE_CHAIN (clauses);
601 
602       switch (OMP_CLAUSE_CODE (clauses))
603 	{
604 	case OMP_CLAUSE_PRIVATE:
605 	case OMP_CLAUSE_SHARED:
606 	case OMP_CLAUSE_FIRSTPRIVATE:
607 	case OMP_CLAUSE_LASTPRIVATE:
608 	case OMP_CLAUSE_REDUCTION:
609 	case OMP_CLAUSE_COPYIN:
610 	case OMP_CLAUSE_IF:
611 	case OMP_CLAUSE_NUM_THREADS:
612 	case OMP_CLAUSE_DEFAULT:
613 	  OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
614 	  *par_clauses = clauses;
615 	  break;
616 
617 	case OMP_CLAUSE_SCHEDULE:
618 	case OMP_CLAUSE_ORDERED:
619 	case OMP_CLAUSE_COLLAPSE:
620 	  OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
621 	  *ws_clauses = clauses;
622 	  break;
623 
624 	default:
625 	  gcc_unreachable ();
626 	}
627     }
628 }
629 
630 /* True if OpenMP sharing attribute of DECL is predetermined.  */
631 
632 enum omp_clause_default_kind
633 c_omp_predetermined_sharing (tree decl)
634 {
635   /* Variables with const-qualified type having no mutable member
636      are predetermined shared.  */
637   if (TREE_READONLY (decl))
638     return OMP_CLAUSE_DEFAULT_SHARED;
639 
640   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
641 }
642