[gcc/devel/omp/gcc-16] Various OpenACC reduction enhancements - FE changes

Sandra Loosemore via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:23251983e020d265e8d40c7a48ba9b383d15e585

commit 23251983e020d265e8d40c7a48ba9b383d15e585
Author: Julian Brown <[email protected]>
Date:   Fri Apr 3 23:20:36 2026 +0000

    Various OpenACC reduction enhancements - FE changes
    
    gcc/c/ChangeLog
            * c-parser.cc (c_parser_omp_variable_list): New c_omp_region_type
            argument.  Use it to specialize handling of OMP_CLAUSE_REDUCTION for
            OpenACC.
            (c_parser_omp_var_list_parens): Add region-type argument to call.
            (c_parser_oacc_data_clause): Likewise.
            (c_parser_oacc_data_clause_deviceptr): Likewise.
            (c_parser_omp_clause_reduction): Change is_omp boolean parameter to
            c_omp_region_type.  Update call to c_parser_omp_variable_list.
            (c_parser_omp_clause_map): Update call to
            c_parser_omp_variable_list.
            (c_parser_omp_clause_from_to): Likewise.
            (c_parser_omp_clause_init): Likewise.
            (c_parser_oacc_all_clauses): Update calls to
            c_parser_omp_clause_reduction.
            (c_parser_omp_all_clauses): Likewise.
            (c_parser_oacc_cache): Update call to c_parser_omp_variable_list.
            * c-typeck.cc (c_finish_omp_clauses): Emit an error on orphan OpenACC
            gang reductions.  Suppress user-defined reduction error for OpenACC.
    
    gcc/cp/ChangeLog
            * parser.cc (cp_parser_omp_var_list_no_open):  New c_omp_region_type
            argument.  Use it to specialize handling of OMP_CLAUSE_REDUCTION for
            OpenACC.
            (cp_parser_omp_var_list): Add c_omp_region_type argument. Update call
            to cp_parser_omp_var_list_no_open.
            (cp_parser_oacc_data_clause): Update call to
            cp_parser_omp_var_list_no_open.
            (cp_parser_omp_clause_reduction): Change is_omp boolean parameter to
            c_omp_region_type.  Update call to cp_parser_omp_var_list_no_open.
            (cp_parser_omp_clause_from_to): Update call to
            cp_parser_omp_clause_var_list_no_open.
            (cp_parser_omp_clause_map): Likewise.
            (cp_parser_omp_clause_init): Likewise.
            (cp_parser_oacc_all_clauses): Update call to
            cp_parser_omp_clause_reduction.
            (cp_parser_omp_all_clauses): Likewise.
            * semantics.cc (finish_omp_reduction_clause): Add c_omp_region_type
            argument.  Suppress user-defined reduction error for OpenACC.
            (finish_omp_clauses): Update call to finish_omp_reduction_clause.
    
    gcc/fortran/ChangeLog
            * trans-openmp.cc (gfc_omp_clause_copy_ctor): Permit reductions.
    
    Co-Authored-By: Cesar Philippidis <[email protected]>
    Co-Authored-By: Nathan Sidwell <[email protected]>
    Co-Authored-By: Kwok Cheung Yeung  <[email protected]>

Diff:
---
 gcc/c/c-parser.cc           | 46 +++++++++++++++++++++++++--------------------
 gcc/c/c-typeck.cc           |  7 +++++--
 gcc/cp/parser.cc            | 33 +++++++++++++++++---------------
 gcc/cp/semantics.cc         | 13 ++++++++-----
 gcc/fortran/trans-openmp.cc |  3 ++-
 5 files changed, 59 insertions(+), 43 deletions(-)

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 08a1b1e005c3..d521978c8aa0 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -16714,7 +16714,7 @@ c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list)
    in TREE_PURPOSE and the location in TREE_VALUE (accessible using
    EXPR_LOCATION); return the list created.
 
-   The optional ALLOW_DEREF argument is true if list items can use the deref
+   The optional MAP_LVALUE argument is true if list items can use the deref
    (->) operator.  */
 
 struct omp_dim
@@ -16730,6 +16730,7 @@ static tree
 c_parser_omp_variable_list (c_parser *parser,
 			    location_t clause_loc,
 			    enum omp_clause_code kind, tree list,
+			    enum c_omp_region_type ort = C_ORT_OMP,
 			    bool map_lvalue = false)
 {
   auto_vec<omp_dim> dims;
@@ -17002,7 +17003,8 @@ c_parser_omp_variable_list (c_parser *parser,
 	    case OMP_CLAUSE_HAS_DEVICE_ADDR:
 	      array_section_p = false;
 	      dims.truncate (0);
-	      while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+	      while ((ort != C_ORT_ACC || kind != OMP_CLAUSE_REDUCTION)
+		     && c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
 		{
 		  location_t loc = UNKNOWN_LOCATION;
 		  tree low_bound = NULL_TREE, length = NULL_TREE;
@@ -17136,12 +17138,14 @@ c_parser_omp_variable_list (c_parser *parser,
 }
 
 /* Similarly, but expect leading and trailing parenthesis.  This is a very
-   common case for OpenACC and OpenMP clauses.  The optional ALLOW_DEREF
+   common case for OpenACC and OpenMP clauses.  The optional MAP_LVALUE
    argument is true if list items can use the deref (->) operator.  */
 
 static tree
 c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
-			      tree list, bool map_lvalue = false)
+			      tree list,
+			      enum c_omp_region_type ort = C_ORT_OMP,
+			      bool map_lvalue = false)
 {
   /* The clauses location.  */
   location_t loc = c_parser_peek_token (parser)->location;
@@ -17162,7 +17166,8 @@ c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
   matching_parens parens;
   if (parens.require_open (parser))
     {
-      list = c_parser_omp_variable_list (parser, loc, kind, list, map_lvalue);
+      list = c_parser_omp_variable_list (parser, loc, kind, list, ort,
+					 map_lvalue);
       parens.skip_until_found_close (parser);
     }
   return list;
@@ -17257,7 +17262,7 @@ c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
 	    }
 	}
       nl = c_parser_omp_variable_list (parser, open_loc, OMP_CLAUSE_MAP, list,
-				       false);
+				       C_ORT_ACC, false);
       parens.skip_until_found_close (parser);
     }
 
@@ -17282,7 +17287,8 @@ c_parser_oacc_data_clause_deviceptr (c_parser *parser, tree list)
   /* Can't use OMP_CLAUSE_MAP here (that is, can't use the generic
      c_parser_oacc_data_clause), as for PRAGMA_OACC_CLAUSE_DEVICEPTR,
      variable-list must only allow for pointer variables.  */
-  vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
+  vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL,
+				       C_ORT_ACC);
   for (t = vars; t && t; t = TREE_CHAIN (t))
     {
       tree v = TREE_PURPOSE (t);
@@ -18841,7 +18847,7 @@ c_parser_omp_clause_private (c_parser *parser, tree list)
 
 static tree
 c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
-			       bool is_omp, tree list)
+			       enum c_omp_region_type ort, tree list)
 {
   location_t clause_loc = c_parser_peek_token (parser)->location;
   matching_parens parens;
@@ -18852,7 +18858,7 @@ c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
       enum tree_code code = ERROR_MARK;
       tree reduc_id = NULL_TREE;
 
-      if (kind == OMP_CLAUSE_REDUCTION && is_omp)
+      if (kind == OMP_CLAUSE_REDUCTION && ort == C_ORT_OMP)
 	{
 	  if (c_parser_next_token_is_keyword (parser, RID_DEFAULT)
 	      && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
@@ -18886,7 +18892,7 @@ c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
 	  code = MULT_EXPR;
 	  break;
 	case CPP_MINUS:
-	  if (is_omp)
+	  if (ort == C_ORT_OMP)
 	    {
 	      location_t loc = c_parser_peek_token (parser)->location;
 	      gcc_rich_location richloc (loc);
@@ -18942,7 +18948,8 @@ c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
 	{
 	  tree nl, c;
 
-	  nl = c_parser_omp_variable_list (parser, clause_loc, kind, list);
+	  nl = c_parser_omp_variable_list (parser, clause_loc, kind, list, ort);
+
 	  for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
 	    {
 	      tree d = OMP_CLAUSE_DECL (c), type;
@@ -20945,7 +20952,7 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
     }
 
   nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list,
-				   true);
+				   C_ORT_OMP, true);
 
   tree last_new = NULL_TREE;
 
@@ -21375,7 +21382,7 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
   if (colon_pos)
     c_parser_require (parser, CPP_COLON, "expected %<:%>");
 
-  tree nl = c_parser_omp_variable_list (parser, loc, kind, list);
+  tree nl = c_parser_omp_variable_list (parser, loc, kind, list, C_ORT_OMP);
   parens.skip_until_found_close (parser);
 
   if (present)
@@ -21960,8 +21967,7 @@ c_parser_omp_clause_init (c_parser *parser, tree list)
     error_at (loc,
 	      "missing required %<target%> and/or %<targetsync%> modifier");
 
-  tree nl = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_INIT, list,
-					false);
+  tree nl = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_INIT, list);
   parens.skip_until_found_close (parser);
 
   for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
@@ -22153,7 +22159,7 @@ c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
 	case PRAGMA_OACC_CLAUSE_REDUCTION:
 	  clauses
 	    = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
-					     false, clauses);
+					     C_ORT_ACC, clauses);
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OACC_CLAUSE_SELF:
@@ -22319,7 +22325,7 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
 	case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
 	  clauses
 	    = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION,
-					     true, clauses);
+					     C_ORT_OMP, clauses);
 	  c_name = "in_reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_INDIRECT:
@@ -22365,7 +22371,7 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
 	case PRAGMA_OMP_CLAUSE_REDUCTION:
 	  clauses
 	    = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
-					     true, clauses);
+					     C_ORT_OMP, clauses);
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_SCHEDULE:
@@ -22379,7 +22385,7 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
 	case PRAGMA_OMP_CLAUSE_TASK_REDUCTION:
 	  clauses
 	    = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_TASK_REDUCTION,
-					     true, clauses);
+					     C_ORT_OMP, clauses);
 	  c_name = "task_reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_UNTIED:
@@ -22685,7 +22691,7 @@ c_parser_oacc_cache (location_t loc, c_parser *parser)
 	  readonly = true;
 	}
       clauses = c_parser_omp_variable_list (parser, open_loc,
-					    OMP_CLAUSE__CACHE_, NULL_TREE);
+					    OMP_CLAUSE__CACHE_, NULL_TREE, C_ORT_ACC);
       parens.skip_until_found_close (parser);
     }
 
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index f246c6c524f3..15703cf166a5 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -16950,8 +16950,11 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
 	    }
 	  else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == error_mark_node)
 	    {
-	      error_at (OMP_CLAUSE_LOCATION (c),
-			"user defined reduction not found for %qE", t);
+	      /* There are no user-defined reductions in OpenACC (as of
+		 2.6).  */
+	      if (ort & C_ORT_OMP)
+		error_at (OMP_CLAUSE_LOCATION (c),
+			  "user defined reduction not found for %qE", t);
 	      remove = true;
 	      break;
 	    }
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 9f305723acee..1cd827d47f66 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -41511,6 +41511,7 @@ struct omp_dim
 static tree
 cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 				tree list, bool *colon,
+				enum c_omp_region_type ort = C_ORT_OMP,
 				bool map_lvalue = false)
 {
   auto_vec<omp_dim> dims;
@@ -41727,7 +41728,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 	    case OMP_CLAUSE_HAS_DEVICE_ADDR:
 	      array_section_p = false;
 	      dims.truncate (0);
-	      while (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
+	      while ((ort != C_ORT_ACC || kind != OMP_CLAUSE_REDUCTION)
+		     && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
 		{
 		  location_t loc = UNKNOWN_LOCATION;
 		  tree low_bound = NULL_TREE, length = NULL_TREE;
@@ -41875,6 +41877,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 
 static tree
 cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list,
+			enum c_omp_region_type ort = C_ORT_OMP,
 			bool map_lvalue = false)
 {
   if (parser->lexer->in_omp_decl_attribute)
@@ -41893,7 +41896,7 @@ cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list,
     }
 
   if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
-    return cp_parser_omp_var_list_no_open (parser, kind, list, NULL,
+    return cp_parser_omp_var_list_no_open (parser, kind, list, NULL, ort,
 					   map_lvalue);
   return list;
 }
@@ -41985,7 +41988,7 @@ cp_parser_oacc_data_clause (cp_parser *parser, pragma_omp_clause c_kind,
 	    }
 	}
       nl = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_MAP, list, NULL,
-					   false);
+					   C_ORT_ACC, false);
     }
 
   for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
@@ -43349,7 +43352,7 @@ cp_parser_omp_clause_ordered (cp_parser *parser,
 
 static tree
 cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind,
-				bool is_omp, tree list)
+				enum c_omp_region_type ort, tree list)
 {
   enum tree_code code = ERROR_MARK;
   tree nlist, c, id = NULL_TREE;
@@ -43359,7 +43362,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind,
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return list;
 
-  if (kind == OMP_CLAUSE_REDUCTION && is_omp)
+  if (kind == OMP_CLAUSE_REDUCTION && ort == C_ORT_OMP)
     {
       if (cp_lexer_next_token_is_keyword (parser->lexer, RID_DEFAULT)
 	  && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COMMA))
@@ -43389,7 +43392,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind,
     case CPP_PLUS: code = PLUS_EXPR; break;
     case CPP_MULT: code = MULT_EXPR; break;
     case CPP_MINUS:
-      if (is_omp)
+      if (ort == C_ORT_OMP)
 	{
 	  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 	  gcc_rich_location richloc (loc);
@@ -43467,8 +43470,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind,
   if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
     goto resync_fail;
 
-  nlist = cp_parser_omp_var_list_no_open (parser, kind, list,
-					  NULL);
+  nlist = cp_parser_omp_var_list_no_open (parser, kind, list, NULL, ort);
   for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
     {
       OMP_CLAUSE_REDUCTION_CODE (c) = code;
@@ -45301,7 +45303,8 @@ cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind,
   if (colon_pos)
     cp_parser_require (parser, CPP_COLON, RT_COLON);
 
-  tree nl = cp_parser_omp_var_list_no_open (parser, kind, list, NULL, true);
+  tree nl = cp_parser_omp_var_list_no_open (parser, kind, list, NULL, C_ORT_OMP,
+					    true);
   if (present)
     for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
       OMP_CLAUSE_MOTION_PRESENT (c) = 1;
@@ -45715,7 +45718,7 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list, bool declare_mapper_p)
      legally.  */
   begin_scope (sk_omp, NULL);
   nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_MAP, list,
-					  NULL, true);
+					  NULL, C_ORT_OMP, true);
   finish_scope ();
 
   tree last_new = NULL_TREE;
@@ -46422,7 +46425,7 @@ cp_parser_omp_clause_init (cp_parser *parser, tree list)
 	      "missing required %<target%> and/or %<targetsync%> modifier");
 
   tree nl = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_INIT, list,
-					    NULL, false);
+					    NULL);
   for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
     {
       TREE_ADDRESSABLE (OMP_CLAUSE_DECL (c)) = 1;
@@ -46665,7 +46668,7 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	case PRAGMA_OACC_CLAUSE_REDUCTION:
 	  clauses
 	    = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
-					      false, clauses);
+					      C_ORT_ACC, clauses);
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OACC_CLAUSE_SELF:
@@ -46863,7 +46866,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
 	  clauses
 	    = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION,
-					      true, clauses);
+					      C_ORT_OMP, clauses);
 	  c_name = "in_reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_INDIRECT:
@@ -46918,7 +46921,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	case PRAGMA_OMP_CLAUSE_REDUCTION:
 	  clauses
 	    = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
-					      true, clauses);
+					      C_ORT_OMP, clauses);
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_SCHEDULE:
@@ -46935,7 +46938,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	  clauses
 	    = cp_parser_omp_clause_reduction (parser,
 					      OMP_CLAUSE_TASK_REDUCTION,
-					      true, clauses);
+					      C_ORT_OMP, clauses);
 	  c_name = "task_reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_UNTIED:
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index bafb558b2594..b0bfc5a2a9d3 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -7223,7 +7223,8 @@ find_omp_placeholder_r (tree *tp, int *, void *data)
    Return true if there is some error and the clause should be removed.  */
 
 static bool
-finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
+finish_omp_reduction_clause (tree c, enum c_omp_region_type ort,
+			     bool *need_default_ctor, bool *need_dtor)
 {
   tree t = OMP_CLAUSE_DECL (c);
   bool predefined = false;
@@ -7469,9 +7470,11 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
     *need_dtor = true;
   else
     {
-      error_at (OMP_CLAUSE_LOCATION (c),
-		"user defined reduction not found for %qE",
-		omp_clause_printable_decl (t));
+      /* There are no user-defined reductions for OpenACC (as of 2.6).  */
+      if (ort & C_ORT_OMP)
+	error_at (OMP_CLAUSE_LOCATION (c),
+		  "user defined reduction not found for %qE",
+		  omp_clause_printable_decl (t));
       return true;
     }
   if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
@@ -10536,7 +10539,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
 	  if (processing_template_decl
 	      && !VAR_P (t) && TREE_CODE (t) != PARM_DECL)
 	    break;
-	  if (finish_omp_reduction_clause (c, &need_default_ctor,
+	  if (finish_omp_reduction_clause (c, ort, &need_default_ctor,
 					   &need_dtor))
 	    remove = true;
 	  else
diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index ab6f751a79e6..782ab7a15d4b 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -954,7 +954,8 @@ gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
   stmtblock_t block, cond_block;
 
   gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
-	      || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
+	      || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR
+	      || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION);
 
   if (DECL_ARTIFICIAL (orig_decl)
       && DECL_LANG_SPECIFIC (orig_decl)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.