backport: re PR fortran/46752 (OpenMP - Seg fault for unallocated allocatable array...
authorJakub Jelinek <jakub@gcc.gnu.org>
Tue, 2 Aug 2011 16:13:29 +0000 (18:13 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 2 Aug 2011 16:13:29 +0000 (18:13 +0200)
Merge from gomp-3_1-branch branch:

2011-08-02  Jakub Jelinek  <jakub@redhat.com>

gcc/
* c-parser.c (enum c_parser_prec): New enum, moved from within
c_parser_binary_expression.
(c_parser_binary_expression): Add PREC argument.  Stop parsing
if operator has lower or equal precedence than PREC.
(c_parser_conditional_expression, c_parser_omp_for_loop): Adjust
callers.
(c_parser_omp_atomic): Handle parsing OpenMP 3.1 atomics.
Adjust c_finish_omp_atomic caller.
(c_parser_omp_taskyield): New function.
(c_parser_pragma): Handle PRAGMA_OMP_TASKYIELD.
(c_parser_omp_clause_name): Handle final and mergeable clauses.
(c_parser_omp_clause_final, c_parser_omp_clause_mergeable): New
functions.
(c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FINAL
and PRAGMA_OMP_CLAUSE_MERGEABLE.
(OMP_TASK_CLAUSE_MASK): Allow final and mergeable clauses.
(c_parser_omp_clause_reduction): Handle min and max.
* c-typeck.c (c_finish_omp_clauses): Don't complain about
const qualified predetermined vars in firstprivate clause.
andle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE.
Handle MIN_EXPR and MAX_EXPR.
* tree-pretty-print.c (dump_omp_clause): Handle OMP_CLAUSE_FINAL
and OMP_CLAUSE_MERGEABLE.
(dump_generic_node): Handle OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD
and OMP_ATOMIC_CAPTURE_NEW.
* tree.c (omp_clause_num_ops): Add OMP_CLAUSE_FINAL and
OMP_CLAUSE_MERGEABLE.
(omp_clause_code_name): Likewise.
(walk_tree_1): Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE.
* tree.h (enum omp_clause_code): Add OMP_CLAUSE_FINAL
and OMP_CLAUSE_MERGEABLE.
(OMP_CLAUSE_FINAL_EXPR): Define.
* omp-low.c (scan_sharing_clauses): Handle OMP_CLAUSE_FINAL and
OMP_CLAUSE_MERGEABLE.
(expand_task_call): Likewise.
(expand_omp_atomic_load, expand_omp_atomic_store): New functions.
(expand_omp_atomic_fetch_op): Handle cases where old or new
value is needed afterwards.
(expand_omp_atomic): Call expand_omp_atomic_load resp.
expand_omp_atomic_store.
* gimplify.c (gimplify_omp_atomic, gimplify_expr): Handle
OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD and OMP_ATOMIC_CAPTURE_NEW.
(gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses): Handle
OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE.
* tree-nested.c (convert_nonlocal_omp_clauses,
convert_local_omp_clauses): Likewise.
* tree.def (OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD,
OMP_ATOMIC_CAPTURE_NEW): New.
* gimple.h (GF_OMP_ATOMIC_NEED_VALUE): New.
(gimple_omp_atomic_need_value_p, gimple_omp_atomic_set_need_value):
New inlines.
* omp-builtins.def (BUILT_IN_GOMP_TASKYIELD): New builtin.
* doc/generic.texi: Mention OMP_CLAUSE_COLLAPSE,
OMP_CLAUSE_UNTIED, OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE.
gcc/c-family/
* c-common.h (c_finish_omp_atomic): Adjust prototype.
(c_finish_omp_taskyield): New prototype.
* c-omp.c (c_finish_omp_atomic): Add OPCODE, V, LHS1 and RHS1
arguments. Handle OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD and
OMP_ATOMIC_CAPTURE_NEW in addition to OMP_ATOMIC.  If LHS1
or RHS1 have side-effects, evaluate those too in the right spot,
if it is a decl and LHS is also a decl, error out if they
aren't the same.
(c_finish_omp_taskyield): New function.
* c-cppbuiltin.c (c_cpp_builtins): Change _OPENMP to 201107.
* c-pragma.c (omp_pragmas): Add taskyield.
* c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_TASKYIELD.
(enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_FINAL and
PRAGMA_OMP_CLAUSE_MERGEABLE.
gcc/cp/
* cp-tree.h (finish_omp_atomic): Adjust prototype.
(cxx_omp_const_qual_no_mutable): New prototype.
(finish_omp_taskyield): New prototype.
* parser.c (cp_parser_omp_atomic): (cp_parser_omp_atomic): Handle
parsing OpenMP 3.1 atomics.  Adjust finish_omp_atomic caller.
(cp_parser_omp_clause_name): Handle final and mergeable clauses.
(cp_parser_omp_clause_final, cp_parser_omp_clause_mergeable): New
functions.
(cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FINAL
and PRAGMA_OMP_CLAUSE_MERGEABLE.
(OMP_TASK_CLAUSE_MASK): Allow final and mergeable clauses.
(cp_parser_omp_taskyield): New function.
(cp_parser_pragma): Handle PRAGMA_OMP_TASKYIELD.
(cp_parser_omp_clause_reduction): Handle min and max.
* pt.c (tsubst_expr) <case OMP_ATOMIC>: Handle OpenMP 3.1 atomics.
(tsubst_omp_clauses): Handle OMP_CLAUSE_FINAL and
OMP_CLAUSE_MERGEABLE.
* semantics.c (finish_omp_atomic): Add OPCODE, V, LHS1 and RHS1
arguments.  Handle OpenMP 3.1 atomics.  Adjust c_finish_omp_atomic
caller.
(finish_omp_clauses): Don't complain about const qualified
predetermined vars and static data members in firstprivate clause.
Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. Handle MIN_EXPR
and MAX_EXPR.
(finish_omp_taskyield): New function.
* cp-gimplify.c (cxx_omp_const_qual_no_mutable): New function.
(cxx_omp_predetermined_sharing): Use it.
gcc/fortran/
PR fortran/46752
* cpp.c (cpp_define_builtins): Change _OPENMP to 201107.
* openmp.c (gfc_free_omp_clauses): Free also final_expr.
(OMP_CLAUSE_FINAL, OMP_CLAUSE_MERGEABLE): Define.
(gfc_match_omp_clauses): Handle parsing final and mergeable
clauses.
(OMP_TASK_CLAUSES): Allow final and mergeable clauses.
(gfc_match_omp_taskyield): New function.
(resolve_omp_clauses): Resolve final clause.  Allow POINTERs and
Cray pointers in clauses other than REDUCTION.
(gfc_match_omp_atomic): Match optional
read/write/update/capture keywords after !$omp atomic.
(resolve_omp_atomic): Handle all OpenMP 3.1 atomic forms.
* dump-parse-tree.c (show_omp_node): Handle EXEC_OMP_TASKYIELD,
print final and mergeable clauses.
(show_code_node): Handle EXEC_OMP_TASKYIELD.
* trans-openmp.c (gfc_trans_omp_clauses): Handle final and
mergeable clauses.
(gfc_trans_omp_taskyield): New function.
(gfc_trans_omp_directive): Handle EXEC_OMP_TASKYIELD.
(gfc_trans_omp_atomic): Handle all OpenMP 3.1 atomic forms.
(gfc_omp_clause_copy_ctor): Handle non-allocated allocatable.
(gfc_omp_predetermined_sharing): Adjust comment.
* gfortran.h (gfc_statement): Add ST_OMP_TASKYIELD and
ST_OMP_END_ATOMIC.
(gfc_omp_clauses): Add final_expr and mergeable fields.
(gfc_exec_op): Add EXEC_OMP_TASKYIELD.
(gfc_omp_atomic_op): New enum typedef.
(struct gfc_code): Add ext.omp_atomic.
* trans.c (trans_code): Handle EXEC_OMP_TASKYIELD.
* frontend-passes.c (gfc_code_walker): Also walk final_expr.
* resolve.c (gfc_resolve_blocks, resolve_code): Handle
EXEC_OMP_TASKYIELD.
* st.c (gfc_free_statement): Likewise.
* match.h (gfc_match_omp_taskyield): New prototype.
* parse.c (decode_omp_directive): Handle taskyield directive.
Handle !$omp end atomic.
(case_executable): Add ST_OMP_TASKYIELD case.
(gfc_ascii_statement): Handle ST_OMP_TASKYIELD.
(parse_omp_atomic): Return gfc_statement instead of void.
For !$omp atomic capture parse two assignments instead of
just one and require !$omp end atomic afterwards, for
other !$omp atomic forms just allow !$omp end atomic at the
end.
(parse_omp_structured_block, parse_executable): Adjust
parse_omp_atomic callers.

2011-08-02  Tobias Burnus  <burnus@net-b.de>

* intrinsic.c (OMP_LIB): Updated openmp_version's
value to 201107.
* gfortran.texi (OpenMP): Update ref to OpenMP 3.1.
* intrinsic.texi (OpenMP Modules): Update ref to OpenMP 3.1;
remove deleted omp_integer_kind and omp_logical_kind constants.
gcc/testsuite/
PR fortran/46752
* gcc.dg/gomp/atomic-5.c: Adjust expected diagnostics.
* gcc.dg/gomp/atomic-15.c: New test.
* g++.dg/gomp/atomic-5.C: Adjust expected diagnostics.
* g++.dg/gomp/atomic-15.C: New test.
* g++.dg/gomp/private-1.C: New test.
* g++.dg/gomp/sharing-2.C: New test.
* gfortran.dg/gomp/crayptr1.f90: Don't expect error
about Cray pointer in FIRSTPRIVATE/LASTPRIVATE.
* gfortran.dg/gomp/omp_atomic2.f90: New test.
libgomp/
PR fortran/42041
PR fortran/46752
* omp.h.in (omp_in_final): New prototype.
* omp_lib.f90.in (omp_in_final): New interface.
(omp_integer_kind, omp_logical_kind): Remove
and replace all its uses in the module with 4.
(openmp_version): Change to 201107.
* omp_lib.h.in (omp_sched_static, omp_sched_dynamic,
omp_sched_guided, omp_sched_auto): Use omp_sched_kind
kind for the parameters.
(omp_in_final): New external.
(openmp_version): Change to 201107.
* task.c (omp_in_final): New function.
(gomp_init_task): Initialize final_task.
(GOMP_task): Remove unused attribute from flags.  Handle final
tasks.
(GOMP_taskyield): New function.
(omp_in_final): Return true if if (false) or final (true) task
or descendant of final (true).
* fortran.c (omp_in_final_): New function.
* libgomp.map (OMP_3.1): Export omp_in_final and omp_in_final_.
(GOMP_3.0): Export GOMP_taskyield.
* env.c (gomp_nthreads_var_list, gomp_nthreads_var_list_len): New
variables.
(parse_unsigned_long_list): New function.
(initialize_env): Use it for OMP_NUM_THREADS.  Call parse_boolean
with "OMP_PROC_BIND".  If OMP_PROC_BIND=true, call gomp_init_affinity
even if parse_affinity returned false.
* config/linux/affinity.c (gomp_init_affinity): Handle
gomp_cpu_affinity_len == 0.
* libgomp_g.h (GOMP_taskyield): New prototype.
* libgomp.h (struct gomp_task): Add final_task field.
(gomp_nthreads_var_list, gomp_nthreads_var_list_len): New externs.
* team.c (gomp_team_start): Override new task's nthreads_var icv
if list form OMP_NUM_THREADS has been used and it has value for
the new nesting level.

* testsuite/libgomp.c/atomic-11.c: New test.
* testsuite/libgomp.c/atomic-12.c: New test.
* testsuite/libgomp.c/atomic-13.c: New test.
* testsuite/libgomp.c/atomic-14.c: New test.
* testsuite/libgomp.c/reduction-6.c: New test.
* testsuite/libgomp.c/task-5.c: New test.
* testsuite/libgomp.c++/atomic-2.C: New test.
* testsuite/libgomp.c++/atomic-3.C: New test.
* testsuite/libgomp.c++/atomic-4.C: New test.
* testsuite/libgomp.c++/atomic-5.C: New test.
* testsuite/libgomp.c++/atomic-6.C: New test.
* testsuite/libgomp.c++/atomic-7.C: New test.
* testsuite/libgomp.c++/atomic-8.C: New test.
* testsuite/libgomp.c++/atomic-9.C: New test.
* testsuite/libgomp.c++/task-8.C: New test.
* testsuite/libgomp.c++/reduction-4.C: New test.
* testsuite/libgomp.fortran/allocatable7.f90: New test.
* testsuite/libgomp.fortran/allocatable8.f90: New test.
* testsuite/libgomp.fortran/crayptr3.f90: New test.
* testsuite/libgomp.fortran/omp_atomic3.f90: New test.
* testsuite/libgomp.fortran/omp_atomic4.f90: New test.
* testsuite/libgomp.fortran/pointer1.f90: New test.
* testsuite/libgomp.fortran/pointer2.f90: New test.
* testsuite/libgomp.fortran/task4.f90: New test.

2011-08-02  Tobias Burnus  <burnus@net-b.de>

* libgomp.texi: Update OpenMP spec references to 3.1.
(omp_in_final,OMP_PROC_BIND): New sections.
(OMP_NUM_THREADS): Document that the value can be now a list.
(GOMP_STACKSIZE,GOMP_CPU_AFFINITY): Update @ref.

From-SVN: r177194

87 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.h
gcc/c-family/c-cppbuiltin.c
gcc/c-family/c-omp.c
gcc/c-family/c-pragma.c
gcc/c-family/c-pragma.h
gcc/c-parser.c
gcc/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/cp-gimplify.c
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/doc/generic.texi
gcc/fortran/ChangeLog
gcc/fortran/cpp.c
gcc/fortran/dump-parse-tree.c
gcc/fortran/frontend-passes.c
gcc/fortran/gfortran.h
gcc/fortran/gfortran.texi
gcc/fortran/intrinsic.texi
gcc/fortran/match.h
gcc/fortran/openmp.c
gcc/fortran/parse.c
gcc/fortran/resolve.c
gcc/fortran/st.c
gcc/fortran/trans-openmp.c
gcc/fortran/trans.c
gcc/gimple.h
gcc/gimplify.c
gcc/omp-builtins.def
gcc/omp-low.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/gomp/atomic-15.C [new file with mode: 0644]
gcc/testsuite/g++.dg/gomp/atomic-5.C
gcc/testsuite/g++.dg/gomp/clause-3.C
gcc/testsuite/g++.dg/gomp/private-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/gomp/sharing-2.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/gomp/atomic-15.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/gomp/atomic-5.c
gcc/testsuite/gcc.dg/gomp/clause-1.c
gcc/testsuite/gfortran.dg/gomp/crayptr1.f90
gcc/testsuite/gfortran.dg/gomp/omp_atomic2.f90 [new file with mode: 0644]
gcc/tree-nested.c
gcc/tree-pretty-print.c
gcc/tree.c
gcc/tree.def
gcc/tree.h
libgomp/ChangeLog
libgomp/config/linux/affinity.c
libgomp/env.c
libgomp/fortran.c
libgomp/libgomp.h
libgomp/libgomp.map
libgomp/libgomp.texi
libgomp/libgomp_g.h
libgomp/omp.h.in
libgomp/omp_lib.f90.in
libgomp/omp_lib.h.in
libgomp/task.c
libgomp/team.c
libgomp/testsuite/libgomp.c++/atomic-2.C [new file with mode: 0644]
libgomp/testsuite/libgomp.c++/atomic-3.C [new file with mode: 0644]
libgomp/testsuite/libgomp.c++/atomic-4.C [new file with mode: 0644]
libgomp/testsuite/libgomp.c++/atomic-5.C [new file with mode: 0644]
libgomp/testsuite/libgomp.c++/atomic-6.C [new file with mode: 0644]
libgomp/testsuite/libgomp.c++/atomic-7.C [new file with mode: 0644]
libgomp/testsuite/libgomp.c++/atomic-8.C [new file with mode: 0644]
libgomp/testsuite/libgomp.c++/atomic-9.C [new file with mode: 0644]
libgomp/testsuite/libgomp.c++/reduction-4.C [new file with mode: 0644]
libgomp/testsuite/libgomp.c++/task-8.C [new file with mode: 0644]
libgomp/testsuite/libgomp.c/atomic-11.c [new file with mode: 0644]
libgomp/testsuite/libgomp.c/atomic-12.c [new file with mode: 0644]
libgomp/testsuite/libgomp.c/atomic-13.c [new file with mode: 0644]
libgomp/testsuite/libgomp.c/atomic-14.c [new file with mode: 0644]
libgomp/testsuite/libgomp.c/reduction-6.c [new file with mode: 0644]
libgomp/testsuite/libgomp.c/task-5.c [new file with mode: 0644]
libgomp/testsuite/libgomp.fortran/allocatable7.f90 [new file with mode: 0644]
libgomp/testsuite/libgomp.fortran/allocatable8.f90 [new file with mode: 0644]
libgomp/testsuite/libgomp.fortran/crayptr3.f90 [new file with mode: 0644]
libgomp/testsuite/libgomp.fortran/omp_atomic3.f90 [new file with mode: 0644]
libgomp/testsuite/libgomp.fortran/omp_atomic4.f90 [new file with mode: 0644]
libgomp/testsuite/libgomp.fortran/pointer1.f90 [new file with mode: 0644]
libgomp/testsuite/libgomp.fortran/pointer2.f90 [new file with mode: 0644]
libgomp/testsuite/libgomp.fortran/task4.f90 [new file with mode: 0644]

index 7493d2313b237f6424c3afa2f1031dcf3b243a86..18e0107d71ed1e36cb3479f1f6656c61c66498b1 100644 (file)
@@ -1,3 +1,60 @@
+2011-08-02  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-parser.c (enum c_parser_prec): New enum, moved from within
+       c_parser_binary_expression.
+       (c_parser_binary_expression): Add PREC argument.  Stop parsing
+       if operator has lower or equal precedence than PREC.
+       (c_parser_conditional_expression, c_parser_omp_for_loop): Adjust
+       callers.
+       (c_parser_omp_atomic): Handle parsing OpenMP 3.1 atomics.
+       Adjust c_finish_omp_atomic caller.
+       (c_parser_omp_taskyield): New function.
+       (c_parser_pragma): Handle PRAGMA_OMP_TASKYIELD.
+       (c_parser_omp_clause_name): Handle final and mergeable clauses.
+       (c_parser_omp_clause_final, c_parser_omp_clause_mergeable): New
+       functions.
+       (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FINAL
+       and PRAGMA_OMP_CLAUSE_MERGEABLE.
+       (OMP_TASK_CLAUSE_MASK): Allow final and mergeable clauses.
+       (c_parser_omp_clause_reduction): Handle min and max.
+       * c-typeck.c (c_finish_omp_clauses): Don't complain about
+       const qualified predetermined vars in firstprivate clause.
+       andle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE.
+       Handle MIN_EXPR and MAX_EXPR.
+       * tree-pretty-print.c (dump_omp_clause): Handle OMP_CLAUSE_FINAL
+       and OMP_CLAUSE_MERGEABLE.
+       (dump_generic_node): Handle OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD
+       and OMP_ATOMIC_CAPTURE_NEW.
+       * tree.c (omp_clause_num_ops): Add OMP_CLAUSE_FINAL and
+       OMP_CLAUSE_MERGEABLE.
+       (omp_clause_code_name): Likewise.
+       (walk_tree_1): Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE.
+       * tree.h (enum omp_clause_code): Add OMP_CLAUSE_FINAL
+       and OMP_CLAUSE_MERGEABLE.
+       (OMP_CLAUSE_FINAL_EXPR): Define.
+       * omp-low.c (scan_sharing_clauses): Handle OMP_CLAUSE_FINAL and
+       OMP_CLAUSE_MERGEABLE.
+       (expand_task_call): Likewise.
+       (expand_omp_atomic_load, expand_omp_atomic_store): New functions.
+       (expand_omp_atomic_fetch_op): Handle cases where old or new
+       value is needed afterwards.
+       (expand_omp_atomic): Call expand_omp_atomic_load resp.
+       expand_omp_atomic_store.
+       * gimplify.c (gimplify_omp_atomic, gimplify_expr): Handle
+       OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD and OMP_ATOMIC_CAPTURE_NEW.
+       (gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses): Handle
+       OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE.
+       * tree-nested.c (convert_nonlocal_omp_clauses,
+       convert_local_omp_clauses): Likewise.
+       * tree.def (OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD,
+       OMP_ATOMIC_CAPTURE_NEW): New.
+       * gimple.h (GF_OMP_ATOMIC_NEED_VALUE): New.
+       (gimple_omp_atomic_need_value_p, gimple_omp_atomic_set_need_value):
+       New inlines.
+       * omp-builtins.def (BUILT_IN_GOMP_TASKYIELD): New builtin.
+       * doc/generic.texi: Mention OMP_CLAUSE_COLLAPSE,
+       OMP_CLAUSE_UNTIED, OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE.
+
 2011-08-02  Kai Tietz  <ktietz@redhat.com>
 
        * gimple.c (canonicalize_cond_expr_cond): Handle cast from
index 42df0a9ec6613a9f48e5f0cd3b4d95b85aed7786..91ed861b5b34073cf74c6470ab298448b858f6cd 100644 (file)
@@ -1,3 +1,20 @@
+2011-08-02  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-common.h (c_finish_omp_atomic): Adjust prototype.
+       (c_finish_omp_taskyield): New prototype.
+       * c-omp.c (c_finish_omp_atomic): Add OPCODE, V, LHS1 and RHS1
+       arguments. Handle OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD and
+       OMP_ATOMIC_CAPTURE_NEW in addition to OMP_ATOMIC.  If LHS1
+       or RHS1 have side-effects, evaluate those too in the right spot,
+       if it is a decl and LHS is also a decl, error out if they
+       aren't the same.
+       (c_finish_omp_taskyield): New function.
+       * c-cppbuiltin.c (c_cpp_builtins): Change _OPENMP to 201107.
+       * c-pragma.c (omp_pragmas): Add taskyield.
+       * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_TASKYIELD.
+       (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_FINAL and
+       PRAGMA_OMP_CLAUSE_MERGEABLE.
+
 2011-07-25  Dodji Seketeli  <dodji@redhat.com>
 
        * c-common.h (set_underlying_type): Remove parm name from
index 4ac7c4a3adc47624906452ab6566bd94babff299..3a4977929d91b735af4e06b2eb6b5f016043c93b 100644 (file)
@@ -1029,9 +1029,11 @@ extern tree c_finish_omp_master (location_t, tree);
 extern tree c_finish_omp_critical (location_t, tree, tree);
 extern tree c_finish_omp_ordered (location_t, tree);
 extern void c_finish_omp_barrier (location_t);
-extern tree c_finish_omp_atomic (location_t, enum tree_code, tree, tree);
+extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code,
+                                tree, tree, tree, tree, tree);
 extern void c_finish_omp_flush (location_t);
 extern void c_finish_omp_taskwait (location_t);
+extern void c_finish_omp_taskyield (location_t);
 extern tree c_finish_omp_for (location_t, tree, tree, tree, tree, tree, tree);
 extern void c_split_parallel_clauses (location_t, tree, tree *, tree *);
 extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
index 9f0918daed671473b9475cbc748ae912e7f38d98..a960cbea8743d8fa4b1231df3efce00e5e3dcfac 100644 (file)
@@ -807,7 +807,7 @@ c_cpp_builtins (cpp_reader *pfile)
     cpp_define (pfile, "__SSP__=1");
 
   if (flag_openmp)
-    cpp_define (pfile, "_OPENMP=200805");
+    cpp_define (pfile, "_OPENMP=201107");
 
   if (int128_integer_type_node != NULL_TREE)
     builtin_define_type_sizeof ("__SIZEOF_INT128__",
index 340656fa14feed0ce25ca868ec7ecd13f7bcb639..4a5b0ca928b01552540983afb0419c668596e196 100644 (file)
@@ -1,7 +1,8 @@
 /* This file contains routines to construct GNU OpenMP constructs,
    called from parsing in the C and C++ front ends.
 
-   Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
+   Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@redhat.com>,
                  Diego Novillo <dnovillo@redhat.com>.
 
@@ -96,18 +97,39 @@ c_finish_omp_taskwait (location_t loc)
 }
 
 
-/* Complete a #pragma omp atomic construct.  The expression to be
-   implemented atomically is LHS code= RHS.  LOC is the location of
-   the atomic statement.  The value returned is either error_mark_node
-   (if the construct was erroneous) or an OMP_ATOMIC node which should
-   be added to the current statement tree with add_stmt.*/
+/* Complete a #pragma omp taskyield construct.  LOC is the location of the
+   pragma.  */
+
+void
+c_finish_omp_taskyield (location_t loc)
+{
+  tree x;
+
+  x = built_in_decls[BUILT_IN_GOMP_TASKYIELD];
+  x = build_call_expr_loc (loc, x, 0);
+  add_stmt (x);
+}
+
+
+/* Complete a #pragma omp atomic construct.  For CODE OMP_ATOMIC
+   the expression to be implemented atomically is LHS opcode= RHS. 
+   For OMP_ATOMIC_READ V = LHS, for OMP_ATOMIC_CAPTURE_{NEW,OLD} LHS
+   opcode= RHS with the new or old content of LHS returned.
+   LOC is the location of the atomic statement.  The value returned
+   is either error_mark_node (if the construct was erroneous) or an
+   OMP_ATOMIC* node which should be added to the current statement
+   tree with add_stmt.  */
 
 tree
-c_finish_omp_atomic (location_t loc, enum tree_code code, tree lhs, tree rhs)
+c_finish_omp_atomic (location_t loc, enum tree_code code,
+                    enum tree_code opcode, tree lhs, tree rhs,
+                    tree v, tree lhs1, tree rhs1)
 {
   tree x, type, addr;
 
-  if (lhs == error_mark_node || rhs == error_mark_node)
+  if (lhs == error_mark_node || rhs == error_mark_node
+      || v == error_mark_node || lhs1 == error_mark_node
+      || rhs1 == error_mark_node)
     return error_mark_node;
 
   /* ??? According to one reading of the OpenMP spec, complex type are
@@ -143,10 +165,19 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, tree lhs, tree rhs)
     }
   lhs = build_indirect_ref (loc, addr, RO_NULL);
 
+  if (code == OMP_ATOMIC_READ)
+    {
+      x = build1 (OMP_ATOMIC_READ, type, addr);
+      SET_EXPR_LOCATION (x, loc);
+      return build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
+                               loc, x, NULL_TREE);
+      return x;
+    }
+
   /* There are lots of warnings, errors, and conversions that need to happen
      in the course of interpreting a statement.  Use the normal mechanisms
      to do this, and then take it apart again.  */
-  x = build_modify_expr (input_location, lhs, NULL_TREE, code,
+  x = build_modify_expr (input_location, lhs, NULL_TREE, opcode,
                         input_location, rhs, NULL_TREE);
   if (x == error_mark_node)
     return error_mark_node;
@@ -154,8 +185,68 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, tree lhs, tree rhs)
   rhs = TREE_OPERAND (x, 1);
 
   /* Punt the actual generation of atomic operations to common code.  */
-  x = build2 (OMP_ATOMIC, void_type_node, addr, rhs);
+  if (code == OMP_ATOMIC)
+    type = void_type_node;
+  x = build2 (code, type, addr, rhs);
   SET_EXPR_LOCATION (x, loc);
+
+  /* Generally it is hard to prove lhs1 and lhs are the same memory
+     location, just diagnose different variables.  */
+  if (rhs1
+      && TREE_CODE (rhs1) == VAR_DECL
+      && TREE_CODE (lhs) == VAR_DECL
+      && rhs1 != lhs)
+    {
+      if (code == OMP_ATOMIC)
+       error_at (loc, "%<#pragma omp atomic update%> uses two different variables for memory");
+      else
+       error_at (loc, "%<#pragma omp atomic capture%> uses two different variables for memory");
+      return error_mark_node;
+    }
+
+  if (code != OMP_ATOMIC)
+    {
+      /* Generally it is hard to prove lhs1 and lhs are the same memory
+        location, just diagnose different variables.  */
+      if (lhs1 && TREE_CODE (lhs1) == VAR_DECL && TREE_CODE (lhs) == VAR_DECL)
+       {
+         if (lhs1 != lhs)
+           {
+             error_at (loc, "%<#pragma omp atomic capture%> uses two different variables for memory");
+             return error_mark_node;
+           }
+       }
+      x = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
+                            loc, x, NULL_TREE);
+      if (rhs1 && rhs1 != lhs)
+       {
+         tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, 0);
+         if (rhs1addr == error_mark_node)
+           return error_mark_node;
+         x = omit_one_operand_loc (loc, type, x, rhs1addr);
+       }
+      if (lhs1 && lhs1 != lhs)
+       {
+         tree lhs1addr = build_unary_op (loc, ADDR_EXPR, lhs1, 0);
+         if (lhs1addr == error_mark_node)
+           return error_mark_node;
+         if (code == OMP_ATOMIC_CAPTURE_OLD)
+           x = omit_one_operand_loc (loc, type, x, lhs1addr);
+         else
+           {
+             x = save_expr (x);
+             x = omit_two_operands_loc (loc, type, x, x, lhs1addr);
+           }
+       }
+    }
+  else if (rhs1 && rhs1 != lhs)
+    {
+      tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, 0);
+      if (rhs1addr == error_mark_node)
+       return error_mark_node;
+      x = omit_one_operand_loc (loc, type, x, rhs1addr);
+    }
+
   return x;
 }
 
index 5c8bc1f8ac786c3797c775ed276e166c05cf3303..7622f0b155e7d7d4ab44cceebfaaf5af7d521bfd 100644 (file)
@@ -1196,6 +1196,7 @@ static const struct omp_pragma_def omp_pragmas[] = {
   { "single", PRAGMA_OMP_SINGLE },
   { "task", PRAGMA_OMP_TASK },
   { "taskwait", PRAGMA_OMP_TASKWAIT },
+  { "taskyield", PRAGMA_OMP_TASKYIELD },
   { "threadprivate", PRAGMA_OMP_THREADPRIVATE }
 };
 
index d231c256e46b460c6e8c29969f688c7257424dca..04af94f3ddfec0512089ac11556808a48420c4d8 100644 (file)
@@ -43,6 +43,7 @@ typedef enum pragma_kind {
   PRAGMA_OMP_SINGLE,
   PRAGMA_OMP_TASK,
   PRAGMA_OMP_TASKWAIT,
+  PRAGMA_OMP_TASKYIELD,
   PRAGMA_OMP_THREADPRIVATE,
 
   PRAGMA_GCC_PCH_PREPROCESS,
@@ -70,7 +71,9 @@ typedef enum pragma_omp_clause {
   PRAGMA_OMP_CLAUSE_REDUCTION,
   PRAGMA_OMP_CLAUSE_SCHEDULE,
   PRAGMA_OMP_CLAUSE_SHARED,
-  PRAGMA_OMP_CLAUSE_UNTIED
+  PRAGMA_OMP_CLAUSE_UNTIED,
+  PRAGMA_OMP_CLAUSE_FINAL,
+  PRAGMA_OMP_CLAUSE_MERGEABLE
 } pragma_omp_clause;
 
 extern struct cpp_reader* parse_in;
index 65966a9b50ff0108fe7689f98a53f1ab3f3dccc2..0d2a1b7dfca075640c70c711e11e07804e3abcf6 100644 (file)
@@ -1090,6 +1090,23 @@ typedef enum c_dtr_syn {
   C_DTR_PARM
 } c_dtr_syn;
 
+/* The binary operation precedence levels, where 0 is a dummy lowest level
+   used for the bottom of the stack.  */
+enum c_parser_prec {
+  PREC_NONE,
+  PREC_LOGOR,
+  PREC_LOGAND,
+  PREC_BITOR,
+  PREC_BITXOR,
+  PREC_BITAND,
+  PREC_EQ,
+  PREC_REL,
+  PREC_SHIFT,
+  PREC_ADD,
+  PREC_MULT,
+  NUM_PRECS
+};
+
 static void c_parser_external_declaration (c_parser *);
 static void c_parser_asm_definition (c_parser *);
 static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
@@ -1138,7 +1155,8 @@ static tree c_parser_asm_clobbers (c_parser *);
 static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *);
 static struct c_expr c_parser_conditional_expression (c_parser *,
                                                      struct c_expr *);
-static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *);
+static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
+                                                enum c_parser_prec);
 static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
 static struct c_expr c_parser_unary_expression (c_parser *);
 static struct c_expr c_parser_sizeof_expression (c_parser *);
@@ -1159,6 +1177,7 @@ static void c_parser_omp_threadprivate (c_parser *);
 static void c_parser_omp_barrier (c_parser *);
 static void c_parser_omp_flush (c_parser *);
 static void c_parser_omp_taskwait (c_parser *);
+static void c_parser_omp_taskyield (c_parser *);
 
 enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
 static bool c_parser_pragma (c_parser *, enum pragma_context);
@@ -5308,7 +5327,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
 
   gcc_assert (!after || c_dialect_objc ());
 
-  cond = c_parser_binary_expression (parser, after);
+  cond = c_parser_binary_expression (parser, after, PREC_NONE);
 
   if (c_parser_next_token_is_not (parser, CPP_QUERY))
     return cond;
@@ -5393,7 +5412,8 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
 /* Parse a binary expression; that is, a logical-OR-expression (C90
    6.3.5-6.3.14, C99 6.5.5-6.5.14).  If AFTER is not NULL then it is
    an Objective-C message expression which is the primary-expression
-   starting the expression as an initializer.
+   starting the expression as an initializer.  PREC is the starting
+   precedence, usually PREC_NONE.
 
    multiplicative-expression:
      cast-expression
@@ -5445,7 +5465,8 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
 */
 
 static struct c_expr
-c_parser_binary_expression (c_parser *parser, struct c_expr *after)
+c_parser_binary_expression (c_parser *parser, struct c_expr *after,
+                           enum c_parser_prec prec)
 {
   /* A binary expression is parsed using operator-precedence parsing,
      with the operands being cast expressions.  All the binary
@@ -5468,28 +5489,12 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
      expressions, we also need to adjust c_inhibit_evaluation_warnings
      as appropriate when the operators are pushed and popped.  */
 
-  /* The precedence levels, where 0 is a dummy lowest level used for
-     the bottom of the stack.  */
-  enum prec {
-    PREC_NONE,
-    PREC_LOGOR,
-    PREC_LOGAND,
-    PREC_BITOR,
-    PREC_BITXOR,
-    PREC_BITAND,
-    PREC_EQ,
-    PREC_REL,
-    PREC_SHIFT,
-    PREC_ADD,
-    PREC_MULT,
-    NUM_PRECS
-  };
   struct {
     /* The expression at this stack level.  */
     struct c_expr expr;
     /* The precedence of the operator on its left, PREC_NONE at the
        bottom of the stack.  */
-    enum prec prec;
+    enum c_parser_prec prec;
     /* The operation on its left.  */
     enum tree_code op;
     /* The source location of this operation.  */
@@ -5528,11 +5533,11 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
   gcc_assert (!after || c_dialect_objc ());
   stack[0].loc = c_parser_peek_token (parser)->location;
   stack[0].expr = c_parser_cast_expression (parser, after);
-  stack[0].prec = PREC_NONE;
+  stack[0].prec = prec;
   sp = 0;
   while (true)
     {
-      enum prec oprec;
+      enum c_parser_prec oprec;
       enum tree_code ocode;
       if (parser->error)
        goto out;
@@ -5616,9 +5621,13 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
          goto out;
        }
       binary_loc = c_parser_peek_token (parser)->location;
-      c_parser_consume_token (parser);
       while (oprec <= stack[sp].prec)
-       POP;
+       {
+         if (sp == 0)
+           goto out;
+         POP;
+       }
+      c_parser_consume_token (parser);
       switch (ocode)
        {
        case TRUTH_ANDIF_EXPR:
@@ -8243,6 +8252,17 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
       c_parser_omp_taskwait (parser);
       return false;
 
+    case PRAGMA_OMP_TASKYIELD:
+      if (context != pragma_compound)
+       {
+         if (context == pragma_stmt)
+           c_parser_error (parser, "%<#pragma omp taskyield%> may only be "
+                           "used in compound statements");
+         goto bad_stmt;
+       }
+      c_parser_omp_taskyield (parser);
+      return false;
+
     case PRAGMA_OMP_THREADPRIVATE:
       c_parser_omp_threadprivate (parser);
       return false;
@@ -8358,13 +8378,19 @@ c_parser_omp_clause_name (c_parser *parser)
            result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
          break;
        case 'f':
-         if (!strcmp ("firstprivate", p))
+         if (!strcmp ("final", p))
+           result = PRAGMA_OMP_CLAUSE_FINAL;
+         else if (!strcmp ("firstprivate", p))
            result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
          break;
        case 'l':
          if (!strcmp ("lastprivate", p))
            result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
          break;
+       case 'm':
+         if (!strcmp ("mergeable", p))
+           result = PRAGMA_OMP_CLAUSE_MERGEABLE;
+         break;
        case 'n':
          if (!strcmp ("nowait", p))
            result = PRAGMA_OMP_CLAUSE_NOWAIT;
@@ -8606,6 +8632,31 @@ c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
   return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FIRSTPRIVATE, list);
 }
 
+/* OpenMP 3.1:
+   final ( expression ) */
+
+static tree
+c_parser_omp_clause_final (c_parser *parser, tree list)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      tree t = c_parser_paren_condition (parser);
+      tree c;
+
+      check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final");
+
+      c = build_omp_clause (loc, OMP_CLAUSE_FINAL);
+      OMP_CLAUSE_FINAL_EXPR (c) = t;
+      OMP_CLAUSE_CHAIN (c) = list;
+      list = c;
+    }
+  else
+    c_parser_error (parser, "expected %<(%>");
+
+  return list;
+}
+
 /* OpenMP 2.5:
    if ( expression ) */
 
@@ -8640,6 +8691,24 @@ c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
   return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LASTPRIVATE, list);
 }
 
+/* OpenMP 3.1:
+   mergeable */
+
+static tree
+c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list)
+{
+  tree c;
+
+  /* FIXME: Should we allow duplicates?  */
+  check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable");
+
+  c = build_omp_clause (c_parser_peek_token (parser)->location,
+                       OMP_CLAUSE_MERGEABLE);
+  OMP_CLAUSE_CHAIN (c) = list;
+
+  return c;
+}
+
 /* OpenMP 2.5:
    nowait */
 
@@ -8730,7 +8799,12 @@ c_parser_omp_clause_private (c_parser *parser, tree list)
    reduction ( reduction-operator : variable-list )
 
    reduction-operator:
-     One of: + * - & ^ | && || */
+     One of: + * - & ^ | && ||
+     
+   OpenMP 3.1:
+   
+   reduction-operator:
+     One of: + * - & ^ | && || max min  */
 
 static tree
 c_parser_omp_clause_reduction (c_parser *parser, tree list)
@@ -8766,10 +8840,26 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
        case CPP_OR_OR:
          code = TRUTH_ORIF_EXPR;
          break;
+        case CPP_NAME:
+         {
+           const char *p
+             = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+           if (strcmp (p, "min") == 0)
+             {
+               code = MIN_EXPR;
+               break;
+             }
+           if (strcmp (p, "max") == 0)
+             {
+               code = MAX_EXPR;
+               break;
+             }
+         }
+         /* FALLTHRU */
        default:
          c_parser_error (parser,
                          "expected %<+%>, %<*%>, %<-%>, %<&%>, "
-                         "%<^%>, %<|%>, %<&&%>, or %<||%>");
+                         "%<^%>, %<|%>, %<&&%>, %<||%>, %<min%> or %<max%>");
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
          return list;
        }
@@ -8957,6 +9047,10 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
          clauses = c_parser_omp_clause_firstprivate (parser, clauses);
          c_name = "firstprivate";
          break;
+       case PRAGMA_OMP_CLAUSE_FINAL:
+         clauses = c_parser_omp_clause_final (parser, clauses);
+         c_name = "final";
+         break;
        case PRAGMA_OMP_CLAUSE_IF:
          clauses = c_parser_omp_clause_if (parser, clauses);
          c_name = "if";
@@ -8965,6 +9059,10 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
          clauses = c_parser_omp_clause_lastprivate (parser, clauses);
          c_name = "lastprivate";
          break;
+       case PRAGMA_OMP_CLAUSE_MERGEABLE:
+         clauses = c_parser_omp_clause_mergeable (parser, clauses);
+         c_name = "mergeable";
+         break;
        case PRAGMA_OMP_CLAUSE_NOWAIT:
          clauses = c_parser_omp_clause_nowait (parser, clauses);
          c_name = "nowait";
@@ -9044,38 +9142,158 @@ c_parser_omp_structured_block (c_parser *parser)
 
   where x is an lvalue expression with scalar type.
 
+   OpenMP 3.1:
+   # pragma omp atomic new-line
+     update-stmt
+
+   # pragma omp atomic read new-line
+     read-stmt
+
+   # pragma omp atomic write new-line
+     write-stmt
+
+   # pragma omp atomic update new-line
+     update-stmt
+
+   # pragma omp atomic capture new-line
+     capture-stmt
+
+   # pragma omp atomic capture new-line
+     capture-block
+
+   read-stmt:
+     v = x
+   write-stmt:
+     x = expr
+   update-stmt:
+     expression-stmt | x = x binop expr
+   capture-stmt:
+     v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x
+   capture-block:
+     { v = x; update-stmt; } | { update-stmt; v = x; }
+
+  where x and v are lvalue expressions with scalar type.
+
   LOC is the location of the #pragma token.  */
 
 static void
 c_parser_omp_atomic (location_t loc, c_parser *parser)
 {
-  tree lhs, rhs;
-  tree stmt;
-  enum tree_code code;
+  tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE;
+  tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
+  tree stmt, orig_lhs;
+  enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
   struct c_expr rhs_expr;
+  bool structured_block = false;
 
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+      if (!strcmp (p, "read"))
+       code = OMP_ATOMIC_READ;
+      else if (!strcmp (p, "write"))
+       code = NOP_EXPR;
+      else if (!strcmp (p, "update"))
+       code = OMP_ATOMIC;
+      else if (!strcmp (p, "capture"))
+       code = OMP_ATOMIC_CAPTURE_NEW;
+      else
+       p = NULL;
+      if (p)
+       c_parser_consume_token (parser);
+    }
   c_parser_skip_to_pragma_eol (parser);
 
+  switch (code)
+    {
+    case OMP_ATOMIC_READ:
+    case NOP_EXPR: /* atomic write */
+      v = c_parser_unary_expression (parser).value;
+      v = c_fully_fold (v, false, NULL);
+      if (v == error_mark_node)
+       goto saw_error;
+      loc = c_parser_peek_token (parser)->location;
+      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+       goto saw_error;
+      if (code == NOP_EXPR)
+       lhs = c_parser_expression (parser).value;
+      else
+       lhs = c_parser_unary_expression (parser).value;
+      lhs = c_fully_fold (lhs, false, NULL);
+      if (lhs == error_mark_node)
+       goto saw_error;
+      if (code == NOP_EXPR)
+       {
+         /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
+            opcode.  */
+         code = OMP_ATOMIC;
+         rhs = lhs;
+         lhs = v;
+         v = NULL_TREE;
+       }
+      goto done;
+    case OMP_ATOMIC_CAPTURE_NEW:
+      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+       {
+         c_parser_consume_token (parser);
+         structured_block = true;
+       }
+      else
+       {
+         v = c_parser_unary_expression (parser).value;
+         v = c_fully_fold (v, false, NULL);
+         if (v == error_mark_node)
+           goto saw_error;
+         if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+           goto saw_error;
+       }
+      break;
+    default:
+      break;
+    }
+
+  /* For structured_block case we don't know yet whether
+     old or new x should be captured.  */
+restart:
   lhs = c_parser_unary_expression (parser).value;
   lhs = c_fully_fold (lhs, false, NULL);
+  orig_lhs = lhs;
   switch (TREE_CODE (lhs))
     {
     case ERROR_MARK:
     saw_error:
       c_parser_skip_to_end_of_block_or_statement (parser);
+      if (structured_block)
+       {
+         if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+           c_parser_consume_token (parser);
+         else if (code == OMP_ATOMIC_CAPTURE_NEW)
+           {
+             c_parser_skip_to_end_of_block_or_statement (parser);
+             if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+               c_parser_consume_token (parser);
+           }
+       }
       return;
 
-    case PREINCREMENT_EXPR:
     case POSTINCREMENT_EXPR:
+      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+       code = OMP_ATOMIC_CAPTURE_OLD;
+      /* FALLTHROUGH */
+    case PREINCREMENT_EXPR:
       lhs = TREE_OPERAND (lhs, 0);
-      code = PLUS_EXPR;
+      opcode = PLUS_EXPR;
       rhs = integer_one_node;
       break;
 
-    case PREDECREMENT_EXPR:
     case POSTDECREMENT_EXPR:
+      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+       code = OMP_ATOMIC_CAPTURE_OLD;
+      /* FALLTHROUGH */
+    case PREDECREMENT_EXPR:
       lhs = TREE_OPERAND (lhs, 0);
-      code = MINUS_EXPR;
+      opcode = MINUS_EXPR;
       rhs = integer_one_node;
       break;
 
@@ -9100,7 +9318,11 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
              /* This is pre or post increment.  */
              rhs = TREE_OPERAND (lhs, 1);
              lhs = TREE_OPERAND (lhs, 0);
-             code = NOP_EXPR;
+             opcode = NOP_EXPR;
+             if (code == OMP_ATOMIC_CAPTURE_NEW
+                 && !structured_block
+                 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
+               code = OMP_ATOMIC_CAPTURE_OLD;
              break;
            }
          if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
@@ -9110,7 +9332,11 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
              /* This is pre or post decrement.  */
              rhs = TREE_OPERAND (lhs, 1);
              lhs = TREE_OPERAND (lhs, 0);
-             code = NOP_EXPR;
+             opcode = NOP_EXPR;
+             if (code == OMP_ATOMIC_CAPTURE_NEW
+                 && !structured_block
+                 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
+               code = OMP_ATOMIC_CAPTURE_OLD;
              break;
            }
        }
@@ -9119,32 +9345,114 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
       switch (c_parser_peek_token (parser)->type)
        {
        case CPP_MULT_EQ:
-         code = MULT_EXPR;
+         opcode = MULT_EXPR;
          break;
        case CPP_DIV_EQ:
-         code = TRUNC_DIV_EXPR;
+         opcode = TRUNC_DIV_EXPR;
          break;
        case CPP_PLUS_EQ:
-         code = PLUS_EXPR;
+         opcode = PLUS_EXPR;
          break;
        case CPP_MINUS_EQ:
-         code = MINUS_EXPR;
+         opcode = MINUS_EXPR;
          break;
        case CPP_LSHIFT_EQ:
-         code = LSHIFT_EXPR;
+         opcode = LSHIFT_EXPR;
          break;
        case CPP_RSHIFT_EQ:
-         code = RSHIFT_EXPR;
+         opcode = RSHIFT_EXPR;
          break;
        case CPP_AND_EQ:
-         code = BIT_AND_EXPR;
+         opcode = BIT_AND_EXPR;
          break;
        case CPP_OR_EQ:
-         code = BIT_IOR_EXPR;
+         opcode = BIT_IOR_EXPR;
          break;
        case CPP_XOR_EQ:
-         code = BIT_XOR_EXPR;
+         opcode = BIT_XOR_EXPR;
          break;
+       case CPP_EQ:
+         if (structured_block || code == OMP_ATOMIC)
+           {
+             location_t aloc = c_parser_peek_token (parser)->location;
+             location_t rhs_loc;
+             enum c_parser_prec oprec = PREC_NONE;
+
+             c_parser_consume_token (parser);
+             rhs1 = c_parser_unary_expression (parser).value;
+             rhs1 = c_fully_fold (rhs1, false, NULL);
+             if (rhs1 == error_mark_node)
+               goto saw_error;
+             switch (c_parser_peek_token (parser)->type)
+               {
+               case CPP_SEMICOLON:
+                 if (code == OMP_ATOMIC_CAPTURE_NEW)
+                   {
+                     code = OMP_ATOMIC_CAPTURE_OLD;
+                     v = lhs;
+                     lhs = NULL_TREE;
+                     lhs1 = rhs1;
+                     rhs1 = NULL_TREE;
+                     c_parser_consume_token (parser);
+                     goto restart;
+                   }
+                 c_parser_error (parser,
+                                 "invalid form of %<#pragma omp atomic%>");
+                 goto saw_error;
+               case CPP_MULT:
+                 opcode = MULT_EXPR;
+                 oprec = PREC_MULT;
+                 break;
+               case CPP_DIV:
+                 opcode = TRUNC_DIV_EXPR;
+                 oprec = PREC_MULT;
+                 break;
+               case CPP_PLUS:
+                 opcode = PLUS_EXPR;
+                 oprec = PREC_ADD;
+                 break;
+               case CPP_MINUS:
+                 opcode = MINUS_EXPR;
+                 oprec = PREC_ADD;
+                 break;
+               case CPP_LSHIFT:
+                 opcode = LSHIFT_EXPR;
+                 oprec = PREC_SHIFT;
+                 break;
+               case CPP_RSHIFT:
+                 opcode = RSHIFT_EXPR;
+                 oprec = PREC_SHIFT;
+                 break;
+               case CPP_AND:
+                 opcode = BIT_AND_EXPR;
+                 oprec = PREC_BITAND;
+                 break;
+               case CPP_OR:
+                 opcode = BIT_IOR_EXPR;
+                 oprec = PREC_BITOR;
+                 break;
+               case CPP_XOR:
+                 opcode = BIT_XOR_EXPR;
+                 oprec = PREC_BITXOR;
+                 break;
+               default:
+                 c_parser_error (parser,
+                                 "invalid operator for %<#pragma omp atomic%>");
+                 goto saw_error;
+               }
+             loc = aloc;
+             c_parser_consume_token (parser);
+             rhs_loc = c_parser_peek_token (parser)->location;
+             if (commutative_tree_code (opcode))
+               oprec = (enum c_parser_prec) (oprec - 1);
+             rhs_expr = c_parser_binary_expression (parser, NULL, oprec);
+             rhs_expr = default_function_array_read_conversion (rhs_loc,
+                                                                rhs_expr);
+             rhs = rhs_expr.value;
+             rhs = c_fully_fold (rhs, false, NULL);
+             goto stmt_done; 
+           }
+         /* FALLTHROUGH */
        default:
          c_parser_error (parser,
                          "invalid operator for %<#pragma omp atomic%>");
@@ -9164,10 +9472,34 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
       rhs = c_fully_fold (rhs, false, NULL);
       break;
     }
-  stmt = c_finish_omp_atomic (loc, code, lhs, rhs);
+stmt_done:
+  if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+    {
+      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+       goto saw_error;
+      v = c_parser_unary_expression (parser).value;
+      v = c_fully_fold (v, false, NULL);
+      if (v == error_mark_node)
+       goto saw_error;
+      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+       goto saw_error;
+      lhs1 = c_parser_unary_expression (parser).value;
+      lhs1 = c_fully_fold (lhs1, false, NULL);
+      if (lhs1 == error_mark_node)
+       goto saw_error;
+    }
+  if (structured_block)
+    {
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+      c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
+    }
+done:
+  stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1);
   if (stmt != error_mark_node)
     add_stmt (stmt);
-  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+
+  if (!structured_block)
+    c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
 }
 
 
@@ -9330,7 +9662,8 @@ c_parser_omp_for_loop (location_t loc,
       if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
        {
          location_t cond_loc = c_parser_peek_token (parser)->location;
-         struct c_expr cond_expr = c_parser_binary_expression (parser, NULL);
+         struct c_expr cond_expr = c_parser_binary_expression (parser, NULL,
+                                                               PREC_NONE);
 
          cond = cond_expr.value;
          cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
@@ -9827,7 +10160,9 @@ c_parser_omp_single (location_t loc, c_parser *parser)
        | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
        | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
        | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
-       | (1u << PRAGMA_OMP_CLAUSE_SHARED))
+       | (1u << PRAGMA_OMP_CLAUSE_SHARED)              \
+       | (1u << PRAGMA_OMP_CLAUSE_FINAL)               \
+       | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE))
 
 static tree
 c_parser_omp_task (location_t loc, c_parser *parser)
@@ -9856,6 +10191,20 @@ c_parser_omp_taskwait (c_parser *parser)
   c_finish_omp_taskwait (loc);
 }
 
+/* OpenMP 3.1:
+   # pragma omp taskyield new-line
+*/
+
+static void
+c_parser_omp_taskyield (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_pragma (parser);
+  c_parser_skip_to_pragma_eol (parser);
+
+  c_finish_omp_taskyield (loc);
+}
+
 /* Main entry point to parsing most OpenMP pragmas.  */
 
 static void
index aeb6625a5ee7691999a0c2179cc3e330a4baefa9..f7f782440946f2199a9e9b10346c22db8dc47a23 100644 (file)
@@ -10451,6 +10451,8 @@ c_finish_omp_clauses (tree clauses)
                case PLUS_EXPR:
                case MULT_EXPR:
                case MINUS_EXPR:
+               case MIN_EXPR:
+               case MAX_EXPR:
                  break;
                case BIT_AND_EXPR:
                  r_name = "&";
@@ -10567,6 +10569,8 @@ c_finish_omp_clauses (tree clauses)
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_FINAL:
+       case OMP_CLAUSE_MERGEABLE:
          pc = &OMP_CLAUSE_CHAIN (c);
          continue;
 
@@ -10596,6 +10600,10 @@ c_finish_omp_clauses (tree clauses)
                case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
                  break;
                case OMP_CLAUSE_DEFAULT_SHARED:
+                 /* const vars may be specified in firstprivate clause.  */
+                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+                     && TREE_READONLY (t))
+                   break;
                  share_name = "shared";
                  break;
                case OMP_CLAUSE_DEFAULT_PRIVATE:
index 65d0e7c6628cabf692eb9c644d1d6f3c842018cb..bc972a2ac81aa7aef48cf0c3b35f65e58374e381 100644 (file)
@@ -1,3 +1,33 @@
+2011-08-02  Jakub Jelinek  <jakub@redhat.com>
+
+       * cp-tree.h (finish_omp_atomic): Adjust prototype.
+       (cxx_omp_const_qual_no_mutable): New prototype.
+       (finish_omp_taskyield): New prototype.
+       * parser.c (cp_parser_omp_atomic): (cp_parser_omp_atomic): Handle
+       parsing OpenMP 3.1 atomics.  Adjust finish_omp_atomic caller.
+       (cp_parser_omp_clause_name): Handle final and mergeable clauses.
+       (cp_parser_omp_clause_final, cp_parser_omp_clause_mergeable): New
+       functions.
+       (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FINAL
+       and PRAGMA_OMP_CLAUSE_MERGEABLE.
+       (OMP_TASK_CLAUSE_MASK): Allow final and mergeable clauses.
+       (cp_parser_omp_taskyield): New function.
+       (cp_parser_pragma): Handle PRAGMA_OMP_TASKYIELD.
+       (cp_parser_omp_clause_reduction): Handle min and max.
+       * pt.c (tsubst_expr) <case OMP_ATOMIC>: Handle OpenMP 3.1 atomics.
+       (tsubst_omp_clauses): Handle OMP_CLAUSE_FINAL and
+       OMP_CLAUSE_MERGEABLE.
+       * semantics.c (finish_omp_atomic): Add OPCODE, V, LHS1 and RHS1
+       arguments.  Handle OpenMP 3.1 atomics.  Adjust c_finish_omp_atomic
+       caller.
+       (finish_omp_clauses): Don't complain about const qualified
+       predetermined vars and static data members in firstprivate clause.
+       Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. Handle MIN_EXPR
+       and MAX_EXPR.
+       (finish_omp_taskyield): New function.
+       * cp-gimplify.c (cxx_omp_const_qual_no_mutable): New function.
+       (cxx_omp_predetermined_sharing): Use it.
+
 2011-08-02  Jason Merrill  <jason@redhat.com>
 
        * call.c (build_call_a): Also check at_function_scope_p.
index 2b4e70a75ef90031ff1eea133d5314e72ebdff2e..6aeae75b06336d60c56c194691c28494deafbdf0 100644 (file)
@@ -1365,26 +1365,15 @@ cxx_omp_privatize_by_reference (const_tree decl)
   return is_invisiref_parm (decl);
 }
 
-/* True if OpenMP sharing attribute of DECL is predetermined.  */
-
-enum omp_clause_default_kind
-cxx_omp_predetermined_sharing (tree decl)
+/* Return true if DECL is const qualified var having no mutable member.  */
+bool
+cxx_omp_const_qual_no_mutable (tree decl)
 {
-  tree type;
-
-  /* Static data members are predetermined as shared.  */
-  if (TREE_STATIC (decl))
-    {
-      tree ctx = CP_DECL_CONTEXT (decl);
-      if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
-       return OMP_CLAUSE_DEFAULT_SHARED;
-    }
-
-  type = TREE_TYPE (decl);
+  tree type = TREE_TYPE (decl);
   if (TREE_CODE (type) == REFERENCE_TYPE)
     {
       if (!is_invisiref_parm (decl))
-       return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+       return false;
       type = TREE_TYPE (type);
 
       if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl))
@@ -1408,11 +1397,32 @@ cxx_omp_predetermined_sharing (tree decl)
     }
 
   if (type == error_mark_node)
-    return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+    return false;
 
   /* Variables with const-qualified type having no mutable member
      are predetermined shared.  */
   if (TYPE_READONLY (type) && !cp_has_mutable_p (type))
+    return true;
+
+  return false;
+}
+
+/* True if OpenMP sharing attribute of DECL is predetermined.  */
+
+enum omp_clause_default_kind
+cxx_omp_predetermined_sharing (tree decl)
+{
+  /* Static data members are predetermined shared.  */
+  if (TREE_STATIC (decl))
+    {
+      tree ctx = CP_DECL_CONTEXT (decl);
+      if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
+       return OMP_CLAUSE_DEFAULT_SHARED;
+    }
+
+  /* Const qualified vars having no mutable member are predetermined
+     shared.  */
+  if (cxx_omp_const_qual_no_mutable (decl))
     return OMP_CLAUSE_DEFAULT_SHARED;
 
   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
index fb171782cd70b947926430bdb434e9dd1477b0b2..ff5509e5b3f58d78c35ade379215e1d34bb5ce0e 100644 (file)
@@ -5454,10 +5454,12 @@ extern tree begin_omp_task                      (void);
 extern tree finish_omp_task                    (tree, tree);
 extern tree finish_omp_for                     (location_t, tree, tree,
                                                 tree, tree, tree, tree, tree);
-extern void finish_omp_atomic                  (enum tree_code, tree, tree);
+extern void finish_omp_atomic                  (enum tree_code, enum tree_code,
+                                                tree, tree, tree, tree, tree);
 extern void finish_omp_barrier                 (void);
 extern void finish_omp_flush                   (void);
 extern void finish_omp_taskwait                        (void);
+extern void finish_omp_taskyield               (void);
 extern bool cxx_omp_create_clause_info         (tree, tree, bool, bool, bool);
 extern tree baselink_for_fns                    (tree);
 extern void finish_static_assert                (tree, tree, location_t,
@@ -5765,6 +5767,7 @@ extern void init_shadowed_var_for_decl            (void);
 extern int cp_gimplify_expr                    (tree *, gimple_seq *,
                                                 gimple_seq *);
 extern void cp_genericize                      (tree);
+extern bool cxx_omp_const_qual_no_mutable      (tree);
 extern enum omp_clause_default_kind cxx_omp_predetermined_sharing (tree);
 extern tree cxx_omp_clause_default_ctor                (tree, tree, tree);
 extern tree cxx_omp_clause_copy_ctor           (tree, tree, tree);
index 3828ca98796a9cc58deb802220057a35150aea43..576c842e89fca486e8f50cc3db987a3b01803a96 100644 (file)
@@ -23600,13 +23600,19 @@ cp_parser_omp_clause_name (cp_parser *parser)
            result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
          break;
        case 'f':
-         if (!strcmp ("firstprivate", p))
+         if (!strcmp ("final", p))
+           result = PRAGMA_OMP_CLAUSE_FINAL;
+         else if (!strcmp ("firstprivate", p))
            result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
          break;
        case 'l':
          if (!strcmp ("lastprivate", p))
            result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
          break;
+       case 'm':
+         if (!strcmp ("mergeable", p))
+           result = PRAGMA_OMP_CLAUSE_MERGEABLE;
+         break;
        case 'n':
          if (!strcmp ("nowait", p))
            result = PRAGMA_OMP_CLAUSE_NOWAIT;
@@ -23836,6 +23842,34 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list, location_t location)
   return c;
 }
 
+/* OpenMP 3.1:
+   final ( expression ) */
+
+static tree
+cp_parser_omp_clause_final (cp_parser *parser, tree list, location_t location)
+{
+  tree t, c;
+
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+    return list;
+
+  t = cp_parser_condition (parser);
+
+  if (t == error_mark_node
+      || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+    cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                          /*or_comma=*/false,
+                                          /*consume_paren=*/true);
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final", location);
+
+  c = build_omp_clause (location, OMP_CLAUSE_FINAL);
+  OMP_CLAUSE_FINAL_EXPR (c) = t;
+  OMP_CLAUSE_CHAIN (c) = list;
+
+  return c;
+}
+
 /* OpenMP 2.5:
    if ( expression ) */
 
@@ -23864,6 +23898,23 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location)
   return c;
 }
 
+/* OpenMP 3.1:
+   mergeable */
+
+static tree
+cp_parser_omp_clause_mergeable (cp_parser *parser ATTRIBUTE_UNUSED,
+                               tree list, location_t location)
+{
+  tree c;
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable",
+                            location);
+
+  c = build_omp_clause (location, OMP_CLAUSE_MERGEABLE);
+  OMP_CLAUSE_CHAIN (c) = list;
+  return c;
+}
+
 /* OpenMP 2.5:
    nowait */
 
@@ -23931,7 +23982,12 @@ cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED,
    reduction ( reduction-operator : variable-list )
 
    reduction-operator:
-     One of: + * - & ^ | && || */
+     One of: + * - & ^ | && ||
+
+   OpenMP 3.1:
+
+   reduction-operator:
+     One of: + * - & ^ | && || min max  */
 
 static tree
 cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
@@ -23968,9 +24024,26 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
     case CPP_OR_OR:
       code = TRUTH_ORIF_EXPR;
       break;
+    case CPP_NAME:
+      {
+       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+       const char *p = IDENTIFIER_POINTER (id);
+
+       if (strcmp (p, "min") == 0)
+         {
+           code = MIN_EXPR;
+           break;
+         }
+       if (strcmp (p, "max") == 0)
+         {
+           code = MAX_EXPR;
+           break;
+         }
+      }
+      /* FALLTHROUGH */
     default:
       cp_parser_error (parser, "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, "
-                              "%<|%>, %<&&%>, or %<||%>");
+                              "%<|%>, %<&&%>, %<||%>, %<min%> or %<max%>");
     resync_fail:
       cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                             /*or_comma=*/false,
@@ -24143,6 +24216,10 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
                                                  token->location);
          c_name = "default";
          break;
+       case PRAGMA_OMP_CLAUSE_FINAL:
+         clauses = cp_parser_omp_clause_final (parser, clauses, token->location);
+         c_name = "final";
+         break;
        case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
          clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FIRSTPRIVATE,
                                            clauses);
@@ -24157,6 +24234,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
                                            clauses);
          c_name = "lastprivate";
          break;
+       case PRAGMA_OMP_CLAUSE_MERGEABLE:
+         clauses = cp_parser_omp_clause_mergeable (parser, clauses,
+                                                   token->location);
+         c_name = "mergeable";
+         break;
        case PRAGMA_OMP_CLAUSE_NOWAIT:
          clauses = cp_parser_omp_clause_nowait (parser, clauses, token->location);
          c_name = "nowait";
@@ -24267,34 +24349,140 @@ cp_parser_omp_structured_block (cp_parser *parser)
    binop:
      +, *, -, /, &, ^, |, <<, >>
 
-  where x is an lvalue expression with scalar type.  */
+  where x is an lvalue expression with scalar type.
+
+   OpenMP 3.1:
+   # pragma omp atomic new-line
+     update-stmt
+
+   # pragma omp atomic read new-line
+     read-stmt
+
+   # pragma omp atomic write new-line
+     write-stmt
+
+   # pragma omp atomic update new-line
+     update-stmt
+
+   # pragma omp atomic capture new-line
+     capture-stmt
+
+   # pragma omp atomic capture new-line
+     capture-block
+
+   read-stmt:
+     v = x
+   write-stmt:
+     x = expr
+   update-stmt:
+     expression-stmt | x = x binop expr
+   capture-stmt:
+     v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x
+   capture-block:
+     { v = x; update-stmt; } | { update-stmt; v = x; }
+
+  where x and v are lvalue expressions with scalar type.  */
 
 static void
 cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
 {
-  tree lhs, rhs;
-  enum tree_code code;
+  tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, lhs1 = NULL_TREE;
+  tree rhs1 = NULL_TREE, orig_lhs;
+  enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
+  bool structured_block = false;
+
+  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+    {
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+      const char *p = IDENTIFIER_POINTER (id);
 
+      if (!strcmp (p, "read"))
+       code = OMP_ATOMIC_READ;
+      else if (!strcmp (p, "write"))
+       code = NOP_EXPR;
+      else if (!strcmp (p, "update"))
+       code = OMP_ATOMIC;
+      else if (!strcmp (p, "capture"))
+       code = OMP_ATOMIC_CAPTURE_NEW;
+      else
+       p = NULL;
+      if (p)
+       cp_lexer_consume_token (parser->lexer);
+    }
   cp_parser_require_pragma_eol (parser, pragma_tok);
 
+  switch (code)
+    {
+    case OMP_ATOMIC_READ:
+    case NOP_EXPR: /* atomic write */
+      v = cp_parser_unary_expression (parser, /*address_p=*/false,
+                                     /*cast_p=*/false, NULL);
+      if (v == error_mark_node)
+       goto saw_error;
+      if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+       goto saw_error;
+      if (code == NOP_EXPR)
+       lhs = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+      else
+       lhs = cp_parser_unary_expression (parser, /*address_p=*/false,
+                                         /*cast_p=*/false, NULL);
+      if (lhs == error_mark_node)
+       goto saw_error;
+      if (code == NOP_EXPR)
+       {
+         /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
+            opcode.  */
+         code = OMP_ATOMIC;
+         rhs = lhs;
+         lhs = v;
+         v = NULL_TREE;
+       }
+      goto done;
+    case OMP_ATOMIC_CAPTURE_NEW:
+      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+       {
+         cp_lexer_consume_token (parser->lexer);
+         structured_block = true;
+       }
+      else
+       {
+         v = cp_parser_unary_expression (parser, /*address_p=*/false,
+                                         /*cast_p=*/false, NULL);
+         if (v == error_mark_node)
+           goto saw_error;
+         if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+           goto saw_error;
+       }
+    default:
+      break;
+    }
+
+restart:
   lhs = cp_parser_unary_expression (parser, /*address_p=*/false,
                                    /*cast_p=*/false, NULL);
+  orig_lhs = lhs;
   switch (TREE_CODE (lhs))
     {
     case ERROR_MARK:
       goto saw_error;
 
-    case PREINCREMENT_EXPR:
     case POSTINCREMENT_EXPR:
+      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+       code = OMP_ATOMIC_CAPTURE_OLD;
+      /* FALLTHROUGH */
+    case PREINCREMENT_EXPR:
       lhs = TREE_OPERAND (lhs, 0);
-      code = PLUS_EXPR;
+      opcode = PLUS_EXPR;
       rhs = integer_one_node;
       break;
 
-    case PREDECREMENT_EXPR:
     case POSTDECREMENT_EXPR:
+      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+       code = OMP_ATOMIC_CAPTURE_OLD;
+      /* FALLTHROUGH */
+    case PREDECREMENT_EXPR:
       lhs = TREE_OPERAND (lhs, 0);
-      code = MINUS_EXPR;
+      opcode = MINUS_EXPR;
       rhs = integer_one_node;
       break;
 
@@ -24312,48 +24500,123 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
     case MODIFY_EXPR:
       if (TREE_CODE (lhs) == MODIFY_EXPR
         && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE)
-       {
-        /* Undo effects of boolean_increment.  */
-        if (integer_onep (TREE_OPERAND (lhs, 1)))
-          {
-            /* This is pre or post increment.  */
-            rhs = TREE_OPERAND (lhs, 1);
-            lhs = TREE_OPERAND (lhs, 0);
-            code = NOP_EXPR;
-            break;
-          }
-       }
+       {
+         /* Undo effects of boolean_increment.  */
+         if (integer_onep (TREE_OPERAND (lhs, 1)))
+           {
+             /* This is pre or post increment.  */
+             rhs = TREE_OPERAND (lhs, 1);
+             lhs = TREE_OPERAND (lhs, 0);
+             opcode = NOP_EXPR;
+             if (code == OMP_ATOMIC_CAPTURE_NEW
+                 && !structured_block
+                 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
+               code = OMP_ATOMIC_CAPTURE_OLD;
+             break;
+           }
+       }
       /* FALLTHRU */
     default:
       switch (cp_lexer_peek_token (parser->lexer)->type)
        {
        case CPP_MULT_EQ:
-         code = MULT_EXPR;
+         opcode = MULT_EXPR;
          break;
        case CPP_DIV_EQ:
-         code = TRUNC_DIV_EXPR;
+         opcode = TRUNC_DIV_EXPR;
          break;
        case CPP_PLUS_EQ:
-         code = PLUS_EXPR;
+         opcode = PLUS_EXPR;
          break;
        case CPP_MINUS_EQ:
-         code = MINUS_EXPR;
+         opcode = MINUS_EXPR;
          break;
        case CPP_LSHIFT_EQ:
-         code = LSHIFT_EXPR;
+         opcode = LSHIFT_EXPR;
          break;
        case CPP_RSHIFT_EQ:
-         code = RSHIFT_EXPR;
+         opcode = RSHIFT_EXPR;
          break;
        case CPP_AND_EQ:
-         code = BIT_AND_EXPR;
+         opcode = BIT_AND_EXPR;
          break;
        case CPP_OR_EQ:
-         code = BIT_IOR_EXPR;
+         opcode = BIT_IOR_EXPR;
          break;
        case CPP_XOR_EQ:
-         code = BIT_XOR_EXPR;
+         opcode = BIT_XOR_EXPR;
          break;
+       case CPP_EQ:
+         if (structured_block || code == OMP_ATOMIC)
+           {
+             enum cp_parser_prec oprec;
+             cp_token *token;
+             cp_lexer_consume_token (parser->lexer);
+             rhs1 = cp_parser_unary_expression (parser, /*address_p=*/false,
+                                                /*cast_p=*/false, NULL);
+             if (rhs1 == error_mark_node)
+               goto saw_error;
+             token = cp_lexer_peek_token (parser->lexer);
+             switch (token->type)
+               {
+               case CPP_SEMICOLON:
+                 if (code == OMP_ATOMIC_CAPTURE_NEW)
+                   {
+                     code = OMP_ATOMIC_CAPTURE_OLD;
+                     v = lhs;
+                     lhs = NULL_TREE;
+                     lhs1 = rhs1;
+                     rhs1 = NULL_TREE;
+                     cp_lexer_consume_token (parser->lexer);
+                     goto restart;
+                   }
+                 cp_parser_error (parser,
+                                  "invalid form of %<#pragma omp atomic%>");
+                 goto saw_error;
+               case CPP_MULT:
+                 opcode = MULT_EXPR;
+                 break;
+               case CPP_DIV:
+                 opcode = TRUNC_DIV_EXPR;
+                 break;
+               case CPP_PLUS:
+                 opcode = PLUS_EXPR;
+                 break;
+               case CPP_MINUS:
+                 opcode = MINUS_EXPR;
+                 break;
+               case CPP_LSHIFT:
+                 opcode = LSHIFT_EXPR;
+                 break;
+               case CPP_RSHIFT:
+                 opcode = RSHIFT_EXPR;
+                 break;
+               case CPP_AND:
+                 opcode = BIT_AND_EXPR;
+                 break;
+               case CPP_OR:
+                 opcode = BIT_IOR_EXPR;
+                 break;
+               case CPP_XOR:
+                 opcode = BIT_XOR_EXPR;
+                 break;
+               default:
+                 cp_parser_error (parser,
+                                  "invalid operator for %<#pragma omp atomic%>");
+                 goto saw_error;
+               }
+             oprec = TOKEN_PRECEDENCE (token);
+             gcc_assert (oprec != PREC_NOT_OPERATOR);
+             if (commutative_tree_code (opcode))
+               oprec = (enum cp_parser_prec) (oprec - 1);
+             cp_lexer_consume_token (parser->lexer);
+             rhs = cp_parser_binary_expression (parser, false, false,
+                                                oprec, NULL);
+             if (rhs == error_mark_node)
+               goto saw_error;
+             goto stmt_done;
+           }
+         /* FALLTHROUGH */
        default:
          cp_parser_error (parser,
                           "invalid operator for %<#pragma omp atomic%>");
@@ -24366,12 +24629,46 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
        goto saw_error;
       break;
     }
-  finish_omp_atomic (code, lhs, rhs);
-  cp_parser_consume_semicolon_at_end_of_statement (parser);
+stmt_done:
+  if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+    {
+      if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
+       goto saw_error;
+      v = cp_parser_unary_expression (parser, /*address_p=*/false,
+                                     /*cast_p=*/false, NULL);
+      if (v == error_mark_node)
+       goto saw_error;
+      if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+       goto saw_error;
+      lhs1 = cp_parser_unary_expression (parser, /*address_p=*/false,
+                                        /*cast_p=*/false, NULL);
+      if (lhs1 == error_mark_node)
+       goto saw_error;
+    }
+  if (structured_block)
+    {
+      cp_parser_consume_semicolon_at_end_of_statement (parser);
+      cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+    }
+done:
+  finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1);
+  if (!structured_block)
+    cp_parser_consume_semicolon_at_end_of_statement (parser);
   return;
 
  saw_error:
   cp_parser_skip_to_end_of_block_or_statement (parser);
+  if (structured_block)
+    {
+      if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+        cp_lexer_consume_token (parser->lexer);
+      else if (code == OMP_ATOMIC_CAPTURE_NEW)
+       {
+         cp_parser_skip_to_end_of_block_or_statement (parser);
+         if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+           cp_lexer_consume_token (parser->lexer);
+       }
+    }
 }
 
 
@@ -25233,7 +25530,9 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok)
        | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
        | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
        | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
-       | (1u << PRAGMA_OMP_CLAUSE_SHARED))
+       | (1u << PRAGMA_OMP_CLAUSE_SHARED)              \
+       | (1u << PRAGMA_OMP_CLAUSE_FINAL)               \
+       | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE))
 
 static tree
 cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok)
@@ -25260,6 +25559,16 @@ cp_parser_omp_taskwait (cp_parser *parser, cp_token *pragma_tok)
   finish_omp_taskwait ();
 }
 
+/* OpenMP 3.1:
+   # pragma omp taskyield new-line  */
+
+static void
+cp_parser_omp_taskyield (cp_parser *parser, cp_token *pragma_tok)
+{
+  cp_parser_require_pragma_eol (parser, pragma_tok);
+  finish_omp_taskyield ();
+}
+
 /* OpenMP 2.5:
    # pragma omp threadprivate (variable-list) */
 
@@ -25435,6 +25744,22 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
        }
       break;
 
+    case PRAGMA_OMP_TASKYIELD:
+      switch (context)
+       {
+       case pragma_compound:
+         cp_parser_omp_taskyield (parser, pragma_tok);
+         return false;
+       case pragma_stmt:
+         error_at (pragma_tok->location,
+                   "%<#pragma omp taskyield%> may only be "
+                   "used in compound statements");
+         break;
+       default:
+         goto bad_stmt;
+       }
+      break;
+
     case PRAGMA_OMP_THREADPRIVATE:
       cp_parser_omp_threadprivate (parser, pragma_tok);
       return false;
index a3cd9568d23a3e59ca058e4a6af41bca56f60c95..3131e613882fa85016397b32c13ab333678d7159 100644 (file)
@@ -12181,6 +12181,7 @@ tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
        case OMP_CLAUSE_NUM_THREADS:
        case OMP_CLAUSE_SCHEDULE:
        case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_FINAL:
          OMP_CLAUSE_OPERAND (nc, 0)
            = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, 
                           in_decl, /*integral_constant_expression_p=*/false);
@@ -12189,6 +12190,7 @@ tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_UNTIED:
+       case OMP_CLAUSE_MERGEABLE:
          break;
        default:
          gcc_unreachable ();
@@ -12819,12 +12821,56 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 
     case OMP_ATOMIC:
       gcc_assert (OMP_ATOMIC_DEPENDENT_P (t));
-      {
-       tree op1 = TREE_OPERAND (t, 1);
-       tree lhs = RECUR (TREE_OPERAND (op1, 0));
-       tree rhs = RECUR (TREE_OPERAND (op1, 1));
-       finish_omp_atomic (TREE_CODE (op1), lhs, rhs);
-      }
+      if (TREE_CODE (TREE_OPERAND (t, 1)) != MODIFY_EXPR)
+       {
+         tree op1 = TREE_OPERAND (t, 1);
+         tree rhs1 = NULL_TREE;
+         tree lhs, rhs;
+         if (TREE_CODE (op1) == COMPOUND_EXPR)
+           {
+             rhs1 = RECUR (TREE_OPERAND (op1, 0));
+             op1 = TREE_OPERAND (op1, 1);
+           }
+         lhs = RECUR (TREE_OPERAND (op1, 0));
+         rhs = RECUR (TREE_OPERAND (op1, 1));
+         finish_omp_atomic (OMP_ATOMIC, TREE_CODE (op1), lhs, rhs,
+                            NULL_TREE, NULL_TREE, rhs1);
+       }
+      else
+       {
+         tree op1 = TREE_OPERAND (t, 1);
+         tree v = NULL_TREE, lhs, rhs = NULL_TREE, lhs1 = NULL_TREE;
+         tree rhs1 = NULL_TREE;
+         enum tree_code code = TREE_CODE (TREE_OPERAND (op1, 1));
+         enum tree_code opcode = NOP_EXPR;
+         if (code == OMP_ATOMIC_READ)
+           {
+             v = RECUR (TREE_OPERAND (op1, 0));
+             lhs = RECUR (TREE_OPERAND (TREE_OPERAND (op1, 1), 0));
+           }
+         else if (code == OMP_ATOMIC_CAPTURE_OLD
+                  || code == OMP_ATOMIC_CAPTURE_NEW)
+           {
+             tree op11 = TREE_OPERAND (TREE_OPERAND (op1, 1), 1);
+             v = RECUR (TREE_OPERAND (op1, 0));
+             lhs1 = RECUR (TREE_OPERAND (TREE_OPERAND (op1, 1), 0));
+             if (TREE_CODE (op11) == COMPOUND_EXPR)
+               {
+                 rhs1 = RECUR (TREE_OPERAND (op11, 0));
+                 op11 = TREE_OPERAND (op11, 1);
+               }
+             lhs = RECUR (TREE_OPERAND (op11, 0));
+             rhs = RECUR (TREE_OPERAND (op11, 1));
+             opcode = TREE_CODE (op11);
+           }
+         else
+           {
+             code = OMP_ATOMIC;
+             lhs = RECUR (TREE_OPERAND (op1, 0));
+             rhs = RECUR (TREE_OPERAND (op1, 1));
+           }
+         finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1);
+       }
       break;
 
     case EXPR_PACK_EXPANSION:
index 0b2a96fa4d2de1bb3979913560dac37835bf82f5..a52847733e63f644d6950687bf8648613160011d 100644 (file)
@@ -3905,6 +3905,14 @@ finish_omp_clauses (tree clauses)
          OMP_CLAUSE_IF_EXPR (c) = t;
          break;
 
+       case OMP_CLAUSE_FINAL:
+         t = OMP_CLAUSE_FINAL_EXPR (c);
+         t = maybe_convert_cond (t);
+         if (t == error_mark_node)
+           remove = true;
+         OMP_CLAUSE_FINAL_EXPR (c) = t;
+         break;
+
        case OMP_CLAUSE_NUM_THREADS:
          t = OMP_CLAUSE_NUM_THREADS_EXPR (c);
          if (t == error_mark_node)
@@ -3936,6 +3944,7 @@ finish_omp_clauses (tree clauses)
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        default:
@@ -4030,6 +4039,8 @@ finish_omp_clauses (tree clauses)
                case PLUS_EXPR:
                case MULT_EXPR:
                case MINUS_EXPR:
+               case MIN_EXPR:
+               case MAX_EXPR:
                  break;
                default:
                  error ("%qE has invalid type for %<reduction(%s)%>",
@@ -4074,6 +4085,10 @@ finish_omp_clauses (tree clauses)
            case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
              break;
            case OMP_CLAUSE_DEFAULT_SHARED:
+             /* const vars may be specified in firstprivate clause.  */
+             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+                 && cxx_omp_const_qual_no_mutable (t))
+               break;
              share_name = "shared";
              break;
            case OMP_CLAUSE_DEFAULT_PRIVATE:
@@ -4697,15 +4712,22 @@ finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
 }
 
 void
-finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
+finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
+                  tree rhs, tree v, tree lhs1, tree rhs1)
 {
   tree orig_lhs;
   tree orig_rhs;
+  tree orig_v;
+  tree orig_lhs1;
+  tree orig_rhs1;
   bool dependent_p;
   tree stmt;
 
   orig_lhs = lhs;
   orig_rhs = rhs;
+  orig_v = v;
+  orig_lhs1 = lhs1;
+  orig_rhs1 = rhs1;
   dependent_p = false;
   stmt = NULL_TREE;
 
@@ -4714,22 +4736,53 @@ finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
   if (processing_template_decl)
     {
       dependent_p = (type_dependent_expression_p (lhs)
-                    || type_dependent_expression_p (rhs));
+                    || (rhs && type_dependent_expression_p (rhs))
+                    || (v && type_dependent_expression_p (v))
+                    || (lhs1 && type_dependent_expression_p (lhs1))
+                    || (rhs1 && type_dependent_expression_p (rhs1)));
       if (!dependent_p)
        {
          lhs = build_non_dependent_expr (lhs);
-         rhs = build_non_dependent_expr (rhs);
+         if (rhs)
+           rhs = build_non_dependent_expr (rhs);
+         if (v)
+           v = build_non_dependent_expr (v);
+         if (lhs1)
+           lhs1 = build_non_dependent_expr (lhs1);
+         if (rhs1)
+           rhs1 = build_non_dependent_expr (rhs1);
        }
     }
   if (!dependent_p)
     {
-      stmt = c_finish_omp_atomic (input_location, code, lhs, rhs);
+      stmt = c_finish_omp_atomic (input_location, code, opcode, lhs, rhs,
+                                 v, lhs1, rhs1);
       if (stmt == error_mark_node)
        return;
     }
   if (processing_template_decl)
-    stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node,
-                  build2 (code, void_type_node, orig_lhs, orig_rhs));
+    {
+      if (code == OMP_ATOMIC_READ)
+       {
+         stmt = build_min_nt (OMP_ATOMIC_READ, orig_lhs);
+         stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
+       }
+      else
+       {
+         if (opcode == NOP_EXPR)
+           stmt = build2 (MODIFY_EXPR, void_type_node, orig_lhs, orig_rhs);
+         else 
+           stmt = build2 (opcode, void_type_node, orig_lhs, orig_rhs);
+         if (orig_rhs1)
+           stmt = build_min_nt (COMPOUND_EXPR, orig_rhs1, stmt);
+         if (code != OMP_ATOMIC)
+           {
+             stmt = build_min_nt (code, orig_lhs1, stmt);
+             stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
+           }
+       }
+      stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node, stmt);
+    }
   add_stmt (stmt);
 }
 
@@ -4762,6 +4815,16 @@ finish_omp_taskwait (void)
   release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
+
+void
+finish_omp_taskyield (void)
+{
+  tree fn = built_in_decls[BUILT_IN_GOMP_TASKYIELD];
+  VEC(tree,gc) *vec = make_tree_vector ();
+  tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+  release_tree_vector (vec);
+  finish_expr_stmt (stmt);
+}
 \f
 void
 init_cp_semantics (void)
index 0cc8dfb22cc23aed8318fe99aeb23c8aea5c164b..dba71e2e0ee66480fb7882e0c2e61efe4ca4a1b0 100644 (file)
@@ -2210,7 +2210,9 @@ Clauses are represented by separate sub-codes defined in
 @code{OMP_CLAUSE_COPYPRIVATE}, @code{OMP_CLAUSE_IF},
 @code{OMP_CLAUSE_NUM_THREADS}, @code{OMP_CLAUSE_SCHEDULE},
 @code{OMP_CLAUSE_NOWAIT}, @code{OMP_CLAUSE_ORDERED},
-@code{OMP_CLAUSE_DEFAULT}, and @code{OMP_CLAUSE_REDUCTION}.  Each code
+@code{OMP_CLAUSE_DEFAULT}, @code{OMP_CLAUSE_REDUCTION},
+@code{OMP_CLAUSE_COLLAPSE}, @code{OMP_CLAUSE_UNTIED},
+@code{OMP_CLAUSE_FINAL}, and @code{OMP_CLAUSE_MERGEABLE}.  Each code
 represents the corresponding OpenMP clause.
 
 Clauses associated with the same directive are chained together
index d2e2044eff0a74bb4204c5d1df513f0b0d9c9e2f..123990f66b00893e6cfb13c514032b0601b6618b 100644 (file)
@@ -1,3 +1,60 @@
+2011-08-02  Jakub Jelinek  <jakub@redhat.com>
+
+       PR fortran/46752
+       * cpp.c (cpp_define_builtins): Change _OPENMP to 201107.
+       * openmp.c (gfc_free_omp_clauses): Free also final_expr.
+       (OMP_CLAUSE_FINAL, OMP_CLAUSE_MERGEABLE): Define.
+       (gfc_match_omp_clauses): Handle parsing final and mergeable
+       clauses.
+       (OMP_TASK_CLAUSES): Allow final and mergeable clauses.
+       (gfc_match_omp_taskyield): New function.
+       (resolve_omp_clauses): Resolve final clause.  Allow POINTERs and
+       Cray pointers in clauses other than REDUCTION.
+       (gfc_match_omp_atomic): Match optional
+       read/write/update/capture keywords after !$omp atomic.
+       (resolve_omp_atomic): Handle all OpenMP 3.1 atomic forms.
+       * dump-parse-tree.c (show_omp_node): Handle EXEC_OMP_TASKYIELD,
+       print final and mergeable clauses.
+       (show_code_node): Handle EXEC_OMP_TASKYIELD.
+       * trans-openmp.c (gfc_trans_omp_clauses): Handle final and
+       mergeable clauses.
+       (gfc_trans_omp_taskyield): New function.
+       (gfc_trans_omp_directive): Handle EXEC_OMP_TASKYIELD.
+       (gfc_trans_omp_atomic): Handle all OpenMP 3.1 atomic forms.
+       (gfc_omp_clause_copy_ctor): Handle non-allocated allocatable.
+       (gfc_omp_predetermined_sharing): Adjust comment.
+       * gfortran.h (gfc_statement): Add ST_OMP_TASKYIELD and
+       ST_OMP_END_ATOMIC.
+       (gfc_omp_clauses): Add final_expr and mergeable fields.
+       (gfc_exec_op): Add EXEC_OMP_TASKYIELD.
+       (gfc_omp_atomic_op): New enum typedef.
+       (struct gfc_code): Add ext.omp_atomic.
+       * trans.c (trans_code): Handle EXEC_OMP_TASKYIELD.
+       * frontend-passes.c (gfc_code_walker): Also walk final_expr.
+       * resolve.c (gfc_resolve_blocks, resolve_code): Handle
+       EXEC_OMP_TASKYIELD.
+       * st.c (gfc_free_statement): Likewise.
+       * match.h (gfc_match_omp_taskyield): New prototype.
+       * parse.c (decode_omp_directive): Handle taskyield directive.
+       Handle !$omp end atomic.
+       (case_executable): Add ST_OMP_TASKYIELD case.
+       (gfc_ascii_statement): Handle ST_OMP_TASKYIELD.
+       (parse_omp_atomic): Return gfc_statement instead of void.
+       For !$omp atomic capture parse two assignments instead of
+       just one and require !$omp end atomic afterwards, for
+       other !$omp atomic forms just allow !$omp end atomic at the
+       end.
+       (parse_omp_structured_block, parse_executable): Adjust
+       parse_omp_atomic callers.
+
+2011-08-02  Tobias Burnus  <burnus@net-b.de>
+
+       * intrinsic.c (OMP_LIB): Updated openmp_version's
+       value to 201107.
+       * gfortran.texi (OpenMP): Update ref to OpenMP 3.1.
+       * intrinsic.texi (OpenMP Modules): Update ref to OpenMP 3.1;
+       remove deleted omp_integer_kind and omp_logical_kind constants.
+
 2011-07-31  Janus Weil  <janus@gcc.gnu.org>
 
        PR fortran/49112
index 0dece6cd536fb7b7e45b3a6bc0518bfbd5342eae..a40442ee4d7be92df536b24902f7e0b2d00046ee 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+/* Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -166,7 +166,7 @@ cpp_define_builtins (cpp_reader *pfile)
   cpp_define (pfile, "_LANGUAGE_FORTRAN=1");
 
   if (gfc_option.gfc_flag_openmp)
-    cpp_define (pfile, "_OPENMP=200805");
+    cpp_define (pfile, "_OPENMP=201107");
 
   /* The defines below are necessary for the TARGET_* macros.
 
index 87b8b68408f317fa8bd5aec965566a9aff20a1a4..ad8b5548071ce1b7041d866113b51c6a9fb471de 100644 (file)
@@ -1039,6 +1039,7 @@ show_omp_node (int level, gfc_code *c)
     case EXEC_OMP_SINGLE: name = "SINGLE"; break;
     case EXEC_OMP_TASK: name = "TASK"; break;
     case EXEC_OMP_TASKWAIT: name = "TASKWAIT"; break;
+    case EXEC_OMP_TASKYIELD: name = "TASKYIELD"; break;
     case EXEC_OMP_WORKSHARE: name = "WORKSHARE"; break;
     default:
       gcc_unreachable ();
@@ -1071,6 +1072,7 @@ show_omp_node (int level, gfc_code *c)
       return;
     case EXEC_OMP_BARRIER:
     case EXEC_OMP_TASKWAIT:
+    case EXEC_OMP_TASKYIELD:
       return;
     default:
       break;
@@ -1085,6 +1087,12 @@ show_omp_node (int level, gfc_code *c)
          show_expr (omp_clauses->if_expr);
          fputc (')', dumpfile);
        }
+      if (omp_clauses->final_expr)
+       {
+         fputs (" FINAL(", dumpfile);
+         show_expr (omp_clauses->final_expr);
+         fputc (')', dumpfile);
+       }
       if (omp_clauses->num_threads)
        {
          fputs (" NUM_THREADS(", dumpfile);
@@ -1130,6 +1138,8 @@ show_omp_node (int level, gfc_code *c)
        fputs (" ORDERED", dumpfile);
       if (omp_clauses->untied)
        fputs (" UNTIED", dumpfile);
+      if (omp_clauses->mergeable)
+       fputs (" MERGEABLE", dumpfile);
       if (omp_clauses->collapse)
        fprintf (dumpfile, " COLLAPSE(%d)", omp_clauses->collapse);
       for (list_type = 0; list_type < OMP_LIST_NUM; list_type++)
@@ -2167,6 +2177,7 @@ show_code_node (int level, gfc_code *c)
     case EXEC_OMP_SINGLE:
     case EXEC_OMP_TASK:
     case EXEC_OMP_TASKWAIT:
+    case EXEC_OMP_TASKYIELD:
     case EXEC_OMP_WORKSHARE:
       show_omp_node (level, c);
       break;
index 5c3e280df1c0a75e5cca06cd6a8b33df697f51ab..8ab46f6e457bc104c0b554b8b386cdbd8f1d99d0 100644 (file)
@@ -1235,6 +1235,7 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
              if (co->ext.omp_clauses)
                {
                  WALK_SUBEXPR (co->ext.omp_clauses->if_expr);
+                 WALK_SUBEXPR (co->ext.omp_clauses->final_expr);
                  WALK_SUBEXPR (co->ext.omp_clauses->num_threads);
                  WALK_SUBEXPR (co->ext.omp_clauses->chunk_size);
                }
index acb54004e9d8159992d360839fd6b98e7ff6fadd..acfa9d4c555b683842c10c299f16aafd3d27c9dd 100644 (file)
@@ -199,16 +199,16 @@ typedef enum
   ST_WRITE, ST_ASSIGNMENT, ST_POINTER_ASSIGNMENT, ST_SELECT_CASE, ST_SEQUENCE,
   ST_SIMPLE_IF, ST_STATEMENT_FUNCTION, ST_DERIVED_DECL, ST_LABEL_ASSIGNMENT,
   ST_ENUM, ST_ENUMERATOR, ST_END_ENUM, ST_SELECT_TYPE, ST_TYPE_IS, ST_CLASS_IS,
-  ST_OMP_ATOMIC, ST_OMP_BARRIER, ST_OMP_CRITICAL, ST_OMP_END_CRITICAL,
-  ST_OMP_END_DO, ST_OMP_END_MASTER, ST_OMP_END_ORDERED, ST_OMP_END_PARALLEL,
-  ST_OMP_END_PARALLEL_DO, ST_OMP_END_PARALLEL_SECTIONS,
+  ST_OMP_ATOMIC, ST_OMP_BARRIER, ST_OMP_CRITICAL, ST_OMP_END_ATOMIC,
+  ST_OMP_END_CRITICAL, ST_OMP_END_DO, ST_OMP_END_MASTER, ST_OMP_END_ORDERED,
+  ST_OMP_END_PARALLEL, ST_OMP_END_PARALLEL_DO, ST_OMP_END_PARALLEL_SECTIONS,
   ST_OMP_END_PARALLEL_WORKSHARE, ST_OMP_END_SECTIONS, ST_OMP_END_SINGLE,
   ST_OMP_END_WORKSHARE, ST_OMP_DO, ST_OMP_FLUSH, ST_OMP_MASTER, ST_OMP_ORDERED,
   ST_OMP_PARALLEL, ST_OMP_PARALLEL_DO, ST_OMP_PARALLEL_SECTIONS,
   ST_OMP_PARALLEL_WORKSHARE, ST_OMP_SECTIONS, ST_OMP_SECTION, ST_OMP_SINGLE,
   ST_OMP_THREADPRIVATE, ST_OMP_WORKSHARE, ST_OMP_TASK, ST_OMP_END_TASK,
-  ST_OMP_TASKWAIT, ST_PROCEDURE, ST_GENERIC, ST_CRITICAL, ST_END_CRITICAL,
-  ST_GET_FCN_CHARACTERISTICS, ST_LOCK, ST_UNLOCK, ST_NONE
+  ST_OMP_TASKWAIT, ST_OMP_TASKYIELD, ST_PROCEDURE, ST_GENERIC, ST_CRITICAL,
+  ST_END_CRITICAL, ST_GET_FCN_CHARACTERISTICS, ST_LOCK, ST_UNLOCK, ST_NONE
 }
 gfc_statement;
 
@@ -1050,13 +1050,14 @@ enum gfc_omp_default_sharing
 typedef struct gfc_omp_clauses
 {
   struct gfc_expr *if_expr;
+  struct gfc_expr *final_expr;
   struct gfc_expr *num_threads;
   gfc_namelist *lists[OMP_LIST_NUM];
   enum gfc_omp_sched_kind sched_kind;
   struct gfc_expr *chunk_size;
   enum gfc_omp_default_sharing default_sharing;
   int collapse;
-  bool nowait, ordered, untied;
+  bool nowait, ordered, untied, mergeable;
 }
 gfc_omp_clauses;
 
@@ -2064,10 +2065,20 @@ typedef enum
   EXEC_OMP_PARALLEL_SECTIONS, EXEC_OMP_PARALLEL_WORKSHARE,
   EXEC_OMP_SECTIONS, EXEC_OMP_SINGLE, EXEC_OMP_WORKSHARE,
   EXEC_OMP_ATOMIC, EXEC_OMP_BARRIER, EXEC_OMP_END_NOWAIT,
-  EXEC_OMP_END_SINGLE, EXEC_OMP_TASK, EXEC_OMP_TASKWAIT
+  EXEC_OMP_END_SINGLE, EXEC_OMP_TASK, EXEC_OMP_TASKWAIT,
+  EXEC_OMP_TASKYIELD
 }
 gfc_exec_op;
 
+typedef enum
+{
+  GFC_OMP_ATOMIC_UPDATE,
+  GFC_OMP_ATOMIC_READ,
+  GFC_OMP_ATOMIC_WRITE,
+  GFC_OMP_ATOMIC_CAPTURE
+}
+gfc_omp_atomic_op;
+
 typedef struct gfc_code
 {
   gfc_exec_op op;
@@ -2118,6 +2129,7 @@ typedef struct gfc_code
     const char *omp_name;
     gfc_namelist *omp_namelist;
     bool omp_bool;
+    gfc_omp_atomic_op omp_atomic;
   }
   ext;         /* Points to additional structures required by statement */
 
index 4858b2e39e9cde33e02b5e7edcd8d577a88720cc..389c05bfaab10ba0255aadfbba902e71f646052a 100644 (file)
@@ -530,7 +530,7 @@ support is reported in the @ref{Fortran 2003 status} and
 @ref{Fortran 2008 status} sections of the documentation.
 
 Additionally, the GNU Fortran compilers supports the OpenMP specification
-(version 3.0, @url{http://openmp.org/@/wp/@/openmp-specifications/}).
+(version 3.1, @url{http://openmp.org/@/wp/@/openmp-specifications/}).
 
 @node Varying Length Character Strings
 @subsection Varying Length Character Strings
@@ -1762,8 +1762,8 @@ It consists of a set of compiler directives, library routines,
 and environment variables that influence run-time behavior.
 
 GNU Fortran strives to be compatible to the 
-@uref{http://www.openmp.org/mp-documents/spec30.pdf,
-OpenMP Application Program Interface v3.0}.
+@uref{http://www.openmp.org/mp-documents/spec31.pdf,
+OpenMP Application Program Interface v3.1}.
 
 To enable the processing of the OpenMP directive @code{!$omp} in
 free-form source code; the @code{c$omp}, @code{*$omp} and @code{!$omp}
index 57338f141007361aeec81730bf6f4b8356c6a327..9adeeabf60dcde853e14932e39fc7befb0842e3b 100644 (file)
@@ -13072,7 +13072,7 @@ Both are equivalent to the value @code{NULL} in C.
 @section OpenMP Modules @code{OMP_LIB} and @code{OMP_LIB_KINDS}
 @table @asis
 @item @emph{Standard}:
-OpenMP Application Program Interface v3.0
+OpenMP Application Program Interface v3.1
 @end table
 
 
@@ -13085,15 +13085,13 @@ the named constants defined in the modules are listed
 below.
 
 For details refer to the actual
-@uref{http://www.openmp.org/mp-documents/spec30.pdf,
-OpenMP Application Program Interface v3.0}.
+@uref{http://www.openmp.org/mp-documents/spec31.pdf,
+OpenMP Application Program Interface v3.1}.
 
 @code{OMP_LIB_KINDS} provides the following scalar default-integer
 named constants:
 
 @table @asis
-@item @code{omp_integer_kind}
-@item @code{omp_logical_kind}
 @item @code{omp_lock_kind}
 @item @code{omp_nest_lock_kind}
 @item @code{omp_sched_kind}
@@ -13102,7 +13100,7 @@ named constants:
 @code{OMP_LIB} provides the scalar default-integer
 named constant @code{openmp_version} with a value of the form
 @var{yyyymm}, where @code{yyyy} is the year and @var{mm} the month
-of the OpenMP version; for OpenMP v3.0 the value is @code{200805}.
+of the OpenMP version; for OpenMP v3.1 the value is @code{201107}.
 
 And the following scalar integer named constants of the
 kind @code{omp_sched_kind}:
index 5a40d7a173a11f03d28d069753acfcc0575c5a12..0d841044b98ed3373afbd52fa10c00789d6eaed6 100644 (file)
@@ -138,6 +138,7 @@ match gfc_match_omp_sections (void);
 match gfc_match_omp_single (void);
 match gfc_match_omp_task (void);
 match gfc_match_omp_taskwait (void);
+match gfc_match_omp_taskyield (void);
 match gfc_match_omp_threadprivate (void);
 match gfc_match_omp_workshare (void);
 match gfc_match_omp_end_nowait (void);
index 69a6bca352e6d314f33ae14b1af57c7b87ab6ad7..f5a58779c0cc463058748c1d6d43d1f5ebd49ccc 100644 (file)
@@ -1,5 +1,5 @@
 /* OpenMP directive matching and resolving.
-   Copyright (C) 2005, 2006, 2007, 2008, 2010
+   Copyright (C) 2005, 2006, 2007, 2008, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Jakub Jelinek
 
@@ -66,6 +66,7 @@ gfc_free_omp_clauses (gfc_omp_clauses *c)
     return;
 
   gfc_free_expr (c->if_expr);
+  gfc_free_expr (c->final_expr);
   gfc_free_expr (c->num_threads);
   gfc_free_expr (c->chunk_size);
   for (i = 0; i < OMP_LIST_NUM; i++)
@@ -182,6 +183,8 @@ cleanup:
 #define OMP_CLAUSE_ORDERED     (1 << 11)
 #define OMP_CLAUSE_COLLAPSE    (1 << 12)
 #define OMP_CLAUSE_UNTIED      (1 << 13)
+#define OMP_CLAUSE_FINAL       (1 << 14)
+#define OMP_CLAUSE_MERGEABLE   (1 << 15)
 
 /* Match OpenMP directive clauses. MASK is a bitmask of
    clauses that are allowed for a particular directive.  */
@@ -205,6 +208,9 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, int mask)
       if ((mask & OMP_CLAUSE_IF) && c->if_expr == NULL
          && gfc_match ("if ( %e )", &c->if_expr) == MATCH_YES)
        continue;
+      if ((mask & OMP_CLAUSE_FINAL) && c->final_expr == NULL
+         && gfc_match ("final ( %e )", &c->final_expr) == MATCH_YES)
+       continue;
       if ((mask & OMP_CLAUSE_NUM_THREADS) && c->num_threads == NULL
          && gfc_match ("num_threads ( %e )", &c->num_threads) == MATCH_YES)
        continue;
@@ -383,6 +389,12 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, int mask)
          c->untied = needs_space = true;
          continue;
        }
+      if ((mask & OMP_CLAUSE_MERGEABLE) && !c->mergeable
+         && gfc_match ("mergeable") == MATCH_YES)
+       {
+         c->mergeable = needs_space = true;
+         continue;
+       }
       if ((mask & OMP_CLAUSE_COLLAPSE) && !c->collapse)
        {
          gfc_expr *cexpr = NULL;
@@ -435,7 +447,8 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, int mask)
    | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
 #define OMP_TASK_CLAUSES \
   (OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED    \
-   | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED)
+   | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED            \
+   | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE)
 
 match
 gfc_match_omp_parallel (void)
@@ -475,6 +488,20 @@ gfc_match_omp_taskwait (void)
 }
 
 
+match
+gfc_match_omp_taskyield (void)
+{
+  if (gfc_match_omp_eos () != MATCH_YES)
+    {
+      gfc_error ("Unexpected junk after TASKYIELD clause at %C");
+      return MATCH_ERROR;
+    }
+  new_st.op = EXEC_OMP_TASKYIELD;
+  new_st.ext.omp_clauses = NULL;
+  return MATCH_YES;
+}
+
+
 match
 gfc_match_omp_critical (void)
 {
@@ -700,13 +727,22 @@ gfc_match_omp_ordered (void)
 match
 gfc_match_omp_atomic (void)
 {
+  gfc_omp_atomic_op op = GFC_OMP_ATOMIC_UPDATE;
+  if (gfc_match ("% update") == MATCH_YES)
+    op = GFC_OMP_ATOMIC_UPDATE;
+  else if (gfc_match ("% read") == MATCH_YES)
+    op = GFC_OMP_ATOMIC_READ;
+  else if (gfc_match ("% write") == MATCH_YES)
+    op = GFC_OMP_ATOMIC_WRITE;
+  else if (gfc_match ("% capture") == MATCH_YES)
+    op = GFC_OMP_ATOMIC_CAPTURE;
   if (gfc_match_omp_eos () != MATCH_YES)
     {
       gfc_error ("Unexpected junk after $OMP ATOMIC statement at %C");
       return MATCH_ERROR;
     }
   new_st.op = EXEC_OMP_ATOMIC;
-  new_st.ext.omp_clauses = NULL;
+  new_st.ext.omp_atomic = op;
   return MATCH_YES;
 }
 
@@ -783,6 +819,14 @@ resolve_omp_clauses (gfc_code *code)
        gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
                   &expr->where);
     }
+  if (omp_clauses->final_expr)
+    {
+      gfc_expr *expr = omp_clauses->final_expr;
+      if (gfc_resolve_expr (expr) == FAILURE
+         || expr->ts.type != BT_LOGICAL || expr->rank != 0)
+       gfc_error ("FINAL clause at %L requires a scalar LOGICAL expression",
+                  &expr->where);
+    }
   if (omp_clauses->num_threads)
     {
       gfc_expr *expr = omp_clauses->num_threads;
@@ -940,15 +984,20 @@ resolve_omp_clauses (gfc_code *code)
                            n->sym->name, name, &code->loc);
                if (list != OMP_LIST_PRIVATE)
                  {
-                   if (n->sym->attr.pointer)
+                   if (n->sym->attr.pointer
+                       && list >= OMP_LIST_REDUCTION_FIRST
+                       && list <= OMP_LIST_REDUCTION_LAST)
                      gfc_error ("POINTER object '%s' in %s clause at %L",
                                 n->sym->name, name, &code->loc);
                    /* Variables in REDUCTION-clauses must be of intrinsic type (flagged below).  */
-                   if ((list < OMP_LIST_REDUCTION_FIRST || list > OMP_LIST_REDUCTION_LAST) &&
-                       n->sym->ts.type == BT_DERIVED && n->sym->ts.u.derived->attr.alloc_comp)
+                   if ((list < OMP_LIST_REDUCTION_FIRST || list > OMP_LIST_REDUCTION_LAST)
+                        && n->sym->ts.type == BT_DERIVED
+                        && n->sym->ts.u.derived->attr.alloc_comp)
                      gfc_error ("%s clause object '%s' has ALLOCATABLE components at %L",
                                 name, n->sym->name, &code->loc);
-                   if (n->sym->attr.cray_pointer)
+                   if (n->sym->attr.cray_pointer
+                       && list >= OMP_LIST_REDUCTION_FIRST
+                       && list <= OMP_LIST_REDUCTION_LAST)
                      gfc_error ("Cray pointer '%s' in %s clause at %L",
                                 n->sym->name, name, &code->loc);
                  }
@@ -1095,12 +1144,18 @@ is_conversion (gfc_expr *expr, bool widening)
 static void
 resolve_omp_atomic (gfc_code *code)
 {
+  gfc_code *atomic_code = code;
   gfc_symbol *var;
-  gfc_expr *expr2;
+  gfc_expr *expr2, *expr2_tmp;
 
   code = code->block->next;
   gcc_assert (code->op == EXEC_ASSIGN);
-  gcc_assert (code->next == NULL);
+  gcc_assert ((atomic_code->ext.omp_atomic != GFC_OMP_ATOMIC_CAPTURE
+              && code->next == NULL)
+             || (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_CAPTURE
+                 && code->next != NULL
+                 && code->next->op == EXEC_ASSIGN
+                 && code->next->next == NULL));
 
   if (code->expr1->expr_type != EXPR_VARIABLE
       || code->expr1->symtree == NULL
@@ -1118,7 +1173,86 @@ resolve_omp_atomic (gfc_code *code)
   var = code->expr1->symtree->n.sym;
   expr2 = is_conversion (code->expr2, false);
   if (expr2 == NULL)
-    expr2 = code->expr2;
+    {
+      if (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_READ
+         || atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_WRITE)
+       expr2 = is_conversion (code->expr2, true);
+      if (expr2 == NULL)
+       expr2 = code->expr2;
+    }
+
+  switch (atomic_code->ext.omp_atomic)
+    {
+    case GFC_OMP_ATOMIC_READ:
+      if (expr2->expr_type != EXPR_VARIABLE
+         || expr2->symtree == NULL
+         || expr2->rank != 0
+         || (expr2->ts.type != BT_INTEGER
+             && expr2->ts.type != BT_REAL
+             && expr2->ts.type != BT_COMPLEX
+             && expr2->ts.type != BT_LOGICAL))
+       gfc_error ("!$OMP ATOMIC READ statement must read from a scalar "
+                  "variable of intrinsic type at %L", &expr2->where);
+      return;
+    case GFC_OMP_ATOMIC_WRITE:
+      if (expr2->rank != 0 || expr_references_sym (code->expr2, var, NULL))
+       gfc_error ("expr in !$OMP ATOMIC WRITE assignment var = expr "
+                  "must be scalar and cannot reference var at %L",
+                  &expr2->where);
+      return;
+    case GFC_OMP_ATOMIC_CAPTURE:
+      expr2_tmp = expr2;
+      if (expr2 == code->expr2)
+       {
+         expr2_tmp = is_conversion (code->expr2, true);
+         if (expr2_tmp == NULL)
+           expr2_tmp = expr2;
+       }
+      if (expr2_tmp->expr_type == EXPR_VARIABLE)
+       {
+         if (expr2_tmp->symtree == NULL
+             || expr2_tmp->rank != 0
+             || (expr2_tmp->ts.type != BT_INTEGER
+                 && expr2_tmp->ts.type != BT_REAL
+                 && expr2_tmp->ts.type != BT_COMPLEX
+                 && expr2_tmp->ts.type != BT_LOGICAL)
+             || expr2_tmp->symtree->n.sym == var)
+           {
+             gfc_error ("!$OMP ATOMIC CAPTURE capture statement must read from "
+                        "a scalar variable of intrinsic type at %L",
+                        &expr2_tmp->where);
+             return;
+           }
+         var = expr2_tmp->symtree->n.sym;
+         code = code->next;
+         if (code->expr1->expr_type != EXPR_VARIABLE
+             || code->expr1->symtree == NULL
+             || code->expr1->rank != 0
+             || (code->expr1->ts.type != BT_INTEGER
+                 && code->expr1->ts.type != BT_REAL
+                 && code->expr1->ts.type != BT_COMPLEX
+                 && code->expr1->ts.type != BT_LOGICAL))
+           {
+             gfc_error ("!$OMP ATOMIC CAPTURE update statement must set "
+                        "a scalar variable of intrinsic type at %L",
+                        &code->expr1->where);
+             return;
+           }
+         if (code->expr1->symtree->n.sym != var)
+           {
+             gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
+                        "different variable than update statement writes "
+                        "into at %L", &code->expr1->where);
+             return;
+           }
+         expr2 = is_conversion (code->expr2, false);
+         if (expr2 == NULL)
+           expr2 = code->expr2;
+       }
+      break;
+    default:
+      break;
+    }
 
   if (expr2->expr_type == EXPR_OP)
     {
@@ -1320,6 +1454,53 @@ resolve_omp_atomic (gfc_code *code)
   else
     gfc_error ("!$OMP ATOMIC assignment must have an operator or intrinsic "
               "on right hand side at %L", &expr2->where);
+
+  if (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_CAPTURE && code->next)
+    {
+      code = code->next;
+      if (code->expr1->expr_type != EXPR_VARIABLE
+         || code->expr1->symtree == NULL
+         || code->expr1->rank != 0
+         || (code->expr1->ts.type != BT_INTEGER
+             && code->expr1->ts.type != BT_REAL
+             && code->expr1->ts.type != BT_COMPLEX
+             && code->expr1->ts.type != BT_LOGICAL))
+       {
+         gfc_error ("!$OMP ATOMIC CAPTURE capture statement must set "
+                    "a scalar variable of intrinsic type at %L",
+                    &code->expr1->where);
+         return;
+       }
+
+      expr2 = is_conversion (code->expr2, false);
+      if (expr2 == NULL)
+       {
+         expr2 = is_conversion (code->expr2, true);
+         if (expr2 == NULL)
+           expr2 = code->expr2;
+       }
+
+      if (expr2->expr_type != EXPR_VARIABLE
+         || expr2->symtree == NULL
+         || expr2->rank != 0
+         || (expr2->ts.type != BT_INTEGER
+             && expr2->ts.type != BT_REAL
+             && expr2->ts.type != BT_COMPLEX
+             && expr2->ts.type != BT_LOGICAL))
+       {
+         gfc_error ("!$OMP ATOMIC CAPTURE capture statement must read "
+                    "from a scalar variable of intrinsic type at %L",
+                    &expr2->where);
+         return;
+       }
+      if (expr2->symtree->n.sym != var)
+       {
+         gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
+                    "different variable than update statement writes "
+                    "into at %L", &expr2->where);
+         return;
+       }
+    }
 }
 
 
index ba28648ec2cdb1693fa852b2ffb6b3c40a9d641d..2910ab513188d0ceea106c8c2bc1602aedf7d40f 100644 (file)
@@ -526,6 +526,7 @@ decode_omp_directive (void)
       match ("do", gfc_match_omp_do, ST_OMP_DO);
       break;
     case 'e':
+      match ("end atomic", gfc_match_omp_eos, ST_OMP_END_ATOMIC);
       match ("end critical", gfc_match_omp_critical, ST_OMP_END_CRITICAL);
       match ("end do", gfc_match_omp_end_nowait, ST_OMP_END_DO);
       match ("end master", gfc_match_omp_eos, ST_OMP_END_MASTER);
@@ -567,6 +568,7 @@ decode_omp_directive (void)
     case 't':
       match ("task", gfc_match_omp_task, ST_OMP_TASK);
       match ("taskwait", gfc_match_omp_taskwait, ST_OMP_TASKWAIT);
+      match ("taskyield", gfc_match_omp_taskyield, ST_OMP_TASKYIELD);
       match ("threadprivate", gfc_match_omp_threadprivate,
             ST_OMP_THREADPRIVATE);
     case 'w':
@@ -957,9 +959,9 @@ next_statement (void)
   case ST_POINTER_ASSIGNMENT: case ST_EXIT: case ST_CYCLE: \
   case ST_ASSIGNMENT: case ST_ARITHMETIC_IF: case ST_WHERE: case ST_FORALL: \
   case ST_LABEL_ASSIGNMENT: case ST_FLUSH: case ST_OMP_FLUSH: \
-  case ST_OMP_BARRIER: case ST_OMP_TASKWAIT: case ST_ERROR_STOP: \
-  case ST_SYNC_ALL: case ST_SYNC_IMAGES: case ST_SYNC_MEMORY: \
-  case ST_LOCK: case ST_UNLOCK
+  case ST_OMP_BARRIER: case ST_OMP_TASKWAIT: case ST_OMP_TASKYIELD: \
+  case ST_ERROR_STOP: case ST_SYNC_ALL: case ST_SYNC_IMAGES: \
+  case ST_SYNC_MEMORY: case ST_LOCK: case ST_UNLOCK
 
 /* Statements that mark other executable statements.  */
 
@@ -1470,6 +1472,9 @@ gfc_ascii_statement (gfc_statement st)
     case ST_OMP_DO:
       p = "!$OMP DO";
       break;
+    case ST_OMP_END_ATOMIC:
+      p = "!$OMP END ATOMIC";
+      break;
     case ST_OMP_END_CRITICAL:
       p = "!$OMP END CRITICAL";
       break;
@@ -1542,6 +1547,9 @@ gfc_ascii_statement (gfc_statement st)
     case ST_OMP_TASKWAIT:
       p = "!$OMP TASKWAIT";
       break;
+    case ST_OMP_TASKYIELD:
+      p = "!$OMP TASKYIELD";
+      break;
     case ST_OMP_THREADPRIVATE:
       p = "!$OMP THREADPRIVATE";
       break;
@@ -3420,12 +3428,13 @@ parse_omp_do (gfc_statement omp_st)
 
 /* Parse the statements of OpenMP atomic directive.  */
 
-static void
+static gfc_statement
 parse_omp_atomic (void)
 {
   gfc_statement st;
   gfc_code *cp, *np;
   gfc_state_data s;
+  int count;
 
   accept_statement (ST_OMP_ATOMIC);
 
@@ -3434,21 +3443,35 @@ parse_omp_atomic (void)
   np = new_level (cp);
   np->op = cp->op;
   np->block = NULL;
+  count = 1 + (cp->ext.omp_atomic == GFC_OMP_ATOMIC_CAPTURE);
 
-  for (;;)
+  while (count)
     {
       st = next_statement ();
       if (st == ST_NONE)
        unexpected_eof ();
       else if (st == ST_ASSIGNMENT)
-       break;
+       {
+         accept_statement (st);
+         count--;
+       }
       else
        unexpected_statement (st);
     }
 
-  accept_statement (st);
-
   pop_state ();
+
+  st = next_statement ();
+  if (st == ST_OMP_END_ATOMIC)
+    {
+      gfc_clear_new_st ();
+      gfc_commit_symbols ();
+      gfc_warning_check ();
+      st = next_statement ();
+    }
+  else if (cp->ext.omp_atomic == GFC_OMP_ATOMIC_CAPTURE)
+    gfc_error ("Missing !$OMP END ATOMIC after !$OMP ATOMIC CAPTURE at %C");
+  return st;
 }
 
 
@@ -3558,8 +3581,8 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
                  continue;
 
                case ST_OMP_ATOMIC:
-                 parse_omp_atomic ();
-                 break;
+                 st = parse_omp_atomic ();
+                 continue;
 
                default:
                  cycle = false;
@@ -3739,8 +3762,8 @@ parse_executable (gfc_statement st)
          continue;
 
        case ST_OMP_ATOMIC:
-         parse_omp_atomic ();
-         break;
+         st = parse_omp_atomic ();
+         continue;
 
        default:
          return st;
index b4d66cc968b24fde342100fe413a62f69935a3fb..b8a8ebb8a34391f4aaad3286e5da4239af60e92a 100644 (file)
@@ -8824,6 +8824,7 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns)
        case EXEC_OMP_SINGLE:
        case EXEC_OMP_TASK:
        case EXEC_OMP_TASKWAIT:
+       case EXEC_OMP_TASKYIELD:
        case EXEC_OMP_WORKSHARE:
          break;
 
@@ -9390,6 +9391,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
        case EXEC_OMP_SECTIONS:
        case EXEC_OMP_SINGLE:
        case EXEC_OMP_TASKWAIT:
+       case EXEC_OMP_TASKYIELD:
        case EXEC_OMP_WORKSHARE:
          gfc_resolve_omp_directive (code, ns);
          break;
index cedb97c7d553b4aeb4716b620f1037b6503de1d5..c051d6a0c97a3afe47350523d345f1abe67d4462 100644 (file)
@@ -208,6 +208,7 @@ gfc_free_statement (gfc_code *p)
     case EXEC_OMP_ORDERED:
     case EXEC_OMP_END_NOWAIT:
     case EXEC_OMP_TASKWAIT:
+    case EXEC_OMP_TASKYIELD:
       break;
 
     default:
index 29e342f13fbf0c0d877bd74ff941dafabe4884e9..b1f8e09a1b96a71d93abb70da1c2f566247736af 100644 (file)
@@ -88,9 +88,7 @@ gfc_omp_predetermined_sharing (tree decl)
   if (GFC_DECL_CRAY_POINTEE (decl))
     return OMP_CLAUSE_DEFAULT_PRIVATE;
 
-  /* Assumed-size arrays are predetermined to inherit sharing
-     attributes of the associated actual argument, which is shared
-     for all we care.  */
+  /* Assumed-size arrays are predetermined shared.  */
   if (TREE_CODE (decl) == PARM_DECL
       && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
       && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
@@ -215,7 +213,8 @@ tree
 gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
 {
   tree type = TREE_TYPE (dest), ptr, size, esize, rank, call;
-  stmtblock_t block;
+  tree cond, then_b, else_b;
+  stmtblock_t block, cond_block;
 
   if (! GFC_DESCRIPTOR_TYPE_P (type)
       || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
@@ -227,7 +226,9 @@ gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
      and copied from SRC.  */
   gfc_start_block (&block);
 
-  gfc_add_modify (&block, dest, src);
+  gfc_init_block (&cond_block);
+
+  gfc_add_modify (&cond_block, dest, src);
   rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
   size = gfc_conv_descriptor_ubound_get (dest, rank);
   size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
@@ -241,18 +242,30 @@ gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
                        TYPE_SIZE_UNIT (gfc_get_element_type (type)));
   size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
                          size, esize);
-  size = gfc_evaluate_now (fold_convert (size_type_node, size), &block);
+  size = gfc_evaluate_now (fold_convert (size_type_node, size), &cond_block);
 
   ptr = gfc_create_var (pvoid_type_node, NULL);
-  gfc_allocate_using_malloc (&block, ptr, size, NULL_TREE);
-  gfc_conv_descriptor_data_set (&block, dest, ptr);
+  gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
+  gfc_conv_descriptor_data_set (&cond_block, dest, ptr);
 
   call = build_call_expr_loc (input_location,
                          built_in_decls[BUILT_IN_MEMCPY], 3, ptr,
                          fold_convert (pvoid_type_node,
                                        gfc_conv_descriptor_data_get (src)),
                          size);
-  gfc_add_expr_to_block (&block, fold_convert (void_type_node, call));
+  gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
+  then_b = gfc_finish_block (&cond_block);
+
+  gfc_init_block (&cond_block);
+  gfc_conv_descriptor_data_set (&cond_block, dest, null_pointer_node);
+  else_b = gfc_finish_block (&cond_block);
+
+  cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+                         fold_convert (pvoid_type_node,
+                                       gfc_conv_descriptor_data_get (src)),
+                         null_pointer_node);
+  gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
+                        void_type_node, cond, then_b, else_b));
 
   return gfc_finish_block (&block);
 }
@@ -855,6 +868,21 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
     }
 
+  if (clauses->final_expr)
+    {
+      tree final_var;
+
+      gfc_init_se (&se, NULL);
+      gfc_conv_expr (&se, clauses->final_expr);
+      gfc_add_block_to_block (block, &se.pre);
+      final_var = gfc_evaluate_now (se.expr, block);
+      gfc_add_block_to_block (block, &se.post);
+
+      c = build_omp_clause (where.lb->location, OMP_CLAUSE_FINAL);
+      OMP_CLAUSE_FINAL_EXPR (c) = final_var;
+      omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+    }
+
   if (clauses->num_threads)
     {
       tree num_threads;
@@ -948,6 +976,12 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
     }
 
+  if (clauses->mergeable)
+    {
+      c = build_omp_clause (where.lb->location, OMP_CLAUSE_MERGEABLE);
+      omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+    }
+
   if (clauses->collapse)
     {
       c = build_omp_clause (where.lb->location, OMP_CLAUSE_COLLAPSE);
@@ -990,35 +1024,85 @@ static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
 static tree
 gfc_trans_omp_atomic (gfc_code *code)
 {
+  gfc_code *atomic_code = code;
   gfc_se lse;
   gfc_se rse;
+  gfc_se vse;
   gfc_expr *expr2, *e;
   gfc_symbol *var;
   stmtblock_t block;
   tree lhsaddr, type, rhs, x;
   enum tree_code op = ERROR_MARK;
+  enum tree_code aop = OMP_ATOMIC;
   bool var_on_left = false;
 
   code = code->block->next;
   gcc_assert (code->op == EXEC_ASSIGN);
-  gcc_assert (code->next == NULL);
   var = code->expr1->symtree->n.sym;
 
   gfc_init_se (&lse, NULL);
   gfc_init_se (&rse, NULL);
+  gfc_init_se (&vse, NULL);
   gfc_start_block (&block);
 
-  gfc_conv_expr (&lse, code->expr1);
-  gfc_add_block_to_block (&block, &lse.pre);
-  type = TREE_TYPE (lse.expr);
-  lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
-
   expr2 = code->expr2;
   if (expr2->expr_type == EXPR_FUNCTION
       && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
     expr2 = expr2->value.function.actual->expr;
 
-  if (expr2->expr_type == EXPR_OP)
+  switch (atomic_code->ext.omp_atomic)
+    {
+    case GFC_OMP_ATOMIC_READ:
+      gfc_conv_expr (&vse, code->expr1);
+      gfc_add_block_to_block (&block, &vse.pre);
+
+      gfc_conv_expr (&lse, expr2);
+      gfc_add_block_to_block (&block, &lse.pre);
+      type = TREE_TYPE (lse.expr);
+      lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
+
+      x = build1 (OMP_ATOMIC_READ, type, lhsaddr);
+      x = convert (TREE_TYPE (vse.expr), x);
+      gfc_add_modify (&block, vse.expr, x);
+
+      gfc_add_block_to_block (&block, &lse.pre);
+      gfc_add_block_to_block (&block, &rse.pre);
+
+      return gfc_finish_block (&block);
+    case GFC_OMP_ATOMIC_CAPTURE:
+      aop = OMP_ATOMIC_CAPTURE_NEW;
+      if (expr2->expr_type == EXPR_VARIABLE)
+       {
+         aop = OMP_ATOMIC_CAPTURE_OLD;
+         gfc_conv_expr (&vse, code->expr1);
+         gfc_add_block_to_block (&block, &vse.pre);
+
+         gfc_conv_expr (&lse, expr2);
+         gfc_add_block_to_block (&block, &lse.pre);
+         gfc_init_se (&lse, NULL);
+         code = code->next;
+         var = code->expr1->symtree->n.sym;
+         expr2 = code->expr2;
+         if (expr2->expr_type == EXPR_FUNCTION
+             && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
+           expr2 = expr2->value.function.actual->expr;
+       }
+      break;
+    default:
+      break;
+    }
+
+  gfc_conv_expr (&lse, code->expr1);
+  gfc_add_block_to_block (&block, &lse.pre);
+  type = TREE_TYPE (lse.expr);
+  lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
+
+  if (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_WRITE)
+    {
+      gfc_conv_expr (&rse, expr2);
+      gfc_add_block_to_block (&block, &rse.pre);
+    }
+  else if (expr2->expr_type == EXPR_OP)
     {
       gfc_expr *e;
       switch (expr2->value.op.op)
@@ -1134,25 +1218,55 @@ gfc_trans_omp_atomic (gfc_code *code)
 
   lhsaddr = save_expr (lhsaddr);
   rhs = gfc_evaluate_now (rse.expr, &block);
-  x = convert (TREE_TYPE (rhs), build_fold_indirect_ref_loc (input_location,
-                                                        lhsaddr));
 
-  if (var_on_left)
-    x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), x, rhs);
+  if (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_WRITE)
+    x = rhs;
   else
-    x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), rhs, x);
+    {
+      x = convert (TREE_TYPE (rhs),
+                  build_fold_indirect_ref_loc (input_location, lhsaddr));
+      if (var_on_left)
+       x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), x, rhs);
+      else
+       x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), rhs, x);
+    }
 
   if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE
       && TREE_CODE (type) != COMPLEX_TYPE)
     x = fold_build1_loc (input_location, REALPART_EXPR,
                         TREE_TYPE (TREE_TYPE (rhs)), x);
 
-  x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
-  gfc_add_expr_to_block (&block, x);
-
   gfc_add_block_to_block (&block, &lse.pre);
   gfc_add_block_to_block (&block, &rse.pre);
 
+  if (aop == OMP_ATOMIC)
+    {
+      x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
+      gfc_add_expr_to_block (&block, x);
+    }
+  else
+    {
+      if (aop == OMP_ATOMIC_CAPTURE_NEW)
+       {
+         code = code->next;
+         expr2 = code->expr2;
+         if (expr2->expr_type == EXPR_FUNCTION
+             && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
+           expr2 = expr2->value.function.actual->expr;
+
+         gcc_assert (expr2->expr_type == EXPR_VARIABLE);
+         gfc_conv_expr (&vse, code->expr1);
+         gfc_add_block_to_block (&block, &vse.pre);
+
+         gfc_init_se (&lse, NULL);
+         gfc_conv_expr (&lse, expr2);
+         gfc_add_block_to_block (&block, &lse.pre);
+       }
+      x = build2 (aop, type, lhsaddr, convert (type, x));
+      x = convert (TREE_TYPE (vse.expr), x);
+      gfc_add_modify (&block, vse.expr, x);
+    }
+
   return gfc_finish_block (&block);
 }
 
@@ -1628,6 +1742,13 @@ gfc_trans_omp_taskwait (void)
   return build_call_expr_loc (input_location, decl, 0);
 }
 
+static tree
+gfc_trans_omp_taskyield (void)
+{
+  tree decl = built_in_decls [BUILT_IN_GOMP_TASKYIELD];
+  return build_call_expr_loc (input_location, decl, 0);
+}
+
 static tree
 gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
 {
@@ -1821,6 +1942,8 @@ gfc_trans_omp_directive (gfc_code *code)
       return gfc_trans_omp_task (code);
     case EXEC_OMP_TASKWAIT:
       return gfc_trans_omp_taskwait ();
+    case EXEC_OMP_TASKYIELD:
+      return gfc_trans_omp_taskyield ();
     case EXEC_OMP_WORKSHARE:
       return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
     default:
index 2f8c7fdc440185921f2e362a4e32e21c81da4883..19f215cd54db8e9c923b84f25ad5fc25cda2e33c 100644 (file)
@@ -1410,6 +1410,7 @@ trans_code (gfc_code * code, tree cond)
        case EXEC_OMP_SINGLE:
        case EXEC_OMP_TASK:
        case EXEC_OMP_TASKWAIT:
+       case EXEC_OMP_TASKYIELD:
        case EXEC_OMP_WORKSHARE:
          res = gfc_trans_omp_directive (code);
          break;
index 184c9733ee5900798ed23d568b7ac17db3147bee..27b20482876acf9455abede717b4865cbcad3a8e 100644 (file)
@@ -114,6 +114,7 @@ enum gf_mask {
     GF_OMP_RETURN_NOWAIT       = 1 << 0,
 
     GF_OMP_SECTION_LAST                = 1 << 0,
+    GF_OMP_ATOMIC_NEED_VALUE   = 1 << 0,
     GF_PREDICT_TAKEN           = 1 << 15
 };
 
@@ -1634,6 +1635,29 @@ gimple_omp_parallel_set_combined_p (gimple g, bool combined_p)
 }
 
 
+/* Return true if OMP atomic load/store statement G has the
+   GF_OMP_ATOMIC_NEED_VALUE flag set.  */
+
+static inline bool
+gimple_omp_atomic_need_value_p (const_gimple g)
+{
+  if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
+    GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
+  return (gimple_omp_subcode (g) & GF_OMP_ATOMIC_NEED_VALUE) != 0;
+}
+
+
+/* Set the GF_OMP_ATOMIC_NEED_VALUE flag on G.  */
+
+static inline void
+gimple_omp_atomic_set_need_value (gimple g)
+{
+  if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
+    GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
+  g->gsbase.subcode |= GF_OMP_ATOMIC_NEED_VALUE;
+}
+
+
 /* Return the number of operands for statement GS.  */
 
 static inline unsigned
index af9cdd7c848fe8bfff63878e711cb2987bcd8ff7..5376ca361bfdcbfe3f855c7751cce86ee9ce50e2 100644 (file)
@@ -5932,6 +5932,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
            }
          break;
 
+       case OMP_CLAUSE_FINAL:
        case OMP_CLAUSE_IF:
          OMP_CLAUSE_OPERAND (c, 0)
            = gimple_boolify (OMP_CLAUSE_OPERAND (c, 0));
@@ -5948,6 +5949,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        case OMP_CLAUSE_DEFAULT:
@@ -6088,6 +6090,8 @@ gimplify_adjust_omp_clauses (tree *list_p)
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_FINAL:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        default:
@@ -6490,24 +6494,45 @@ static enum gimplify_status
 gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
 {
   tree addr = TREE_OPERAND (*expr_p, 0);
-  tree rhs = TREE_OPERAND (*expr_p, 1);
+  tree rhs = TREE_CODE (*expr_p) == OMP_ATOMIC_READ
+            ? NULL : TREE_OPERAND (*expr_p, 1);
   tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
   tree tmp_load;
+  gimple loadstmt, storestmt;
 
-   tmp_load = create_tmp_reg (type, NULL);
-   if (goa_stabilize_expr (&rhs, pre_p, addr, tmp_load) < 0)
-     return GS_ERROR;
+  tmp_load = create_tmp_reg (type, NULL);
+  if (rhs && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load) < 0)
+    return GS_ERROR;
+
+  if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)
+      != GS_ALL_DONE)
+    return GS_ERROR;
 
-   if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)
-       != GS_ALL_DONE)
-     return GS_ERROR;
+  loadstmt = gimple_build_omp_atomic_load (tmp_load, addr);
+  gimplify_seq_add_stmt (pre_p, loadstmt);
+  if (rhs && gimplify_expr (&rhs, pre_p, NULL, is_gimple_val, fb_rvalue)
+      != GS_ALL_DONE)
+    return GS_ERROR;
 
-   gimplify_seq_add_stmt (pre_p, gimple_build_omp_atomic_load (tmp_load, addr));
-   if (gimplify_expr (&rhs, pre_p, NULL, is_gimple_val, fb_rvalue)
-       != GS_ALL_DONE)
-     return GS_ERROR;
-   gimplify_seq_add_stmt (pre_p, gimple_build_omp_atomic_store (rhs));
-   *expr_p = NULL;
+  if (TREE_CODE (*expr_p) == OMP_ATOMIC_READ)
+    rhs = tmp_load;
+  storestmt = gimple_build_omp_atomic_store (rhs);
+  gimplify_seq_add_stmt (pre_p, storestmt);
+  switch (TREE_CODE (*expr_p))
+    {
+    case OMP_ATOMIC_READ:
+    case OMP_ATOMIC_CAPTURE_OLD:
+      *expr_p = tmp_load;
+      gimple_omp_atomic_set_need_value (loadstmt);
+      break;
+    case OMP_ATOMIC_CAPTURE_NEW:
+      *expr_p = rhs;
+      gimple_omp_atomic_set_need_value (storestmt);
+      break;
+    default:
+      *expr_p = NULL;
+      break;
+    }
 
    return GS_ALL_DONE;
 }
@@ -7230,6 +7255,9 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          }
 
        case OMP_ATOMIC:
+       case OMP_ATOMIC_READ:
+       case OMP_ATOMIC_CAPTURE_OLD:
+       case OMP_ATOMIC_CAPTURE_NEW:
          ret = gimplify_omp_atomic (expr_p, pre_p);
          break;
 
index 125b76c44530408948b11f52645f44b3014faab2..a56fa61d929b72112fb6cf62dac033711858fd67 100644 (file)
@@ -37,6 +37,8 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_BARRIER, "GOMP_barrier",
                  BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
 DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKWAIT, "GOMP_taskwait",
                  BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKYIELD, "GOMP_taskyield",
+                 BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
 DEF_GOMP_BUILTIN (BUILT_IN_GOMP_CRITICAL_START, "GOMP_critical_start",
                  BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
 DEF_GOMP_BUILTIN (BUILT_IN_GOMP_CRITICAL_END, "GOMP_critical_end",
index 0376d927f02060cd01fe2926006c905dc78a67ed..fbbef9c785cc7551b4e37f8e8db873d8a5e38931 100644 (file)
@@ -1443,6 +1443,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
          ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
          break;
 
+       case OMP_CLAUSE_FINAL:
        case OMP_CLAUSE_IF:
        case OMP_CLAUSE_NUM_THREADS:
        case OMP_CLAUSE_SCHEDULE:
@@ -1454,6 +1455,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_COLLAPSE:
        case OMP_CLAUSE_UNTIED:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        default:
@@ -1504,6 +1506,8 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_COLLAPSE:
        case OMP_CLAUSE_UNTIED:
+       case OMP_CLAUSE_FINAL:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        default:
@@ -3081,7 +3085,7 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
 static void
 expand_task_call (basic_block bb, gimple entry_stmt)
 {
-  tree t, t1, t2, t3, flags, cond, c, clauses;
+  tree t, t1, t2, t3, flags, cond, c, c2, clauses;
   gimple_stmt_iterator gsi;
   location_t loc = gimple_location (entry_stmt);
 
@@ -3094,7 +3098,19 @@ expand_task_call (basic_block bb, gimple entry_stmt)
     cond = boolean_true_node;
 
   c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
-  flags = build_int_cst (unsigned_type_node, (c ? 1 : 0));
+  c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
+  flags = build_int_cst (unsigned_type_node,
+                        (c ? 1 : 0) + (c2 ? 4 : 0));
+
+  c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
+  if (c)
+    {
+      c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
+      c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
+                          build_int_cst (unsigned_type_node, 2),
+                          build_int_cst (unsigned_type_node, 0));
+      flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
+    }
 
   gsi = gsi_last_bb (bb);
   t = gimple_omp_task_data_arg (entry_stmt);
@@ -4944,6 +4960,31 @@ expand_omp_synch (struct omp_region *region)
     }
 }
 
+/* A subroutine of expand_omp_atomic.  Attempt to implement the atomic
+   operation as a normal volatile load.  */
+
+static bool
+expand_omp_atomic_load (basic_block load_bb, tree addr, tree loaded_val)
+{
+  /* FIXME */
+  (void) load_bb;
+  (void) addr;
+  (void) loaded_val;
+  return false;
+}
+
+/* A subroutine of expand_omp_atomic.  Attempt to implement the atomic
+   operation as a normal volatile store.  */
+
+static bool
+expand_omp_atomic_store (basic_block load_bb, tree addr)
+{
+  /* FIXME */
+  (void) load_bb;
+  (void) addr;
+  return false;
+}
+
 /* A subroutine of expand_omp_atomic.  Attempt to implement the atomic
    operation as a __sync_fetch_and_op builtin.  INDEX is log2 of the
    size of the data type, and thus usable to find the index of the builtin
@@ -4954,14 +4995,15 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
                            tree addr, tree loaded_val,
                            tree stored_val, int index)
 {
-  enum built_in_function base;
+  enum built_in_function oldbase, newbase;
   tree decl, itype, call;
-  direct_optab optab;
-  tree rhs;
+  direct_optab optab, oldoptab, newoptab;
+  tree lhs, rhs;
   basic_block store_bb = single_succ (load_bb);
   gimple_stmt_iterator gsi;
   gimple stmt;
   location_t loc;
+  bool need_old, need_new;
 
   /* We expect to find the following sequences:
 
@@ -4985,6 +5027,9 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
   gsi_next (&gsi);
   if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
     return false;
+  need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
+  need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
+  gcc_checking_assert (!need_old || !need_new);
 
   if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
     return false;
@@ -4994,24 +5039,39 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
     {
     case PLUS_EXPR:
     case POINTER_PLUS_EXPR:
-      base = BUILT_IN_SYNC_FETCH_AND_ADD_N;
+      oldbase = BUILT_IN_SYNC_FETCH_AND_ADD_N;
+      newbase = BUILT_IN_SYNC_ADD_AND_FETCH_N;
       optab = sync_add_optab;
+      oldoptab = sync_old_add_optab;
+      newoptab = sync_new_add_optab;
       break;
     case MINUS_EXPR:
-      base = BUILT_IN_SYNC_FETCH_AND_SUB_N;
+      oldbase = BUILT_IN_SYNC_FETCH_AND_SUB_N;
+      newbase = BUILT_IN_SYNC_SUB_AND_FETCH_N;
       optab = sync_add_optab;
+      oldoptab = sync_old_add_optab;
+      newoptab = sync_new_add_optab;
       break;
     case BIT_AND_EXPR:
-      base = BUILT_IN_SYNC_FETCH_AND_AND_N;
+      oldbase = BUILT_IN_SYNC_FETCH_AND_AND_N;
+      newbase = BUILT_IN_SYNC_AND_AND_FETCH_N;
       optab = sync_and_optab;
+      oldoptab = sync_old_and_optab;
+      newoptab = sync_new_and_optab;
       break;
     case BIT_IOR_EXPR:
-      base = BUILT_IN_SYNC_FETCH_AND_OR_N;
+      oldbase = BUILT_IN_SYNC_FETCH_AND_OR_N;
+      newbase = BUILT_IN_SYNC_OR_AND_FETCH_N;
       optab = sync_ior_optab;
+      oldoptab = sync_old_ior_optab;
+      newoptab = sync_new_ior_optab;
       break;
     case BIT_XOR_EXPR:
-      base = BUILT_IN_SYNC_FETCH_AND_XOR_N;
+      oldbase = BUILT_IN_SYNC_FETCH_AND_XOR_N;
+      newbase = BUILT_IN_SYNC_XOR_AND_FETCH_N;
       optab = sync_xor_optab;
+      oldoptab = sync_old_xor_optab;
+      newoptab = sync_new_xor_optab;
       break;
     default:
       return false;
@@ -5025,20 +5085,49 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
   else
     return false;
 
-  decl = built_in_decls[base + index + 1];
+  decl = built_in_decls[(need_new ? newbase : oldbase) + index + 1];
   if (decl == NULL_TREE)
     return false;
   itype = TREE_TYPE (TREE_TYPE (decl));
 
-  if (direct_optab_handler (optab, TYPE_MODE (itype)) == CODE_FOR_nothing)
+  if (need_new)
+    {
+      /* expand_sync_fetch_operation can always compensate when interested
+        in the new value.  */
+      if (direct_optab_handler (newoptab, TYPE_MODE (itype))
+         == CODE_FOR_nothing
+         && direct_optab_handler (oldoptab, TYPE_MODE (itype))
+            == CODE_FOR_nothing)
+       return false;
+    }
+  else if (need_old)
+    {
+      /* When interested in the old value, expand_sync_fetch_operation
+        can compensate only if the operation is reversible.  AND and OR
+        are not reversible.  */
+      if (direct_optab_handler (oldoptab, TYPE_MODE (itype))
+         == CODE_FOR_nothing
+         && (oldbase == BUILT_IN_SYNC_FETCH_AND_AND_N
+             || oldbase == BUILT_IN_SYNC_FETCH_AND_OR_N
+             || direct_optab_handler (newoptab, TYPE_MODE (itype))
+                == CODE_FOR_nothing))
+       return false;
+    }
+  else if (direct_optab_handler (optab, TYPE_MODE (itype)) == CODE_FOR_nothing)
     return false;
 
   gsi = gsi_last_bb (load_bb);
   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
-  call = build_call_expr_loc (loc,
-                         decl, 2, addr,
-                         fold_convert_loc (loc, itype, rhs));
-  call = fold_convert_loc (loc, void_type_node, call);
+  call = build_call_expr_loc (loc, decl, 2, addr,
+                             fold_convert_loc (loc, itype, rhs));
+  if (need_old || need_new)
+    {
+      lhs = need_old ? loaded_val : stored_val;
+      call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
+      call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
+    }
+  else
+    call = fold_convert_loc (loc, void_type_node, call);
   force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
   gsi_remove (&gsi, true);
 
@@ -5319,6 +5408,25 @@ expand_omp_atomic (struct omp_region *region)
       /* __sync builtins require strict data alignment.  */
       if (exact_log2 (align) >= index)
        {
+         /* Atomic load.  FIXME: have some target hook signalize what loads
+            are actually atomic?  */
+         if (loaded_val == stored_val
+             && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
+                 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
+             && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
+             && expand_omp_atomic_load (load_bb, addr, loaded_val))
+           return;
+
+         /* Atomic store.  FIXME: have some target hook signalize what
+            stores are actually atomic?  */
+         if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
+              || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
+             && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
+             && store_bb == single_succ (load_bb)
+             && first_stmt (store_bb) == store
+             && expand_omp_atomic_store (load_bb, addr))
+           return;
+
          /* When possible, use specialized atomic update functions.  */
          if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
              && store_bb == single_succ (load_bb))
index 5c3ea861295eb8b1413fa8cfba8b0fcb4b5c7666..fc949f94257436ed7dd831a4635eb30f321ebda6 100644 (file)
@@ -1,3 +1,16 @@
+2011-08-02  Jakub Jelinek  <jakub@redhat.com>
+
+       PR fortran/46752
+       * gcc.dg/gomp/atomic-5.c: Adjust expected diagnostics.
+       * gcc.dg/gomp/atomic-15.c: New test.
+       * g++.dg/gomp/atomic-5.C: Adjust expected diagnostics.
+       * g++.dg/gomp/atomic-15.C: New test.
+       * g++.dg/gomp/private-1.C: New test.
+       * g++.dg/gomp/sharing-2.C: New test.
+       * gfortran.dg/gomp/crayptr1.f90: Don't expect error
+       about Cray pointer in FIRSTPRIVATE/LASTPRIVATE.
+       * gfortran.dg/gomp/omp_atomic2.f90: New test.
+
 2011-08-02  Tobias Burnus  <burnus@net-b.de>
 
        * trim_optimize_5.f90: Remove spurious "use foo".
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-15.C b/gcc/testsuite/g++.dg/gomp/atomic-15.C
new file mode 100644 (file)
index 0000000..95eb8b4
--- /dev/null
@@ -0,0 +1,46 @@
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+int x = 6;
+
+int
+main ()
+{
+  int v;
+  #pragma omp atomic
+    x = x * 7 + 6;     // { dg-error "expected" }
+  #pragma omp atomic
+    x = x * 7 ^ 6;     // { dg-error "expected" }
+  #pragma omp atomic update
+    x = x - 8 + 6;     // { dg-error "expected" }
+  #pragma omp atomic
+    x = x ^ 7 | 2;     // { dg-error "expected" }
+  #pragma omp atomic
+    x = x / 7 * 2;     // { dg-error "expected" }
+  #pragma omp atomic
+    x = x / 7 / 2;     // { dg-error "expected" }
+  #pragma omp atomic capture
+    v = x = x | 6;     // { dg-error "invalid operator" }
+  #pragma omp atomic capture
+    { v = x; x = x * 7 + 6; }  // { dg-error "expected" }
+  #pragma omp atomic capture
+    { v = x; x = x * 7 ^ 6; }  // { dg-error "expected" }
+  #pragma omp atomic capture
+    { v = x; x = x - 8 + 6; }  // { dg-error "expected" }
+  #pragma omp atomic capture
+    { v = x; x = x ^ 7 | 2; }  // { dg-error "expected" }
+  #pragma omp atomic capture
+    { v = x; x = x / 7 * 2; }  // { dg-error "expected" }
+  #pragma omp atomic capture
+    { v = x; x = x / 7 / 2; }  // { dg-error "expected" }
+  #pragma omp atomic capture
+    { x = x * 7 + 6; v = x; }  // { dg-error "expected" }
+  #pragma omp atomic capture
+    { x = x * 7 ^ 6; v = x; }  // { dg-error "expected" }
+  #pragma omp atomic capture
+    { x = x - 8 + 6; v = x; }  // { dg-error "expected" }
+  #pragma omp atomic capture
+    { x = x ^ 7 | 2; v = x; }  // { dg-error "expected" }
+  (void) v;
+  return 0;
+}
index 0f750c73d742c49ff3bd3757f90d60fcb1545fd6..b277ebf3ddef6ab047418241ded987bc910a0226 100644 (file)
@@ -9,9 +9,9 @@ void f1(void)
   #pragma omp atomic
     x %= 2;            /* { dg-error "invalid operator" } */
   #pragma omp atomic
-    x = x + 1;         /* { dg-error "invalid operator" } */
+    x = x + 1;
   #pragma omp atomic
-    x = 1;             /* { dg-error "invalid operator" } */
+    x = 1;             /* { dg-error "invalid form" } */
   #pragma omp atomic
     ++y;               /* { dg-error "read-only variable" } */
   #pragma omp atomic
index 6b3d410a9334c442405287bd8889526dcd6ee69c..a048c60b8af950543b3da3b7295bb2c6601e87bc 100644 (file)
@@ -84,7 +84,7 @@ foo (int x)
     ;
 #pragma omp p private (c) // { dg-error "predetermined 'shared'" }
     ;
-#pragma omp p firstprivate (c) // { dg-error "predetermined 'shared'" }
+#pragma omp p firstprivate (c)
     ;
 #pragma omp p for lastprivate (c) // { dg-error "predetermined 'shared'" }
   for (i = 0; i < 10; i++)
diff --git a/gcc/testsuite/g++.dg/gomp/private-1.C b/gcc/testsuite/g++.dg/gomp/private-1.C
new file mode 100644 (file)
index 0000000..09f15e3
--- /dev/null
@@ -0,0 +1,33 @@
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+struct A { int i; A (); ~A (); };
+struct B { int i; };
+struct C { int i; mutable int j; C (); ~C (); };
+
+template <typename T> void bar (const T *);
+
+const A a;
+const C c;
+
+const A foo (const A d, const C e)
+{
+  const A f;
+  const B b = { 4 };
+  A g;
+  #pragma omp parallel private (a)     // { dg-error "predetermined" }
+    bar (&a);
+  #pragma omp parallel private (b)     // { dg-error "predetermined" }
+    bar (&b);
+  #pragma omp parallel private (c)
+    bar (&c);
+  #pragma omp parallel private (d)     // { dg-error "predetermined" }
+    bar (&d);
+  #pragma omp parallel private (e)
+    bar (&e);
+  #pragma omp parallel private (f)     // { dg-error "predetermined" }
+    bar (&f);
+  #pragma omp parallel private (g)
+    bar (&g);
+  return f;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/sharing-2.C b/gcc/testsuite/g++.dg/gomp/sharing-2.C
new file mode 100644 (file)
index 0000000..6145b92
--- /dev/null
@@ -0,0 +1,47 @@
+// { dg-do compile }
+
+struct T
+{
+  int i;
+  mutable int j;
+};
+struct S
+{
+  const static int d = 1;
+  const static T e;
+  void foo (int, T);
+};
+
+const int S::d;
+const T S::e = { 2, 3 };
+
+void bar (const int &);
+
+void
+S::foo (const int x, const T y)
+{
+  #pragma omp parallel firstprivate (x)
+    bar (x);
+  #pragma omp parallel firstprivate (d)
+    bar (d);
+  #pragma omp parallel firstprivate (y)
+    bar (y.i);
+  #pragma omp parallel firstprivate (e)        // { dg-error "is predetermined" }
+    bar (e.i);
+  #pragma omp parallel shared (x)      // { dg-error "is predetermined" }
+    bar (x);
+  #pragma omp parallel shared (d)      // { dg-error "is predetermined" }
+    bar (d);
+  #pragma omp parallel shared (e)      // { dg-error "is predetermined" }
+    bar (e.i);
+  #pragma omp parallel shared (y)
+    bar (y.i);
+  #pragma omp parallel private (x)     // { dg-error "is predetermined" }
+    bar (x);
+  #pragma omp parallel private (d)     // { dg-error "is predetermined" }
+    bar (d);
+  #pragma omp parallel private (y)
+    bar (y.i);
+  #pragma omp parallel private (e)     // { dg-error "is predetermined" }
+    bar (e.i);
+}
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-15.c b/gcc/testsuite/gcc.dg/gomp/atomic-15.c
new file mode 100644 (file)
index 0000000..13a9e0c
--- /dev/null
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+int x = 6;
+
+int
+main ()
+{
+  int v;
+  #pragma omp atomic
+    x = x * 7 + 6;     /* { dg-error "expected" } */
+  #pragma omp atomic
+    x = x * 7 ^ 6;     /* { dg-error "expected" } */
+  #pragma omp atomic update
+    x = x - 8 + 6;     /* { dg-error "expected" } */
+  #pragma omp atomic
+    x = x ^ 7 | 2;     /* { dg-error "expected" } */
+  #pragma omp atomic
+    x = x / 7 * 2;     /* { dg-error "expected" } */
+  #pragma omp atomic
+    x = x / 7 / 2;     /* { dg-error "expected" } */
+  #pragma omp atomic capture
+    v = x = x | 6;     /* { dg-error "invalid operator" } */
+  #pragma omp atomic capture
+    { v = x; x = x * 7 + 6; }  /* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { v = x; x = x * 7 ^ 6; }  /* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { v = x; x = x - 8 + 6; }  /* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { v = x; x = x ^ 7 | 2; }  /* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { v = x; x = x / 7 * 2; }  /* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { v = x; x = x / 7 / 2; }  /* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { x = x * 7 + 6; v = x; }  /* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { x = x * 7 ^ 6; v = x; }  /* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { x = x - 8 + 6; v = x; }  /* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { x = x ^ 7 | 2; v = x; }  /* { dg-error "expected" } */
+  (void) v;
+  return 0;
+}
index be7cbb862acfebf14ade71abed71650fe2b925b0..0ad9d3b48c26bda90231d93e6354c9e24cd20c2d 100644 (file)
@@ -11,9 +11,9 @@ void f1(void)
   #pragma omp atomic
     x %= 2;            /* { dg-error "invalid operator" } */
   #pragma omp atomic
-    x = x + 1;         /* { dg-error "invalid operator" } */
+    x = x + 1;
   #pragma omp atomic
-    x = 1;             /* { dg-error "invalid operator" } */
+    x = 1;             /* { dg-error "invalid form" } */
   #pragma omp atomic
     ++y;               /* { dg-error "read-only variable" } */
   #pragma omp atomic
index ace9738043a98016e8f6ed24653e3398f79f3ec6..ba189896c62701ff832d75a9c3576851c377be6d 100644 (file)
@@ -84,7 +84,7 @@ foo (int x)
     ;
 #pragma omp p private (c) /* { dg-error "predetermined 'shared'" } */
     ;
-#pragma omp p firstprivate (c) /* { dg-error "predetermined 'shared'" } */
+#pragma omp p firstprivate (c)
     ;
 #pragma omp p for lastprivate (c) /* { dg-error "predetermined 'shared'" } */
   for (i = 0; i < 10; i++)
index fca5606e0324ccc247df121d142a50c835394717..d246e8f04cf0bb3f0d27361f9e47423b2e15e06b 100644 (file)
 !$omp end parallel
 
   ip3 = loc (i)
-!$omp parallel firstprivate (ip3) ! { dg-error "Cray pointer 'ip3' in FIRSTPRIVATE clause" }
+!$omp parallel firstprivate (ip3)
 !$omp end parallel
 
-!$omp parallel do lastprivate (ip4) ! { dg-error "Cray pointer 'ip4' in LASTPRIVATE clause" }
+!$omp parallel do lastprivate (ip4)
   do i = 1, 10
     if (i .eq. 10) ip4 = loc (i)
   end do
diff --git a/gcc/testsuite/gfortran.dg/gomp/omp_atomic2.f90 b/gcc/testsuite/gfortran.dg/gomp/omp_atomic2.f90
new file mode 100644 (file)
index 0000000..7dcfe41
--- /dev/null
@@ -0,0 +1,54 @@
+  real :: r1, r2
+  complex :: c1, c2
+  integer :: i1, i2
+!$omp atomic write
+  c1 = 0
+!$omp atomic write
+  r2 = 0
+!$omp atomic write
+  i2 = 0
+!$omp atomic read
+  r1 = c1
+!$omp atomic read
+  c2 = r2
+!$omp atomic read
+  i1 = r2
+!$omp atomic read
+  c2 = i2
+!$omp atomic write
+  c1 = r1
+!$omp atomic write
+  r2 = c2
+!$omp atomic write
+  r2 = i1
+!$omp atomic write
+  i2 = c2
+!$omp end atomic
+!$omp atomic write
+  c1 = 1 + 2 + r1
+!$omp atomic write
+  r2 = c2 + 2 + 3
+!$omp atomic write
+  r2 = 3 + 4 + i1
+!$omp atomic write
+  i2 = c2 + 4 + 5
+!$omp atomic
+  c1 = c1 * 2.
+!$omp atomic update
+  r2 = r2 / 4
+!$omp end atomic
+!$omp atomic update
+  i2 = i2 + 8
+!$omp atomic capture
+  c1 = c1 * 2.
+  r1 = c1
+!$omp end atomic
+!$omp atomic capture
+  c2 = r2
+  r2 = r2 / 4
+!$omp end atomic
+!$omp atomic capture
+  i2 = i2 + 8
+  c2 = i2
+!$omp end atomic
+end
index 1b26eca5a2a2cfb08978c4ec5859031489ebafd1..ef51ff48882e89f9109feba259bdef1271ddbd4d 100644 (file)
@@ -1097,6 +1097,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
          if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL)
            break;
          /* FALLTHRU */
+       case OMP_CLAUSE_FINAL:
        case OMP_CLAUSE_IF:
        case OMP_CLAUSE_NUM_THREADS:
          wi->val_only = true;
@@ -1111,6 +1112,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_COPYIN:
        case OMP_CLAUSE_COLLAPSE:
        case OMP_CLAUSE_UNTIED:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        default:
@@ -1594,6 +1596,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
          if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL)
            break;
          /* FALLTHRU */
+       case OMP_CLAUSE_FINAL:
        case OMP_CLAUSE_IF:
        case OMP_CLAUSE_NUM_THREADS:
          wi->val_only = true;
@@ -1608,6 +1611,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_COPYIN:
        case OMP_CLAUSE_COLLAPSE:
        case OMP_CLAUSE_UNTIED:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        default:
index 2a938b72a09c4d638ea766d9dee806e445923576..e24c7866208ff0831d2751946319bca0990eac93 100644 (file)
@@ -421,6 +421,17 @@ dump_omp_clause (pretty_printer *buffer, tree clause, int spc, int flags)
       pp_character (buffer, ')');
       break;
 
+    case OMP_CLAUSE_FINAL:
+      pp_string (buffer, "final(");
+      dump_generic_node (buffer, OMP_CLAUSE_FINAL_EXPR (clause),
+         spc, flags, false);
+      pp_character (buffer, ')');
+      break;
+
+    case OMP_CLAUSE_MERGEABLE:
+      pp_string (buffer, "mergeable");
+      break;
+
     default:
       /* Should never happen.  */
       dump_generic_node (buffer, clause, spc, flags, false);
@@ -2208,6 +2219,24 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
       dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
       break;
 
+    case OMP_ATOMIC_READ:
+      pp_string (buffer, "#pragma omp atomic read");
+      newline_and_indent (buffer, spc + 2);
+      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+      pp_space (buffer);
+      break;
+
+    case OMP_ATOMIC_CAPTURE_OLD:
+    case OMP_ATOMIC_CAPTURE_NEW:
+      pp_string (buffer, "#pragma omp atomic capture");
+      newline_and_indent (buffer, spc + 2);
+      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+      pp_space (buffer);
+      pp_character (buffer, '=');
+      pp_space (buffer);
+      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
+      break;
+
     case OMP_SINGLE:
       pp_string (buffer, "#pragma omp single");
       dump_omp_clauses (buffer, OMP_SINGLE_CLAUSES (node), spc, flags);
index c474b7344eaf3af44d4c0ca766d0c0fd7fac5be6..d20751a9c7b055eeb8f4901aad729954cf3e956b 100644 (file)
@@ -247,7 +247,9 @@ unsigned const char omp_clause_num_ops[] =
   0, /* OMP_CLAUSE_ORDERED  */
   0, /* OMP_CLAUSE_DEFAULT  */
   3, /* OMP_CLAUSE_COLLAPSE  */
-  0  /* OMP_CLAUSE_UNTIED   */
+  0, /* OMP_CLAUSE_UNTIED   */
+  1, /* OMP_CLAUSE_FINAL  */
+  0  /* OMP_CLAUSE_MERGEABLE  */
 };
 
 const char * const omp_clause_code_name[] =
@@ -267,7 +269,9 @@ const char * const omp_clause_code_name[] =
   "ordered",
   "default",
   "collapse",
-  "untied"
+  "untied",
+  "final",
+  "mergeable"
 };
 
 
@@ -10546,6 +10550,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
        case OMP_CLAUSE_FIRSTPRIVATE:
        case OMP_CLAUSE_COPYIN:
        case OMP_CLAUSE_COPYPRIVATE:
+       case OMP_CLAUSE_FINAL:
        case OMP_CLAUSE_IF:
        case OMP_CLAUSE_NUM_THREADS:
        case OMP_CLAUSE_SCHEDULE:
@@ -10556,6 +10561,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_UNTIED:
+       case OMP_CLAUSE_MERGEABLE:
          WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
 
        case OMP_CLAUSE_LASTPRIVATE:
index 9c6606d0c9cdc23e3442cdafbeb1ef52b1ca6b51..d4b3cb98d6e3279083dd0a54b84c6b1c5e5ea160 100644 (file)
@@ -1040,6 +1040,22 @@ DEFTREECODE (OMP_CRITICAL, "omp_critical", tcc_statement, 2)
        build_fold_indirect_ref of the address.  */
 DEFTREECODE (OMP_ATOMIC, "omp_atomic", tcc_statement, 2)
 
+/* OpenMP - #pragma omp atomic read
+   Operand 0: The address at which the atomic operation is to be performed.
+       This address should be stabilized with save_expr.  */
+DEFTREECODE (OMP_ATOMIC_READ, "omp_atomic_read", tcc_statement, 1)
+
+/* OpenMP - #pragma omp atomic capture
+   Operand 0: The address at which the atomic operation is to be performed.
+       This address should be stabilized with save_expr.
+   Operand 1: The expression to evaluate.  When the old value of the object
+       at the address is used in the expression, it should appear as if
+       build_fold_indirect_ref of the address.
+   OMP_ATOMIC_CAPTURE_OLD returns the old memory content,
+   OMP_ATOMIC_CAPTURE_NEW the new value.  */
+DEFTREECODE (OMP_ATOMIC_CAPTURE_OLD, "omp_atomic_capture_old", tcc_statement, 2)
+DEFTREECODE (OMP_ATOMIC_CAPTURE_NEW, "omp_atomic_capture_new", tcc_statement, 2)
+
 /* OpenMP clauses.  */
 DEFTREECODE (OMP_CLAUSE, "omp_clause", tcc_exceptional, 0)
 
index 5fd62c7e8cb347e6b0c02b9a6d798926d597eece..6b13a2a5c51e05628690b87168f453cf6f368d2a 100644 (file)
@@ -403,7 +403,13 @@ enum omp_clause_code
   OMP_CLAUSE_COLLAPSE,
 
   /* OpenMP clause: untied.  */
-  OMP_CLAUSE_UNTIED
+  OMP_CLAUSE_UNTIED,
+
+  /* OpenMP clause: final (scalar-expression).  */
+  OMP_CLAUSE_FINAL,
+
+  /* OpenMP clause: mergeable.  */
+  OMP_CLAUSE_MERGEABLE
 };
 \f
 /* The definition of tree nodes fills the next several pages.  */
@@ -1879,6 +1885,8 @@ extern void protected_set_expr_location (tree, location_t);
 #define OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ(NODE) \
   (OMP_CLAUSE_CHECK (NODE))->omp_clause.gimple_reduction_init
 
+#define OMP_CLAUSE_FINAL_EXPR(NODE) \
+  OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_FINAL), 0)
 #define OMP_CLAUSE_IF_EXPR(NODE) \
   OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_IF), 0)
 #define OMP_CLAUSE_NUM_THREADS_EXPR(NODE) \
index efd0c04c71b86ba7a1ed6f1a0cdabbd2fc4c8d5e..b26dcd54cd670bc8178676d9c2f745d2edecc8ad 100644 (file)
@@ -1,3 +1,74 @@
+2011-08-02  Jakub Jelinek  <jakub@redhat.com>
+
+       PR fortran/42041
+       PR fortran/46752
+       * omp.h.in (omp_in_final): New prototype.
+       * omp_lib.f90.in (omp_in_final): New interface.
+       (omp_integer_kind, omp_logical_kind): Remove
+       and replace all its uses in the module with 4.
+       (openmp_version): Change to 201107.
+       * omp_lib.h.in (omp_sched_static, omp_sched_dynamic,
+       omp_sched_guided, omp_sched_auto): Use omp_sched_kind
+       kind for the parameters.
+       (omp_in_final): New external.
+       (openmp_version): Change to 201107.
+       * task.c (omp_in_final): New function.
+       (gomp_init_task): Initialize final_task.
+       (GOMP_task): Remove unused attribute from flags.  Handle final
+       tasks.
+       (GOMP_taskyield): New function.
+       (omp_in_final): Return true if if (false) or final (true) task
+       or descendant of final (true).
+       * fortran.c (omp_in_final_): New function.
+       * libgomp.map (OMP_3.1): Export omp_in_final and omp_in_final_.
+       (GOMP_3.0): Export GOMP_taskyield.
+       * env.c (gomp_nthreads_var_list, gomp_nthreads_var_list_len): New
+       variables.
+       (parse_unsigned_long_list): New function.
+       (initialize_env): Use it for OMP_NUM_THREADS.  Call parse_boolean
+       with "OMP_PROC_BIND".  If OMP_PROC_BIND=true, call gomp_init_affinity
+       even if parse_affinity returned false.
+       * config/linux/affinity.c (gomp_init_affinity): Handle
+       gomp_cpu_affinity_len == 0.
+       * libgomp_g.h (GOMP_taskyield): New prototype.
+       * libgomp.h (struct gomp_task): Add final_task field.
+       (gomp_nthreads_var_list, gomp_nthreads_var_list_len): New externs.
+       * team.c (gomp_team_start): Override new task's nthreads_var icv
+       if list form OMP_NUM_THREADS has been used and it has value for
+       the new nesting level.
+
+       * testsuite/libgomp.c/atomic-11.c: New test.
+       * testsuite/libgomp.c/atomic-12.c: New test.
+       * testsuite/libgomp.c/atomic-13.c: New test.
+       * testsuite/libgomp.c/atomic-14.c: New test.
+       * testsuite/libgomp.c/reduction-6.c: New test.
+       * testsuite/libgomp.c/task-5.c: New test.
+       * testsuite/libgomp.c++/atomic-2.C: New test.
+       * testsuite/libgomp.c++/atomic-3.C: New test.
+       * testsuite/libgomp.c++/atomic-4.C: New test.
+       * testsuite/libgomp.c++/atomic-5.C: New test.
+       * testsuite/libgomp.c++/atomic-6.C: New test.
+       * testsuite/libgomp.c++/atomic-7.C: New test.
+       * testsuite/libgomp.c++/atomic-8.C: New test.
+       * testsuite/libgomp.c++/atomic-9.C: New test.
+       * testsuite/libgomp.c++/task-8.C: New test.
+       * testsuite/libgomp.c++/reduction-4.C: New test.
+       * testsuite/libgomp.fortran/allocatable7.f90: New test.
+       * testsuite/libgomp.fortran/allocatable8.f90: New test.
+       * testsuite/libgomp.fortran/crayptr3.f90: New test.
+       * testsuite/libgomp.fortran/omp_atomic3.f90: New test.
+       * testsuite/libgomp.fortran/omp_atomic4.f90: New test.
+       * testsuite/libgomp.fortran/pointer1.f90: New test.
+       * testsuite/libgomp.fortran/pointer2.f90: New test.
+       * testsuite/libgomp.fortran/task4.f90: New test.
+
+2011-08-02  Tobias Burnus  <burnus@net-b.de>
+
+       * libgomp.texi: Update OpenMP spec references to 3.1.
+       (omp_in_final,OMP_PROC_BIND): New sections.
+       (OMP_NUM_THREADS): Document that the value can be now a list.
+       (GOMP_STACKSIZE,GOMP_CPU_AFFINITY): Update @ref.
+
 2011-08-02  H.J. Lu  <hongjiu.lu@intel.com>
 
        * config/linux/x86/futex.h: Check __x86_64__ instead of
index da9f3d8fdcb0c1a492911a7d5f5df8d735397657..d8d575628ff487adff150528380e312d90bf846f 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+/* Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
+   Free Software Foundation, Inc.
    Contributed by Jakub Jelinek <jakub@redhat.com>.
 
    This file is part of the GNU OpenMP Library (libgomp).
@@ -53,17 +54,36 @@ gomp_init_affinity (void)
     }
 
   CPU_ZERO (&cpusetnew);
-  for (widx = idx = 0; idx < gomp_cpu_affinity_len; idx++)
-    if (gomp_cpu_affinity[idx] < CPU_SETSIZE
-        && CPU_ISSET (gomp_cpu_affinity[idx], &cpuset))
-      {
-       if (! CPU_ISSET (gomp_cpu_affinity[idx], &cpusetnew))
+  if (gomp_cpu_affinity_len == 0)
+    {
+      unsigned long count = CPU_COUNT (&cpuset);
+      if (count >= 65536)
+       count = 65536;
+      gomp_cpu_affinity = malloc (count * sizeof (unsigned short));
+      if (gomp_cpu_affinity == NULL)
+       {
+         gomp_error ("not enough memory to store CPU affinity list");
+         return;
+       }
+      for (widx = idx = 0; widx < count && idx < 65536; idx++)
+       if (CPU_ISSET (idx, &cpuset))
          {
            cpus++;
-           CPU_SET (gomp_cpu_affinity[idx], &cpusetnew);
+           gomp_cpu_affinity[widx++] = idx;
          }
-       gomp_cpu_affinity[widx++] = gomp_cpu_affinity[idx];
-      }
+    }
+  else
+    for (widx = idx = 0; idx < gomp_cpu_affinity_len; idx++)
+      if (gomp_cpu_affinity[idx] < CPU_SETSIZE
+         && CPU_ISSET (gomp_cpu_affinity[idx], &cpuset))
+       {
+         if (! CPU_ISSET (gomp_cpu_affinity[idx], &cpusetnew))
+           {
+             cpus++;
+             CPU_SET (gomp_cpu_affinity[idx], &cpusetnew);
+           }
+         gomp_cpu_affinity[widx++] = gomp_cpu_affinity[idx];
+       }
 
   if (widx == 0)
     {
index 0ca9a1c9e0060433e9d19b245a95870a6c7f1416..aff7490a8b71f6b2d6321f3df3501c9a61919b87 100644 (file)
@@ -67,6 +67,7 @@ gomp_mutex_t gomp_remaining_threads_lock;
 #endif
 unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
 unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
+unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
 
 /* Parse the OMP_SCHEDULE environment variable.  */
 
@@ -184,6 +185,95 @@ parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
   return false;
 }
 
+/* Parse an unsigned long list environment variable.  Return true if one was
+   present and it was successfully parsed.  */
+
+static bool
+parse_unsigned_long_list (const char *name, unsigned long *p1stvalue,
+                         unsigned long **pvalues,
+                         unsigned long *pnvalues)
+{
+  char *env, *end;
+  unsigned long value, *values = NULL;
+
+  env = getenv (name);
+  if (env == NULL)
+    return false;
+
+  while (isspace ((unsigned char) *env))
+    ++env;
+  if (*env == '\0')
+    goto invalid;
+
+  errno = 0;
+  value = strtoul (env, &end, 10);
+  if (errno || (long) value <= 0)
+    goto invalid;
+
+  while (isspace ((unsigned char) *end))
+    ++end;
+  if (*end != '\0')
+    {
+      if (*end == ',')
+       {
+         unsigned long nvalues = 0, nalloced = 0;
+
+         do
+           {
+             env = end + 1;
+             if (nvalues == nalloced)
+               {
+                 unsigned long *n;
+                 nalloced = nalloced ? nalloced * 2 : 16;
+                 n = realloc (values, nalloced * sizeof (unsigned long));
+                 if (n == NULL)
+                   {
+                     free (values);
+                     gomp_error ("Out of memory while trying to parse"
+                                 " environment variable %s", name);
+                     return false;
+                   }
+                 values = n;
+                 if (nvalues == 0)
+                   values[nvalues++] = value;
+               }
+
+             while (isspace ((unsigned char) *env))
+               ++env;
+             if (*env == '\0')
+               goto invalid;
+
+             errno = 0;
+             value = strtoul (env, &end, 10);
+             if (errno || (long) value <= 0)
+               goto invalid;
+
+             values[nvalues++] = value;
+             while (isspace ((unsigned char) *end))
+               ++end;
+             if (*end == '\0')
+               break;
+             if (*end != ',')
+               goto invalid;
+           }
+         while (1);
+         *p1stvalue = values[0];
+         *pvalues = values;
+         *pnvalues = nvalues;
+         return true;
+       }
+      goto invalid;
+    }
+
+  *p1stvalue = value;
+  return true;
+
+ invalid:
+  free (values);
+  gomp_error ("Invalid value for environment variable %s", name);
+  return false;
+}
+
 /* Parse the OMP_STACKSIZE environment varible.  Return true if one was
    present and it was successfully parsed.  */
 
@@ -481,6 +571,7 @@ initialize_env (void)
 {
   unsigned long stacksize;
   int wait_policy;
+  bool bind_var = false;
 
   /* Do a compile time check that mkomp_h.pl did good job.  */
   omp_check_defines ();
@@ -488,6 +579,7 @@ initialize_env (void)
   parse_schedule ();
   parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
   parse_boolean ("OMP_NESTED", &gomp_global_icv.nest_var);
+  parse_boolean ("OMP_PROC_BIND", &bind_var);
   parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var,
                       true);
   parse_unsigned_long ("OMP_THREAD_LIMIT", &gomp_thread_limit_var, false);
@@ -498,10 +590,12 @@ initialize_env (void)
 #endif
   gomp_init_num_threads ();
   gomp_available_cpus = gomp_global_icv.nthreads_var;
-  if (!parse_unsigned_long ("OMP_NUM_THREADS", &gomp_global_icv.nthreads_var,
-                           false))
+  if (!parse_unsigned_long_list ("OMP_NUM_THREADS",
+                                &gomp_global_icv.nthreads_var,
+                                &gomp_nthreads_var_list,
+                                &gomp_nthreads_var_list_len))
     gomp_global_icv.nthreads_var = gomp_available_cpus;
-  if (parse_affinity ())
+  if (parse_affinity () || bind_var)
     gomp_init_affinity ();
   wait_policy = parse_wait_policy ();
   if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
index 39bd7486b07e13dca6560a1a88d45a90bb6c31f2..de806f8aba4a001131445fcbd78da88b6481baa4 100644 (file)
@@ -69,6 +69,7 @@ ialias_redirect (omp_get_level)
 ialias_redirect (omp_get_ancestor_thread_num)
 ialias_redirect (omp_get_team_size)
 ialias_redirect (omp_get_active_level)
+ialias_redirect (omp_in_final)
 #endif
 
 #ifndef LIBGOMP_GNU_SYMBOL_VERSIONING
@@ -428,3 +429,9 @@ omp_get_active_level_ (void)
 {
   return omp_get_active_level ();
 }
+
+int32_t
+omp_in_final_ (void)
+{
+  return omp_in_final ();
+}
index aa2f580ca5bca38ce7cf822879aeb296c1fda2d6..9cf9d3221c5ee2d481d8c14ec4709fd5551a1524 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
+   Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@redhat.com>.
 
    This file is part of the GNU OpenMP Library (libgomp).
@@ -226,6 +227,7 @@ extern gomp_mutex_t gomp_remaining_threads_lock;
 extern unsigned long gomp_max_active_levels_var;
 extern unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
 extern unsigned long gomp_available_cpus, gomp_managed_threads;
+extern unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
 
 enum gomp_task_kind
 {
@@ -251,6 +253,7 @@ struct gomp_task
   enum gomp_task_kind kind;
   bool in_taskwait;
   bool in_tied_task;
+  bool final_task;
   gomp_sem_t taskwait_sem;
 };
 
index d95693dbddefef2af12c62b95b619e8528fb4807..7b051f96aabb2e4ba61a34ec03ba48d5cd6baff9 100644 (file)
@@ -107,6 +107,12 @@ OMP_3.0 {
        omp_unset_nest_lock_;
 } OMP_2.0;
 
+OMP_3.1 {
+  global:
+       omp_in_final;
+       omp_in_final_;
+} OMP_3.0;
+
 GOMP_1.0 {
   global:
        GOMP_atomic_end;
@@ -173,3 +179,8 @@ GOMP_2.0 {
        GOMP_loop_ull_static_next;
        GOMP_loop_ull_static_start;
 } GOMP_1.0;
+
+GOMP_3.0 {
+  global:
+       GOMP_taskyield;
+} GOMP_2.0;
index 58199437a5fc70628f726e0e6a2463de9015cb13..29c078b668e8f1fa67c4d150745719cea2984c52 100644 (file)
@@ -116,7 +116,7 @@ arranges for automatic linking of the OpenMP runtime library
 
 A complete description of all OpenMP directives accepted may be found in 
 the @uref{http://www.openmp.org, OpenMP Application Program Interface} manual,
-version 3.0.
+version 3.1.
 
 
 @c ---------------------------------------------------------------------
@@ -127,7 +127,7 @@ version 3.0.
 @chapter Runtime Library Routines
 
 The runtime routines described here are defined by section 3 of the OpenMP 
-specifications in version 3.0. The routines are structured in following
+specifications in version 3.1. The routines are structured in following
 three parts:
 
 Control threads, processors and the parallel environment.
@@ -147,6 +147,7 @@ Control threads, processors and the parallel environment.
 * omp_get_thread_limit::        Maximum number of threads
 * omp_get_thread_num::          Current thread ID
 * omp_in_parallel::             Whether a parallel region is active
+* omp_in_final::                Whether in final or included task region
 * omp_set_dynamic::             Enable/disable dynamic teams
 * omp_set_max_active_levels::   Limits the number of active parallel regions
 * omp_set_nested::              Enable/disable nested parallel regions
@@ -199,7 +200,7 @@ which enclose the calling call.
 @ref{omp_get_level}, @ref{omp_get_max_active_levels}, @ref{omp_set_max_active_levels}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.19.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.19.
 @end table
 
 
@@ -228,7 +229,7 @@ zero to @code{omp_get_level} -1 is returned; if @var{level} is
 @ref{omp_get_level}, @ref{omp_get_thread_num}, @ref{omp_get_team_size}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.17.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.17.
 @end table
 
 
@@ -260,7 +261,7 @@ disabled by default.
 @ref{omp_set_dynamic}, @ref{OMP_DYNAMIC}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.8.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.8.
 @end table
 
 
@@ -286,7 +287,7 @@ which enclose the calling call.
 @ref{omp_get_active_level}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.16.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.16.
 @end table
 
 
@@ -311,7 +312,7 @@ This function obtains the maximum allowed number of nested, active parallel regi
 @ref{omp_set_max_active_levels}, @ref{omp_get_active_level}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.14.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.15.
 @end table
 
 
@@ -337,7 +338,7 @@ that does not use the clause @code{num_threads}.
 @ref{omp_set_num_threads}, @ref{omp_set_dynamic}, @ref{omp_get_thread_limit}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.3.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.3.
 @end table
 
 
@@ -369,7 +370,7 @@ disabled by default.
 @ref{omp_set_nested}, @ref{OMP_NESTED}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.10.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.10.
 @end table
 
 
@@ -391,7 +392,7 @@ Returns the number of processors online.
 @end multitable
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.5.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.5.
 @end table
 
 
@@ -424,7 +425,7 @@ one thread per CPU online is used.
 @ref{omp_get_max_threads}, @ref{omp_set_num_threads}, @ref{OMP_NUM_THREADS}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.2.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.2.
 @end table
 
 
@@ -440,7 +441,7 @@ set to the value @code{omp_sched_static}, @code{omp_sched_dynamic},
 
 @item @emph{C/C++}
 @multitable @columnfractions .20 .80
-@item @emph{Prototype}: @tab @code{omp_schedule(omp_sched_t *kind, int *modifier);}
+@item @emph{Prototype}: @tab @code{void omp_schedule(omp_sched_t *kind, int *modifier);}
 @end multitable
 
 @item @emph{Fortran}:
@@ -454,7 +455,7 @@ set to the value @code{omp_sched_static}, @code{omp_sched_dynamic},
 @ref{omp_set_schedule}, @ref{OMP_SCHEDULE}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.12.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.12.
 @end table
 
 
@@ -484,7 +485,7 @@ to @code{omp_get_num_threads}.
 @ref{omp_get_num_threads}, @ref{omp_get_level}, @ref{omp_get_ancestor_thread_num}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.18.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.18.
 @end table
 
 
@@ -509,7 +510,7 @@ Return the maximum number of threads of the program.
 @ref{omp_get_max_threads}, @ref{OMP_THREAD_LIMIT}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.13.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.13.
 @end table
 
 
@@ -538,7 +539,7 @@ value of the master thread of a team is always 0.
 @ref{omp_get_num_threads}, @ref{omp_get_ancestor_thread_num}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.4.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.4.
 @end table
 
 
@@ -562,7 +563,30 @@ their language-specific counterparts.
 @end multitable
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.6.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.6.
+@end table
+
+
+@node omp_in_final
+@section @code{omp_in_final} -- Whether in final or included task region
+@table @asis
+@item @emph{Description}:
+This function returns @code{true} if currently running in a final
+or included task region, @code{false} otherwise. Here, @code{true}
+and @code{false} represent their language-specific counterparts.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{int omp_in_final(void);}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{logical function omp_in_final()}
+@end multitable
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.20.
 @end table
 
 
@@ -590,7 +614,7 @@ adjustment of team sizes and @code{false} disables it.
 @ref{OMP_DYNAMIC}, @ref{omp_get_dynamic}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.7.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.7.
 @end table
 
 
@@ -617,7 +641,7 @@ parallel regions.
 @ref{omp_get_max_active_levels}, @ref{omp_get_active_level}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.14.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.14.
 @end table
 
 
@@ -646,7 +670,7 @@ dynamic adjustment of team sizes and @code{false} disables it.
 @ref{OMP_NESTED}, @ref{omp_get_nested}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.9.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.9.
 @end table
 
 
@@ -674,7 +698,7 @@ argument of @code{omp_set_num_threads} shall be a positive integer.
 @ref{OMP_NUM_THREADS}, @ref{omp_get_num_threads}, @ref{omp_get_max_threads}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.1.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.1.
 @end table
 
 
@@ -692,7 +716,7 @@ For @code{omp_sched_auto} the @var{modifier} argument is ignored.
 
 @item @emph{C/C++}
 @multitable @columnfractions .20 .80
-@item @emph{Prototype}: @tab @code{int omp_set_schedule(omp_sched_t *kind, int *modifier);}
+@item @emph{Prototype}: @tab @code{void omp_set_schedule(omp_sched_t *kind, int *modifier);}
 @end multitable
 
 @item @emph{Fortran}:
@@ -707,7 +731,7 @@ For @code{omp_sched_auto} the @var{modifier} argument is ignored.
 @ref{OMP_SCHEDULE}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.2.11.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.11.
 @end table
 
 
@@ -734,7 +758,7 @@ an unlocked state.
 @ref{omp_destroy_lock}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.1.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.1.
 @end table
 
 
@@ -763,7 +787,7 @@ a deadlock occurs.
 @ref{omp_init_lock}, @ref{omp_test_lock}, @ref{omp_unset_lock}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.3.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.3.
 @end table
 
 
@@ -785,8 +809,7 @@ does not block if the lock is not available. This function returns
 
 @item @emph{Fortran}:
 @multitable @columnfractions .20 .80
-@item @emph{Interface}: @tab @code{subroutine omp_test_lock(lock)}
-@item                   @tab @code{logical(omp_logical_kind) :: omp_test_lock}
+@item @emph{Interface}: @tab @code{logical function omp_test_lock(lock)}
 @item                   @tab @code{integer(omp_lock_kind), intent(inout) :: lock}
 @end multitable
 
@@ -794,7 +817,7 @@ does not block if the lock is not available. This function returns
 @ref{omp_init_lock}, @ref{omp_set_lock}, @ref{omp_set_lock}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.5.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.5.
 @end table
 
 
@@ -807,7 +830,7 @@ A simple lock about to be unset must have been locked by @code{omp_set_lock}
 or @code{omp_test_lock} before. In addition, the lock must be held by the 
 thread calling @code{omp_unset_lock}. Then, the lock becomes unlocked. If one 
 or more threads attempted to set the lock before, one of them is chosen to, 
-again, set the lock for itself.
+again, set the lock to itself.
 
 @item @emph{C/C++}:
 @multitable @columnfractions .20 .80
@@ -824,7 +847,7 @@ again, set the lock for itself.
 @ref{omp_set_lock}, @ref{omp_test_lock}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.4.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.4.
 @end table
 
 
@@ -851,7 +874,7 @@ in the unlocked state.
 @ref{omp_init_lock}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.2.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.2.
 @end table
 
 
@@ -878,7 +901,7 @@ an unlocked state and the nesting count is set to zero.
 @ref{omp_destroy_nest_lock}
 
 @item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.1.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.1.
 @end table
 
 
@@ -889,7 +912,7 @@ an unlocked state and the nesting count is set to zero.
 Before setting a nested lock, the lock variable must be initialized by 
 @code{omp_init_nest_lock}. The calling thread is blocked until the lock 
 is available. If the lock is already held by the current thread, the 
-nesting count for the lock in incremented.
+nesting count for the lock is incremented.
 
 @item @emph{C/C++}:
 @multitable @columnfractions .20 .80
@@ -906,7 +929,7 @@ nesting count for the lock in incremented.
 @ref{omp_init_nest_lock}, @ref{omp_unset_nest_lock}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.3.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.3.
 @end table
 
 
@@ -928,8 +951,7 @@ is returned. Otherwise, the return value equals zero.
 
 @item @emph{Fortran}:
 @multitable @columnfractions .20 .80
-@item @emph{Interface}: @tab @code{integer function omp_test_nest_lock(lock)}
-@item                   @tab @code{integer(omp_integer_kind) :: omp_test_nest_lock}
+@item @emph{Interface}: @tab @code{logical function omp_test_nest_lock(lock)}
 @item                   @tab @code{integer(omp_nest_lock_kind), intent(inout) :: lock}
 @end multitable
 
@@ -938,7 +960,7 @@ is returned. Otherwise, the return value equals zero.
 @ref{omp_init_lock}, @ref{omp_set_lock}, @ref{omp_set_lock}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.5.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.5.
 @end table
 
 
@@ -951,7 +973,7 @@ A nested lock about to be unset must have been locked by @code{omp_set_nested_lo
 or @code{omp_test_nested_lock} before. In addition, the lock must be held by the 
 thread calling @code{omp_unset_nested_lock}. If the nesting count drops to zero, the 
 lock becomes unlocked. If one ore more threads attempted to set the lock before, 
-one of them is chosen to, again, set the lock for itself.
+one of them is chosen to, again, set the lock to itself.
 
 @item @emph{C/C++}:
 @multitable @columnfractions .20 .80
@@ -968,7 +990,7 @@ one of them is chosen to, again, set the lock for itself.
 @ref{omp_set_nest_lock}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.4.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.4.
 @end table
 
 
@@ -995,7 +1017,7 @@ in the unlocked state and its nesting count must equal zero.
 @ref{omp_init_lock}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.3.2.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.2.
 @end table
 
 
@@ -1021,7 +1043,7 @@ successive clock ticks.
 @ref{omp_get_wtime}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.4.2.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.4.2.
 @end table
 
 
@@ -1049,7 +1071,7 @@ guaranteed not to change during the execution of the program.
 @ref{omp_get_wtick}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 3.4.1.
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.4.1.
 @end table
 
 
@@ -1064,7 +1086,7 @@ guaranteed not to change during the execution of the program.
 The variables @env{OMP_DYNAMIC}, @env{OMP_MAX_ACTIVE_LEVELS},
 @env{OMP_NESTED}, @env{OMP_NUM_THREADS}, @env{OMP_SCHEDULE},
 @env{OMP_STACKSIZE},@env{OMP_THREAD_LIMIT} and @env{OMP_WAIT_POLICY}
-are defined by section 4 of the OpenMP specifications in version 3.0,
+are defined by section 4 of the OpenMP specifications in version 3.1,
 while @env{GOMP_CPU_AFFINITY} and @env{GOMP_STACKSIZE} are GNU 
 extensions.
 
@@ -1077,6 +1099,7 @@ extensions.
 * OMP_SCHEDULE::          How threads are scheduled
 * OMP_THREAD_LIMIT::      Set the maximum number of threads
 * OMP_WAIT_POLICY::       How waiting threads are handled
+* OMP_PROC_BIND::         Whether theads may be moved between CPUs
 * GOMP_CPU_AFFINITY::     Bind threads to specific CPUs
 * GOMP_STACKSIZE::        Set default thread stack size
 @end menu
@@ -1096,7 +1119,7 @@ disabled by default.
 @ref{omp_set_dynamic}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 4.3
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 4.3
 @end table
 
 
@@ -1107,14 +1130,14 @@ disabled by default.
 @table @asis
 @item @emph{Description}:
 Specifies the initial value for the maximum number of nested parallel
-regions. The value of this variable shall be positive integer.
+regions. The value of this variable shall be positive integer.
 If undefined, the number of active levels is unlimited.
 
 @item @emph{See also}:
 @ref{omp_set_max_active_levels}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 4.7
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 4.8
 @end table
 
 
@@ -1134,7 +1157,7 @@ regions are disabled by default.
 @ref{omp_set_nested}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 4.4
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 4.5
 @end table
 
 
@@ -1146,14 +1169,15 @@ regions are disabled by default.
 @table @asis
 @item @emph{Description}:
 Specifies the default number of threads to use in parallel regions. The 
-value of this variable shall be a positive integer. If undefined one thread 
-per CPU is used.
+value of this variable shall be a comma-separated list of positive integers;
+the value specified the number of threads to use for the corresponding nested
+level. If undefined one thread per CPU is used.
 
 @item @emph{See also}:
 @ref{omp_set_num_threads}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 4.2
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 4.2
 @end table
 
 
@@ -1174,7 +1198,7 @@ dynamic scheduling and a chunk size of 1 is used.
 @ref{omp_set_schedule}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, sections 2.5.1 and 4.1
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, sections 2.5.1 and 4.1
 @end table
 
 
@@ -1188,13 +1212,13 @@ Set the default thread stack size in kilobytes, unless the number
 is suffixed by @code{B}, @code{K}, @code{M} or @code{G}, in which
 case the size is, respectively, in bytes, kilobytes, megabytes
 or gigabytes. This is different from @code{pthread_attr_setstacksize}
-which gets the number of bytes as an argument. If the stacksize cannot
+which gets the number of bytes as an argument. If the stack size cannot
 be set due to system constraints, an error is reported and the initial
-stacksize is left unchanged. If undefined, the stack size is system
+stack size is left unchanged. If undefined, the stack size is system
 dependent.
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, sections 4.5
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, sections 4.6
 @end table
 
 
@@ -1213,7 +1237,7 @@ the number of threads is not limited.
 @ref{omp_get_thread_limit}
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, section 4.8
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 4.9
 @end table
 
 
@@ -1229,7 +1253,25 @@ power while waiting; while the value is @code{ACTIVE} specifies that
 they should.
 
 @item @emph{Reference}: 
-@uref{http://www.openmp.org/, OpenMP specifications v3.0}, sections 4.6
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, sections 4.7
+@end table
+
+
+
+@node OMP_PROC_BIND
+@section @env{OMP_PROC_BIND} -- Whether theads may be moved between CPUs
+@cindex Environment Variable
+@table @asis
+@item @emph{Description}:
+Specifies whether threads may be moved between processors. If set to
+@code{true}, OpenMP theads should not be moved, if set to @code{false}
+they may be moved.
+
+@item @emph{See also}:
+@ref{GOMP_CPU_AFFINITY}
+
+@item @emph{Reference}: 
+@uref{http://www.openmp.org/, OpenMP specifications v3.1}, sections 4.4
 @end table
 
 
@@ -1258,6 +1300,9 @@ or disabled during the runtime of the application.
 
 If this environment variable is omitted, the host system will handle the 
 assignment of threads to CPUs. 
+
+@item @emph{See also}:
+@ref{OMP_PROC_BIND}
 @end table
 
 
@@ -1270,8 +1315,8 @@ assignment of threads to CPUs.
 @item @emph{Description}:
 Set the default thread stack size in kilobytes. This is different from
 @code{pthread_attr_setstacksize} which gets the number of bytes as an 
-argument. If the stacksize cannot be set due to system constraints, an 
-error is reported and the initial stacksize is left unchanged. If undefined,
+argument. If the stack size cannot be set due to system constraints, an 
+error is reported and the initial stack size is left unchanged. If undefined,
 the stack size is system dependent.
 
 @item @emph{See also}:
index 18f69bc1e31703e4efeeea94675e883e9757cd12..8a7c31f0d2abb73770e87fcf7cda5abd141c6cce 100644 (file)
@@ -158,11 +158,12 @@ extern void GOMP_ordered_end (void);
 extern void GOMP_parallel_start (void (*) (void *), void *, unsigned);
 extern void GOMP_parallel_end (void);
 
-/* team.c */
+/* task.c */
 
 extern void GOMP_task (void (*) (void *), void *, void (*) (void *, void *),
                       long, long, bool, unsigned);
 extern void GOMP_taskwait (void);
+extern void GOMP_taskyield (void);
 
 /* sections.c */
 
index 0198b8fd7ec9817492b924ca5a9f0ca192952fa3..f2d7ba4e1157e3bc5f5d3ec058ba776504b38851 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@redhat.com>.
 
    This file is part of the GNU OpenMP Library (libgomp).
@@ -98,6 +98,8 @@ int omp_get_ancestor_thread_num (int) __GOMP_NOTHROW;
 int omp_get_team_size (int) __GOMP_NOTHROW;
 int omp_get_active_level (void) __GOMP_NOTHROW;
 
+int omp_in_final (void) __GOMP_NOTHROW;
+
 #ifdef __cplusplus
 }
 #endif
index 6b0b7aa26ca76a7bac548a0a404344c6a90da5f5..d00fa0551f681a34c436d9cbc798500c200f09e9 100644 (file)
@@ -1,4 +1,4 @@
-!  Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+!  Copyright (C) 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
 !  Contributed by Jakub Jelinek <jakub@redhat.com>.
 
 !  This file is part of the GNU OpenMP Library (libgomp).
@@ -24,8 +24,6 @@
 
       module omp_lib_kinds
         implicit none
-        integer, parameter :: omp_integer_kind = 4
-        integer, parameter :: omp_logical_kind = 4
         integer, parameter :: omp_lock_kind = @OMP_LOCK_KIND@
         integer, parameter :: omp_nest_lock_kind = @OMP_NEST_LOCK_KIND@
         integer, parameter :: omp_sched_kind = 4
@@ -34,7 +32,7 @@
       module omp_lib
         use omp_lib_kinds
         implicit none
-        integer, parameter :: openmp_version = 200805
+        integer, parameter :: openmp_version = 201107
         integer (omp_sched_kind), parameter :: omp_sched_static = 1
         integer (omp_sched_kind), parameter :: omp_sched_dynamic = 2
         integer (omp_sched_kind), parameter :: omp_sched_guided = 3
         interface
           function omp_get_dynamic ()
             use omp_lib_kinds
-            logical (omp_logical_kind) :: omp_get_dynamic
+            logical (4) :: omp_get_dynamic
           end function omp_get_dynamic
         end interface
 
         interface
           function omp_get_nested ()
             use omp_lib_kinds
-            logical (omp_logical_kind) :: omp_get_nested
+            logical (4) :: omp_get_nested
           end function omp_get_nested
         end interface
 
         interface
           function omp_in_parallel ()
             use omp_lib_kinds
-            logical (omp_logical_kind) :: omp_in_parallel
+            logical (4) :: omp_in_parallel
           end function omp_in_parallel
         end interface
 
         interface
           function omp_test_lock (lock)
             use omp_lib_kinds
-            logical (omp_logical_kind) :: omp_test_lock
+            logical (4) :: omp_test_lock
             integer (omp_lock_kind), intent (inout) :: lock
           end function omp_test_lock
         end interface
         interface
           function omp_get_max_threads ()
             use omp_lib_kinds
-            integer (omp_integer_kind) :: omp_get_max_threads
+            integer (4) :: omp_get_max_threads
           end function omp_get_max_threads
         end interface
 
         interface
           function omp_get_num_procs ()
             use omp_lib_kinds
-            integer (omp_integer_kind) :: omp_get_num_procs
+            integer (4) :: omp_get_num_procs
           end function omp_get_num_procs
         end interface
 
         interface
           function omp_get_num_threads ()
             use omp_lib_kinds
-            integer (omp_integer_kind) :: omp_get_num_threads
+            integer (4) :: omp_get_num_threads
           end function omp_get_num_threads
         end interface
 
         interface
           function omp_get_thread_num ()
             use omp_lib_kinds
-            integer (omp_integer_kind) :: omp_get_thread_num
+            integer (4) :: omp_get_thread_num
           end function omp_get_thread_num
         end interface
 
         interface
           function omp_test_nest_lock (lock)
             use omp_lib_kinds
-            integer (omp_integer_kind) :: omp_test_nest_lock
+            integer (4) :: omp_test_nest_lock
             integer (omp_nest_lock_kind), intent (inout) :: lock
           end function omp_test_nest_lock
         end interface
         interface
           function omp_get_thread_limit ()
             use omp_lib_kinds
-            integer (omp_integer_kind) :: omp_get_thread_limit
+            integer (4) :: omp_get_thread_limit
           end function omp_get_thread_limit
         end interface
 
         interface
           function omp_get_max_active_levels ()
             use omp_lib_kinds
-            integer (omp_integer_kind) :: omp_get_max_active_levels
+            integer (4) :: omp_get_max_active_levels
           end function omp_get_max_active_levels
         end interface
 
         interface
           function omp_get_level ()
             use omp_lib_kinds
-            integer (omp_integer_kind) :: omp_get_level
+            integer (4) :: omp_get_level
           end function omp_get_level
         end interface
 
           function omp_get_ancestor_thread_num (level)
             use omp_lib_kinds
             integer (4), intent (in) :: level
-            integer (omp_integer_kind) :: omp_get_ancestor_thread_num
+            integer (4) :: omp_get_ancestor_thread_num
           end function omp_get_ancestor_thread_num
           function omp_get_ancestor_thread_num_8 (level)
             use omp_lib_kinds
             integer (8), intent (in) :: level
-            integer (omp_integer_kind) :: omp_get_ancestor_thread_num_8
+            integer (4) :: omp_get_ancestor_thread_num_8
           end function omp_get_ancestor_thread_num_8
         end interface
 
           function omp_get_team_size (level)
             use omp_lib_kinds
             integer (4), intent (in) :: level
-            integer (omp_integer_kind) :: omp_get_team_size
+            integer (4) :: omp_get_team_size
           end function omp_get_team_size
           function omp_get_team_size_8 (level)
             use omp_lib_kinds
             integer (8), intent (in) :: level
-            integer (omp_integer_kind) :: omp_get_team_size_8
+            integer (4) :: omp_get_team_size_8
           end function omp_get_team_size_8
         end interface
 
         interface
           function omp_get_active_level ()
             use omp_lib_kinds
-            integer (omp_integer_kind) :: omp_get_active_level
+            integer (4) :: omp_get_active_level
           end function omp_get_active_level
         end interface
 
+        interface
+          function omp_in_final ()
+            use omp_lib_kinds
+            logical (4) :: omp_in_final
+          end function omp_in_final
+        end interface
+
       end module omp_lib
index 2ff7a42fa8f566b3c6888f39eeb4875f3d08be29..c583ba3d24a36dfbc6ca4a720ae694814f7cb338 100644 (file)
@@ -1,4 +1,4 @@
-!  Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+!  Copyright (C) 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
 !  Contributed by Jakub Jelinek <jakub@redhat.com>.
 
 !  This file is part of the GNU OpenMP Library (libgomp).
 !  <http://www.gnu.org/licenses/>.
 
       integer omp_lock_kind, omp_nest_lock_kind, openmp_version
-      integer omp_sched_kind, omp_sched_static, omp_sched_dynamic
-      integer omp_sched_guided, omp_sched_auto
       parameter (omp_lock_kind = @OMP_LOCK_KIND@)
       parameter (omp_nest_lock_kind = @OMP_NEST_LOCK_KIND@)
+      integer omp_sched_kind
       parameter (omp_sched_kind = 4)
+      integer (omp_sched_kind) omp_sched_static, omp_sched_dynamic
+      integer (omp_sched_kind) omp_sched_guided, omp_sched_auto
       parameter (omp_sched_static = 1)
       parameter (omp_sched_dynamic = 2)
       parameter (omp_sched_guided = 3)
       parameter (omp_sched_auto = 4)
-      parameter (openmp_version = 200805)
+      parameter (openmp_version = 201107)
 
       external omp_init_lock, omp_init_nest_lock
       external omp_destroy_lock, omp_destroy_nest_lock
@@ -64,3 +65,6 @@
       integer(4) omp_get_thread_limit, omp_get_max_active_levels
       integer(4) omp_get_level, omp_get_ancestor_thread_num
       integer(4) omp_get_team_size, omp_get_active_level
+
+      external omp_in_final
+      logical(4) omp_in_final
index 95f163d53cd72c3c78026270d8442bceef81783d..b93f77a38167e613235b3f5a14ef3588a9e2e5d1 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@redhat.com>.
 
    This file is part of the GNU OpenMP Library (libgomp).
@@ -41,6 +41,7 @@ gomp_init_task (struct gomp_task *task, struct gomp_task *parent_task,
   task->kind = GOMP_TASK_IMPLICIT;
   task->in_taskwait = false;
   task->in_tied_task = false;
+  task->final_task = false;
   task->children = NULL;
   gomp_sem_init (&task->taskwait_sem, 0);
 }
@@ -77,8 +78,7 @@ gomp_clear_parent (struct gomp_task *children)
 
 void
 GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
-          long arg_size, long arg_align, bool if_clause,
-          unsigned flags __attribute__((unused)))
+          long arg_size, long arg_align, bool if_clause, unsigned flags)
 {
   struct gomp_thread *thr = gomp_thread ();
   struct gomp_team *team = thr->ts.team;
@@ -95,12 +95,14 @@ GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
 #endif
 
   if (!if_clause || team == NULL
+      || (thr->task && thr->task->final_task)
       || team->task_count > 64 * team->nthreads)
     {
       struct gomp_task task;
 
       gomp_init_task (&task, thr->task, gomp_icv (false));
       task.kind = GOMP_TASK_IFFALSE;
+      task.final_task = (thr->task && thr->task->final_task) || (flags & 2);
       if (thr->task)
        task.in_tied_task = thr->task->in_tied_task;
       thr->task = &task;
@@ -145,6 +147,7 @@ GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
       task->fn = fn;
       task->fn_data = arg;
       task->in_tied_task = true;
+      task->final_task = (flags & 2) >> 1;
       gomp_mutex_lock (&team->task_lock);
       if (parent->children)
        {
@@ -362,3 +365,20 @@ GOMP_taskwait (void)
        }
     }
 }
+
+/* Called when encountering a taskyield directive.  */
+
+void
+GOMP_taskyield (void)
+{
+  /* Nothing at the moment.  */
+}
+
+int
+omp_in_final (void)
+{
+  struct gomp_thread *thr = gomp_thread ();
+  return thr->task && thr->task->final_task;
+}
+
+ialias (omp_in_final)
index 44ffd56095ffb425da26579a4696775db67a7e0a..633902ca5679a23f6ae2efc08ba4194d9637b728 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2011
+   Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@redhat.com>.
 
    This file is part of the GNU OpenMP Library (libgomp).
@@ -260,6 +261,7 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
   struct gomp_thread_pool *pool;
   unsigned i, n, old_threads_used = 0;
   pthread_attr_t thread_attr, *attr;
+  unsigned long nthreads_var;
 
   thr = gomp_thread ();
   nested = thr->ts.team != NULL;
@@ -289,7 +291,12 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
 #endif
   thr->ts.static_trip = 0;
   thr->task = &team->implicit_task[0];
+  nthreads_var = icv->nthreads_var;
+  if (__builtin_expect (gomp_nthreads_var_list != NULL, 0)
+      && thr->ts.level < gomp_nthreads_var_list_len)
+    nthreads_var = gomp_nthreads_var_list[thr->ts.level];
   gomp_init_task (thr->task, task, icv);
+  team->implicit_task[0].icv.nthreads_var = nthreads_var;
 
   if (nthreads == 1)
     return;
@@ -342,6 +349,7 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
          nthr->ts.static_trip = 0;
          nthr->task = &team->implicit_task[i];
          gomp_init_task (nthr->task, task, icv);
+         team->implicit_task[i].icv.nthreads_var = nthreads_var;
          nthr->fn = fn;
          nthr->data = data;
          team->ordered_release[i] = &nthr->release;
@@ -413,6 +421,7 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
       start_data->ts.static_trip = 0;
       start_data->task = &team->implicit_task[i];
       gomp_init_task (start_data->task, task, icv);
+      team->implicit_task[i].icv.nthreads_var = nthreads_var;
       start_data->thread_pool = pool;
       start_data->nested = nested;
 
diff --git a/libgomp/testsuite/libgomp.c++/atomic-2.C b/libgomp/testsuite/libgomp.c++/atomic-2.C
new file mode 100644 (file)
index 0000000..e721759
--- /dev/null
@@ -0,0 +1,156 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+int x = 6;
+float y;
+
+int
+main (void)
+{
+  int v;
+  float f;
+  #pragma omp atomic read
+    v = x;
+  if (v != 6)
+    abort ();
+  #pragma omp atomic write
+    x = 17;
+  #pragma omp atomic read
+  v = x;
+  if (v != 17)
+    abort ();
+  #pragma omp atomic update
+    x++;
+  #pragma omp atomic read
+    v = x;
+  if (v != 18)
+    abort ();
+  #pragma omp atomic capture
+    v = x++;
+  if (v != 18)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 19)
+    abort ();
+  #pragma omp atomic capture
+    v = ++x;
+  if (v != 20)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 20)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; x *= 3; }
+  if (v != 20)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 60)
+    abort ();
+  #pragma omp atomic capture
+    {
+      x |= 2;
+      v = x;
+    }
+  if (v != 62)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 62)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; x++; }
+  if (v != 62)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; ++x; }
+  if (v != 63)
+    abort ();
+  #pragma omp atomic capture
+    {
+      ++x;
+      v = x;
+    }
+  if (v != 65)
+    abort ();
+#pragma omp atomic capture
+{x++;v=x;}if (v != 66)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 66)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; x--; }
+  if (v != 66)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; --x; }
+  if (v != 65)
+    abort ();
+  #pragma omp atomic capture
+    {
+      --x;
+      v = x;
+    }
+  if (v != 63)
+    abort ();
+  #pragma omp atomic capture
+  { x--; v = x; } if (v != 62)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 62)
+    abort ();
+  #pragma omp atomic write
+    y = 17.5f;
+  #pragma omp atomic read
+    f = y;
+  if (f != 17.5)
+    abort ();
+  #pragma omp atomic update
+    y *= 2.0f;
+  #pragma omp atomic read
+    f = y;
+  if (y != 35.0)
+    abort ();
+  #pragma omp atomic capture
+    f = y *= 2.0f;
+  if (f != 70.0)
+    abort ();
+  #pragma omp atomic capture
+    f = y++;
+  if (f != 70.0)
+    abort ();
+  #pragma omp atomic read
+    f = y;
+  if (f != 71.0)
+    abort ();
+  #pragma omp atomic capture
+    f = --y;
+  if (f != 70.0)
+    abort ();
+  #pragma omp atomic read
+    f = y;
+  if (f != 70.0)
+    abort ();
+  #pragma omp atomic capture
+    { f = y; y /= 2.0f; }
+  if (f != 70.0)
+    abort ();
+  #pragma omp atomic read
+    f = y;
+  if (f != 35.0)
+    abort ();
+  #pragma omp atomic capture
+    { y /= 2.0f; f = y; }
+  if (f != 17.5)
+    abort ();
+  #pragma omp atomic read
+    f = y;
+  if (f != 17.5)
+    abort ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-3.C b/libgomp/testsuite/libgomp.c++/atomic-3.C
new file mode 100644 (file)
index 0000000..660b260
--- /dev/null
@@ -0,0 +1,74 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+bool v, x1, x2, x3, x4, x5, x6;
+
+void
+foo ()
+{
+  #pragma omp atomic capture
+  v = ++x1;
+  if (!v)
+    abort ();
+  #pragma omp atomic capture
+  v = x2++;
+  if (v)
+    abort ();
+  #pragma omp atomic read
+  v = x3;
+  if (!v)
+    abort ();
+  #pragma omp atomic read
+  v = x4;
+  if (!v)
+    abort ();
+  #pragma omp atomic capture
+  { v = x5; x5 |= 1; }
+  if (v)
+    abort ();
+  #pragma omp atomic capture
+  { x6 |= 1; v = x6; }
+  if (!v)
+    abort ();
+}
+
+void
+bar ()
+{
+  #pragma omp atomic write
+  x1 = false;
+  #pragma omp atomic write
+  x2 = false;
+  #pragma omp atomic capture
+  { ++x1; v = x1; }
+  if (!v)
+    abort ();
+  #pragma omp atomic capture
+  { v = x2; x2++; }
+  if (v)
+    abort ();
+  #pragma omp atomic write
+  x1 = false;
+  #pragma omp atomic write
+  x2 = false;
+  #pragma omp atomic capture
+  { x1++; v = x1; }
+  if (!v)
+    abort ();
+  #pragma omp atomic capture
+  { v = x2; ++x2; }
+  if (v)
+    abort ();
+}
+
+int
+main ()
+{
+  #pragma omp atomic write
+  x3 = true;
+  #pragma omp atomic write
+  x4 = true;
+  foo ();
+  bar ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-4.C b/libgomp/testsuite/libgomp.c++/atomic-4.C
new file mode 100644 (file)
index 0000000..82439df
--- /dev/null
@@ -0,0 +1,166 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+template <typename T, typename T2>
+int
+foo (void)
+{
+  extern T x;
+  extern T2 y;
+  T v;
+  T2 f;
+  #pragma omp atomic read
+    v = x;
+  if (v != 6)
+    abort ();
+  #pragma omp atomic write
+    x = 17;
+  #pragma omp atomic read
+  v = x;
+  if (v != 17)
+    abort ();
+  #pragma omp atomic update
+    x++;
+  #pragma omp atomic read
+    v = x;
+  if (v != 18)
+    abort ();
+  #pragma omp atomic capture
+    v = x++;
+  if (v != 18)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 19)
+    abort ();
+  #pragma omp atomic capture
+    v = ++x;
+  if (v != 20)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 20)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; x *= 3; }
+  if (v != 20)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 60)
+    abort ();
+  #pragma omp atomic capture
+    {
+      x |= 2;
+      v = x;
+    }
+  if (v != 62)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 62)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; x++; }
+  if (v != 62)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; ++x; }
+  if (v != 63)
+    abort ();
+  #pragma omp atomic capture
+    {
+      ++x;
+      v = x;
+    }
+  if (v != 65)
+    abort ();
+#pragma omp atomic capture
+{x++;v=x;}if (v != 66)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 66)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; x--; }
+  if (v != 66)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; --x; }
+  if (v != 65)
+    abort ();
+  #pragma omp atomic capture
+    {
+      --x;
+      v = x;
+    }
+  if (v != 63)
+    abort ();
+  #pragma omp atomic capture
+  { x--; v = x; } if (v != 62)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 62)
+    abort ();
+  #pragma omp atomic write
+    y = 17.5f;
+  #pragma omp atomic read
+    f = y;
+  if (f != 17.5)
+    abort ();
+  #pragma omp atomic update
+    y *= 2.0f;
+  #pragma omp atomic read
+    f = y;
+  if (y != 35.0)
+    abort ();
+  #pragma omp atomic capture
+    f = y *= 2.0f;
+  if (f != 70.0)
+    abort ();
+  #pragma omp atomic capture
+    f = y++;
+  if (f != 70.0)
+    abort ();
+  #pragma omp atomic read
+    f = y;
+  if (f != 71.0)
+    abort ();
+  #pragma omp atomic capture
+    f = --y;
+  if (f != 70.0)
+    abort ();
+  #pragma omp atomic read
+    f = y;
+  if (f != 70.0)
+    abort ();
+  #pragma omp atomic capture
+    { f = y; y /= 2.0f; }
+  if (f != 70.0)
+    abort ();
+  #pragma omp atomic read
+    f = y;
+  if (f != 35.0)
+    abort ();
+  #pragma omp atomic capture
+    { y /= 2.0f; f = y; }
+  if (f != 17.5)
+    abort ();
+  #pragma omp atomic read
+    f = y;
+  if (f != 17.5)
+    abort ();
+  return 0;
+}
+
+int x = 6;
+float y;
+
+int
+main ()
+{
+  foo <int, float> ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-5.C b/libgomp/testsuite/libgomp.c++/atomic-5.C
new file mode 100644 (file)
index 0000000..e9bd2cc
--- /dev/null
@@ -0,0 +1,79 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+
+template <typename T>
+void
+foo ()
+{
+  extern T v, x1, x2, x3, x4, x5, x6;
+  #pragma omp atomic capture
+  v = ++x1;
+  if (!v)
+    abort ();
+  #pragma omp atomic capture
+  v = x2++;
+  if (v)
+    abort ();
+  #pragma omp atomic read
+  v = x3;
+  if (!v)
+    abort ();
+  #pragma omp atomic read
+  v = x4;
+  if (!v)
+    abort ();
+  #pragma omp atomic capture
+  { v = x5; x5 |= 1; }
+  if (v)
+    abort ();
+  #pragma omp atomic capture
+  { x6 |= 1; v = x6; }
+  if (!v)
+    abort ();
+}
+
+template <typename T>
+void
+bar ()
+{
+  extern T v, x1, x2;
+  #pragma omp atomic write
+  x1 = false;
+  #pragma omp atomic write
+  x2 = false;
+  #pragma omp atomic capture
+  { ++x1; v = x1; }
+  if (!v)
+    abort ();
+  #pragma omp atomic capture
+  { v = x2; x2++; }
+  if (v)
+    abort ();
+  #pragma omp atomic write
+  x1 = false;
+  #pragma omp atomic write
+  x2 = false;
+  #pragma omp atomic capture
+  { x1++; v = x1; }
+  if (!v)
+    abort ();
+  #pragma omp atomic capture
+  { v = x2; ++x2; }
+  if (v)
+    abort ();
+}
+
+bool v, x1, x2, x3, x4, x5, x6;
+
+int
+main ()
+{
+  #pragma omp atomic write
+  x3 = true;
+  #pragma omp atomic write
+  x4 = true;
+  foo <bool> ();
+  bar <bool> ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-6.C b/libgomp/testsuite/libgomp.c++/atomic-6.C
new file mode 100644 (file)
index 0000000..d7d0eb9
--- /dev/null
@@ -0,0 +1,58 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+long long l, m;
+int i, j;
+
+void
+foo (void)
+{
+  #pragma omp atomic read
+    i = l;
+  #pragma omp atomic read
+    m = j;
+  if (i != 77 || m != 88)
+    abort ();
+  #pragma omp atomic write
+    l = 1 + i + 6 * 1;
+  #pragma omp atomic write
+    j = 170 - 170 + m + 1 * 7;
+  #pragma omp atomic capture
+    i = l += 4;
+  #pragma omp atomic capture
+    m = j += 4;
+  if (i != 88 || m != 99)
+    abort ();
+  #pragma omp atomic capture
+    {
+      i = l;
+      l += 4;
+    }
+  #pragma omp atomic capture
+    {
+      m = j;
+      j += 4;
+    }
+  if (i != 88 || m != 99)
+    abort ();
+  #pragma omp atomic capture
+    {
+      l += 4;
+      i = l;
+    }
+  #pragma omp atomic capture
+    {
+      j += 4;
+      m = j;
+    }
+  if (i != 96 || m != 107)
+    abort ();
+}
+
+int
+main ()
+{
+  l = 77;
+  j = 88;
+  foo ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-7.C b/libgomp/testsuite/libgomp.c++/atomic-7.C
new file mode 100644 (file)
index 0000000..fe1b4d7
--- /dev/null
@@ -0,0 +1,63 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+
+template <typename S, typename T>
+void
+foo (void)
+{
+  extern S l, m;
+  extern T i, j;
+
+  #pragma omp atomic read
+    i = l;
+  #pragma omp atomic read
+    m = j;
+  if (i != 77 || m != 88)
+    abort ();
+  #pragma omp atomic write
+    l = 1 + i + 6 * 1;
+  #pragma omp atomic write
+    j = 170 - 170 + m + 1 * 7;
+  #pragma omp atomic capture
+    i = l += 4;
+  #pragma omp atomic capture
+    m = j += 4;
+  if (i != 88 || m != 99)
+    abort ();
+  #pragma omp atomic capture
+    {
+      i = l;
+      l += 4;
+    }
+  #pragma omp atomic capture
+    {
+      m = j;
+      j += 4;
+    }
+  if (i != 88 || m != 99)
+    abort ();
+  #pragma omp atomic capture
+    {
+      l += 4;
+      i = l;
+    }
+  #pragma omp atomic capture
+    {
+      j += 4;
+      m = j;
+    }
+  if (i != 96 || m != 107)
+    abort ();
+}
+
+long long l, m;
+int i, j;
+
+int
+main ()
+{
+  l = 77;
+  j = 88;
+  foo <long long, int> ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-8.C b/libgomp/testsuite/libgomp.c++/atomic-8.C
new file mode 100644 (file)
index 0000000..744b340
--- /dev/null
@@ -0,0 +1,137 @@
+// { dg-do run }
+
+extern "C" void abort ();
+int x = 6, cnt;
+
+int
+foo ()
+{
+  return cnt++;
+}
+
+int
+main ()
+{
+  int v, *p;
+  #pragma omp atomic update
+    x = x + 7;
+  #pragma omp atomic
+    x = x + 7 + 6;
+  #pragma omp atomic update
+    x = x + 2 * 3;
+  #pragma omp atomic
+    x = x * (2 - 1);
+  #pragma omp atomic read
+    v = x;
+  if (v != 32)
+    abort ();
+  #pragma omp atomic write
+    x = 0;
+  #pragma omp atomic capture
+    {
+      v = x;
+      x = x | 1 ^ 2;
+    }
+  if (v != 0)
+    abort ();
+  #pragma omp atomic capture
+    {
+      v = x;
+      x = x | 4 | 2;
+    }
+  if (v != 3)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 7)
+    abort ();
+  #pragma omp atomic capture
+    {
+      x = x ^ 6 & 2;
+      v = x;
+    }
+  if (v != 5)
+    abort ();
+  #pragma omp atomic capture
+    { x = x - (6 + 4); v = x; }
+  if (v != -5)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; x = x - (1 | 2); }
+  if (v != -5)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != -8)
+    abort ();
+  #pragma omp atomic
+    x = x * -4 / 2;
+  #pragma omp atomic read
+    v = x;
+  if (v != 16)
+    abort ();
+  p = &x;
+  #pragma omp atomic update
+    p[foo (), 0] = p[foo (), 0] - 16;
+  #pragma omp atomic read
+    v = x;
+  if (cnt != 2 || v != 0)
+    abort ();
+  #pragma omp atomic capture
+    {
+      p[foo (), 0] += 6;
+      v = p[foo (), 0];
+    }
+  if (cnt != 4 || v != 6)
+    abort ();
+  #pragma omp atomic capture
+    {
+      v = p[foo (), 0];
+      p[foo (), 0] += 6;
+    }
+  if (cnt != 6 || v != 6)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic capture
+    {
+      p[foo (), 0] = p[foo (), 0] + 6;
+      v = p[foo (), 0];
+    }
+  if (cnt != 9 || v != 18)
+    abort ();
+  #pragma omp atomic capture
+    {
+      v = p[foo (), 0];
+      p[foo (), 0] = p[foo (), 0] + 6;
+    }
+  if (cnt != 12 || v != 18)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 24)
+    abort ();
+  #pragma omp atomic capture
+  { v = p[foo (), 0]; p[foo (), 0]++; }
+  #pragma omp atomic capture
+  { v = p[foo (), 0]; ++p[foo (), 0]; }
+  #pragma omp atomic capture
+  { p[foo (), 0]++; v = p[foo (), 0]; }
+  #pragma omp atomic capture
+  { ++p[foo (), 0]; v = p[foo (), 0]; }
+  if (cnt != 20 || v != 28)
+    abort ();
+  #pragma omp atomic capture
+  { v = p[foo (), 0]; p[foo (), 0]--; }
+  #pragma omp atomic capture
+  { v = p[foo (), 0]; --p[foo (), 0]; }
+  #pragma omp atomic capture
+  { p[foo (), 0]--; v = p[foo (), 0]; }
+  #pragma omp atomic capture
+  { --p[foo (), 0]; v = p[foo (), 0]; }
+  if (cnt != 28 || v != 24)
+    abort ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-9.C b/libgomp/testsuite/libgomp.c++/atomic-9.C
new file mode 100644 (file)
index 0000000..ece1bf3
--- /dev/null
@@ -0,0 +1,148 @@
+// { dg-do run }
+
+extern "C" void abort ();
+
+int cnt;
+
+int
+foo ()
+{
+  return cnt++;
+}
+
+template <typename T>
+void
+bar ()
+{
+  extern T x;
+  T v, *p;
+  #pragma omp atomic update
+    x = x + 7;
+  #pragma omp atomic
+    x = x + 7 + 6;
+  #pragma omp atomic update
+    x = x + 2 * 3;
+  #pragma omp atomic
+    x = x * (2 - 1);
+  #pragma omp atomic read
+    v = x;
+  if (v != 32)
+    abort ();
+  #pragma omp atomic write
+    x = 0;
+  #pragma omp atomic capture
+    {
+      v = x;
+      x = x | 1 ^ 2;
+    }
+  if (v != 0)
+    abort ();
+  #pragma omp atomic capture
+    {
+      v = x;
+      x = x | 4 | 2;
+    }
+  if (v != 3)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 7)
+    abort ();
+  #pragma omp atomic capture
+    {
+      x = x ^ 6 & 2;
+      v = x;
+    }
+  if (v != 5)
+    abort ();
+  #pragma omp atomic capture
+    { x = x - (6 + 4); v = x; }
+  if (v != -5)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; x = x - (1 | 2); }
+  if (v != -5)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != -8)
+    abort ();
+  #pragma omp atomic
+    x = x * -4 / 2;
+  #pragma omp atomic read
+    v = x;
+  if (v != 16)
+    abort ();
+  p = &x;
+  #pragma omp atomic update
+    p[foo (), 0] = p[foo (), 0] - 16;
+  #pragma omp atomic read
+    v = x;
+  if (cnt != 2 || v != 0)
+    abort ();
+  #pragma omp atomic capture
+    {
+      p[foo (), 0] += 6;
+      v = p[foo (), 0];
+    }
+  if (cnt != 4 || v != 6)
+    abort ();
+  #pragma omp atomic capture
+    {
+      v = p[foo (), 0];
+      p[foo (), 0] += 6;
+    }
+  if (cnt != 6 || v != 6)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic capture
+    {
+      p[foo (), 0] = p[foo (), 0] + 6;
+      v = p[foo (), 0];
+    }
+  if (cnt != 9 || v != 18)
+    abort ();
+  #pragma omp atomic capture
+    {
+      v = p[foo (), 0];
+      p[foo (), 0] = p[foo (), 0] + 6;
+    }
+  if (cnt != 12 || v != 18)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 24)
+    abort ();
+  #pragma omp atomic capture
+  { v = p[foo (), 0]; p[foo (), 0]++; }
+  #pragma omp atomic capture
+  { v = p[foo (), 0]; ++p[foo (), 0]; }
+  #pragma omp atomic capture
+  { p[foo (), 0]++; v = p[foo (), 0]; }
+  #pragma omp atomic capture
+  { ++p[foo (), 0]; v = p[foo (), 0]; }
+  if (cnt != 20 || v != 28)
+    abort ();
+  #pragma omp atomic capture
+  { v = p[foo (), 0]; p[foo (), 0]--; }
+  #pragma omp atomic capture
+  { v = p[foo (), 0]; --p[foo (), 0]; }
+  #pragma omp atomic capture
+  { p[foo (), 0]--; v = p[foo (), 0]; }
+  #pragma omp atomic capture
+  { --p[foo (), 0]; v = p[foo (), 0]; }
+  if (cnt != 28 || v != 24)
+    abort ();
+}
+
+int x = 6;
+
+int
+main ()
+{
+  bar <int> ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/reduction-4.C b/libgomp/testsuite/libgomp.c++/reduction-4.C
new file mode 100644 (file)
index 0000000..e7ef8a1
--- /dev/null
@@ -0,0 +1,54 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+
+template <typename I, typename F>
+void
+foo ()
+{
+  I j = -10000;
+  F f = 1024.0;
+  int i;
+  #pragma omp parallel for reduction (min:f) reduction (max:j)
+    for (i = 0; i < 4; i++)
+      switch (i)
+       {
+       case 0:
+         if (j < -16) j = -16; break;
+       case 1:
+         if (f > -2.0) f = -2.0; break;
+       case 2:
+         if (j < 8) j = 8; if (f > 9.0) f = 9.0; break;
+       case 3:
+         break;
+       }
+  if (j != 8 || f != -2.0)
+    abort ();
+}
+
+int
+main ()
+{
+  int j = -10000;
+  float f = 1024.0;
+  int i;
+  #pragma omp parallel for reduction (min:f) reduction (max:j)
+    for (i = 0; i < 4; i++)
+      switch (i)
+       {
+       case 0:
+         if (j < -16) j = -16; break;
+       case 1:
+         if (f > -2.0) f = -2.0; break;
+       case 2:
+         if (j < 8) j = 8; if (f > 9.0) f = 9.0; break;
+       case 3:
+         break;
+       }
+  if (j != 8 || f != -2.0)
+    abort ();
+  foo <int, float> ();
+  foo <long, double> ();
+  foo <long long, long double> ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-8.C b/libgomp/testsuite/libgomp.c++/task-8.C
new file mode 100644 (file)
index 0000000..3e1b469
--- /dev/null
@@ -0,0 +1,44 @@
+// { dg-do run }
+
+#include <omp.h>
+#include <cstdlib>
+
+int err;
+
+int
+main ()
+{
+  int e;
+#pragma omp parallel shared(err)
+  {
+    if (omp_in_final ())
+      #pragma omp atomic write
+       err = 1;
+    #pragma omp task if (0) shared(err)
+      {
+       if (omp_in_final ())
+         #pragma omp atomic write
+           err = 1;
+       #pragma omp task if (0) shared(err)
+         if (omp_in_final ())
+           #pragma omp atomic write
+             err = 1;
+      }
+    #pragma omp task final (1) shared(err)
+      {
+       if (!omp_in_final ())
+         #pragma omp atomic write
+           err = 1;
+       #pragma omp taskyield
+       #pragma omp taskwait
+       #pragma omp task shared(err)
+         if (!omp_in_final ())
+           #pragma omp atomic write
+             err = 1;
+      }
+  }
+  #pragma omp atomic read
+    e = err;
+  if (e)
+    abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c/atomic-11.c b/libgomp/testsuite/libgomp.c/atomic-11.c
new file mode 100644 (file)
index 0000000..d1d6ca5
--- /dev/null
@@ -0,0 +1,156 @@
+/* { dg-do run } */
+
+extern void abort (void);
+int x = 6;
+float y;
+
+int
+main (void)
+{
+  int v;
+  float f;
+  #pragma omp atomic read
+    v = x;
+  if (v != 6)
+    abort ();
+  #pragma omp atomic write
+    x = 17;
+  #pragma omp atomic read
+  v = x;
+  if (v != 17)
+    abort ();
+  #pragma omp atomic update
+    x++;
+  #pragma omp atomic read
+    v = x;
+  if (v != 18)
+    abort ();
+  #pragma omp atomic capture
+    v = x++;
+  if (v != 18)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 19)
+    abort ();
+  #pragma omp atomic capture
+    v = ++x;
+  if (v != 20)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 20)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; x *= 3; }
+  if (v != 20)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 60)
+    abort ();
+  #pragma omp atomic capture
+    {
+      x |= 2;
+      v = x;
+    }
+  if (v != 62)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 62)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; x++; }
+  if (v != 62)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; ++x; }
+  if (v != 63)
+    abort ();
+  #pragma omp atomic capture
+    {
+      ++x;
+      v = x;
+    }
+  if (v != 65)
+    abort ();
+#pragma omp atomic capture
+{x++;v=x;}if (v != 66)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 66)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; x--; }
+  if (v != 66)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; --x; }
+  if (v != 65)
+    abort ();
+  #pragma omp atomic capture
+    {
+      --x;
+      v = x;
+    }
+  if (v != 63)
+    abort ();
+  #pragma omp atomic capture
+  { x--; v = x; } if (v != 62)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 62)
+    abort ();
+  #pragma omp atomic write
+    y = 17.5f;
+  #pragma omp atomic read
+    f = y;
+  if (f != 17.5)
+    abort ();
+  #pragma omp atomic update
+    y *= 2.0f;
+  #pragma omp atomic read
+    f = y;
+  if (y != 35.0)
+    abort ();
+  #pragma omp atomic capture
+    f = y *= 2.0f;
+  if (f != 70.0)
+    abort ();
+  #pragma omp atomic capture
+    f = y++;
+  if (f != 70.0)
+    abort ();
+  #pragma omp atomic read
+    f = y;
+  if (f != 71.0)
+    abort ();
+  #pragma omp atomic capture
+    f = --y;
+  if (f != 70.0)
+    abort ();
+  #pragma omp atomic read
+    f = y;
+  if (f != 70.0)
+    abort ();
+  #pragma omp atomic capture
+    { f = y; y /= 2.0f; }
+  if (f != 70.0)
+    abort ();
+  #pragma omp atomic read
+    f = y;
+  if (f != 35.0)
+    abort ();
+  #pragma omp atomic capture
+    { y /= 2.0f; f = y; }
+  if (f != 17.5)
+    abort ();
+  #pragma omp atomic read
+    f = y;
+  if (f != 17.5)
+    abort ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/atomic-12.c b/libgomp/testsuite/libgomp.c/atomic-12.c
new file mode 100644 (file)
index 0000000..a9fe560
--- /dev/null
@@ -0,0 +1,98 @@
+/* { dg-do run } */
+
+extern void abort (void);
+_Bool v, x1, x2, x3, x4, x5, x6;
+
+void
+foo (void)
+{
+  #pragma omp atomic capture
+  v = ++x1;
+  if (!v)
+    abort ();
+  #pragma omp atomic capture
+  v = x2++;
+  if (v)
+    abort ();
+  #pragma omp atomic capture
+  v = --x3;
+  if (v)
+    abort ();
+  #pragma omp atomic capture
+  v = x4--;
+  if (!v)
+    abort ();
+  #pragma omp atomic capture
+  { v = x5; x5 |= 1; }
+  if (v)
+    abort ();
+  #pragma omp atomic capture
+  { x6 |= 1; v = x6; }
+  if (!v)
+    abort ();
+}
+
+void
+bar (void)
+{
+  #pragma omp atomic write
+  x1 = 0;
+  #pragma omp atomic write
+  x2 = 0;
+  #pragma omp atomic write
+  x3 = 1;
+  #pragma omp atomic write
+  x4 = 1;
+  #pragma omp atomic capture
+  { ++x1; v = x1; }
+  if (!v)
+    abort ();
+  #pragma omp atomic capture
+  { v = x2; x2++; }
+  if (v)
+    abort ();
+  #pragma omp atomic capture
+  { --x3; v = x3; }
+  if (v)
+    abort ();
+  #pragma omp atomic capture
+  { v = x4; x4--; }
+  if (!v)
+    abort ();
+  #pragma omp atomic write
+  x1 = 0;
+  #pragma omp atomic write
+  x2 = 0;
+  #pragma omp atomic write
+  x3 = 1;
+  #pragma omp atomic write
+  x4 = 1;
+  #pragma omp atomic capture
+  { x1++; v = x1; }
+  if (!v)
+    abort ();
+  #pragma omp atomic capture
+  { v = x2; ++x2; }
+  if (v)
+    abort ();
+  #pragma omp atomic capture
+  { x3--; v = x3; }
+  if (v)
+    abort ();
+  #pragma omp atomic capture
+  { v = x4; --x4; }
+  if (!v)
+    abort ();
+}
+
+int
+main ()
+{
+  #pragma omp atomic write
+  x3 = 1;
+  #pragma omp atomic write
+  x4 = 1;
+  foo ();
+  bar ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/atomic-13.c b/libgomp/testsuite/libgomp.c/atomic-13.c
new file mode 100644 (file)
index 0000000..52800fc
--- /dev/null
@@ -0,0 +1,59 @@
+/* { dg-do run } */
+
+extern void abort (void);
+long long l, m;
+int i, j;
+
+void
+foo (void)
+{
+  #pragma omp atomic read
+    i = l;
+  #pragma omp atomic read
+    m = j;
+  if (i != 77 || m != 88)
+    abort ();
+  #pragma omp atomic write
+    l = 1 + i + 6 * 1;
+  #pragma omp atomic write
+    j = 170 - 170 + m + 1 * 7;
+  #pragma omp atomic capture
+    i = l += 4;
+  #pragma omp atomic capture
+    m = j += 4;
+  if (i != 88 || m != 99)
+    abort ();
+  #pragma omp atomic capture
+    {
+      i = l;
+      l += 4;
+    }
+  #pragma omp atomic capture
+    {
+      m = j;
+      j += 4;
+    }
+  if (i != 88 || m != 99)
+    abort ();
+  #pragma omp atomic capture
+    {
+      l += 4;
+      i = l;
+    }
+  #pragma omp atomic capture
+    {
+      j += 4;
+      m = j;
+    }
+  if (i != 96 || m != 107)
+    abort ();
+}
+
+int
+main ()
+{
+  l = 77;
+  j = 88;
+  foo ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/atomic-14.c b/libgomp/testsuite/libgomp.c/atomic-14.c
new file mode 100644 (file)
index 0000000..5936650
--- /dev/null
@@ -0,0 +1,137 @@
+/* { dg-do run } */
+
+extern void abort (void);
+int x = 6, cnt;
+
+int
+foo (void)
+{
+  return cnt++;
+}
+
+int
+main ()
+{
+  int v, *p;
+  #pragma omp atomic update
+    x = x + 7;
+  #pragma omp atomic
+    x = x + 7 + 6;
+  #pragma omp atomic update
+    x = x + 2 * 3;
+  #pragma omp atomic
+    x = x * (2 - 1);
+  #pragma omp atomic read
+    v = x;
+  if (v != 32)
+    abort ();
+  #pragma omp atomic write
+    x = 0;
+  #pragma omp atomic capture
+    {
+      v = x;
+      x = x | 1 ^ 2;
+    }
+  if (v != 0)
+    abort ();
+  #pragma omp atomic capture
+    {
+      v = x;
+      x = x | 4 | 2;
+    }
+  if (v != 3)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 7)
+    abort ();
+  #pragma omp atomic capture
+    {
+      x = x ^ 6 & 2;
+      v = x;
+    }
+  if (v != 5)
+    abort ();
+  #pragma omp atomic capture
+    { x = x - (6 + 4); v = x; }
+  if (v != -5)
+    abort ();
+  #pragma omp atomic capture
+    { v = x; x = x - (1 | 2); }
+  if (v != -5)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != -8)
+    abort ();
+  #pragma omp atomic
+    x = x * -4 / 2;
+  #pragma omp atomic read
+    v = x;
+  if (v != 16)
+    abort ();
+  p = &x;
+  #pragma omp atomic update
+    p[foo (), 0] = p[foo (), 0] - 16;
+  #pragma omp atomic read
+    v = x;
+  if (cnt != 2 || v != 0)
+    abort ();
+  #pragma omp atomic capture
+    {
+      p[foo (), 0] += 6;
+      v = p[foo (), 0];
+    }
+  if (cnt != 4 || v != 6)
+    abort ();
+  #pragma omp atomic capture
+    {
+      v = p[foo (), 0];
+      p[foo (), 0] += 6;
+    }
+  if (cnt != 6 || v != 6)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 12)
+    abort ();
+  #pragma omp atomic capture
+    {
+      p[foo (), 0] = p[foo (), 0] + 6;
+      v = p[foo (), 0];
+    }
+  if (cnt != 9 || v != 18)
+    abort ();
+  #pragma omp atomic capture
+    {
+      v = p[foo (), 0];
+      p[foo (), 0] = p[foo (), 0] + 6;
+    }
+  if (cnt != 12 || v != 18)
+    abort ();
+  #pragma omp atomic read
+    v = x;
+  if (v != 24)
+    abort ();
+  #pragma omp atomic capture
+  { v = p[foo (), 0]; p[foo (), 0]++; }
+  #pragma omp atomic capture
+  { v = p[foo (), 0]; ++p[foo (), 0]; }
+  #pragma omp atomic capture
+  { p[foo (), 0]++; v = p[foo (), 0]; }
+  #pragma omp atomic capture
+  { ++p[foo (), 0]; v = p[foo (), 0]; }
+  if (cnt != 20 || v != 28)
+    abort ();
+  #pragma omp atomic capture
+  { v = p[foo (), 0]; p[foo (), 0]--; }
+  #pragma omp atomic capture
+  { v = p[foo (), 0]; --p[foo (), 0]; }
+  #pragma omp atomic capture
+  { p[foo (), 0]--; v = p[foo (), 0]; }
+  #pragma omp atomic capture
+  { --p[foo (), 0]; v = p[foo (), 0]; }
+  if (cnt != 28 || v != 24)
+    abort ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/reduction-6.c b/libgomp/testsuite/libgomp.c/reduction-6.c
new file mode 100644 (file)
index 0000000..d378bad
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+
+extern void abort (void);
+int j;
+float f;
+
+int
+main ()
+{
+  j = -10000;
+  f = 1024.0;
+  int i;
+  #pragma omp parallel for reduction (min:f) reduction (max:j)
+    for (i = 0; i < 4; i++)
+      switch (i)
+       {
+       case 0:
+         if (j < -16) j = -16; break;
+       case 1:
+         if (f > -2.0) f = -2.0; break;
+       case 2:
+         if (j < 8) j = 8; if (f > 9.0) f = 9.0; break;
+       case 3:
+         break;
+       }
+  if (j != 8 || f != -2.0)
+    abort ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/task-5.c b/libgomp/testsuite/libgomp.c/task-5.c
new file mode 100644 (file)
index 0000000..b152371
--- /dev/null
@@ -0,0 +1,45 @@
+/* { dg-do run } */
+
+#include <omp.h>
+#include <stdlib.h>
+
+int err;
+
+int
+main ()
+{
+  int e;
+#pragma omp parallel shared(err)
+  {
+    if (omp_in_final ())
+      #pragma omp atomic write
+       err = 1;
+    #pragma omp task if (0) shared(err)
+      {
+       if (omp_in_final ())
+         #pragma omp atomic write
+           err = 1;
+       #pragma omp task if (0) shared(err)
+         if (omp_in_final ())
+           #pragma omp atomic write
+             err = 1;
+      }
+    #pragma omp task final (1) shared(err)
+      {
+       if (!omp_in_final ())
+         #pragma omp atomic write
+           err = 1;
+       #pragma omp taskyield
+       #pragma omp taskwait
+       #pragma omp task shared(err)
+         if (!omp_in_final ())
+           #pragma omp atomic write
+             err = 1;
+      }
+  }
+  #pragma omp atomic read
+    e = err;
+  if (e)
+    abort ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.fortran/allocatable7.f90 b/libgomp/testsuite/libgomp.fortran/allocatable7.f90
new file mode 100644 (file)
index 0000000..dc68baa
--- /dev/null
@@ -0,0 +1,16 @@
+! { dg-do run }
+
+  integer, allocatable :: a(:)
+  logical :: l
+  l = .false.
+!$omp parallel firstprivate (a) reduction (.or.:l)
+  l = allocated (a)
+  allocate (a(10))
+  l = l .or. .not. allocated (a)
+  a = 10
+  if (any (a .ne. 10)) l = .true.
+  deallocate (a)
+  l = l .or. allocated (a)
+!$omp end parallel
+  if (l) call abort
+end
diff --git a/libgomp/testsuite/libgomp.fortran/allocatable8.f90 b/libgomp/testsuite/libgomp.fortran/allocatable8.f90
new file mode 100644 (file)
index 0000000..2093782
--- /dev/null
@@ -0,0 +1,14 @@
+! { dg-do run }
+! { dg-require-effective-target tls_runtime }
+!$ use omp_lib
+
+  integer, save, allocatable :: a(:, :)
+  logical :: l
+!$omp threadprivate (a)
+  if (allocated (a)) call abort
+  l = .false.
+!$omp parallel copyin (a) num_threads (4) reduction(.or.:l)
+  l = l.or.allocated (a)
+!$omp end parallel
+  if (l.or.allocated (a)) call abort
+end
diff --git a/libgomp/testsuite/libgomp.fortran/crayptr3.f90 b/libgomp/testsuite/libgomp.fortran/crayptr3.f90
new file mode 100644 (file)
index 0000000..9777c6b
--- /dev/null
@@ -0,0 +1,36 @@
+! { dg-do run }
+! { dg-options "-fopenmp -fcray-pointer" }
+
+  use omp_lib
+  integer :: a, b, c, i, p
+  logical :: l
+  pointer (ip, p)
+  a = 1
+  b = 2
+  c = 3
+  l = .false.
+  ip = loc (a)
+
+!$omp parallel num_threads (2) reduction (.or.:l) firstprivate (ip)
+  l = p .ne. 1
+  ip = loc (b)
+  if (omp_get_thread_num () .eq. 1) ip = loc (c)
+  l = l .or. (p .ne. (2 + omp_get_thread_num ()))
+!$omp end parallel
+
+  if (l) call abort
+
+  l = .false.
+  ip = loc (a)
+!$omp parallel do num_threads (2) reduction (.or.:l) &
+!$omp & firstprivate (ip) lastprivate (ip)
+  do i = 0, 1
+    l = l .or. (p .ne. 1)
+    ip = loc (b)
+    if (i .eq. 1) ip = loc (c)
+    l = l .or. (p .ne. (2 + i))
+  end do
+
+  if (l) call abort
+  if (p .ne. 3) call abort
+end
diff --git a/libgomp/testsuite/libgomp.fortran/omp_atomic3.f90 b/libgomp/testsuite/libgomp.fortran/omp_atomic3.f90
new file mode 100644 (file)
index 0000000..e8923d1
--- /dev/null
@@ -0,0 +1,58 @@
+! { dg-do run }
+    integer (kind = 4) :: a, a2
+    integer (kind = 2) :: b, b2
+    real :: c, f
+    double precision :: d, d2, c2
+    integer, dimension (10) :: e
+!$omp atomic write
+    a = 1
+!$omp atomic write
+    b = 2
+!$omp end atomic
+!$omp atomic write
+    c = 3
+!$omp atomic write
+    d = 1 + 2 + 3 - 2
+    e = 5
+!$omp atomic write
+    f = 6
+!$omp end atomic
+!$omp atomic
+    a = a + 4
+!$omp end atomic
+!$omp atomic update
+    b = 4 - b
+!$omp atomic
+    c = c * 2
+!$omp atomic update
+    d = 2 / d
+!$omp end atomic
+!$omp atomic read
+    a2 = a
+!$omp atomic read
+    b2 = b
+!$omp end atomic
+!$omp atomic read
+    c2 = c
+!$omp atomic read
+    d2 = d
+    if (a2 .ne. 5 .or. b2 .ne. 2 .or. c2 .ne. 6 .or. d2 .ne. 0.5) call abort
+!$omp atomic write
+    d = 1.2
+!$omp atomic
+    a = a + c + d
+!$omp atomic
+    b = b - (a + c + d)
+    if (a .ne. 12 .or. b .ne. -17) call abort
+!$omp atomic
+    a = c + d + a
+!$omp atomic
+    b = a + c + d - b
+    if (a .ne. 19 .or. b .ne. 43) call abort
+!$omp atomic
+    b = (a + c + d) - b
+    a = 32
+!$omp atomic
+    a = a / 3.4
+    if (a .ne. 9 .or. b .ne. -16) call abort
+end
diff --git a/libgomp/testsuite/libgomp.fortran/omp_atomic4.f90 b/libgomp/testsuite/libgomp.fortran/omp_atomic4.f90
new file mode 100644 (file)
index 0000000..725a3bc
--- /dev/null
@@ -0,0 +1,37 @@
+! { dg-do run }
+    integer (kind = 4) :: a, a2
+    integer (kind = 2) :: b, b2
+    real :: c
+    double precision :: d, d2, c2
+    integer, dimension (10) :: e
+!$omp atomic write
+    a = 1
+!$omp atomic write
+    b = 2
+!$omp atomic write
+    c = 3
+!$omp atomic write
+    d = 4
+!$omp atomic capture
+    a2 = a
+    a = a + 4
+!$omp end atomic
+!$omp atomic capture
+    b = b - 18
+    b2 = b
+!$omp end atomic
+!$omp atomic capture
+    c2 = c
+    c = 2.0 * c
+!$omp end atomic
+!$omp atomic capture
+    d = d / 2.0
+    d2 = d
+!$omp end atomic
+    if (a2 .ne. 1 .or. b2 .ne. -16 .or. c2 .ne. 3 .or. d2 .ne. 2) call abort
+!$omp atomic read
+    a2 = a
+!$omp atomic read
+    c2 = c
+    if (a2 .ne. 5 .or. b2 .ne. -16 .or. c2 .ne. 6 .or. d2 .ne. 2) call abort
+end
diff --git a/libgomp/testsuite/libgomp.fortran/pointer1.f90 b/libgomp/testsuite/libgomp.fortran/pointer1.f90
new file mode 100644 (file)
index 0000000..d55ef35
--- /dev/null
@@ -0,0 +1,77 @@
+! { dg-do run }
+  integer, pointer :: a, c(:)
+  integer, target :: b, d(10)
+  b = 0
+  a => b
+  d = 0
+  c => d
+  call foo (a, c)
+  b = 0
+  d = 0
+  call bar (a, c)
+contains
+  subroutine foo (a, c)
+    integer, pointer :: a, c(:), b, d(:)
+    integer :: r, r2
+    r = 0
+    !$omp parallel firstprivate (a, c) reduction (+:r)
+      !$omp atomic
+        a = a + 1
+      !$omp atomic
+        c(1) = c(1) + 1
+      r = r + 1
+    !$omp end parallel
+    if (a.ne.r.or.c(1).ne.r) call abort
+    r2 = r
+    b => a
+    d => c
+    r = 0
+    !$omp parallel firstprivate (b, d) reduction (+:r)
+      !$omp atomic
+        b = b + 1
+      !$omp atomic
+        d(1) = d(1) + 1
+      r = r + 1
+    !$omp end parallel
+    if (b.ne.r+r2.or.d(1).ne.r+r2) call abort
+  end subroutine foo
+  subroutine bar (a, c)
+    integer, pointer :: a, c(:), b, d(:)
+    integer, target :: q, r(5)
+    integer :: i
+    q = 17
+    r = 21
+    b => a
+    d => c
+    !$omp parallel do firstprivate (a, c) lastprivate (a, c)
+      do i = 1, 100
+        !$omp atomic
+          a = a + 1
+        !$omp atomic
+          c((i+9)/10) = c((i+9)/10) + 1
+        if (i.eq.100) then
+          a => q
+          c => r
+       end if
+      end do
+    !$omp end parallel do
+    if (b.ne.100.or.any(d.ne.10)) call abort
+    if (a.ne.17.or.any(c.ne.21)) call abort
+    a => b
+    c => d
+    !$omp parallel do firstprivate (b, d) lastprivate (b, d)
+      do i = 1, 100
+        !$omp atomic
+          b = b + 1
+        !$omp atomic
+          d((i+9)/10) = d((i+9)/10) + 1
+        if (i.eq.100) then
+          b => q
+          d => r
+       end if
+      end do
+    !$omp end parallel do
+    if (a.ne.200.or.any(c.ne.20)) call abort
+    if (b.ne.17.or.any(d.ne.21)) call abort
+  end subroutine bar
+end
diff --git a/libgomp/testsuite/libgomp.fortran/pointer2.f90 b/libgomp/testsuite/libgomp.fortran/pointer2.f90
new file mode 100644 (file)
index 0000000..f172aed
--- /dev/null
@@ -0,0 +1,28 @@
+! { dg-do run }
+! { dg-require-effective-target tls_runtime }
+  integer, pointer, save :: thr(:)
+!$omp threadprivate (thr)
+  integer, target :: s(3), t(3), u(3)
+  integer :: i
+  logical :: l
+  s = 2
+  t = 7
+  u = 13
+  thr => t
+  l = .false.
+  i = 0
+!$omp parallel copyin (thr) reduction(.or.:l) reduction(+:i)
+  if (any (thr.ne.7)) l = .true.
+  thr => s
+!$omp master
+  thr => u
+!$omp end master
+!$omp atomic
+  thr(1) = thr(1) + 1
+  i = i + 1
+!$omp end parallel
+  if (l) call abort
+  if (thr(1).ne.14) call abort
+  if (s(1).ne.1+i) call abort
+  if (u(1).ne.14) call abort
+end
diff --git a/libgomp/testsuite/libgomp.fortran/task4.f90 b/libgomp/testsuite/libgomp.fortran/task4.f90
new file mode 100644 (file)
index 0000000..9fa67d9
--- /dev/null
@@ -0,0 +1,45 @@
+! { dg-do run }
+
+  use omp_lib
+  integer :: err, e
+
+!$omp atomic write
+  err = 0
+!$omp parallel shared(err) private(e)
+  if (omp_in_final ()) then
+!$omp atomic write
+    err = 1
+  endif
+!$omp task if (.false.) shared(err)
+  if (omp_in_final ()) then
+!$omp atomic write
+    err = 1
+  endif
+!$omp task if (.false.) shared(err)
+  if (omp_in_final ()) then
+!$omp atomic write
+    err = 1
+  endif
+!$omp end task
+!$omp end task
+!$omp atomic read
+  e = err
+!$omp task final (e .eq. 0) shared(err)
+  if (.not.omp_in_final ()) then
+!$omp atomic write
+    err = 1
+  endif
+!$omp taskyield
+!$omp taskwait
+!$omp task shared(err)
+  if (.not.omp_in_final ()) then
+!$omp atomic write
+    err = 1
+  endif
+!$omp end task
+!$omp end task
+!$omp end parallel
+!$omp atomic read
+  e = err
+  if (e .ne. 0) call abort
+end