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