--- 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:
