Hi!

This patch adds parsing of in_reduction and task_reduction clauses
and reduction on taskloop.  The lowering/expansion and library side is not
done yet.

Committed to gomp-5_0-branch.

2017-06-12  Jakub Jelinek  <ja...@redhat.com>

        * tree.def (OMP_TASKGROUP): Add another operand, move next to other
        OpenMP constructs with body and clauses operands.
        * gimple-pretty-print.c (dump_gimple_omp_taskgroup): New function.
        (pp_gimple_stmt_1): Handle GIMPLE_OMP_TASKGROUP.
        * gimple.h (gimple_build_omp_taskgroup): Add clauses argument.
        (gimple_omp_taskgroup_clauses): New inline function.
        (gimple_omp_taskgroup_clauses_ptr): Likewise.
        (gimple_omp_taskgroup_set_clauses): Likewise.
        * tree.h (OMP_BODY): Use OMP_MASTER instead of OMP_TASKGROUP.
        (OMP_CLAUSES): Use OMP_TASKGROUP instead of OMP_SINGLE.
        (OMP_TASKGROUP_CLAUSES): Define.
        (OMP_CLAUSE_REDUCTION_CODE): Handle OMP_CLAUSE_{,IN_,TASK_}REDUCTION.
        (OMP_CLAUSE_REDUCTION_INIT): Likewise.
        (OMP_CLAUSE_REDUCTION_MERGE): Likewise.
        (OMP_CLAUSE_REDUCTION_PLACEHOLDER): Likewise.
        (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER): Likewise.
        (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF): Likewise.
        * tree-pretty-print.c (dump_omp_clause): Handle
        OMP_CLAUSE_{TASK,IN}_REDUCTION.
        (dump_generic_node): Print taskgroup clauses.
        * gimple.def (GIMPLE_OMP_TASKGROUP): Use GSS_OMP_SINGLE_LAYOUT
        instead of GSS_OMP.
        * tree.c (omp_clause_num_ops): Add in_reduction and task_reduction
        clause entries.
        (omp_clause_code_name): Likewise.
        (walk_tree_1): Handle OMP_CLAUSE_{TASK,IN}_REDUCTION.
        * tree-streamer-out.c (pack_ts_omp_clause_value_fields): Likewise.
        (write_ts_omp_clause_tree_pointers): Likewise.
        * tree-streamer-in.c (unpack_ts_omp_clause_value_fields): Likewise.
        * gimple.c (gimple_build_omp_taskgroup): Add CLAUSES argument.  Call
        gimple_omp_taskgroup_set_clauses.
        (gimple_copy): Copy taskgroup clauses.
        * omp-low.c (scan_sharing_clauses): Handle
        OMP_CLAUSE_{TASK,IN}_REDUCTION like OMP_CLAUSE_REDUCTION.
        (lower_rec_input_clauses): Likewise.
        (scan_omp_for): Fix comment formatting.
        * lto-streamer-out.c (hash_tree): Handle
        OMP_CLAUSE_{TASK,IN}_REDUCTION.
        * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_TASK_REDUCTION
        and OMP_CLAUSE_IN_REDUCTION.
        * gimplify.c (gimplify_scan_omp_clauses): Handle
        OMP_CLAUSE_{TASK,IN}_REDUCTION.
        (gimplify_adjust_omp_clauses): Likewise.
        (gimplify_expr): Handle taskgroup clauses.
        * tree-inline.c (remap_gimple_stmt): Remap taskgroup clauses.
c-family/
        * c-common.h (c_finish_omp_taskgroup): Add CLAUSES argument.
        * c-omp.c (c_finish_omp_taskgroup): Likewise.  Set
        OMP_TASKGROUP_CLAUSES to it.
        (c_omp_split_clauses): Handle in_reduction clause.  Handle
        reduction clause on taskloop simd.
        * c-pragma.h (enum pragma_omp_clause): Add
        PRAGMA_OMP_CLAUSE_IN_REDUCTION and PRAGMA_OMP_CLAUSE_TASK_REDUCTION.
c/
        * c-parser.c (c_parser_omp_clause_name): Handle
        in_reduction and task_reduction clauses.
        (c_parser_omp_variable_list): Handle
        OMP_CLAUSE_IN_REDUCTION and OMP_CLAUSE_TASK_REDUCTION.
        (c_parser_omp_clause_reduction): Add KIND argument.  Pass
        it to c_parser_omp_variable_list.
        (c_parser_oacc_all_clauses): Adjust c_parser_omp_clause_reduction
        caller.
        (c_parser_omp_all_clauses): Likewise.  Handle
        PRAGMA_OMP_CLAUSE_IN_REDUCTION and PRAGMA_OMP_CLAUSE_TASK_REDUCTION.
        (OMP_TASK_CLAUSE_MASK): Add in_reduction clause.
        (OMP_TASKGROUP_CLAUSE_MASK): Define.
        (c_parser_omp_taskgroup): Add LOC argument.  Parse taskgroup clauses.
        (OMP_TASKLOOP_CLAUSE_MASK): Add reduction and in_reduction clauses.
        (c_parser_omp_taskloop): Don't mask off PRAGMA_OMP_CLAUSE_REDUCTION.
        (c_parser_omp_construct): Adjust c_parser_omp_taskgroup caller.
        (c_parser_cilk_all_clauses): Adjust c_parser_omp_clause_reduction
        caller.
        * c-typeck.c (handle_omp_array_sections_1): Handle
        OMP_CLAUSE_{IN,TASK}_REDUCTION like OMP_CLAUSE_REDUCTION.
        (handle_omp_array_sections): Likewise.
        (c_finish_omp_clauses): Likewise.
cp/
        * parser.c (cp_parser_omp_clause_name): Handle
        in_reduction and task_reduction clauses.
        (cp_parser_omp_var_list_no_open): Handle
        OMP_CLAUSE_IN_REDUCTION and OMP_CLAUSE_TASK_REDUCTION.
        (cp_parser_omp_clause_reduction): Add KIND argument.  Pass
        it to cp_parser_omp_var_list_no_open.
        (cp_parser_omp_clause_lastprivate): Remove unused loc argument.
        (cp_parser_oacc_all_clauses): Adjust cp_parser_omp_clause_reduction
        caller.
        (cp_parser_omp_all_clauses): Likewise.  Handle
        PRAGMA_OMP_CLAUSE_IN_REDUCTION and PRAGMA_OMP_CLAUSE_TASK_REDUCTION.
        Adjust cp_parser_omp_clause_lastprivate caller.
        (cp_parser_omp_for_loop): Handle OMP_CLAUSE_IN_REDUCTION like
        OMP_CLAUSE_REDUCTION.
        (OMP_TASK_CLAUSE_MASK): Add in_reduction clause.
        (OMP_TASKGROUP_CLAUSE_MASK): Define.
        (cp_parser_omp_taskgroup): Parse taskgroup clauses, adjust
        c_finish_omp_taskgroup caller.
        (OMP_TASKLOOP_CLAUSE_MASK): Add reduction and in_reduction clauses.
        (cp_parser_cilk_simd_all_clauses): Adjust
        cp_parser_omp_clause_reduction caller.
        * semantics.c (handle_omp_array_sections_1): Handle
        OMP_CLAUSE_{IN,TASK}_REDUCTION like OMP_CLAUSE_REDUCTION.
        (handle_omp_array_sections): Likewise.
        (finish_omp_clauses): Likewise.
        * cp-gimplify.c (cp_genericize_r): Handle OMP_CLAUSE_IN_REDUCTION
        and OMP_CLAUSE_TASK_REDUCTION.
        * pt.c (tsubst_expr): Handle clauses on OMP_TASKGROUP.

--- gcc/tree.def.jj     2017-05-24 11:33:38.199146293 +0200
+++ gcc/tree.def        2017-05-24 11:56:00.086183470 +0200
@@ -1183,6 +1183,11 @@ DEFTREECODE (OMP_CRITICAL, "omp_critical
    Operand 1: OMP_SINGLE_CLAUSES: List of clauses.  */
 DEFTREECODE (OMP_SINGLE, "omp_single", tcc_statement, 2)
 
+/* OpenMP - #pragma omp taskgroup
+   Operand 0: OMP_TASKGROUP_BODY: Taskgroup body.
+   Operand 1: OMP_SINGLE_CLAUSES: List of clauses.  */
+DEFTREECODE (OMP_TASKGROUP, "omp_taskgroup", tcc_statement, 2)
+
 /* OpenMP - #pragma omp section
    Operand 0: OMP_SECTION_BODY: Section body.  */
 DEFTREECODE (OMP_SECTION, "omp_section", tcc_statement, 1)
@@ -1191,10 +1196,6 @@ DEFTREECODE (OMP_SECTION, "omp_section",
    Operand 0: OMP_MASTER_BODY: Master section body.  */
 DEFTREECODE (OMP_MASTER, "omp_master", tcc_statement, 1)
 
-/* OpenMP - #pragma omp taskgroup
-   Operand 0: OMP_TASKGROUP_BODY: Taskgroup body.  */
-DEFTREECODE (OMP_TASKGROUP, "omp_taskgroup", tcc_statement, 1)
-
 /* OpenACC - #pragma acc cache (variable1 ... variableN)
    Operand 0: OACC_CACHE_CLAUSES: List of variables (transformed into
        OMP_CLAUSE__CACHE_ clauses).  */
--- gcc/cp/parser.c.jj  2017-05-24 11:47:22.511726226 +0200
+++ gcc/cp/parser.c     2017-05-24 11:56:00.095183356 +0200
@@ -30607,7 +30607,7 @@ cp_parser_objc_at_dynamic_declaration (c
 }
 
 
-/* OpenMP 2.5 / 3.0 / 3.1 / 4.0 parsing routines.  */
+/* OpenMP 2.5 / 3.0 / 3.1 / 4.0 / 4.5 / 5.0 parsing routines.  */
 
 /* Returns name of the next clause.
    If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
@@ -30693,7 +30693,9 @@ cp_parser_omp_clause_name (cp_parser *pa
            result = PRAGMA_OACC_CLAUSE_HOST;
          break;
        case 'i':
-         if (!strcmp ("inbranch", p))
+         if (!strcmp ("in_reduction", p))
+           result = PRAGMA_OMP_CLAUSE_IN_REDUCTION;
+         else if (!strcmp ("inbranch", p))
            result = PRAGMA_OMP_CLAUSE_INBRANCH;
          else if (!strcmp ("independent", p))
            result = PRAGMA_OACC_CLAUSE_INDEPENDENT;
@@ -30785,7 +30787,9 @@ cp_parser_omp_clause_name (cp_parser *pa
            result = PRAGMA_OMP_CLAUSE_SIMDLEN;
          break;
        case 't':
-         if (!strcmp ("taskgroup", p))
+         if (!strcmp ("task_reduction", p))
+           result = PRAGMA_OMP_CLAUSE_TASK_REDUCTION;
+         else if (!strcmp ("taskgroup", p))
            result = PRAGMA_OMP_CLAUSE_TASKGROUP;
          else if (!strcmp ("thread_limit", p))
            result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
@@ -30945,6 +30949,8 @@ cp_parser_omp_var_list_no_open (cp_parse
              /* FALLTHROUGH.  */
            case OMP_CLAUSE_DEPEND:
            case OMP_CLAUSE_REDUCTION:
+           case OMP_CLAUSE_IN_REDUCTION:
+           case OMP_CLAUSE_TASK_REDUCTION:
              while (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
                {
                  tree low_bound = NULL_TREE, length = NULL_TREE;
@@ -32054,10 +32060,15 @@ cp_parser_omp_clause_ordered (cp_parser
 
    reduction-operator:
      One of: + * - & ^ | && ||
-     id-expression  */
+     id-expression
+
+   OpenMP 5.0:
+   in_reduction ( reduction-operator : variable-list )
+   task_reduction ( reduction-operator : variable-list )  */
 
 static tree
-cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
+cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind,
+                               tree list)
 {
   enum tree_code code = ERROR_MARK;
   tree nlist, c, id = NULL_TREE;
@@ -32137,7 +32148,7 @@ cp_parser_omp_clause_reduction (cp_parse
   if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
     goto resync_fail;
 
-  nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_REDUCTION, list,
+  nlist = cp_parser_omp_var_list_no_open (parser, kind, list,
                                          NULL);
   for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
     {
@@ -32463,7 +32474,7 @@ cp_parser_omp_clause_aligned (cp_parser
    lastprivate ( [ lastprivate-modifier : ] variable-list )  */
 
 static tree
-cp_parser_omp_clause_lastprivate (cp_parser *parser, tree list, location_t loc)
+cp_parser_omp_clause_lastprivate (cp_parser *parser, tree list)
 {
   bool conditional = false;
 
@@ -33216,7 +33227,9 @@ cp_parser_oacc_all_clauses (cp_parser *p
          c_name = "private";
          break;
        case PRAGMA_OACC_CLAUSE_REDUCTION:
-         clauses = cp_parser_omp_clause_reduction (parser, clauses);
+         clauses
+           = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
+                                             clauses);
          c_name = "reduction";
          break;
        case PRAGMA_OACC_CLAUSE_SELF:
@@ -33367,9 +33380,14 @@ cp_parser_omp_all_clauses (cp_parser *pa
                                             true);
          c_name = "if";
          break;
+       case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
+         clauses
+           = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION,
+                                             clauses);
+         c_name = "in_reduction";
+         break;
        case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
-         clauses = cp_parser_omp_clause_lastprivate (parser, clauses,
-                                                     token->location);
+         clauses = cp_parser_omp_clause_lastprivate (parser, clauses);
          c_name = "lastprivate";
          break;
        case PRAGMA_OMP_CLAUSE_MERGEABLE:
@@ -33407,7 +33425,9 @@ cp_parser_omp_all_clauses (cp_parser *pa
          c_name = "private";
          break;
        case PRAGMA_OMP_CLAUSE_REDUCTION:
-         clauses = cp_parser_omp_clause_reduction (parser, clauses);
+         clauses
+           = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
+                                             clauses);
          c_name = "reduction";
          break;
        case PRAGMA_OMP_CLAUSE_SCHEDULE:
@@ -33420,6 +33440,13 @@ cp_parser_omp_all_clauses (cp_parser *pa
                                            clauses);
          c_name = "shared";
          break;
+       case PRAGMA_OMP_CLAUSE_TASK_REDUCTION:
+         clauses
+           = cp_parser_omp_clause_reduction (parser,
+                                             OMP_CLAUSE_TASK_REDUCTION,
+                                             clauses);
+         c_name = "task_reduction";
+         break;
        case PRAGMA_OMP_CLAUSE_UNTIED:
          clauses = cp_parser_omp_clause_untied (parser, clauses,
                                                 token->location);
@@ -34694,7 +34721,8 @@ cp_parser_omp_for_loop (cp_parser *parse
                error_at (loc, "iteration variable %qD "
                          "should not be firstprivate",
                          decl);
-             else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+             else if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                       || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
                       && OMP_CLAUSE_DECL (c) == decl)
                error_at (loc, "iteration variable %qD should not be reduction",
                          decl);
@@ -35340,7 +35368,8 @@ cp_parser_omp_single (cp_parser *parser,
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL)        \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE)    \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)       \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY))
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY)     \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
 
 static tree
 cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
@@ -35379,15 +35408,24 @@ cp_parser_omp_taskyield (cp_parser *pars
 
 /* OpenMP 4.0:
    # pragma omp taskgroup new-line
-     structured-block  */
+     structured-block
+
+   OpenMP 5.0:
+   # pragma omp taskgroup taskgroup-clause[optseq] new-line  */
+
+#define OMP_TASKGROUP_CLAUSE_MASK                              \
+       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
 
 static tree
 cp_parser_omp_taskgroup (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
 {
-  cp_parser_require_pragma_eol (parser, pragma_tok);
+  tree clauses
+    = cp_parser_omp_all_clauses (parser, OMP_TASKGROUP_CLAUSE_MASK,
+                                "#pragma omp taskgroup", pragma_tok);
   return c_finish_omp_taskgroup (input_location,
                                 cp_parser_omp_structured_block (parser,
-                                                                if_p));
+                                                                if_p),
+                                clauses);
 }
 
 
@@ -37414,7 +37452,9 @@ cp_parser_omp_declare (cp_parser *parser
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL)        \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE)    \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)      \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY))
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY)     \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION)    \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
 
 static tree
 cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
@@ -38784,7 +38824,8 @@ cp_parser_cilk_simd_all_clauses (cp_pars
                                          clauses);
       else if (c_kind == PRAGMA_CILK_CLAUSE_REDUCTION)
        /* Use the OMP 4.0 equivalent function.  */
-       clauses = cp_parser_omp_clause_reduction (parser, clauses);
+       clauses = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
+                                                 clauses);
       else
        {
          clauses = error_mark_node;
--- gcc/cp/semantics.c.jj       2017-05-24 11:47:20.602750358 +0200
+++ gcc/cp/semantics.c  2017-05-24 11:56:00.097183331 +0200
@@ -4591,7 +4591,9 @@ handle_omp_array_sections_1 (tree c, tre
     }
 
   if (ort == C_ORT_OMP
-      && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+      && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+         || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+         || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
       && TREE_CODE (TREE_CHAIN (t)) == FIELD_DECL)
     TREE_CHAIN (t) = omp_privatize_field (TREE_CHAIN (t), false);
   ret = handle_omp_array_sections_1 (c, TREE_CHAIN (t), types,
@@ -4650,7 +4652,9 @@ handle_omp_array_sections_1 (tree c, tre
       if (!integer_nonzerop (length))
        {
          if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
-             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
            {
              if (integer_zerop (length))
                {
@@ -4716,7 +4720,9 @@ handle_omp_array_sections_1 (tree c, tre
              if (tree_int_cst_equal (size, low_bound))
                {
                  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
-                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
                    {
                      error_at (OMP_CLAUSE_LOCATION (c),
                                "zero length array section in %qs clause",
@@ -4735,7 +4741,9 @@ handle_omp_array_sections_1 (tree c, tre
          else if (length == NULL_TREE)
            {
              if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
-                 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
+                 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
+                 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION
+                 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION)
                maybe_zero_len = true;
              if (first_non_one == types.length ())
                first_non_one++;
@@ -4771,7 +4779,9 @@ handle_omp_array_sections_1 (tree c, tre
       else if (length == NULL_TREE)
        {
          if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
-             && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
+             && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
+             && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION
+             && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION)
            maybe_zero_len = true;
          if (first_non_one == types.length ())
            first_non_one++;
@@ -4949,7 +4959,9 @@ handle_omp_array_sections (tree c, enum
 
              if (i > first_non_one
                  && ((length && integer_nonzerop (length))
-                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION))
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION))
                continue;
              if (length)
                l = fold_convert (sizetype, length);
@@ -4977,7 +4989,9 @@ handle_omp_array_sections (tree c, enum
                  tree eltype = TREE_TYPE (types[num - 1]);
                  while (TREE_CODE (eltype) == ARRAY_TYPE)
                    eltype = TREE_TYPE (eltype);
-                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
                    size = size_binop (EXACT_DIV_EXPR, size,
                                       size_in_bytes (eltype));
                  size = size_binop (MULT_EXPR, size, l);
@@ -4993,7 +5007,9 @@ handle_omp_array_sections (tree c, enum
        {
          if (side_effects)
            size = build2 (COMPOUND_EXPR, sizetype, side_effects, size);
-         if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+         if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
            {
              size = size_binop (MINUS_EXPR, size, size_one_node);
              tree index_type = build_index_type (size);
@@ -5869,6 +5885,8 @@ finish_omp_clauses (tree clauses, enum c
          field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
          goto check_dup_generic;
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
          t = OMP_CLAUSE_DECL (c);
          if (TREE_CODE (t) == TREE_LIST)
@@ -7208,6 +7226,8 @@ finish_omp_clauses (tree clauses, enum c
          need_implicitly_determined = true;
          break;
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          need_implicitly_determined = true;
          break;
        case OMP_CLAUSE_LINEAR:
@@ -7294,6 +7314,8 @@ finish_omp_clauses (tree clauses, enum c
          break;
 
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          if (finish_omp_reduction_clause (c, &need_default_ctor,
                                           &need_dtor))
            remove = true;
@@ -7358,7 +7380,9 @@ finish_omp_clauses (tree clauses, enum c
       inner_type = type = TREE_TYPE (t);
       if ((need_complete_type
           || need_copy_assignment
-          || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+          || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+          || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+          || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
          && TREE_CODE (inner_type) == REFERENCE_TYPE)
        inner_type = TREE_TYPE (inner_type);
       while (TREE_CODE (inner_type) == ARRAY_TYPE)
--- gcc/cp/cp-gimplify.c.jj     2017-05-24 11:47:18.921771608 +0200
+++ gcc/cp/cp-gimplify.c        2017-05-24 11:56:00.098183318 +0200
@@ -1171,6 +1171,8 @@ cp_genericize_r (tree *stmt_p, int *walk
          *walk_subtrees = 0;
        break;
       case OMP_CLAUSE_REDUCTION:
+      case OMP_CLAUSE_IN_REDUCTION:
+      case OMP_CLAUSE_TASK_REDUCTION:
        /* Don't dereference an invisiref in reduction clause's
           OMP_CLAUSE_DECL either.  OMP_CLAUSE_REDUCTION_{INIT,MERGE}
           still needs to be genericized.  */
--- gcc/cp/pt.c.jj      2017-05-24 11:47:20.243754896 +0200
+++ gcc/cp/pt.c 2017-05-24 11:56:00.103183255 +0200
@@ -16267,6 +16267,7 @@ tsubst_expr (tree t, tree args, tsubst_f
     case OMP_SINGLE:
     case OMP_TEAMS:
     case OMP_CRITICAL:
+    case OMP_TASKGROUP:
       r = push_omp_privatization_clauses (TREE_CODE (t) == OMP_TEAMS
                                          && OMP_TEAMS_COMBINED (t));
       tmp = tsubst_omp_clauses (OMP_CLAUSES (t), C_ORT_OMP, args, complain,
@@ -16373,7 +16374,6 @@ tsubst_expr (tree t, tree args, tsubst_f
 
     case OMP_SECTION:
     case OMP_MASTER:
-    case OMP_TASKGROUP:
       stmt = push_stmt_list ();
       RECUR (OMP_BODY (t));
       stmt = pop_stmt_list (stmt);
--- gcc/gimple-pretty-print.c.jj        2017-05-24 11:47:44.905443143 +0200
+++ gcc/gimple-pretty-print.c   2017-05-24 11:56:00.104183242 +0200
@@ -1544,6 +1544,35 @@ dump_gimple_omp_single (pretty_printer *
     }
 }
 
+/* Dump a GIMPLE_OMP_TASKGROUP tuple on the pretty_printer BUFFER.  */
+
+static void
+dump_gimple_omp_taskgroup (pretty_printer *buffer, gimple *gs,
+                          int spc, int flags)
+{
+  if (flags & TDF_RAW)
+    {
+      dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S>%nCLAUSES <", gs,
+                      gimple_omp_body (gs));
+      dump_omp_clauses (buffer, gimple_omp_taskgroup_clauses (gs), spc, flags);
+      dump_gimple_fmt (buffer, spc, flags, " >");
+    }
+  else
+    {
+      pp_string (buffer, "#pragma omp taskgroup");
+      dump_omp_clauses (buffer, gimple_omp_taskgroup_clauses (gs), spc, flags);
+      if (!gimple_seq_empty_p (gimple_omp_body (gs)))
+       {
+         newline_and_indent (buffer, spc + 2);
+         pp_left_brace (buffer);
+         pp_newline (buffer);
+         dump_gimple_seq (buffer, gimple_omp_body (gs), spc + 4, flags);
+         newline_and_indent (buffer, spc + 2);
+         pp_right_brace (buffer);
+       }
+    }
+}
+
 /* Dump a GIMPLE_OMP_TARGET tuple on the pretty_printer BUFFER.  */
 
 static void
@@ -1702,7 +1731,7 @@ dump_gimple_omp_sections (pretty_printer
     }
 }
 
-/* Dump a GIMPLE_OMP_{MASTER,TASKGROUP,ORDERED,SECTION} tuple on the
+/* Dump a GIMPLE_OMP_{MASTER,ORDERED,SECTION} tuple on the
    pretty_printer BUFFER.  */
 
 static void
@@ -2559,8 +2588,11 @@ pp_gimple_stmt_1 (pretty_printer *buffer
       pp_string (buffer, "GIMPLE_SECTIONS_SWITCH");
       break;
 
-    case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_TASKGROUP:
+      dump_gimple_omp_taskgroup (buffer, gs, spc, flags);
+      break;
+
+    case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_GRID_BODY:
       dump_gimple_omp_block (buffer, gs, spc, flags);
--- gcc/gimple.h.jj     2017-05-24 11:33:38.378144030 +0200
+++ gcc/gimple.h        2017-05-24 11:56:00.105183229 +0200
@@ -738,7 +738,8 @@ struct GTY((tag("GSS_OMP_CONTINUE")))
   tree control_use;
 };
 
-/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_TEAMS, GIMPLE_OMP_ORDERED */
+/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_TEAMS, GIMPLE_OMP_ORDERED,
+   GIMPLE_OMP_TASKGROUP.  */
 
 struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
   gimple_statement_omp_single_layout : public gimple_statement_omp
@@ -1467,7 +1468,7 @@ gomp_task *gimple_build_omp_task (gimple
 gimple *gimple_build_omp_section (gimple_seq);
 gimple *gimple_build_omp_master (gimple_seq);
 gimple *gimple_build_omp_grid_body (gimple_seq);
-gimple *gimple_build_omp_taskgroup (gimple_seq);
+gimple *gimple_build_omp_taskgroup (gimple_seq, tree);
 gomp_continue *gimple_build_omp_continue (tree, tree);
 gomp_ordered *gimple_build_omp_ordered (gimple_seq, tree);
 gimple *gimple_build_omp_return (bool);
@@ -4848,6 +4849,40 @@ gimple_omp_ordered_set_clauses (gomp_ord
 }
 
 
+/* Return the clauses associated with OMP_TASKGROUP statement GS.  */
+
+static inline tree
+gimple_omp_taskgroup_clauses (const gimple *gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_OMP_TASKGROUP);
+  return
+    static_cast <const gimple_statement_omp_single_layout *> (gs)->clauses;
+}
+
+
+/* Return a pointer to the clauses associated with OMP taskgroup statement
+   GS.  */
+
+static inline tree *
+gimple_omp_taskgroup_clauses_ptr (gimple *gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_OMP_TASKGROUP);
+  return &static_cast <gimple_statement_omp_single_layout *> (gs)->clauses;
+}
+
+
+/* Set CLAUSES to be the clauses associated with OMP taskgroup statement
+   GS.  */
+
+static inline void
+gimple_omp_taskgroup_set_clauses (gimple *gs, tree clauses)
+{
+  GIMPLE_CHECK (gs, GIMPLE_OMP_TASKGROUP);
+  static_cast <gimple_statement_omp_single_layout *> (gs)->clauses
+    = clauses;
+}
+
+
 /* Return the kind of the OMP_FOR statemement G.  */
 
 static inline int
--- gcc/tree.h.jj       2017-05-24 11:46:34.159337458 +0200
+++ gcc/tree.h  2017-05-24 11:56:00.106183217 +0200
@@ -1299,9 +1299,9 @@ extern void protected_set_expr_location
 /* Generic accessors for OMP nodes that keep the body as operand 0, and clauses
    as operand 1.  */
 #define OMP_BODY(NODE) \
-  TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_TASKGROUP), 0)
+  TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_MASTER), 0)
 #define OMP_CLAUSES(NODE) \
-  TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_SINGLE), 1)
+  TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_TASKGROUP), 1)
 
 /* Generic accessors for OMP nodes that keep clauses as operand 0.  */
 #define OMP_STANDALONE_CLAUSES(NODE) \
@@ -1362,6 +1362,8 @@ extern void protected_set_expr_location
 #define OMP_MASTER_BODY(NODE)     TREE_OPERAND (OMP_MASTER_CHECK (NODE), 0)
 
 #define OMP_TASKGROUP_BODY(NODE)   TREE_OPERAND (OMP_TASKGROUP_CHECK (NODE), 0)
+#define OMP_TASKGROUP_CLAUSES(NODE) \
+  TREE_OPERAND (OMP_TASKGROUP_CHECK (NODE), 1)
 
 #define OMP_ORDERED_BODY(NODE)    TREE_OPERAND (OMP_ORDERED_CHECK (NODE), 0)
 #define OMP_ORDERED_CLAUSES(NODE)  TREE_OPERAND (OMP_ORDERED_CHECK (NODE), 1)
@@ -1576,24 +1578,30 @@ extern void protected_set_expr_location
   OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDERED), 0)
 
 #define OMP_CLAUSE_REDUCTION_CODE(NODE)        \
-  (OMP_CLAUSE_SUBCODE_CHECK (NODE, 
OMP_CLAUSE_REDUCTION)->omp_clause.subcode.reduction_code)
+  (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \
+     OMP_CLAUSE_IN_REDUCTION)->omp_clause.subcode.reduction_code)
 #define OMP_CLAUSE_REDUCTION_INIT(NODE) \
-  OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION), 1)
+  OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \
+                                             OMP_CLAUSE_IN_REDUCTION), 1)
 #define OMP_CLAUSE_REDUCTION_MERGE(NODE) \
-  OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION), 2)
+  OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \
+                                             OMP_CLAUSE_IN_REDUCTION), 2)
 #define OMP_CLAUSE_REDUCTION_GIMPLE_INIT(NODE) \
   (OMP_CLAUSE_CHECK (NODE))->omp_clause.gimple_reduction_init
 #define OMP_CLAUSE_REDUCTION_GIMPLE_MERGE(NODE) \
   (OMP_CLAUSE_CHECK (NODE))->omp_clause.gimple_reduction_merge
 #define OMP_CLAUSE_REDUCTION_PLACEHOLDER(NODE) \
-  OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION), 3)
+  OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \
+                                             OMP_CLAUSE_IN_REDUCTION), 3)
 #define OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER(NODE) \
-  OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION), 4)
+  OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \
+                                             OMP_CLAUSE_IN_REDUCTION), 4)
 
 /* True if a REDUCTION clause may reference the original list item (omp_orig)
    in its OMP_CLAUSE_REDUCTION_{,GIMPLE_}INIT.  */
 #define OMP_CLAUSE_REDUCTION_OMP_ORIG_REF(NODE) \
-  (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION)->base.public_flag)
+  (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \
+                          OMP_CLAUSE_IN_REDUCTION)->base.public_flag)
 
 /* True if a LINEAR clause doesn't need copy in.  True for iterator vars which
    are always initialized inside of the loop construct, false otherwise.  */
--- gcc/tree-pretty-print.c.jj  2017-05-24 11:46:27.181425667 +0200
+++ gcc/tree-pretty-print.c     2017-05-24 11:56:00.107183204 +0200
@@ -428,6 +428,11 @@ dump_omp_clause (pretty_printer *pp, tre
       pp_right_paren (pp);
       break;
 
+    case OMP_CLAUSE_TASK_REDUCTION:
+    case OMP_CLAUSE_IN_REDUCTION:
+      pp_string (pp, OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_IN_REDUCTION
+                    ? "in_" : "task_");
+      /* FALLTHRU */
     case OMP_CLAUSE_REDUCTION:
       pp_string (pp, "reduction(");
       if (OMP_CLAUSE_REDUCTION_CODE (clause) != ERROR_MARK)
@@ -3130,6 +3135,7 @@ dump_generic_node (pretty_printer *pp, t
 
     case OMP_TASKGROUP:
       pp_string (pp, "#pragma omp taskgroup");
+      dump_omp_clauses (pp, OMP_TASKGROUP_CLAUSES (node), spc, flags);
       goto dump_omp_body;
 
     case OMP_ORDERED:
--- gcc/gimple.def.jj   2017-05-24 11:33:38.031148416 +0200
+++ gcc/gimple.def      2017-05-24 11:56:00.107183204 +0200
@@ -279,9 +279,10 @@ DEFGSCODE(GIMPLE_OMP_FOR, "gimple_omp_fo
    BODY is the sequence of statements to execute in the master section.  */
 DEFGSCODE(GIMPLE_OMP_MASTER, "gimple_omp_master", GSS_OMP)
 
-/* GIMPLE_OMP_TASKGROUP <BODY> represents #pragma omp taskgroup.
-   BODY is the sequence of statements to execute in the taskgroup section.  */
-DEFGSCODE(GIMPLE_OMP_TASKGROUP, "gimple_omp_taskgroup", GSS_OMP)
+/* GIMPLE_OMP_TASKGROUP <BODY, CLAUSES> represents #pragma omp taskgroup.
+   BODY is the sequence of statements inside the taskgroup section.
+   CLAUSES is an OMP_CLAUSE chain holding the associated clauses.  */
+DEFGSCODE(GIMPLE_OMP_TASKGROUP, "gimple_omp_taskgroup", GSS_OMP_SINGLE_LAYOUT)
 
 /* GIMPLE_OMP_PARALLEL <BODY, CLAUSES, CHILD_FN, DATA_ARG> represents
 
--- gcc/c/c-parser.c.jj 2017-05-24 11:46:31.022377113 +0200
+++ gcc/c/c-parser.c    2017-05-24 11:56:00.111183154 +0200
@@ -10515,7 +10515,9 @@ c_parser_omp_clause_name (c_parser *pars
            result = PRAGMA_OACC_CLAUSE_HOST;
          break;
        case 'i':
-         if (!strcmp ("inbranch", p))
+         if (!strcmp ("in_reduction", p))
+           result = PRAGMA_OMP_CLAUSE_IN_REDUCTION;
+         else if (!strcmp ("inbranch", p))
            result = PRAGMA_OMP_CLAUSE_INBRANCH;
          else if (!strcmp ("independent", p))
            result = PRAGMA_OACC_CLAUSE_INDEPENDENT;
@@ -10609,7 +10611,9 @@ c_parser_omp_clause_name (c_parser *pars
            result = PRAGMA_OACC_CLAUSE_SELF;
          break;
        case 't':
-         if (!strcmp ("taskgroup", p))
+         if (!strcmp ("task_reduction", p))
+           result = PRAGMA_OMP_CLAUSE_TASK_REDUCTION;
+         else if (!strcmp ("taskgroup", p))
            result = PRAGMA_OMP_CLAUSE_TASKGROUP;
          else if (!strcmp ("thread_limit", p))
            result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
@@ -10868,6 +10872,8 @@ c_parser_omp_variable_list (c_parser *pa
              /* FALLTHROUGH  */
            case OMP_CLAUSE_DEPEND:
            case OMP_CLAUSE_REDUCTION:
+           case OMP_CLAUSE_IN_REDUCTION:
+           case OMP_CLAUSE_TASK_REDUCTION:
              while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
                {
                  tree low_bound = NULL_TREE, length = NULL_TREE;
@@ -12164,10 +12170,15 @@ c_parser_omp_clause_private (c_parser *p
 
    reduction-operator:
      One of: + * - & ^ | && ||
-     identifier  */
+     identifier
+
+   OpenMP 5.0:
+   in_reduction ( reduction-operator : variable-list )
+   task_reduction ( reduction-operator : variable-list )  */
 
 static tree
-c_parser_omp_clause_reduction (c_parser *parser, tree list)
+c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
+                              tree list)
 {
   location_t clause_loc = c_parser_peek_token (parser)->location;
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
@@ -12231,8 +12242,7 @@ c_parser_omp_clause_reduction (c_parser
        {
          tree nl, c;
 
-         nl = c_parser_omp_variable_list (parser, clause_loc,
-                                          OMP_CLAUSE_REDUCTION, list);
+         nl = c_parser_omp_variable_list (parser, clause_loc, kind, list);
          for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
            {
              tree d = OMP_CLAUSE_DECL (c), type;
@@ -13374,7 +13384,9 @@ c_parser_oacc_all_clauses (c_parser *par
          c_name = "private";
          break;
        case PRAGMA_OACC_CLAUSE_REDUCTION:
-         clauses = c_parser_omp_clause_reduction (parser, clauses);
+         clauses
+           = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
+                                            clauses);
          c_name = "reduction";
          break;
        case PRAGMA_OACC_CLAUSE_SELF:
@@ -13504,6 +13516,12 @@ c_parser_omp_all_clauses (c_parser *pars
          clauses = c_parser_omp_clause_if (parser, clauses, true);
          c_name = "if";
          break;
+       case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
+         clauses
+           = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION,
+                                            clauses);
+         c_name = "in_reduction";
+         break;
        case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
          clauses = c_parser_omp_clause_lastprivate (parser, clauses);
          c_name = "lastprivate";
@@ -13537,7 +13555,9 @@ c_parser_omp_all_clauses (c_parser *pars
          c_name = "private";
          break;
        case PRAGMA_OMP_CLAUSE_REDUCTION:
-         clauses = c_parser_omp_clause_reduction (parser, clauses);
+         clauses
+           = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
+                                            clauses);
          c_name = "reduction";
          break;
        case PRAGMA_OMP_CLAUSE_SCHEDULE:
@@ -13548,6 +13568,12 @@ c_parser_omp_all_clauses (c_parser *pars
          clauses = c_parser_omp_clause_shared (parser, clauses);
          c_name = "shared";
          break;
+       case PRAGMA_OMP_CLAUSE_TASK_REDUCTION:
+         clauses
+           = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_TASK_REDUCTION,
+                                            clauses);
+         c_name = "task_reduction";
+         break;
        case PRAGMA_OMP_CLAUSE_UNTIED:
          clauses = c_parser_omp_clause_untied (parser, clauses);
          c_name = "untied";
@@ -15817,7 +15843,8 @@ c_parser_omp_single (location_t loc, c_p
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL)        \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE)    \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)       \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY))
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY)     \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
 
 static tree
 c_parser_omp_task (location_t loc, c_parser *parser, bool *if_p)
@@ -15862,15 +15889,22 @@ c_parser_omp_taskyield (c_parser *parser
 
 /* OpenMP 4.0:
    # pragma omp taskgroup new-line
+
+   OpenMP 5.0:
+   # pragma omp taskgroup taskgroup-clause[optseq] new-line
 */
 
+#define OMP_TASKGROUP_CLAUSE_MASK                              \
+       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
+
 static tree
-c_parser_omp_taskgroup (c_parser *parser, bool *if_p)
+c_parser_omp_taskgroup (location_t loc, c_parser *parser, bool *if_p)
 {
-  location_t loc = c_parser_peek_token (parser)->location;
-  c_parser_skip_to_pragma_eol (parser);
-  return c_finish_omp_taskgroup (loc, c_parser_omp_structured_block (parser,
-                                                                    if_p));
+  tree clauses = c_parser_omp_all_clauses (parser, OMP_TASKGROUP_CLAUSE_MASK,
+                                          "#pragma omp taskgroup");
+
+  tree body = c_parser_omp_structured_block (parser, if_p);
+  return c_finish_omp_taskgroup (loc, body, clauses);
 }
 
 /* OpenMP 4.0:
@@ -17380,7 +17414,9 @@ c_parser_omp_declare (c_parser *parser,
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL)        \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE)    \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)      \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY))
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY)     \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION)    \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
 
 static tree
 c_parser_omp_taskloop (location_t loc, c_parser *parser,
@@ -17401,7 +17437,6 @@ c_parser_omp_taskloop (location_t loc, c
          tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
          if (cclauses == NULL)
            cclauses = cclauses_buf;
-         mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION);
          c_parser_consume_token (parser);
          if (!flag_openmp)  /* flag_openmp_simd  */
            return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
@@ -17521,7 +17556,7 @@ c_parser_omp_construct (c_parser *parser
       stmt = c_parser_omp_task (loc, parser, if_p);
       break;
     case PRAGMA_OMP_TASKGROUP:
-      stmt = c_parser_omp_taskgroup (parser, if_p);
+      stmt = c_parser_omp_taskgroup (loc, parser, if_p);
       break;
     case PRAGMA_OMP_TASKLOOP:
       strcpy (p_name, "#pragma omp");
@@ -17838,7 +17873,9 @@ c_parser_cilk_all_clauses (c_parser *par
          break;
        case PRAGMA_CILK_CLAUSE_REDUCTION:
          /* Use the OpenMP counterpart.  */
-         clauses = c_parser_omp_clause_reduction (parser, clauses);
+         clauses
+           = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
+                                            clauses);
          break;
        default:
          c_parser_error (parser, "expected %<#pragma simd%> clause");
--- gcc/c/c-typeck.c.jj 2017-05-24 11:46:31.399372347 +0200
+++ gcc/c/c-typeck.c    2017-05-24 11:56:00.114183116 +0200
@@ -12309,7 +12309,9 @@ handle_omp_array_sections_1 (tree c, tre
       if (!integer_nonzerop (length))
        {
          if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
-             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
            {
              if (integer_zerop (length))
                {
@@ -12375,7 +12377,9 @@ handle_omp_array_sections_1 (tree c, tre
              if (tree_int_cst_equal (size, low_bound))
                {
                  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
-                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
                    {
                      error_at (OMP_CLAUSE_LOCATION (c),
                                "zero length array section in %qs clause",
@@ -12394,7 +12398,9 @@ handle_omp_array_sections_1 (tree c, tre
          else if (length == NULL_TREE)
            {
              if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
-                 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
+                 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
+                 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION
+                 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION)
                maybe_zero_len = true;
              if (first_non_one == types.length ())
                first_non_one++;
@@ -12430,7 +12436,9 @@ handle_omp_array_sections_1 (tree c, tre
       else if (length == NULL_TREE)
        {
          if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
-             && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
+             && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
+             && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION
+             && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION)
            maybe_zero_len = true;
          if (first_non_one == types.length ())
            first_non_one++;
@@ -12602,7 +12610,9 @@ handle_omp_array_sections (tree c, enum
 
              if (i > first_non_one
                  && ((length && integer_nonzerop (length))
-                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION))
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION))
                continue;
              if (length)
                l = fold_convert (sizetype, length);
@@ -12630,7 +12640,9 @@ handle_omp_array_sections (tree c, enum
                  tree eltype = TREE_TYPE (types[num - 1]);
                  while (TREE_CODE (eltype) == ARRAY_TYPE)
                    eltype = TREE_TYPE (eltype);
-                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
                    {
                      if (integer_zerop (size)
                          || integer_zerop (size_in_bytes (eltype)))
@@ -12654,7 +12666,9 @@ handle_omp_array_sections (tree c, enum
        }
       if (side_effects)
        size = build2 (COMPOUND_EXPR, sizetype, side_effects, size);
-      if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+      if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+         || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+         || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
        {
          size = size_binop (MINUS_EXPR, size, size_one_node);
          size = c_fully_fold (size, false, NULL);
@@ -12840,6 +12854,8 @@ c_finish_omp_clauses (tree clauses, enum
          goto check_dup_generic;
 
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          need_implicitly_determined = true;
          t = OMP_CLAUSE_DECL (c);
          if (TREE_CODE (t) == TREE_LIST)
--- gcc/tree.c.jj       2017-05-24 11:46:33.961339961 +0200
+++ gcc/tree.c  2017-05-24 11:56:00.116183090 +0200
@@ -266,6 +266,8 @@ unsigned const char omp_clause_num_ops[]
   1, /* OMP_CLAUSE_FIRSTPRIVATE  */
   2, /* OMP_CLAUSE_LASTPRIVATE  */
   5, /* OMP_CLAUSE_REDUCTION  */
+  5, /* OMP_CLAUSE_TASK_REDUCTION  */
+  5, /* OMP_CLAUSE_IN_REDUCTION  */
   1, /* OMP_CLAUSE_COPYIN  */
   1, /* OMP_CLAUSE_COPYPRIVATE  */
   3, /* OMP_CLAUSE_LINEAR  */
@@ -338,6 +340,8 @@ const char * const omp_clause_code_name[
   "firstprivate",
   "lastprivate",
   "reduction",
+  "task_reduction",
+  "in_reduction",
   "copyin",
   "copyprivate",
   "linear",
@@ -12042,6 +12046,8 @@ walk_tree_1 (tree *tp, walk_tree_fn func
          WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
 
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
          {
            int i;
            for (i = 0; i < 5; i++)
--- gcc/tree-streamer-out.c.jj  2017-05-24 11:33:38.022148530 +0200
+++ gcc/tree-streamer-out.c     2017-05-24 11:56:00.116183090 +0200
@@ -395,6 +395,8 @@ pack_ts_omp_clause_value_fields (struct
                    OMP_CLAUSE_PROC_BIND_KIND (expr));
       break;
     case OMP_CLAUSE_REDUCTION:
+    case OMP_CLAUSE_TASK_REDUCTION:
+    case OMP_CLAUSE_IN_REDUCTION:
       bp_pack_enum (bp, tree_code, MAX_TREE_CODES,
                    OMP_CLAUSE_REDUCTION_CODE (expr));
       break;
@@ -852,12 +854,18 @@ write_ts_omp_clause_tree_pointers (struc
   int i;
   for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (expr)]; i++)
     stream_write_tree (ob, OMP_CLAUSE_OPERAND (expr, i), ref_p);
-  if (OMP_CLAUSE_CODE (expr) == OMP_CLAUSE_REDUCTION)
+  switch (OMP_CLAUSE_CODE (expr))
     {
+    case OMP_CLAUSE_REDUCTION:
+    case OMP_CLAUSE_TASK_REDUCTION:
+    case OMP_CLAUSE_IN_REDUCTION:
       /* We don't stream these right now, handle it if streaming
         of them is needed.  */
       gcc_assert (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (expr) == NULL);
       gcc_assert (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (expr) == NULL);
+      break;
+    default:
+      break;
     }
   stream_write_tree (ob, OMP_CLAUSE_CHAIN (expr), ref_p);
 }
--- gcc/tree-streamer-in.c.jj   2017-05-24 11:33:38.363144220 +0200
+++ gcc/tree-streamer-in.c      2017-05-24 11:56:00.117183078 +0200
@@ -445,6 +445,8 @@ unpack_ts_omp_clause_value_fields (struc
                          OMP_CLAUSE_PROC_BIND_LAST);
       break;
     case OMP_CLAUSE_REDUCTION:
+    case OMP_CLAUSE_TASK_REDUCTION:
+    case OMP_CLAUSE_IN_REDUCTION:
       OMP_CLAUSE_REDUCTION_CODE (expr)
        = bp_unpack_enum (bp, tree_code, MAX_TREE_CODES);
       break;
--- gcc/gimple.c.jj     2017-05-24 11:33:38.369144144 +0200
+++ gcc/gimple.c        2017-05-24 11:56:00.118183065 +0200
@@ -857,7 +857,7 @@ gimple_build_omp_critical (gimple_seq bo
 
    BODY is sequence of statements inside the for loop.
    KIND is the `for' variant.
-   CLAUSES, are any of the construct's clauses.
+   CLAUSES are any of the construct's clauses.
    COLLAPSE is the collapse count.
    PRE_BODY is the sequence of statements that are loop invariant.  */
 
@@ -883,7 +883,7 @@ gimple_build_omp_for (gimple_seq body, i
 /* Build a GIMPLE_OMP_PARALLEL statement.
 
    BODY is sequence of statements which are executed in parallel.
-   CLAUSES, are the OMP parallel construct's clauses.
+   CLAUSES are the OMP parallel construct's clauses.
    CHILD_FN is the function created for the parallel threads to execute.
    DATA_ARG are the shared data argument(s).  */
 
@@ -906,7 +906,7 @@ gimple_build_omp_parallel (gimple_seq bo
 /* Build a GIMPLE_OMP_TASK statement.
 
    BODY is sequence of statements which are executed by the explicit task.
-   CLAUSES, are the OMP parallel construct's clauses.
+   CLAUSES are the OMP task construct's clauses.
    CHILD_FN is the function created for the parallel threads to execute.
    DATA_ARG are the shared data argument(s).
    COPY_FN is the optional function for firstprivate initialization.
@@ -977,12 +977,14 @@ gimple_build_omp_grid_body (gimple_seq b
 /* Build a GIMPLE_OMP_TASKGROUP statement.
 
    BODY is the sequence of statements to be executed by the taskgroup
-   construct.  */
+   construct.
+   CLAUSES are any of the construct's clauses.  */
 
 gimple *
-gimple_build_omp_taskgroup (gimple_seq body)
+gimple_build_omp_taskgroup (gimple_seq body, tree clauses)
 {
   gimple *p = gimple_alloc (GIMPLE_OMP_TASKGROUP, 0);
+  gimple_omp_taskgroup_set_clauses (p, clauses);
   if (body)
     gimple_omp_set_body (p, body);
 
@@ -1817,6 +1819,11 @@ gimple_copy (gimple *stmt)
          gimple_omp_ordered_set_clauses (as_a <gomp_ordered *> (copy), t);
          goto copy_omp_body;
 
+       case GIMPLE_OMP_TASKGROUP:
+         t = unshare_expr (gimple_omp_taskgroup_clauses (stmt));
+         gimple_omp_taskgroup_set_clauses (copy, t);
+         goto copy_omp_body;
+
        case GIMPLE_OMP_SECTIONS:
          t = unshare_expr (gimple_omp_sections_clauses (stmt));
          gimple_omp_sections_set_clauses (copy, t);
@@ -1829,7 +1836,6 @@ gimple_copy (gimple *stmt)
        case GIMPLE_OMP_TEAMS:
        case GIMPLE_OMP_SECTION:
        case GIMPLE_OMP_MASTER:
-       case GIMPLE_OMP_TASKGROUP:
        case GIMPLE_OMP_GRID_BODY:
        copy_omp_body:
          new_seq = gimple_seq_copy (gimple_omp_body (stmt));
--- gcc/c-family/c-common.h.jj  2017-05-24 11:46:28.793405290 +0200
+++ gcc/c-family/c-common.h     2017-05-24 11:56:00.118183065 +0200
@@ -1280,7 +1280,7 @@ enum c_omp_region_type
 };
 
 extern tree c_finish_omp_master (location_t, tree);
-extern tree c_finish_omp_taskgroup (location_t, tree);
+extern tree c_finish_omp_taskgroup (location_t, tree, tree);
 extern tree c_finish_omp_critical (location_t, tree, tree, tree);
 extern tree c_finish_omp_ordered (location_t, tree, tree);
 extern void c_finish_omp_barrier (location_t);
--- gcc/c-family/c-omp.c.jj     2017-05-24 11:33:37.966149238 +0200
+++ gcc/c-family/c-omp.c        2017-05-24 11:56:00.119183052 +0200
@@ -70,7 +70,7 @@ c_finish_oacc_wait (location_t loc, tree
 }
 
 /* Complete a #pragma omp master construct.  STMT is the structured-block
-   that follows the pragma.  LOC is the l*/
+   that follows the pragma.  LOC is the location of the #pragma.  */
 
 tree
 c_finish_omp_master (location_t loc, tree stmt)
@@ -80,18 +80,21 @@ c_finish_omp_master (location_t loc, tre
   return t;
 }
 
-/* Complete a #pragma omp taskgroup construct.  STMT is the structured-block
-   that follows the pragma.  LOC is the l*/
+/* Complete a #pragma omp taskgroup construct.  BODY is the structured-block
+   that follows the pragma.  LOC is the location of the #pragma.  */
 
 tree
-c_finish_omp_taskgroup (location_t loc, tree stmt)
+c_finish_omp_taskgroup (location_t loc, tree body, tree clauses)
 {
-  tree t = add_stmt (build1 (OMP_TASKGROUP, void_type_node, stmt));
-  SET_EXPR_LOCATION (t, loc);
-  return t;
+  tree stmt = make_node (OMP_TASKGROUP);
+  TREE_TYPE (stmt) = void_type_node;
+  OMP_TASKGROUP_BODY (stmt) = body;
+  OMP_TASKGROUP_CLAUSES (stmt) = clauses;
+  SET_EXPR_LOCATION (stmt, loc);
+  return add_stmt (stmt);
 }
 
-/* Complete a #pragma omp critical construct.  STMT is the structured-block
+/* Complete a #pragma omp critical construct.  BODY is the structured-block
    that follows the pragma, NAME is the identifier in the pragma, or null
    if it was omitted.  LOC is the location of the #pragma.  */
 
@@ -1031,6 +1034,7 @@ c_omp_split_clauses (location_t loc, enu
        case OMP_CLAUSE_MERGEABLE:
        case OMP_CLAUSE_NOGROUP:
        case OMP_CLAUSE_PRIORITY:
+       case OMP_CLAUSE_IN_REDUCTION:
          s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
          break;
        /* Duplicate this to all of taskloop, distribute, for and simd.  */
@@ -1298,7 +1302,24 @@ c_omp_split_clauses (location_t loc, enu
          else if (code == OMP_SECTIONS || code == OMP_PARALLEL)
            s = C_OMP_CLAUSE_SPLIT_PARALLEL;
          else if (code == OMP_SIMD)
-           s = C_OMP_CLAUSE_SPLIT_SIMD;
+           {
+             if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
+                 != 0)
+               {
+                 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+                                       OMP_CLAUSE_REDUCTION);
+                 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
+                 OMP_CLAUSE_REDUCTION_CODE (c)
+                   = OMP_CLAUSE_REDUCTION_CODE (clauses);
+                 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
+                   = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
+                 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
+                   = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
+                 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
+                 cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
+               }
+             s = C_OMP_CLAUSE_SPLIT_SIMD;
+           }
          else
            s = C_OMP_CLAUSE_SPLIT_TEAMS;
          break;
--- gcc/c-family/c-pragma.h.jj  2017-05-24 11:33:37.988148960 +0200
+++ gcc/c-family/c-pragma.h     2017-05-24 11:56:00.119183052 +0200
@@ -80,8 +80,8 @@ enum pragma_kind {
 };
 
 
-/* All clauses defined by OpenACC 2.0, and OpenMP 2.5, 3.0, 3.1, 4.0 and 4.5.
-   Used internally by both C and C++ parsers.  */
+/* All clauses defined by OpenACC 2.0, and OpenMP 2.5, 3.0, 3.1, 4.0, 4.5
+   and 5.0.  Used internally by both C and C++ parsers.  */
 enum pragma_omp_clause {
   PRAGMA_OMP_CLAUSE_NONE = 0,
 
@@ -101,6 +101,7 @@ enum pragma_omp_clause {
   PRAGMA_OMP_CLAUSE_GRAINSIZE,
   PRAGMA_OMP_CLAUSE_HINT,
   PRAGMA_OMP_CLAUSE_IF,
+  PRAGMA_OMP_CLAUSE_IN_REDUCTION,
   PRAGMA_OMP_CLAUSE_INBRANCH,
   PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR,
   PRAGMA_OMP_CLAUSE_LASTPRIVATE,
@@ -126,6 +127,7 @@ enum pragma_omp_clause {
   PRAGMA_OMP_CLAUSE_SHARED,
   PRAGMA_OMP_CLAUSE_SIMD,
   PRAGMA_OMP_CLAUSE_SIMDLEN,
+  PRAGMA_OMP_CLAUSE_TASK_REDUCTION,
   PRAGMA_OMP_CLAUSE_TASKGROUP,
   PRAGMA_OMP_CLAUSE_THREAD_LIMIT,
   PRAGMA_OMP_CLAUSE_THREADS,
--- gcc/omp-low.c.jj    2017-05-24 11:46:38.000000000 +0200
+++ gcc/omp-low.c       2017-05-24 15:16:02.939448638 +0200
@@ -1053,9 +1053,9 @@ scan_sharing_clauses (tree clauses, omp_
          goto do_private;
 
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
          decl = OMP_CLAUSE_DECL (c);
-         if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
-             && TREE_CODE (decl) == MEM_REF)
+         if (TREE_CODE (decl) == MEM_REF)
            {
              tree t = TREE_OPERAND (decl, 0);
              if (TREE_CODE (t) == POINTER_PLUS_EXPR)
@@ -1382,6 +1382,7 @@ scan_sharing_clauses (tree clauses, omp_
          break;
 
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
          decl = OMP_CLAUSE_DECL (c);
          if (TREE_CODE (decl) != MEM_REF)
            {
@@ -1510,7 +1511,9 @@ scan_sharing_clauses (tree clauses, omp_
   if (scan_array_reductions)
     {
       for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
-       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+       if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+            || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+            || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
            && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
          {
            scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
@@ -2196,7 +2199,7 @@ scan_omp_for (gomp_for *stmt, omp_contex
 
       if (tgt && is_oacc_kernels (tgt))
        {
-         /* Strip out reductions, as they are not  handled yet.  */
+         /* Strip out reductions, as they are not handled yet.  */
          tree *prev_ptr = &clauses;
 
          while (tree probe = *prev_ptr)
@@ -3616,6 +3619,7 @@ lower_rec_input_clauses (tree clauses, g
            sctx.max_vf = 1;
          break;
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
          if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
              || is_variable_sized (OMP_CLAUSE_DECL (c)))
            sctx.max_vf = 1;
@@ -3666,6 +3670,7 @@ lower_rec_input_clauses (tree clauses, g
                lastprivate_firstprivate = true;
              break;
            case OMP_CLAUSE_REDUCTION:
+           case OMP_CLAUSE_IN_REDUCTION:
              if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
                reduction_omp_orig_ref = true;
              break;
@@ -3732,7 +3737,9 @@ lower_rec_input_clauses (tree clauses, g
            }
 
          new_var = var = OMP_CLAUSE_DECL (c);
-         if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
+         if ((c_kind == OMP_CLAUSE_REDUCTION
+              || c_kind == OMP_CLAUSE_IN_REDUCTION)
+             && TREE_CODE (var) == MEM_REF)
            {
              var = TREE_OPERAND (var, 0);
              if (TREE_CODE (var) == POINTER_PLUS_EXPR)
@@ -3759,7 +3766,8 @@ lower_rec_input_clauses (tree clauses, g
                continue;
            }
          /* C/C++ array section reductions.  */
-         else if (c_kind == OMP_CLAUSE_REDUCTION
+         else if ((c_kind == OMP_CLAUSE_REDUCTION
+                   || c_kind == OMP_CLAUSE_IN_REDUCTION)
                   && var != OMP_CLAUSE_DECL (c))
            {
              if (pass == 0)
@@ -4111,7 +4119,8 @@ lower_rec_input_clauses (tree clauses, g
 
              new_var = build_simple_mem_ref_loc (clause_loc, new_var);
            }
-         else if (c_kind == OMP_CLAUSE_REDUCTION
+         else if ((c_kind == OMP_CLAUSE_REDUCTION
+                   || c_kind == OMP_CLAUSE_IN_REDUCTION)
                   && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
            {
              if (pass == 0)
@@ -4346,6 +4355,7 @@ lower_rec_input_clauses (tree clauses, g
              break;
 
            case OMP_CLAUSE_REDUCTION:
+           case OMP_CLAUSE_IN_REDUCTION:
              /* OpenACC reductions are initialized using the
                 GOACC_REDUCTION internal function.  */
              if (is_gimple_omp_oacc (ctx->stmt))
--- gcc/lto-streamer-out.c.jj   2017-05-24 11:33:38.108147443 +0200
+++ gcc/lto-streamer-out.c      2017-05-24 11:56:00.120183040 +0200
@@ -1346,6 +1346,8 @@ hash_tree (struct streamer_tree_cache_d
          val = OMP_CLAUSE_PROC_BIND_KIND (t);
          break;
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
          val = OMP_CLAUSE_REDUCTION_CODE (t);
          break;
        default:
--- gcc/tree-core.h.jj  2017-05-24 11:48:23.287957942 +0200
+++ gcc/tree-core.h     2017-05-24 11:56:00.120183040 +0200
@@ -269,6 +269,12 @@ enum omp_clause_code {
                reductions.  */
   OMP_CLAUSE_REDUCTION,
 
+  /* OpenMP clause: task_reduction (operator:variable_list).  */
+  OMP_CLAUSE_TASK_REDUCTION,
+
+  /* OpenMP clause: in_reduction (operator:variable_list).  */
+  OMP_CLAUSE_IN_REDUCTION,
+
   /* OpenMP clause: copyin (variable_list).  */
   OMP_CLAUSE_COPYIN,
 
@@ -1086,7 +1092,7 @@ struct GTY(()) tree_base {
           OMP_CLAUSE_MAP
 
        OMP_CLAUSE_REDUCTION_OMP_ORIG_REF in
-          OMP_CLAUSE_REDUCTION
+          OMP_CLAUSE_{,TASK_,IN_}REDUCTION
 
        TRANSACTION_EXPR_RELAXED in
           TRANSACTION_EXPR
--- gcc/gimplify.c.jj   2017-05-24 11:47:49.536384602 +0200
+++ gcc/gimplify.c      2017-05-24 14:45:26.612050315 +0200
@@ -7550,10 +7550,14 @@ gimplify_scan_omp_clauses (tree *list_p,
            }
          goto do_add;
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          flags = GOVD_REDUCTION | GOVD_SEEN | GOVD_EXPLICIT;
          /* OpenACC permits reductions on private variables.  */
-         if (!(region_type & ORT_ACC))
-           check_non_private = "reduction";
+         if (!(region_type & ORT_ACC)
+             /* taskgroup is actually not a worksharing region.  */
+             && code != OMP_TASKGROUP)
+           check_non_private = omp_clause_code_name[OMP_CLAUSE_CODE (c)];
          decl = OMP_CLAUSE_DECL (c);
          if (TREE_CODE (decl) == MEM_REF)
            {
@@ -8239,7 +8243,9 @@ gimplify_scan_omp_clauses (tree *list_p,
              && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
            flags |= GOVD_MAP_0LEN_ARRAY;
          omp_add_variable (ctx, decl, flags);
-         if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+         if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+              || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+              || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
              && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
            {
              omp_add_variable (ctx, OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
@@ -9155,6 +9161,8 @@ gimplify_adjust_omp_clauses (gimple_seq
          break;
 
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          decl = OMP_CLAUSE_DECL (c);
          /* OpenACC reductions need a present_or_copy data clause.
             Add one if necessary.  Error is the reduction is private.  */
@@ -11859,7 +11867,12 @@ gimplify_expr (tree *expr_p, gimple_seq
                  g = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
                  body = NULL;
                  gimple_seq_add_stmt (&body, g);
-                 g = gimple_build_omp_taskgroup (body);
+                 tree *pclauses = &OMP_TASKGROUP_CLAUSES (*expr_p);
+                 gimplify_scan_omp_clauses (pclauses, pre_p, ORT_WORKSHARE,
+                                            OMP_TASKGROUP);
+                 gimplify_adjust_omp_clauses (pre_p, body, pclauses,
+                                              OMP_TASKGROUP);
+                 g = gimple_build_omp_taskgroup (body, *pclauses);
                }
                break;
              case OMP_ORDERED:
--- gcc/tree-inline.c.jj        2017-05-24 11:48:20.650991277 +0200
+++ gcc/tree-inline.c   2017-05-24 11:56:00.124182989 +0200
@@ -1495,7 +1495,8 @@ remap_gimple_stmt (gimple *stmt, copy_bo
 
        case GIMPLE_OMP_TASKGROUP:
          s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
-         copy = gimple_build_omp_taskgroup (s1);
+         copy = gimple_build_omp_taskgroup
+                  (s1, gimple_omp_taskgroup_clauses (stmt));
          break;
 
        case GIMPLE_OMP_ORDERED:

        Jakub

Reply via email to