[gcc r16-6103] openmp: Provide fixit hints for -Wdeprecated-openmp diagnostics from C++ FE
Jakub Jelinek
jakub@gcc.gnu.org
Sat Dec 13 09:04:40 GMT 2025
https://gcc.gnu.org/g:d5320610cd3614a83ea1f2c8122a6cfbad987eab
commit r16-6103-gd5320610cd3614a83ea1f2c8122a6cfbad987eab
Author: Jakub Jelinek <jakub@redhat.com>
Date: Sat Dec 13 10:02:55 2025 +0100
openmp: Provide fixit hints for -Wdeprecated-openmp diagnostics from C++ FE
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 an attempt to provide fixit hints from the C++ FE for most
of these warnings, and even -fdiagnostics-generate-patch can then be
useful for porting.
2025-12-13 Jakub Jelinek <jakub@redhat.com>
* parser.cc (cp_parser_omp_clause_reduction): Provide fixit hints
for -Wdeprecated-openmp diagnostics.
(cp_parser_omp_clause_linear): Likewise.
(cp_parser_omp_clause_depend): Likewise.
(cp_parser_omp_clause_map): Likewise. Reset num_commas after the
diagnostics.
(cp_parser_omp_clause_proc_bind): Provide fixit hints for
-Wdeprecated-openmp diagnostics.
(cp_parser_omp_all_clauses): Move -Wdeprecated-openmp diagnostics
for to vs. enter here, add fixit hints for it.
(cp_parser_omp_master):Add MASTER_LOC argument. Provide fixit hints
for -Wdeprecated-openmp diagnostics.
(cp_parser_omp_parallel): Adjust cp_parser_omp_master caller.
(cp_parser_omp_declare_target): Don't emit -Wdeprecated-openmp
warning for to vs. enter here.
(cp_parser_omp_metadirective): Provide fixit hints for
-Wdeprecated-openmp diagnostics.
(cp_parser_omp_construct): Adjust cp_parser_omp_master caller.
* g++.dg/gomp/deprecate-1.C: New test.
Diff:
---
gcc/cp/parser.cc | 139 +++++++++++++++++++++++++-------
gcc/testsuite/g++.dg/gomp/deprecate-1.C | 124 ++++++++++++++++++++++++++++
2 files changed, 236 insertions(+), 27 deletions(-)
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index a0acd9cf6f3e..214dababeb55 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -42168,9 +42168,14 @@ cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind,
case CPP_MULT: code = MULT_EXPR; break;
case CPP_MINUS:
if (is_omp)
- warning_at (cp_lexer_peek_token (parser->lexer)->location,
- OPT_Wdeprecated_openmp,
- "%<-%> operator for reductions deprecated in OpenMP 5.2");
+ {
+ location_t loc = cp_lexer_peek_token (parser->lexer)->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: code = BIT_AND_EXPR; break;
@@ -43041,6 +43046,9 @@ cp_parser_omp_clause_linear (cp_parser *parser, tree list,
bool colon;
enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT;
bool old_linear_modifier = false;
+ location_t mod_loc = UNKNOWN_LOCATION, after_colon_loc = UNKNOWN_LOCATION;
+ location_t rm1_loc = UNKNOWN_LOCATION, rm2_loc = UNKNOWN_LOCATION;
+ location_t close_loc = UNKNOWN_LOCATION;
matching_parens parens;
if (!parens.require_open (parser))
@@ -43059,12 +43067,12 @@ cp_parser_omp_clause_linear (cp_parser *parser, tree list,
kind = OMP_CLAUSE_LINEAR_UVAL;
if (cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN))
{
+ mod_loc = cp_lexer_peek_token (parser->lexer)->location;
+ rm1_loc = make_location (mod_loc, mod_loc,
+ cp_lexer_peek_nth_token (parser->lexer,
+ 2)->location);
cp_lexer_consume_token (parser->lexer);
old_linear_modifier = true;
- warning_at (cp_lexer_peek_token (parser->lexer)->location,
- OPT_Wdeprecated_openmp,
- "specifying the list items as arguments to the "
- "modifiers is deprecated since OpenMP 5.2");
}
else
kind = OMP_CLAUSE_LINEAR_DEFAULT;
@@ -43075,8 +43083,20 @@ cp_parser_omp_clause_linear (cp_parser *parser, tree list,
&colon);
else
{
+ size_t end = cp_parser_skip_balanced_tokens (parser, 1);
+ cp_token *next = UNKNOWN_LOCATION;
+ if (end > 1
+ && cp_lexer_nth_token_is (parser->lexer, end - 1, CPP_CLOSE_PAREN))
+ {
+ rm2_loc = cp_lexer_peek_nth_token (parser->lexer, end - 1)->location;
+ next = cp_lexer_peek_nth_token (parser->lexer, end);
+ }
nlist = cp_parser_omp_var_list (parser, OMP_CLAUSE_LINEAR, list);
+ if (next && cp_lexer_peek_token (parser->lexer) != next)
+ rm2_loc = UNKNOWN_LOCATION;
colon = cp_lexer_next_token_is (parser->lexer, CPP_COLON);
+ if (!colon && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+ close_loc = cp_lexer_peek_token (parser->lexer)->location;
if (colon)
cp_parser_require (parser, CPP_COLON, RT_COLON);
else if (!parens.require_close (parser))
@@ -43192,6 +43212,7 @@ cp_parser_omp_clause_linear (cp_parser *parser, tree list,
&& cp_lexer_nth_token_is (parser->lexer, 2, CPP_CLOSE_PAREN))
{
cp_token *token = cp_lexer_peek_token (parser->lexer);
+ after_colon_loc = token->location;
cp_parser_parse_tentatively (parser);
step = cp_parser_id_expression (parser, /*template_p=*/false,
/*check_dependency_p=*/true,
@@ -43209,7 +43230,13 @@ cp_parser_omp_clause_linear (cp_parser *parser, tree list,
step = NULL_TREE;
}
if (!step)
- step = cp_parser_assignment_expression (parser);
+ {
+ after_colon_loc = cp_lexer_peek_token (parser->lexer)->location;
+ step = cp_parser_assignment_expression (parser);
+ }
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+ close_loc = cp_lexer_peek_token (parser->lexer)->location;
if (!parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
@@ -43227,6 +43254,42 @@ cp_parser_omp_clause_linear (cp_parser *parser, tree list,
OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (c) = old_linear_modifier;
}
+ if (old_linear_modifier)
+ {
+ gcc_rich_location richloc (mod_loc);
+ if (rm2_loc != UNKNOWN_LOCATION && close_loc != UNKNOWN_LOCATION)
+ {
+ richloc.add_fixit_remove (rm1_loc);
+ if (after_colon_loc != UNKNOWN_LOCATION)
+ {
+ richloc.add_fixit_remove (rm2_loc);
+ if (kind == OMP_CLAUSE_LINEAR_REF)
+ richloc.add_fixit_insert_before (after_colon_loc,
+ "ref, step (");
+ else if (kind == OMP_CLAUSE_LINEAR_VAL)
+ richloc.add_fixit_insert_before (after_colon_loc,
+ "val, step (");
+ else if (kind == OMP_CLAUSE_LINEAR_UVAL)
+ richloc.add_fixit_insert_before (after_colon_loc,
+ "uval, step (");
+ else
+ gcc_unreachable ();
+ richloc.add_fixit_insert_before (close_loc, ")");
+ }
+ else if (kind == OMP_CLAUSE_LINEAR_REF)
+ richloc.add_fixit_replace (rm2_loc, " : ref");
+ else if (kind == OMP_CLAUSE_LINEAR_VAL)
+ richloc.add_fixit_replace (rm2_loc, " : val");
+ else if (kind == OMP_CLAUSE_LINEAR_UVAL)
+ richloc.add_fixit_replace (rm2_loc, " : uval");
+ else
+ gcc_unreachable ();
+ }
+ warning_at (&richloc, OPT_Wdeprecated_openmp,
+ "specifying the list items as arguments to the "
+ "modifiers is deprecated since OpenMP 5.2");
+ }
+
return nlist;
}
@@ -43675,14 +43738,18 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc)
kind = OMP_CLAUSE_DEPEND_DEPOBJ;
else if (strcmp ("sink", p) == 0)
{
- warning_at (loc, OPT_Wdeprecated_openmp,
+ gcc_rich_location richloc (loc);
+ richloc.add_fixit_replace ("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 (loc, OPT_Wdeprecated_openmp,
+ gcc_rich_location richloc (loc);
+ richloc.add_fixit_replace ("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;
@@ -44271,10 +44338,15 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list, bool declare_mapper_p)
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 (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
@@ -44517,7 +44589,11 @@ cp_parser_omp_clause_proc_bind (cp_parser *parser, tree list,
kind = OMP_CLAUSE_PROC_BIND_PRIMARY;
else if (strcmp ("master", p) == 0)
{
- warning_at (location, OPT_Wdeprecated_openmp,
+ gcc_rich_location richloc (location);
+ location_t master_loc
+ = cp_lexer_peek_token (parser->lexer)->location;
+ richloc.add_fixit_replace (master_loc, "primary");
+ warning_at (&richloc, OPT_Wdeprecated_openmp,
"%<master%> affinity deprecated since OpenMP 5.1, "
"use %<primary%>");
kind = OMP_CLAUSE_PROC_BIND_MASTER;
@@ -45603,6 +45679,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
case PRAGMA_OMP_CLAUSE_TO:
if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)) != 0)
{
+ gcc_rich_location richloc (token->location);
+ 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 = cp_parser_omp_var_list (parser, OMP_CLAUSE_ENTER,
clauses);
for (tree c = nl; c != clauses; c = OMP_CLAUSE_CHAIN (c))
@@ -49236,12 +49317,15 @@ static tree cp_parser_omp_taskloop (cp_parser *, cp_token *, char *,
static tree
cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok,
char *p_name, omp_clause_mask mask, tree *cclauses,
- bool *if_p)
+ bool *if_p, location_t master_loc)
{
tree clauses, sb, ret;
unsigned int save;
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
- warning_at (loc, OPT_Wdeprecated_openmp,
+ gcc_rich_location richloc (master_loc ? master_loc : 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%>");
@@ -49615,6 +49699,7 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
{
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
+ location_t ploc = cp_lexer_peek_token (parser->lexer)->location;
if (cclauses == NULL && strcmp (p, "masked") == 0)
{
tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
@@ -49653,11 +49738,11 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
cp_lexer_consume_token (parser->lexer);
if (!flag_openmp) /* flag_openmp_simd */
return cp_parser_omp_master (parser, pragma_tok, p_name, mask,
- cclauses, if_p);
+ cclauses, if_p, ploc);
block = begin_omp_parallel ();
save = cp_parser_begin_omp_structured_block (parser);
tree ret = cp_parser_omp_master (parser, pragma_tok, p_name, mask,
- cclauses, if_p);
+ cclauses, if_p, ploc);
cp_parser_end_omp_structured_block (parser, save);
stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
block);
@@ -52993,10 +53078,6 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok)
}
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 (OMP_CLAUSE_LOCATION (c), 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)
@@ -53418,9 +53499,13 @@ cp_parser_omp_metadirective (cp_parser *parser, cp_token *pragma_tok,
const char *p
= IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value);
if (strcmp (p, "default") == 0)
- warning_at (match_loc, OPT_Wdeprecated_openmp,
- "%<default%> clause on metadirectives deprecated since "
- "OpenMP 5.2, use %<otherwise%>");
+ {
+ gcc_rich_location richloc (match_loc);
+ richloc.add_fixit_replace ("otherwise");
+ warning_at (&richloc, OPT_Wdeprecated_openmp,
+ "%<default%> clause on metadirectives deprecated since "
+ "OpenMP 5.2, use %<otherwise%>");
+ }
cp_lexer_consume_token (parser->lexer);
bool default_p
= strcmp (p, "default") == 0 || strcmp (p, "otherwise") == 0;
@@ -55209,7 +55294,7 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
case PRAGMA_OMP_MASTER:
strcpy (p_name, "#pragma omp");
stmt = cp_parser_omp_master (parser, pragma_tok, p_name, mask, NULL,
- if_p);
+ if_p, UNKNOWN_LOCATION);
break;
case PRAGMA_OMP_PARALLEL:
strcpy (p_name, "#pragma omp");
diff --git a/gcc/testsuite/g++.dg/gomp/deprecate-1.C b/gcc/testsuite/g++.dg/gomp/deprecate-1.C
new file mode 100644
index 000000000000..37ff86a8daaf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/deprecate-1.C
@@ -0,0 +1,124 @@
+/* { 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);
+
+#pragma omp declare simd linear (ref(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 (ref(a) : 1)
+ ^~~
+ ---- - -
+ ref, step (1)
+ { dg-end-multiline-output "" } */
+#pragma omp declare simd linear (ref(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 (ref(b))
+ ^~~
+ ---- -
+ : ref
+ { dg-end-multiline-output "" } */
+int baz (int &a, int &b);
+
+#pragma omp declare simd linear (uval(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 (uval(a) : 1)
+ ^~~~
+ ----- - -
+ uval, step (1)
+ { dg-end-multiline-output "" } */
+#pragma omp declare simd linear (uval(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 (uval(b))
+ ^~~~
+ ----- -
+ : uval
+ { dg-end-multiline-output "" } */
+int qux (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 "" } */
+ ;
+}
More information about the Gcc-cvs
mailing list