Hi!

I think especially the linear clause -Wdeprecated-openmp diagnostics
will be complete nightmare for users, when they have
linear (ref (x, y, z))
or
linear (uval (a, b, c) : 2)
they will have no clue what the new syntax is.

Here is a so far lightly tested attempt to provide fixit hints for most
of these warnings, and even -fdiagnostics-generate-patch can then be
useful for porting.
And so far I've done just the C FE.
I can do C++ FE next.

Some issues:
1) I have no idea what to do about
#pragma omp master
#pragma omp master taskloop
#pragma omp declare target
or their attribute variants, for pragmas the location_t one gets is
the omp keyword, not master or declare, and there is no other location_t
easily available to add a fixit hint that master -> masked or
begin inserted before declare.  And for attributes I have no idea what
location_t we get there.  Note, for omp parallel master or omp parallel
master taskloop I do emit fixit hints.
2) I think there is a missing warning for
#pragma omp declare reduction (-:struct S:omp_out.s += omp_in.s)
(similar case to reduction clause with - identifier)
3) I think the map clause diagnostics for missing comma separation
will not diagnose
#pragma omp target map (always tofrom: x)
just missing commas in between multiple modifiers (and I've fixed it
not to emit diagnostics multiple times if only one comma is missing,
e.g.
#pragma omp target map (always present, close, tofrom: x)
would I think diagnose missing comma twice.

2025-12-12  Jakub Jelinek  <[email protected]>

        * c-parser.cc (c_parser_omp_clause_reduction): Provide fixit hints
        for -Wdeprecated-openmp diagnostics.
        (c_parser_omp_clause_linear): Likewise.
        (c_parser_omp_clause_depend): Likewise.  Add HERE argument.
        (c_parser_omp_clause_map): Provide fixit hints for -Wdeprecated-openmp
        diagnostics.  Reset num_commas after the diagnostics.
        (c_parser_omp_clause_proc_bind): Provide fixit hints for
        -Wdeprecated-openmp diagnostics.
        (c_parser_omp_all_clauses): Move -Wdeprecated-openmp diagnostics
        for to vs. enter here, add fixit hints for it.  Adjust
        c_parser_omp_clause_depend caller.
        (c_parser_omp_depobj): Adjust c_parser_omp_clause_depend caller.
        (c_parser_omp_master): Add MASTER_LOC argument.  Provide fixit hints
        for -Wdeprecated-openmp diagnostics.
        (c_parser_omp_parallel): Adjust c_parser_omp_master caller.
        (c_parser_omp_declare_target): Don't emit -Wdeprecated-openmp
        warning for to vs. enter here.
        (c_parser_omp_metadirective): Provide fixit hints for
        -Wdeprecated-openmp diagnostics.
        (c_parser_omp_construct): Adjust c_parser_omp_master caller.

        * c-c++-common/gomp/52-deps.c: Change locations of 2 warnings for C.
        * gcc.dg/gomp/deprecate-1.c: New test.

--- gcc/c/c-parser.cc.jj        2025-12-11 21:29:28.614228231 +0100
+++ gcc/c/c-parser.cc   2025-12-12 12:01:56.793216348 +0100
@@ -18850,10 +18850,14 @@ c_parser_omp_clause_reduction (c_parser
          break;
        case CPP_MINUS:
          if (is_omp)
-           warning_at (c_parser_peek_token (parser)->location,
-                       OPT_Wdeprecated_openmp,
-                       "%<-%> operator for reductions deprecated in "
-                       "OpenMP 5.2");
+           {
+             location_t loc = c_parser_peek_token (parser)->location;
+             gcc_rich_location richloc (loc);
+             richloc.add_fixit_replace ("+");
+             warning_at (&richloc, OPT_Wdeprecated_openmp,
+                         "%<-%> operator for reductions deprecated in "
+                         "OpenMP 5.2");
+           }
          code = MINUS_EXPR;
          break;
        case CPP_AND:
@@ -19584,6 +19588,8 @@ static tree
 c_parser_omp_clause_linear (c_parser *parser, tree list)
 {
   location_t clause_loc = c_parser_peek_token (parser)->location;
+  location_t rm1_loc = UNKNOWN_LOCATION, rm2_loc = UNKNOWN_LOCATION;
+  location_t after_colon_loc = UNKNOWN_LOCATION;
   tree nl, c, step;
   enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT;
   bool old_linear_modifier = false;
@@ -19602,10 +19608,9 @@ c_parser_omp_clause_linear (c_parser *pa
        kind = OMP_CLAUSE_LINEAR_DEFAULT;
       if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
        {
-         warning_at (clause_loc, OPT_Wdeprecated_openmp,
-                     "specifying the list items as arguments to the "
-                     "modifiers is deprecated since OpenMP 5.2");
          old_linear_modifier = true;
+         rm1_loc = make_location (tok->location, tok->location,
+                                  c_parser_peek_2nd_token (parser)->location);
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
        }
@@ -19615,12 +19620,17 @@ c_parser_omp_clause_linear (c_parser *pa
                                   OMP_CLAUSE_LINEAR, list);
 
   if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
-    parens.skip_until_found_close (parser);
+    {
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+       rm2_loc = c_parser_peek_token (parser)->location;
+      parens.skip_until_found_close (parser);
+    }
 
   if (c_parser_next_token_is (parser, CPP_COLON))
     {
       c_parser_consume_token (parser);
       location_t expr_loc = c_parser_peek_token (parser)->location;
+      after_colon_loc = expr_loc;
       bool has_modifiers = false;
       if (kind == OMP_CLAUSE_LINEAR_DEFAULT
          && c_parser_next_token_is (parser, CPP_NAME))
@@ -19723,6 +19733,27 @@ c_parser_omp_clause_linear (c_parser *pa
       OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (c) = old_linear_modifier;
     }
 
+  if (old_linear_modifier)
+    {
+      gcc_rich_location richloc (clause_loc);
+      if (rm2_loc != UNKNOWN_LOCATION)
+       {
+         richloc.add_fixit_remove (rm1_loc);
+         if (after_colon_loc != UNKNOWN_LOCATION)
+           {
+             richloc.add_fixit_remove (rm2_loc);
+             richloc.add_fixit_insert_before (after_colon_loc, "val, step (");
+             location_t close_loc = c_parser_peek_token (parser)->location;
+             richloc.add_fixit_insert_before (close_loc, ")");
+           }
+         else
+           richloc.add_fixit_replace (rm2_loc, " : val");
+       }
+      warning_at (&richloc, OPT_Wdeprecated_openmp,
+                 "specifying the list items as arguments to the "
+                 "modifiers is deprecated since OpenMP 5.2");
+    }
+
   parens.skip_until_found_close (parser);
   return nl;
 }
@@ -20105,7 +20136,7 @@ c_parser_omp_clause_affinity (c_parser *
      iterator ( iterators-definition )  */
 
 static tree
-c_parser_omp_clause_depend (c_parser *parser, tree list)
+c_parser_omp_clause_depend (c_parser *parser, tree list, location_t here)
 {
   location_t clause_loc = c_parser_peek_token (parser)->location;
   enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST;
@@ -20142,14 +20173,18 @@ c_parser_omp_clause_depend (c_parser *pa
        kind = OMP_CLAUSE_DEPEND_DEPOBJ;
       else if (strcmp ("sink", p) == 0)
        {
-         warning_at (clause_loc, OPT_Wdeprecated_openmp,
+         gcc_rich_location richloc (clause_loc);
+         richloc.add_fixit_replace (here, "doacross");
+         warning_at (&richloc, OPT_Wdeprecated_openmp,
                      "%<sink%> modifier with %<depend%> clause deprecated "
                      "since OpenMP 5.2, use with %<doacross%>");
          dkind = OMP_CLAUSE_DOACROSS_SINK;
        }
       else if (strcmp ("source", p) == 0)
        {
-         warning_at (clause_loc, OPT_Wdeprecated_openmp,
+         gcc_rich_location richloc (clause_loc);
+         richloc.add_fixit_replace (here, "doacross");
+         warning_at (&richloc, OPT_Wdeprecated_openmp,
                      "%<source%> modifier with %<depend%> clause deprecated "
                      "since OpenMP 5.2, use with %<doacross%>");
          dkind = OMP_CLAUSE_DOACROSS_SOURCE;
@@ -20583,10 +20618,15 @@ c_parser_omp_clause_map (c_parser *parse
          return list;
        }
       ++num_identifiers;
-      if (num_identifiers - 1 != num_commas)
-       warning_at (clause_loc, OPT_Wdeprecated_openmp,
-                   "%<map%> clause modifiers without comma separation is "
-                   "deprecated since OpenMP 5.2");
+      if (num_identifiers - 1 > num_commas)
+       {
+         gcc_rich_location richloc (clause_loc);
+         richloc.add_fixit_insert_before (tok->location, ",");
+         warning_at (&richloc, OPT_Wdeprecated_openmp,
+                     "%<map%> clause modifiers without comma separation is "
+                     "deprecated since OpenMP 5.2");
+       }
+      num_commas = num_identifiers - 1;
     }
 
   if (c_parser_next_token_is (parser, CPP_NAME)
@@ -20830,7 +20870,10 @@ c_parser_omp_clause_proc_bind (c_parser
        kind = OMP_CLAUSE_PROC_BIND_PRIMARY;
       else if (strcmp ("master", p) == 0)
        {
-         warning_at (clause_loc, OPT_Wdeprecated_openmp,
+         gcc_rich_location richloc (clause_loc);
+         richloc.add_fixit_replace (c_parser_peek_token (parser)->location,
+                                    "primary");
+         warning_at (&richloc, OPT_Wdeprecated_openmp,
                      "%<master%> affinity deprecated since OpenMP 5.1, "
                      "use %<primary%>");
          kind = OMP_CLAUSE_PROC_BIND_MASTER;
@@ -22051,6 +22094,11 @@ c_parser_omp_all_clauses (c_parser *pars
        case PRAGMA_OMP_CLAUSE_TO:
          if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)) != 0)
            {
+             gcc_rich_location richloc (here);
+             richloc.add_fixit_replace ("enter");
+             warning_at (&richloc, OPT_Wdeprecated_openmp,
+                         "%<to%> clause with %<declare target%> deprecated "
+                         "since OpenMP 5.2, use %<enter%>");
              tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ENTER,
                                                      clauses);
              for (tree c = nl; c != clauses; c = OMP_CLAUSE_CHAIN (c))
@@ -22096,7 +22144,7 @@ c_parser_omp_all_clauses (c_parser *pars
          c_name = "affinity";
          break;
        case PRAGMA_OMP_CLAUSE_DEPEND:
-         clauses = c_parser_omp_clause_depend (parser, clauses);
+         clauses = c_parser_omp_clause_depend (parser, clauses, here);
          c_name = "depend";
          break;
        case PRAGMA_OMP_CLAUSE_DOACROSS:
@@ -24307,7 +24355,7 @@ c_parser_omp_depobj (c_parser *parser)
       c_parser_consume_token (parser);
       if (!strcmp ("depend", p))
        {
-         clause = c_parser_omp_clause_depend (parser, NULL_TREE);
+         clause = c_parser_omp_clause_depend (parser, NULL_TREE, c_loc);
          clause = c_finish_omp_clauses (clause, C_ORT_OMP);
          if (!clause)
            clause = error_mark_node;
@@ -25450,12 +25498,15 @@ static tree c_parser_omp_taskloop (locat
 static tree
 c_parser_omp_master (location_t loc, c_parser *parser,
                     char *p_name, omp_clause_mask mask, tree *cclauses,
-                    bool *if_p)
+                    bool *if_p, location_t master_loc)
 {
-  warning_at (loc, OPT_Wdeprecated_openmp,
+  tree block, clauses, ret;
+  gcc_rich_location richloc (loc);
+  if (master_loc != UNKNOWN_LOCATION)
+    richloc.add_fixit_replace (master_loc, "masked");
+  warning_at (&richloc, OPT_Wdeprecated_openmp,
              "%<master%> construct deprecated since OpenMP 5.1, use "
              "%<masked%>");
-  tree block, clauses, ret;
 
   strcat (p_name, " master");
 
@@ -25869,6 +25920,7 @@ c_parser_omp_parallel (location_t loc, c
   else if (c_parser_next_token_is (parser, CPP_NAME))
     {
       const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      location_t ploc = c_parser_peek_token (parser)->location;
       if (cclauses == NULL && strcmp (p, "masked") == 0)
        {
          tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
@@ -25906,10 +25958,10 @@ c_parser_omp_parallel (location_t loc, c
          c_parser_consume_token (parser);
          if (!flag_openmp)  /* flag_openmp_simd  */
            return c_parser_omp_master (loc, parser, p_name, mask, cclauses,
-                                       if_p);
+                                       if_p, ploc);
          block = c_begin_omp_parallel ();
          tree ret = c_parser_omp_master (loc, parser, p_name, mask, cclauses,
-                                         if_p);
+                                         if_p, ploc);
          stmt = c_finish_omp_parallel (loc,
                                        cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
                                        block);
@@ -28399,11 +28451,6 @@ c_parser_omp_declare_target (c_parser *p
     }
   for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
     {
-      if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ENTER && OMP_CLAUSE_ENTER_TO (c))
-       warning_at (c_parser_peek_token (parser)->location,
-                   OPT_Wdeprecated_openmp,
-                   "%<to%> clause with %<declare target%> deprecated since "
-                   "OpenMP 5.2, use %<enter%>");
       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
        device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
@@ -30210,9 +30257,13 @@ c_parser_omp_metadirective (c_parser *pa
       location_t match_loc = c_parser_peek_token (parser)->location;
       const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
       if (strcmp (p, "default") == 0)
-       warning_at (pragma_loc, OPT_Wdeprecated_openmp,
-                   "%<default%> clause on metadirectives deprecated since "
-                   "OpenMP 5.2, use %<otherwise%>");
+       {
+         gcc_rich_location richloc (pragma_loc);
+         richloc.add_fixit_replace (match_loc, "otherwise");
+         warning_at (&richloc, OPT_Wdeprecated_openmp,
+                     "%<default%> clause on metadirectives deprecated since "
+                     "OpenMP 5.2, use %<otherwise%>");
+       }
       c_parser_consume_token (parser);
       bool default_p
        = strcmp (p, "default") == 0 || strcmp (p, "otherwise") == 0;
@@ -30595,7 +30646,8 @@ c_parser_omp_construct (c_parser *parser
       break;
     case PRAGMA_OMP_MASTER:
       strcpy (p_name, "#pragma omp");
-      stmt = c_parser_omp_master (loc, parser, p_name, mask, NULL, if_p);
+      stmt = c_parser_omp_master (loc, parser, p_name, mask, NULL, if_p,
+                                 UNKNOWN_LOCATION);
       break;
     case PRAGMA_OMP_PARALLEL:
       strcpy (p_name, "#pragma omp");
--- gcc/testsuite/c-c++-common/gomp/52-deps.c.jj        2025-12-11 
19:33:57.695486865 +0100
+++ gcc/testsuite/c-c++-common/gomp/52-deps.c   2025-12-12 12:21:37.024899739 
+0100
@@ -1,19 +1,15 @@
 // tests for deprecation of 'to' clause with 'declare target' and the '-'
 // operator when used in reductions.
-// { dg-warning "'to' clause with 'declare target' deprecated since OpenMP 
5.2, use 'enter' \\\[-Wdeprecated-openmp\\\]" "" { target c } 12 }
-// { dg-warning "'to' clause with 'declare target' deprecated since OpenMP 
5.2, use 'enter' \\\[-Wdeprecated-openmp\\\]" "" { target c } 18 }
-// { dg-warning "'to' clause with 'declare target' deprecated since OpenMP 
5.2, use 'enter' \\\[-Wdeprecated-openmp\\\]" "" { target c++ } 10 }
-// { dg-warning "'to' clause with 'declare target' deprecated since OpenMP 
5.2, use 'enter' \\\[-Wdeprecated-openmp\\\]" "" { target c++ } 16 }
 
 int x = 24;
 
-#pragma omp declare target to(x)
+#pragma omp declare target to(x)       // { dg-warning "'to' clause with 
'declare target' deprecated since OpenMP 5.2, use 'enter' 
\\\[-Wdeprecated-openmp\\\]" }
 
 int foo(int x)
 {
   return x + 1;
 }
-#pragma omp declare target to(foo)
+#pragma omp declare target to(foo)     // { dg-warning "'to' clause with 
'declare target' deprecated since OpenMP 5.2, use 'enter' 
\\\[-Wdeprecated-openmp\\\]" }
 
 int
 main()
--- gcc/testsuite/gcc.dg/gomp/deprecate-1.c.jj  2025-12-12 12:15:23.368347569 
+0100
+++ gcc/testsuite/gcc.dg/gomp/deprecate-1.c     2025-12-12 12:33:11.568854333 
+0100
@@ -0,0 +1,95 @@
+/* { dg-additional-options "-fdiagnostics-show-caret -Wdeprecated-openmp" } */
+#pragma omp declare simd linear (val(a) : 1)   /* { dg-warning "specifying the 
list items as arguments to the modifiers is deprecated since OpenMP 5.2" } */
+/* { dg-begin-multiline-output "" }
+#pragma omp declare simd linear (val(a) : 1)
+                                 ^
+                                  ---- -   -
+                                           val, step (1)
+   { dg-end-multiline-output "" } */
+#pragma omp declare simd linear (val(b))       /* { dg-warning "specifying the 
list items as arguments to the modifiers is deprecated since OpenMP 5.2" } */
+/* { dg-begin-multiline-output "" }
+ #pragma omp declare simd linear (val(b))
+                                 ^
+                                  ---- -
+                                        : val
+   { dg-end-multiline-output "" } */
+int foo (int a, int b);
+
+int v;
+#pragma omp declare target to (v)              /* { dg-warning "'to' clause 
with 'declare target' deprecated since OpenMP 5.2, use 'enter'" } */
+/* { dg-begin-multiline-output "" }
+ #pragma omp declare target to (v)
+                            ^~
+                            enter
+   { dg-end-multiline-output "" } */
+
+void
+bar ()
+{
+  int r = 0;
+  #pragma omp parallel reduction (-:r)         /* { dg-warning "'-' operator 
for reductions deprecated in OpenMP 5.2" } */
+/* { dg-begin-multiline-output "" }
+   #pragma omp parallel reduction (-:r)
+                                   ^
+                                   +
+   { dg-end-multiline-output "" } */
+  ++r;
+  #pragma omp for ordered (1)
+  for (int i = 0; i < 64; i++)
+    {
+      #pragma omp ordered depend (sink: i - 1) /* { dg-warning "'sink' 
modifier with 'depend' clause deprecated since OpenMP 5.2, use with 'doacross'" 
} */
+/* { dg-begin-multiline-output "" }
+       #pragma omp ordered depend (sink: i - 1)
+                                  ^
+                           ------
+                           doacross
+   { dg-end-multiline-output "" } */
+      #pragma omp ordered depend (source)      /* { dg-warning "'source' 
modifier with 'depend' clause deprecated since OpenMP 5.2, use with 'doacross'" 
} */
+/* { dg-begin-multiline-output "" }
+       #pragma omp ordered depend (source)
+                                  ^
+                           ------
+                           doacross
+   { dg-end-multiline-output "" } */
+    }
+  #pragma omp target map (always close present, tofrom: r)     /* { dg-warning 
"'map' clause modifiers without comma separation is deprecated since OpenMP 
5.2" } */
+/* { dg-begin-multiline-output "" }
+   #pragma omp target map (always close present, tofrom: r)
+                          ^
+                                  ,
+   #pragma omp target map (always close present, tofrom: r)
+                          ^
+                                        ,
+   { dg-end-multiline-output "" } */
+  ;
+  #pragma omp parallel proc_bind (master)      /* { dg-warning "'master' 
affinity deprecated since OpenMP 5.1, use 'primary'" } */
+/* { dg-begin-multiline-output "" }
+   #pragma omp parallel proc_bind (master)
+                                  ^
+                                   ------
+                                   primary
+   { dg-end-multiline-output "" } */
+  ;
+  #pragma omp parallel master                  /* { dg-warning "'master' 
construct deprecated since OpenMP 5.1, use 'masked'" } */
+/* { dg-begin-multiline-output "" }
+   #pragma omp parallel master
+           ^~~
+                        ------
+                        masked
+   { dg-end-multiline-output "" } */
+  ;
+  #pragma omp master                           /* { dg-warning "'master' 
construct deprecated since OpenMP 5.1, use 'masked'" } */
+/* { dg-begin-multiline-output "" }
+   #pragma omp master
+           ^~~
+   { dg-end-multiline-output "" } */
+  ;
+  #pragma omp metadirective when (device={arch("blahblah")}: nothing) default 
(nothing)                /* { dg-warning "'default' clause on metadirectives 
deprecated since OpenMP 5.2, use 'otherwise'" } */
+/* { dg-begin-multiline-output "" }
+   #pragma omp metadirective when (device={arch("blahblah")}: nothing) default 
(nothing)
+           ^~~
+                                                                       -------
+                                                                       
otherwise
+   { dg-end-multiline-output "" } */
+  ;
+}

        Jakub

Reply via email to