https://gcc.gnu.org/g:be92d54c5622705b03f7db3e3e214b055bf82176

commit be92d54c5622705b03f7db3e3e214b055bf82176
Author: Sandra Loosemore <sloosem...@baylibre.com>
Date:   Mon Mar 31 22:02:35 2025 +0000

    OpenMP: Require target and/or targetsync init modifier [PR118965]
    
    As noted in PR 118965, the initial interop implementation overlooked
    the requirement in the OpenMP spec that at least one of the "target"
    and "targetsync" modifiers is required in both the interop construct
    init clause and the declare variant append_args clause.
    
    Adding the check was fairly straightforward, but it broke about a
    gazillion existing test cases.  In particular, things like "init (x, y)"
    which were previously accepted (and tested for being accepted) aren't
    supposed to be allowed by the spec, much less things like "init (target)"
    where target was previously interpreted as a variable name instead of a
    modifier.  Since one of the effects of the change is that at least one
    modifier is always required, I found that deleting all the code that was
    trying to detect and handle the no-modifier case allowed for better
    diagnostics.
    
    gcc/c/ChangeLog
            PR middle-end/118965
            * c-parser.cc (c_parser_omp_clause_init_modifiers): Adjust
            error message.
            (c_parser_omp_clause_init): Remove code for recognizing clauses
            without modifiers.  Diagnose missing target/targetsync modifier.
            (c_finish_omp_declare_variant): Diagnose missing target/targetsync
            modifier.
    
    gcc/cp/ChangeLog
            PR middle-end/118965
            * parser.cc (c_parser_omp_clause_init_modifiers): Adjust
            error message.
            (cp_parser_omp_clause_init): Remove code for recognizing clauses
            without modifiers.  Diagnose missing target/targetsync modifier.
            (cp_finish_omp_declare_variant): Diagnose missing target/targetsync
            modifier.
    
    gcc/fortran/ChangeLog
            PR middle-end/118965
            * openmp.cc (gfc_parser_omp_clause_init_modifiers): Fix some
            inconsistent code indentation.  Remove code for recognizing
            clauses without modifiers.  Diagnose prefer_type without a
            following paren.  Adjust error message for an unrecognized modifier.
            Diagnose missing target/targetsync modifier.
            (gfc_match_omp_init): Fix more inconsistent code indentation.
    
    gcc/testsuite/ChangeLog
            PR middle-end/118965
            * c-c++-common/gomp/append-args-1.c: Add target/targetsync
            modifiers so tests do what they were previously supposed to do.
            Adjust expected output.
            * c-c++-common/gomp/append-args-7.c: Likewise.
            * c-c++-common/gomp/append-args-8.c: Likewise.
            * c-c++-common/gomp/append-args-9.c: Likewise.
            * c-c++-common/gomp/interop-1.c: Likewise.
            * c-c++-common/gomp/interop-2.c: Likewise.
            * c-c++-common/gomp/interop-3.c: Likewise.
            * c-c++-common/gomp/interop-4.c: Likewise.
            * c-c++-common/gomp/pr118965-1.c: New.
            * c-c++-common/gomp/pr118965-2.c: New.
            * g++.dg/gomp/append-args-1.C: Add target/targetsync modifiers
            and adjust expected output.
            * g++.dg/gomp/append-args-2.C: Likewise.
            * g++.dg/gomp/append-args-6.C: Likewise.
            * g++.dg/gomp/append-args-7.C: Likewise.
            * g++.dg/gomp/append-args-8.C: Likewise.
            * g++.dg/gomp/interop-5.C: Likewise.
            * gfortran.dg/gomp/append_args-1.f90: Add target/targetsync
            modifiers and adjust expected output.
            * gfortran.dg/gomp/append_args-2.f90: Likewise.
            * gfortran.dg/gomp/append_args-3.f90: Likewise.
            * gfortran.dg/gomp/append_args-4.f90: Likewise.
            * gfortran.dg/gomp/interop-1.f90: Likewise.
            * gfortran.dg/gomp/interop-2.f90: Likewise.
            * gfortran.dg/gomp/interop-3.f90: Likewise.
            * gfortran.dg/gomp/interop-4.f90: Likewise.
            * gfortran.dg/gomp/pr118965-1.f90: New.
            * gfortran.dg/gomp/pr118965-2.f90: New.
    
    (cherry picked from commit aca8155c09001f269a20d6df438fa0e749dd5388)

Diff:
---
 gcc/c/c-parser.cc                                | 44 ++++---------
 gcc/cp/parser.cc                                 | 45 +++++--------
 gcc/fortran/openmp.cc                            | 77 +++++++++++------------
 gcc/testsuite/c-c++-common/gomp/append-args-1.c  |  4 +-
 gcc/testsuite/c-c++-common/gomp/append-args-7.c  |  4 +-
 gcc/testsuite/c-c++-common/gomp/append-args-8.c  |  9 +--
 gcc/testsuite/c-c++-common/gomp/append-args-9.c  |  7 ++-
 gcc/testsuite/c-c++-common/gomp/interop-1.c      | 80 ++++++++++++------------
 gcc/testsuite/c-c++-common/gomp/interop-2.c      | 64 ++++++++-----------
 gcc/testsuite/c-c++-common/gomp/interop-3.c      | 26 +++-----
 gcc/testsuite/c-c++-common/gomp/interop-4.c      |  8 +--
 gcc/testsuite/c-c++-common/gomp/pr118965-1.c     | 57 +++++++++++++++++
 gcc/testsuite/c-c++-common/gomp/pr118965-2.c     | 31 +++++++++
 gcc/testsuite/g++.dg/gomp/append-args-1.C        |  6 +-
 gcc/testsuite/g++.dg/gomp/append-args-2.C        |  6 +-
 gcc/testsuite/g++.dg/gomp/append-args-6.C        |  4 +-
 gcc/testsuite/g++.dg/gomp/append-args-7.C        |  2 +-
 gcc/testsuite/g++.dg/gomp/append-args-8.C        |  9 ++-
 gcc/testsuite/g++.dg/gomp/interop-5.C            |  8 +--
 gcc/testsuite/gfortran.dg/gomp/append_args-1.f90 |  8 +--
 gcc/testsuite/gfortran.dg/gomp/append_args-2.f90 | 24 +++----
 gcc/testsuite/gfortran.dg/gomp/append_args-3.f90 |  2 +-
 gcc/testsuite/gfortran.dg/gomp/append_args-4.f90 |  2 +-
 gcc/testsuite/gfortran.dg/gomp/interop-1.f90     | 62 +++++++++---------
 gcc/testsuite/gfortran.dg/gomp/interop-2.f90     | 36 +++++------
 gcc/testsuite/gfortran.dg/gomp/interop-3.f90     | 16 ++---
 gcc/testsuite/gfortran.dg/gomp/interop-4.f90     |  8 +--
 gcc/testsuite/gfortran.dg/gomp/pr118965-1.f90    | 48 ++++++++++++++
 gcc/testsuite/gfortran.dg/gomp/pr118965-2.f90    | 57 +++++++++++++++++
 29 files changed, 442 insertions(+), 312 deletions(-)

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 5e3eab71b7df..bfe26efff869 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -20558,8 +20558,8 @@ c_parser_omp_clause_init_modifiers (c_parser *parser, 
bool *target,
   while (true);
 
 fail:
-  c_parser_error (parser, "%<init%> clause with modifier other than "
-                         "%<prefer_type%>, %<target%> or %<targetsync%>");
+  c_parser_error (parser,
+                 "expected %<prefer_type%>, %<target%>, or %<targetsync%>");
   return false;
 }
 
@@ -20580,45 +20580,23 @@ c_parser_omp_clause_init (c_parser *parser, tree list)
   if (!parens.require_open (parser))
     return list;
 
-  unsigned raw_pos = 1;
-  while (c_parser_peek_nth_token_raw (parser, raw_pos)->type == CPP_NAME)
-    {
-      raw_pos++;
-      if (c_parser_peek_nth_token_raw (parser, raw_pos)->type == 
CPP_OPEN_PAREN)
-       {
-         raw_pos++;
-         c_parser_check_balanced_raw_token_sequence (parser, &raw_pos);
-         if (c_parser_peek_nth_token_raw (parser, raw_pos)->type != 
CPP_CLOSE_PAREN)
-           {
-             raw_pos = 0;
-             break;
-           }
-         raw_pos++;
-       }
-      if (c_parser_peek_nth_token_raw (parser, raw_pos)->type == CPP_COLON)
-       break;
-      if (c_parser_peek_nth_token_raw (parser, raw_pos)->type != CPP_COMMA)
-       {
-         raw_pos = 0;
-         break;
-       }
-      raw_pos++;
-    }
-
   bool target = false;
   bool targetsync = false;
   tree prefer_type_tree = NULL_TREE;
 
-  if (raw_pos > 1
-      && (!c_parser_omp_clause_init_modifiers (parser, &target, &targetsync,
-                                              &prefer_type_tree)
-         || !c_parser_require (parser, CPP_COLON, "expected %<:%>")))
+  if (!c_parser_omp_clause_init_modifiers (parser, &target, &targetsync,
+                                          &prefer_type_tree)
+      || !c_parser_require (parser, CPP_COLON, "expected %<:%>"))
     {
       if (prefer_type_tree != error_mark_node)
        parens.skip_until_found_close (parser);
       return list;
     }
 
+  if (!target && !targetsync)
+    error_at (loc,
+             "missing required %<target%> and/or %<targetsync%> modifier");
+
   tree nl = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_INIT, list);
   parens.skip_until_found_close (parser);
 
@@ -26944,6 +26922,10 @@ c_finish_omp_declare_variant (c_parser *parser, tree 
fndecl, tree parms)
                  || !c_parser_require (parser, CPP_CLOSE_PAREN,
                                        "expected %<)%> or %<,%>"))
                goto fail;
+             if (!target && !targetsync)
+               error_at (loc,
+                         "missing required %<target%> and/or "
+                         "%<targetsync%> modifier");
              tree t = build_tree_list (target ? boolean_true_node
                                               : boolean_false_node,
                                        targetsync ? boolean_true_node
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 645f2f8fdcaa..0968478b2979 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -43436,8 +43436,8 @@ cp_parser_omp_clause_init_modifiers (cp_parser *parser, 
bool *target,
   while (true);
 
 fail:
-  cp_parser_error (parser, "%<init%> clause with modifier other than "
-                          "%<prefer_type%>, %<target%> or %<targetsync%>");
+  cp_parser_error (parser,
+                  "expected %<prefer_type%>, %<target%>, or %<targetsync%>");
   return false;
 }
 
@@ -43455,39 +43455,14 @@ cp_parser_omp_clause_init (cp_parser *parser, tree 
list)
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return list;
 
-  unsigned raw_pos = 1;
-  while (cp_lexer_peek_nth_token (parser->lexer, raw_pos)->type == CPP_NAME)
-    {
-      raw_pos++;
-      if (cp_lexer_peek_nth_token (parser->lexer, raw_pos)->type
-         == CPP_OPEN_PAREN)
-       {
-         unsigned n = cp_parser_skip_balanced_tokens (parser, raw_pos);
-         if (n == raw_pos)
-           {
-             raw_pos = 0;
-             break;
-           }
-         raw_pos = n;
-       }
-      if (cp_lexer_peek_nth_token (parser->lexer, raw_pos)->type == CPP_COLON)
-       break;
-      if (cp_lexer_peek_nth_token (parser->lexer, raw_pos)->type != CPP_COMMA)
-       {
-         raw_pos = 0;
-         break;
-       }
-      raw_pos++;
-    }
-
   bool target = false;
   bool targetsync = false;
   tree prefer_type_tree = NULL_TREE;
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
-  if (raw_pos > 1
-      && (!cp_parser_omp_clause_init_modifiers (parser, &target, &targetsync,
-                                              &prefer_type_tree)
-         || !cp_parser_require (parser, CPP_COLON, RT_COLON)))
+  if (!cp_parser_omp_clause_init_modifiers (parser, &target, &targetsync,
+                                           &prefer_type_tree)
+      || !cp_parser_require (parser, CPP_COLON, RT_COLON))
     {
       if (prefer_type_tree == error_mark_node)
        return error_mark_node;
@@ -43497,6 +43472,10 @@ cp_parser_omp_clause_init (cp_parser *parser, tree 
list)
       return list;
     }
 
+  if (!target && !targetsync)
+    error_at (loc,
+             "missing required %<target%> and/or %<targetsync%> modifier");
+
   tree nl = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_INIT, list,
                                            NULL);
   for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
@@ -50970,6 +50949,10 @@ cp_finish_omp_declare_variant (cp_parser *parser, 
cp_token *pragma_tok,
                                                        &targetsync,
                                                        &prefer_type_tree))
                goto fail;
+             if (!target && !targetsync)
+               error_at (loc,
+                         "missing required %<target%> and/or "
+                         "%<targetsync%> modifier");
              tree t = build_tree_list (target ? boolean_true_node
                                               : boolean_false_node,
                                        targetsync ? boolean_true_node
diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index 41778fa0d24f..7fe89b5da237 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -2188,10 +2188,8 @@ gfc_match_omp_prefer_type (char **type_str, int 
*type_str_len)
    the 'interop' directive and the 'append_args' directive of 'declare 
variant'.
      [prefer_type(...)][,][<target|targetsync>, ...])
 
-   If is_init_clause, there might be no modifiers but variables like 'target';
-   additionally, the modifier parsing ends with a ':'.
-   If not is_init_clause (i.e. append_args), there must be modifiers and the
-   parsing ends with ')'.  */
+   If is_init_clause, the modifier parsing ends with a ':'.
+   If not is_init_clause (i.e. append_args), the parsing ends with ')'.  */
 
 static match
 gfc_parser_omp_clause_init_modifiers (bool &target, bool &targetsync,
@@ -2203,9 +2201,10 @@ gfc_parser_omp_clause_init_modifiers (bool &target, bool 
&targetsync,
   *type_str = NULL;
   type_str_len = 0;
   match m;
-  locus old_loc = gfc_current_locus;
-  do {
-       if (gfc_match ("prefer_type ( ") == MATCH_YES)
+
+  do
+    {
+      if (gfc_match ("prefer_type ( ") == MATCH_YES)
        {
          if (*type_str)
            {
@@ -2231,12 +2230,17 @@ gfc_parser_omp_clause_init_modifiers (bool &target, 
bool &targetsync,
            }
          return MATCH_ERROR;
        }
-       if (gfc_match ("targetsync ") == MATCH_YES)
+
+      if (gfc_match ("prefer_type ") == MATCH_YES)
+       {
+         gfc_error ("Expected %<(%> after %<prefer_type%> at %C");
+         return MATCH_ERROR;
+       }
+
+      if (gfc_match ("targetsync ") == MATCH_YES)
        {
          if (targetsync)
            {
-             /* Avoid the word 'modifier' as it could be also be no clauses and
-                twice a variable named 'targetsync', which is also invalid.  */
              gfc_error ("Duplicate %<targetsync%> at %C");
              return MATCH_ERROR;
            }
@@ -2252,13 +2256,6 @@ gfc_parser_omp_clause_init_modifiers (bool &target, bool 
&targetsync,
            }
          if (gfc_match (": ") == MATCH_YES)
            break;
-         gfc_char_t c = gfc_peek_char ();
-         if (!*type_str && (c == ')' || (gfc_current_form != FORM_FREE
-                                         && (c == '_' || ISALPHA (c)))))
-           {
-             gfc_current_locus = old_loc;
-             break;
-           }
          gfc_error ("Expected %<,%> or %<:%> at %C");
          return MATCH_ERROR;
        }
@@ -2281,25 +2278,21 @@ gfc_parser_omp_clause_init_modifiers (bool &target, 
bool &targetsync,
            }
          if (gfc_match (": ") == MATCH_YES)
            break;
-         gfc_char_t c = gfc_peek_char ();
-         if (!*type_str && (c == ')' || (gfc_current_form != FORM_FREE
-                                         && (c == '_' || ISALPHA (c)))))
-           {
-             gfc_current_locus = old_loc;
-             break;
-           }
          gfc_error ("Expected %<,%> or %<:%> at %C");
          return MATCH_ERROR;
        }
-      if (*type_str)
-       {
-         gfc_error ("Expected %<target%> or %<targetsync%> at %C");
-         return MATCH_ERROR;
-       }
-      gfc_current_locus = old_loc;
-      break;
+      gfc_error ("Expected %<prefer_type%>, %<target%>, or %<targetsync%> "
+                "at %C");
+      return MATCH_ERROR;
     }
   while (true);
+
+  if (!target && !targetsync)
+    {
+      gfc_error ("Missing required %<target%> and/or %<targetsync%> "
+                "modifier at %C");
+      return MATCH_ERROR;
+    }
   return MATCH_YES;
 }
 
@@ -2316,17 +2309,17 @@ gfc_match_omp_init (gfc_omp_namelist **list)
                                            type_str_len, true) == MATCH_ERROR)
     return MATCH_ERROR;
 
- gfc_omp_namelist **head = NULL;
- if (gfc_match_omp_variable_list ("", list, false, NULL, &head) != MATCH_YES)
-   return MATCH_ERROR;
- for (gfc_omp_namelist *n = *head; n; n = n->next)
-   {
-     n->u.init.target = target;
-     n->u.init.targetsync = targetsync;
-     n->u.init.len = type_str_len;
-     n->u2.init_interop = type_str;
-   }
- return MATCH_YES;
+  gfc_omp_namelist **head = NULL;
+  if (gfc_match_omp_variable_list ("", list, false, NULL, &head) != MATCH_YES)
+    return MATCH_ERROR;
+  for (gfc_omp_namelist *n = *head; n; n = n->next)
+    {
+      n->u.init.target = target;
+      n->u.init.targetsync = targetsync;
+      n->u.init.len = type_str_len;
+      n->u2.init_interop = type_str;
+    }
+  return MATCH_YES;
 }
 
 
diff --git a/gcc/testsuite/c-c++-common/gomp/append-args-1.c 
b/gcc/testsuite/c-c++-common/gomp/append-args-1.c
index bc2eebb798da..4461de8fa97e 100644
--- a/gcc/testsuite/c-c++-common/gomp/append-args-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/append-args-1.c
@@ -28,12 +28,12 @@ float base1();
 void repl2(int *, int *, omp_interop_t, omp_interop_t);
 #pragma omp declare variant(repl2) match(construct={dispatch}) 
adjust_args(need_device_ptr : y) \
         append_args(interop(target, targetsync, prefer_type(1)), \
-                    interop(prefer_type({fr(3), 
attr("ompx_nop")},{fr(2)},{attr("ompx_all")})))
+                    interop(target, prefer_type({fr(3), 
attr("ompx_nop")},{fr(2)},{attr("ompx_all")})))
 void base2(int *x, int *y);
 
 void repl3(int, omp_interop_t, ...);
 #pragma omp declare variant(repl3) match(construct={dispatch}) \
-        append_args(interop(prefer_type("cuda", "hsa")))
+  append_args(interop(target, prefer_type("cuda", "hsa")))
 void base3(int, ...);
 /* { dg-note "'declare variant' candidate 'repl3' declared here" "" { target c 
} .-2 } */
 /* { dg-note "'declare variant' candidate 'void repl3\\(int, omp_interop_t, 
\\.\\.\\.\\)' declared here" "" { target c++ } .-3 } */
diff --git a/gcc/testsuite/c-c++-common/gomp/append-args-7.c 
b/gcc/testsuite/c-c++-common/gomp/append-args-7.c
index b7dff8a2cb07..d8a853e0140a 100644
--- a/gcc/testsuite/c-c++-common/gomp/append-args-7.c
+++ b/gcc/testsuite/c-c++-common/gomp/append-args-7.c
@@ -20,14 +20,14 @@ void g1(...) { }
 void f2(...) { }
 /* { dg-error "argument 1 of 'f2' must be of 'omp_interop_t'" "" { target c } 
.-1 }  */
 /* { dg-error "argument 1 of 'void f2\\(\\.\\.\\.\\)' must be of 
'omp_interop_t'" "" { target c++ } .-2 }  */
-#pragma omp declare variant(f2) append_args(interop(target), 
interop(prefer_type("cuda"))) \
+#pragma omp declare variant(f2) append_args(interop(target), interop(target, 
prefer_type("cuda"))) \
                                 match(construct={dispatch})
 void g2(...) { }
 /* { dg-note "'append_args' specified here" "" { target *-*-* } .-3 }  */
 
 
 void f3(omp_interop_t, omp_interop_t, ...) { }
-#pragma omp declare variant(f3) append_args(interop(target), 
interop(prefer_type("cuda"))) \
+#pragma omp declare variant(f3) append_args(interop(target), interop(target, 
prefer_type("cuda"))) \
                                 match(construct={dispatch})
 void g3(...) { }
 
diff --git a/gcc/testsuite/c-c++-common/gomp/append-args-8.c 
b/gcc/testsuite/c-c++-common/gomp/append-args-8.c
index fb442db4ae4a..d47faa22c013 100644
--- a/gcc/testsuite/c-c++-common/gomp/append-args-8.c
+++ b/gcc/testsuite/c-c++-common/gomp/append-args-8.c
@@ -14,14 +14,15 @@ typedef enum omp_interop_t __GOMP_UINTPTR_T_ENUM
 
 void f1(omp_interop_t) { }
 #pragma omp declare variant(f1) match(construct={dispatch}) \
-                                
append_args(interop(prefer_type({attr("ompx_fun")})))
+  append_args(interop(target, prefer_type({attr("ompx_fun")})))
 void g1(void);
 
 
 int f2(omp_interop_t, omp_interop_t);
-#pragma omp declare variant(f2) append_args(interop(prefer_type("cuda")), \
-                                            
interop(prefer_type({fr("hsa")}),target)) \
-                                match(construct={dispatch})
+#pragma omp declare variant(f2) \
+  append_args(interop(target, prefer_type("cuda")),                    \
+             interop(prefer_type({fr("hsa")}),target))                 \
+  match(construct={dispatch})
 int g2(void) { return 5; }
 
 int foo (omp_interop_t obj1)
diff --git a/gcc/testsuite/c-c++-common/gomp/append-args-9.c 
b/gcc/testsuite/c-c++-common/gomp/append-args-9.c
index b8586e0f54a9..810ab36828ba 100644
--- a/gcc/testsuite/c-c++-common/gomp/append-args-9.c
+++ b/gcc/testsuite/c-c++-common/gomp/append-args-9.c
@@ -14,14 +14,15 @@ void f1(omp_interop_t *) { }
 /* { dg-error "argument 1 of 'f1' must be of 'omp_interop_t'" "" { target c } 
.-1 }  */
 /* { dg-note "initializing argument 1 of 'void f1\\(omp_interop_t\\*\\)'" "" { 
target c++ } .-2 }  */
 #pragma omp declare variant(f1) match(construct={dispatch}) \
-                                
append_args(interop(prefer_type({attr("ompx_fun")})))
+  append_args(interop(targetsync, prefer_type({attr("ompx_fun")})))
 void g1(void);
 /* { dg-note "'append_args' specified here" "" { target c } .-2 }  */
 /* { dg-error "cannot convert 'omp_interop_t' to 'omp_interop_t\\*'" "" { 
target c++ } .-4 }  */
 
 int f2(omp_interop_t);
-#pragma omp declare variant(f2) append_args(interop(prefer_type("cuda"))) \
-                                match(construct={dispatch})
+#pragma omp declare variant(f2)                                        \
+  append_args(interop(targetsync, prefer_type("cuda")))                \
+  match(construct={dispatch})
 int g2(void) { return 5; }
 
 int foo (omp_interop_t *obj1)
diff --git a/gcc/testsuite/c-c++-common/gomp/interop-1.c 
b/gcc/testsuite/c-c++-common/gomp/interop-1.c
index d68611bfe9c7..2a81d4b75d8f 100644
--- a/gcc/testsuite/c-c++-common/gomp/interop-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/interop-1.c
@@ -40,12 +40,12 @@ void f()
   omp_interop_t obj1, obj2, obj3, obj4, obj5;
   int x;
 
-  #pragma omp interop init(obj1) init(target,targetsync : obj2, obj3) nowait   
// OK
-  #pragma omp interop init(obj1) init (targetsync  : obj2, obj3) nowait   // OK
-  #pragma omp interop init(obj1) init (targetsync , target : obj2, obj3) 
nowait   // OK
+  #pragma omp interop init(targetsync: obj1) init(target,targetsync : obj2, 
obj3) nowait   // OK
+  #pragma omp interop init(target: obj1) init (targetsync  : obj2, obj3) 
nowait   // OK
+  #pragma omp interop init(target: obj1) init (targetsync , target : obj2, 
obj3) nowait   // OK
 
-  #pragma omp interop init(obj1) init(target,targetsync,target: obj2, obj3) 
nowait   // { dg-error "duplicate 'target' modifier" }
-  #pragma omp interop init(obj1) init(target,targetsync, targetsync : obj2, 
obj3) nowait   // { dg-error "duplicate 'targetsync' modifier" }
+  #pragma omp interop init(target: obj1) init(target,targetsync,target: obj2, 
obj3) nowait   // { dg-error "duplicate 'target' modifier" }
+  #pragma omp interop init(target: obj1) init(target,targetsync, targetsync : 
obj2, obj3) nowait   // { dg-error "duplicate 'targetsync' modifier" }
 
   #pragma omp interop init(prefer_type("cuda", omp_ifr_opencl, 
omp_ifr_level_zero, "hsa"), targetsync : obj1) \
                       destroy(obj2, obj3) depend(inout: x) use(obj4, obj5) 
device(device_num: 0)
@@ -54,10 +54,10 @@ void f()
 
   #pragma omp assume contains(interop)
   {
-    #pragma omp interop init(prefer_type("cuða") : obj3)  // { dg-warning 
"unknown foreign runtime identifier 'cu\[^'\]*a'" }
+  #pragma omp interop init(target, prefer_type("cuða") : obj3)  // { 
dg-warning "unknown foreign runtime identifier 'cu\[^'\]*a'" }
   }
 
-  #pragma omp interop init(prefer_type("cu\0da") : obj3) // { dg-error "string 
literal must not contain '\\\\0'" }
+#pragma omp interop init(target, prefer_type("cu\0da") : obj3) // { dg-error 
"string literal must not contain '\\\\0'" }
 
   #pragma omp interop depend(inout: x) , use(obj2), destroy(obj3) //  OK, use 
or destroy might have 'targetsync'
 
@@ -69,49 +69,47 @@ void f()
 
   #pragma omp interop init ( target , prefer_type( { fr("hsa"), 
attr("ompx_nothing") , fr("hsa" ) }) :obj1) // { dg-error "duplicated 'fr' 
preference selector before '\\(' token" }
 
-  #pragma omp interop init ( prefer_type( 4, omp_ifr_hip*4) : obj1)  // { 
dg-warning "unknown foreign runtime identifier '20'" }
-  #pragma omp interop init ( prefer_type( __builtin_sin(3.3) : obj1)
-  // { dg-error "'prefer_type' undeclared \\(first use in this function\\)" "" 
{ target c } .-1 }
-  // { dg-error "'prefer_type' has not been declared" "" { target c++ } .-2 }
-  // { dg-error "expected '\\)' before '\\(' token" "" { target *-*-* } .-3 }
-
-  #pragma omp interop init ( prefer_type( __builtin_sin(3.3) ) : obj1)  // { 
dg-error "expected string literal or constant integer expression before '\\)' 
token" }
-  #pragma omp interop init ( prefer_type( {fr(4 ) }) : obj1) // OK
-  #pragma omp interop init ( prefer_type( {fr("cu\0da" ) }) : obj1) // { 
dg-error "string literal must not contain '\\\\0'" }
-  #pragma omp interop init ( prefer_type( {fr("cuda\0") }) : obj1) // { 
dg-error "string literal must not contain '\\\\0'" }
-  #pragma omp interop init ( prefer_type( {fr("cuda" ) }) : obj1) // OK
-  #pragma omp interop init ( prefer_type( {fr(omp_ifr_level_zero ) }, 
{fr(omp_ifr_hip)}) : obj1) // OK
-  #pragma omp interop init ( prefer_type( {fr("cuda",  "cuda_driver") }) : 
obj1) // { dg-error "53: expected '\\)' before ',' token" }
-  #pragma omp interop init ( prefer_type( {fr(my_string) }) : obj1) // { 
dg-error "56: expected string literal or constant integer expression before 
'\\)' token" }
-  #pragma omp interop init ( prefer_type( {fr("hello" }) : obj1) // { dg-error 
"expected '\\)' before '\\(' token" }
-  // { dg-error "'prefer_type' has not been declared" "" { target c++ } .-1 }
-  #pragma omp interop init ( prefer_type( {fr("hello") }) : obj1)
+  #pragma omp interop init (target,  prefer_type( 4, omp_ifr_hip*4) : obj1)  
// { dg-warning "unknown foreign runtime identifier '20'" }
+  #pragma omp interop init (prefer_type( __builtin_sin(3.3), target : obj1)
+  // { dg-error "expected string literal or constant integer expression" "" { 
target *-*-* } .-1 }
+
+#pragma omp interop init (prefer_type( __builtin_sin(3.3)), target : obj1)  // 
{ dg-error "expected string literal or constant integer expression before '\\)' 
token" }
+  #pragma omp interop init (target, prefer_type( {fr(4 ) }) : obj1) // OK
+  #pragma omp interop init (target, prefer_type( {fr("cu\0da" ) }) : obj1) // 
{ dg-error "string literal must not contain '\\\\0'" }
+  #pragma omp interop init (target, prefer_type( {fr("cuda\0") }) : obj1) // { 
dg-error "string literal must not contain '\\\\0'" }
+  #pragma omp interop init (target, prefer_type( {fr("cuda" ) }) : obj1) // OK
+  #pragma omp interop init (target, prefer_type( {fr(omp_ifr_level_zero ) }, 
{fr(omp_ifr_hip)}) : obj1) // OK
+  #pragma omp interop init (target, prefer_type( {fr("cuda",  "cuda_driver") 
}) : obj1) // { dg-error "60: expected '\\)' before ',' token" }
+  #pragma omp interop init (target, prefer_type( {fr(my_string) }) : obj1) // 
{ dg-error "63: expected string literal or constant integer expression before 
'\\)' token" }
+  #pragma omp interop init (target, prefer_type( {fr("hello" }) : obj1) // { 
dg-error "expected '\\)' before '\}' token" }
+  /* { dg-warning "unknown foreign runtime identifier 'hello' 
\\\[-Wopenmp\\\]" "" { target *-*-* } .-1 }  */
+  #pragma omp interop init (target, prefer_type( {fr("hello") }) : obj1)
   /* { dg-warning "unknown foreign runtime identifier 'hello' 
\\\[-Wopenmp\\\]" "" { target *-*-* } .-1 }  */
 
-  #pragma omp interop init ( prefer_type( {fr(x) }) : obj1) // { dg-error 
"expected string literal or constant integer expression before '\\)' token" }
+  #pragma omp interop init (target, prefer_type( {fr(x) }) : obj1) // { 
dg-error "expected string literal or constant integer expression before '\\)' 
token" }
 
-  #pragma omp interop init ( prefer_type( {fr(ifr_scalar ) }) : obj1) // OK
-  #pragma omp interop init ( prefer_type( {fr(ifr_array ) }) : obj1) // { 
dg-error "expected string literal or constant integer expression before '\\)' 
token" }
+  #pragma omp interop init (target, prefer_type( {fr(ifr_scalar ) }) : obj1) 
// OK
+  #pragma omp interop init (target, prefer_type( {fr(ifr_array ) }) : obj1) // 
{ dg-error "expected string literal or constant integer expression before '\\)' 
token" }
   // OK in C++, for C: constexpr arrays are not part of C23; however, they 
are/were under consideration for C2y.
-  #pragma omp interop init ( prefer_type( {fr(ifr_array[0] ) }) : obj1)
+  #pragma omp interop init (target, prefer_type( {fr(ifr_array[0] ) }) : obj1)
   // { dg-error "expected string literal or constant integer expression before 
'\\)' token" "" { target c } .-1 }
 
-  #pragma omp interop init ( prefer_type( omp_ifr_level_zero, omp_ifr_hip ) : 
obj1) // OK
-  #pragma omp interop init ( prefer_type( omp_ifr_level_zero +1 ) : obj1) // OK
-  #pragma omp interop init ( prefer_type( x ) : obj1) // { dg-error "expected 
string literal or constant integer expression before '\\)' token" }
+  #pragma omp interop init (target, prefer_type( omp_ifr_level_zero, 
omp_ifr_hip ) : obj1) // OK
+  #pragma omp interop init (target, prefer_type( omp_ifr_level_zero +1 ) : 
obj1) // OK
+  #pragma omp interop init (target, prefer_type( x ) : obj1) // { dg-error 
"expected string literal or constant integer expression before '\\)' token" }
 
-  #pragma omp interop init ( prefer_type( ifr_scalar ) : obj1) // OK
-  #pragma omp interop init ( prefer_type( ifr_array ) : obj1) // { dg-error 
"expected string literal or constant integer expression before '\\)' token" }
+  #pragma omp interop init (target, prefer_type( ifr_scalar ) : obj1) // OK
+  #pragma omp interop init (target, prefer_type( ifr_array ) : obj1) // { 
dg-error "expected string literal or constant integer expression before '\\)' 
token" }
   // OK in C++, for C: constexpr arrays are not part of C23; however, they 
are/were under consideration for C2y.
-  #pragma omp interop init ( prefer_type( ifr_array[1] ) : obj1)
+  #pragma omp interop init (target, prefer_type( ifr_array[1] ) : obj1)
   // { dg-error "expected string literal or constant integer expression before 
'\\)' token" "" { target c } .-1 }
 
-  #pragma omp interop init ( prefer_type( 4, omp_ifr_hip*4) : obj1) // { 
dg-warning "unknown foreign runtime identifier '20'" }
-  #pragma omp interop init ( prefer_type( 4, 1, 3) : obj1)
+  #pragma omp interop init (target, prefer_type( 4, omp_ifr_hip*4) : obj1) // 
{ dg-warning "unknown foreign runtime identifier '20'" }
+  #pragma omp interop init (target, prefer_type( 4, 1, 3) : obj1)
 
-  #pragma omp interop init ( prefer_type( {fr("cuda") }, {fr(omp_ifr_hsa)} , 
{attr("ompx_a") } , {fr(omp_ifr_hip) }) : obj1)
-  #pragma omp interop init ( prefer_type( {fr("cuda") }, 
{fr(omp_ifr_hsa,omp_ifr_level_zero)} , {attr("ompx_a") } , {fr(omp_ifr_hip) }) 
: obj1) // { dg-error "73: expected '\\)' before ',' token" }
-  #pragma omp interop init ( prefer_type( {fr("cuda",5) }, 
{fr(omp_ifr_hsa,omp_ifr_level_zero)} , {attr("ompx_a") } , {fr(omp_ifr_hip) }) 
: obj1) // { dg-error "53: expected '\\)' before ',' token" }
-  #pragma omp interop init ( prefer_type( {fr("sycl"), attr("ompx_1", 
"ompx_2"), attr("ompx_3") }, {attr("ompx_4", "ompx_5"),fr(omp_ifr_level_zero)} 
) : obj1)
-  #pragma omp interop init ( prefer_type( { fr(5), attr("ompx_1") }, 
{fr(omp_ifr_hsa)} , {attr("ompx_a") } ) : obj1)
+  #pragma omp interop init (target, prefer_type( {fr("cuda") }, 
{fr(omp_ifr_hsa)} , {attr("ompx_a") } , {fr(omp_ifr_hip) }) : obj1)
+  #pragma omp interop init (target, prefer_type( {fr("cuda") }, 
{fr(omp_ifr_hsa,omp_ifr_level_zero)} , {attr("ompx_a") } , {fr(omp_ifr_hip) }) 
: obj1) // { dg-error "80: expected '\\)' before ',' token" }
+  #pragma omp interop init (target, prefer_type( {fr("cuda",5) }, 
{fr(omp_ifr_hsa,omp_ifr_level_zero)} , {attr("ompx_a") } , {fr(omp_ifr_hip) }) 
: obj1) // { dg-error "60: expected '\\)' before ',' token" }
+  #pragma omp interop init (target, prefer_type( {fr("sycl"), attr("ompx_1", 
"ompx_2"), attr("ompx_3") }, {attr("ompx_4", "ompx_5"),fr(omp_ifr_level_zero)} 
) : obj1)
+  #pragma omp interop init (target, prefer_type( { fr(5), attr("ompx_1") }, 
{fr(omp_ifr_hsa)} , {attr("ompx_a") } ) : obj1)
 }
diff --git a/gcc/testsuite/c-c++-common/gomp/interop-2.c 
b/gcc/testsuite/c-c++-common/gomp/interop-2.c
index af81cc673608..3e6ed81d0143 100644
--- a/gcc/testsuite/c-c++-common/gomp/interop-2.c
+++ b/gcc/testsuite/c-c++-common/gomp/interop-2.c
@@ -41,18 +41,18 @@ void f(const omp_interop_t ocp)
   short o2;
   float of;
 
-  #pragma omp interop init (ocp)  // { dg-error "'ocp' shall not be const" }
-  #pragma omp interop init (oce)  // { dg-error "'oce' shall not be const" }
-  #pragma omp interop init (occ)  // { dg-error "'occ' shall not be const" }
-  #pragma omp interop init (od)   // { dg-error "'od' must be of 
'omp_interop_t'" }
-  #pragma omp interop init (od[1])// { dg-error "expected '\\)' before '\\\[' 
token" }
+  #pragma omp interop init (targetsync: ocp)  // { dg-error "'ocp' shall not 
be const" }
+  #pragma omp interop init (targetsync: oce)  // { dg-error "'oce' shall not 
be const" }
+  #pragma omp interop init (targetsync: occ)  // { dg-error "'occ' shall not 
be const" }
+  #pragma omp interop init (targetsync: od)   // { dg-error "'od' must be of 
'omp_interop_t'" }
+  #pragma omp interop init (targetsync: od[1])// { dg-error "expected '\\)' 
before '\\\[' token" }
                                   // { dg-error "'od' must be of 
'omp_interop_t'" "" { target *-*-* } .-1 }
-  #pragma omp interop init (op)   // { dg-error "'op' must be of 
'omp_interop_t'" }
-  #pragma omp interop init (*op)
+  #pragma omp interop init (targetsync: op)   // { dg-error "'op' must be of 
'omp_interop_t'" }
+  #pragma omp interop init (targetsync: *op)
   // { dg-error "expected identifier before '\\*' token" "" { target c } .-1 }
   // { dg-error "expected unqualified-id before '\\*' token" "" { target c++ } 
.-2 }
-  #pragma omp interop init (o2)   // { dg-error "'o2' must be of 
'omp_interop_t'" }
-  #pragma omp interop init (of)   // { dg-error "'of' must be of 
'omp_interop_t'" }
+  #pragma omp interop init (targetsync: o2)   // { dg-error "'o2' must be of 
'omp_interop_t'" }
+  #pragma omp interop init (targetsync: of)   // { dg-error "'of' must be of 
'omp_interop_t'" }
 
   #pragma omp interop use (ocp)  // OK
   #pragma omp interop use (oce)  // odd but okay
@@ -86,40 +86,26 @@ void g()
   omp_interop_t obj1, obj2, obj3, obj4, obj5;
   int x;
 
-  #pragma omp interop init ( prefer_type( {fr("") }) : obj1)  // { dg-error 
"non-empty string literal expected before '\\)' token" }
-  #pragma omp interop init ( prefer_type( {fr("hip") , attr(omp_ifr_cuda) }) : 
obj1) ! { dg-error "expected string literal before 'omp_ifr_cuda'" }
+  #pragma omp interop init (target, prefer_type( {fr("") }) : obj1)  // { 
dg-error "non-empty string literal expected before '\\)' token" }
+  #pragma omp interop init (target, prefer_type( {fr("hip") , 
attr(omp_ifr_cuda) }) : obj1) ! { dg-error "expected string literal before 
'omp_ifr_cuda'" }
 
-  #pragma omp interop init ( prefer_type( {fr("hip") , attr("myooption") }) : 
obj1)  // { dg-error "'attr' string literal must start with 'ompx_'" }
-  #pragma omp interop init ( prefer_type( {fr("hip") , attr("ompx_option") , 
attr("ompx_") } ) : obj1)
-  #pragma omp interop init ( prefer_type( {fr("hip") , attr("ompx_option") }, 
{ attr("ompx_") } ) : obj1)
-  #pragma omp interop init ( prefer_type( {fr("hip") , attr("ompx_option") }  
{ attr("ompx_") } ) : obj1)  // { dg-error "expected '\\)' or ',' before '\{' 
token" }
-  #pragma omp interop init ( prefer_type( {fr("hip") , attr("ompx_option")   ) 
: obj1)
-  // { dg-error "expected ',' or '\}' before '\\)' token" "" { target c } .-1 }
-  // { dg-error "prefer_type' has not been declared" "" { target c++ } .-2 }
-  // { dg-error "expected '\\)' before '\\(' token" "" { target c++ } .-3 }
+  #pragma omp interop init (target, prefer_type( {fr("hip") , 
attr("myooption") }) : obj1)  // { dg-error "'attr' string literal must start 
with 'ompx_'" }
+  #pragma omp interop init (target, prefer_type( {fr("hip") , 
attr("ompx_option") , attr("ompx_") } ) : obj1)
+  #pragma omp interop init (target, prefer_type( {fr("hip") , 
attr("ompx_option") }, { attr("ompx_") } ) : obj1)
+  #pragma omp interop init (target, prefer_type( {fr("hip") , 
attr("ompx_option") }  { attr("ompx_") } ) : obj1)  // { dg-error "expected 
'\\)' or ',' before '\{' token" }
+  #pragma omp interop init (target, prefer_type( {fr("hip") , 
attr("ompx_option")   ) : obj1)  // { dg-error "expected ',' or '\}' before 
'\\)' token" }
 
-  #pragma omp interop init ( prefer_type( {fr("hip") attr("ompx_option")   ) : 
obj1)
-  // { dg-error "expected ',' or '\}' before 'attr'" "" { target c } .-1 }
-  // { dg-error "prefer_type' has not been declared" "" { target c++ } .-2 }
-  // { dg-error "expected '\\)' before '\\(' token" "" { target c++ } .-3 }
-  #pragma omp interop init ( prefer_type( {fr("hip")}), prefer_type("cuda") : 
obj1)  // { dg-error "duplicate 'prefer_type' modifier" }
+  #pragma omp interop init (target, prefer_type( {fr("hip") 
attr("ompx_option")   ) : obj1) // { dg-error "expected ',' or '\}' before 
'attr'" }
+  #pragma omp interop init (target, prefer_type( {fr("hip")}), 
prefer_type("cuda") : obj1)  // { dg-error "duplicate 'prefer_type' modifier" }
 
-  #pragma omp interop init ( prefer_type( {attr("ompx_option1,ompx_option2") } 
) : obj1)  // { dg-error "'attr' string literal must not contain a comma" }
+  #pragma omp interop init (target, prefer_type( 
{attr("ompx_option1,ompx_option2") } ) : obj1)  // { dg-error "'attr' string 
literal must not contain a comma" }
 
-  #pragma omp interop init ( prefer_type( {attr("ompx_option1,ompx_option2")   
) : obj1)
-  // { dg-error "'attr' string literal must not contain a comma" "" { target c 
} .-1 }
-  // { dg-error "prefer_type' has not been declared" "" { target c++ } .-2 }
-  // { dg-error "expected '\\)' before '\\(' token" "" { target c++ } .-3 }
+  #pragma omp interop init (target, prefer_type( 
{attr("ompx_option1,ompx_option2")   ) : obj1) // { dg-error "'attr' string 
literal must not contain a comma" }
 
   #pragma omp interop init ( targetsync other ) : obj1)
-  // { dg-error "'targetsync' undeclared \\(first use in this function\\)" "" 
{ target c } .-1 }
-  // { dg-error "'targetsync' has not been declared" "" { target c++ } .-2 }
-  // { dg-error "expected '\\)' before 'other'" "" { target *-*-* } .-3 }
-  // { dg-error "expected an OpenMP clause before ':' token" "" { target *-*-* 
} .-4 }
-
-  #pragma omp interop init ( prefer_type( {fr("cuda") } ), other : obj1)   // 
{ dg-error "'init' clause with modifier other than 'prefer_type', 'target' or 
'targetsync' before 'other'" }
-  #pragma omp interop init ( prefer_type( {fr("cuda") } ), obj1)
-  // { dg-error "'prefer_type' undeclared \\(first use in this function\\)" "" 
{ target c } .-1 }
-  // { dg-error "'prefer_type' has not been declared" "" { target c++ } .-2 }
-  // { dg-error "expected '\\)' before '\\(' token" "" { target *-*-* } .-3 }
+  // { dg-error "expected an OpenMP clause before ':' token" "" { target *-*-* 
} .-1 }
+  // { dg-error "expected ':' before 'other'" ""  { target *-*-* } .-2 }
+
+  #pragma omp interop init (target, prefer_type( {fr("cuda") } ), other : 
obj1)   // { dg-error "expected 'prefer_type', 'target', or 'targetsync'" }
+  #pragma omp interop init (prefer_type( {fr("cuda") } ), obj1) // { dg-error 
"expected 'prefer_type', 'target', or 'targetsync'" }
 }
diff --git a/gcc/testsuite/c-c++-common/gomp/interop-3.c 
b/gcc/testsuite/c-c++-common/gomp/interop-3.c
index 51d26dd179ea..38d7f658ac28 100644
--- a/gcc/testsuite/c-c++-common/gomp/interop-3.c
+++ b/gcc/testsuite/c-c++-common/gomp/interop-3.c
@@ -34,17 +34,17 @@ void f()
   omp_interop_t target, targetsync, prefer_type;
   int x;
 
-  #pragma omp interop init(obj1) init(target,targetsync : obj2, obj3) nowait
+#pragma omp interop init(target: obj1) init(target,targetsync : obj2, obj3) 
nowait
 
   #pragma omp interop init(prefer_type("cuda", omp_ifr_opencl, 
omp_ifr_level_zero, "hsa"), targetsync : obj1) \
                       destroy(obj2, obj3) depend(inout: x) use(obj4, obj5) 
device(device_num: 0)
 
   #pragma omp assume contains(interop)
     {
-    #pragma omp interop init(prefer_type("cu da") : obj3)  // { dg-warning 
"unknown foreign runtime identifier 'cu da'" }
+  #pragma omp interop init(prefer_type("cu da"), targetsync : obj3)  // { 
dg-warning "unknown foreign runtime identifier 'cu da'" }
     }
 
-  #pragma omp interop init(obj1, obj2, obj1), use(obj4) destroy(obj4)
+  #pragma omp interop init(target: obj1, obj2, obj1), use(obj4) destroy(obj4)
   // { dg-error "'obj4' appears more than once in action clauses" "" { target 
*-*-* } .-1 }
   // { dg-error "'obj1' appears more than once in action clauses" "" { target 
*-*-* } .-2 }
 
@@ -54,27 +54,21 @@ void f()
 
   #pragma omp interop depend(inout: x) use(obj2), destroy(obj3) //  Likewise
 
-  #pragma omp interop depend(inout: x) use(obj2), destroy(obj3) init(obj4) // 
{ dg-error "'depend' clause requires action clauses with 'targetsync' 
interop-type" }
+  #pragma omp interop depend(inout: x) use(obj2), destroy(obj3) init(target: 
obj4) // { dg-error "'depend' clause requires action clauses with 'targetsync' 
interop-type" }
   // { dg-note "69: 'init' clause lacks the 'targetsync' modifier" "" { target 
c } .-1 }
-  // { dg-note "70: 'init' clause lacks the 'targetsync' modifier" "" { target 
c++ } .-2 }
+  // { dg-note "78: 'init' clause lacks the 'targetsync' modifier" "" { target 
c++ } .-2 }
 
-  #pragma omp interop depend(inout: x) init(targetsync : obj5)  use(obj2), 
destroy(obj3) init(obj4) // { dg-error "'depend' clause requires action clauses 
with 'targetsync' interop-type" }
+  #pragma omp interop depend(inout: x) init(targetsync : obj5)  use(obj2), 
destroy(obj3) init(target : obj4) // { dg-error "'depend' clause requires 
action clauses with 'targetsync' interop-type" }
   // { dg-note "'init' clause lacks the 'targetsync' modifier" "" { target 
*-*-* } .-1 }
   #pragma omp interop depend(inout: x) init(targetsync : obj5)  use(obj2), 
destroy(obj3) init(prefer_type("cuda"), targetsync : obj4) // OK
 
-  #pragma omp interop init(target, targetsync, prefer_type, obj1)
-  #pragma omp interop init(prefer_type, obj1, target, targetsync)
+  #pragma omp interop init(target, targetsync, prefer_type, obj1) // { 
dg-error "59: expected '\\(' before ',' token" }
+  #pragma omp interop init(prefer_type, obj1, target, targetsync) // { 
dg-error "39: expected '\\(' before ',' token" }
 
 // Duplicated variable name or duplicated modifier:
   #pragma omp interop init(target, targetsync,target : obj1)  // { dg-error 
"duplicate 'target' modifier" }
-  #pragma omp interop init(target, targetsync,target)         // { dg-error 
"'target' appears more than once in action clauses" }
+#pragma omp interop init(target, targetsync,target: obj1)     // { dg-error 
"duplicate 'target' modifier" }
   #pragma omp interop init(target : target, targetsync,target)  // { dg-error 
"'target' appears more than once in action clauses" }
 
-  #pragma omp interop init(target, targetsync,targetsync : obj1)  // { 
dg-error "duplicate 'targetsync' modifier" }
-  #pragma omp interop init(target, targetsync,targetsync)         // { 
dg-error "targetsync' appears more than once in action clause" }
-  #pragma omp interop init(target : target, targetsync,targetsync)  // { 
dg-error "targetsync' appears more than once in action clause" }
-
-  #pragma omp interop init(, targetsync, prefer_type, obj1, target)
-  // { dg-error "expected identifier before ',' token" "" { target c } .-1 }
-  // { dg-error "expected unqualified-id before ',' token" "" { target c++ } 
.-2 }
+  #pragma omp interop init(, targetsync, prefer_type, obj1, target)   // { 
dg-error "expected 'prefer_type', 'target', or 'targetsync'" }
 }
diff --git a/gcc/testsuite/c-c++-common/gomp/interop-4.c 
b/gcc/testsuite/c-c++-common/gomp/interop-4.c
index 138f293f2ac7..3634cf38c30e 100644
--- a/gcc/testsuite/c-c++-common/gomp/interop-4.c
+++ b/gcc/testsuite/c-c++-common/gomp/interop-4.c
@@ -34,14 +34,14 @@ f()
   omp_interop_t obj1, obj2, obj3, obj4, obj5, obj6, obj7;
   int x[6];
 
-  #pragma omp interop init ( obj1, obj2) use (obj3) destroy(obj4) init(obj5) 
destroy(obj6) use(obj7)
-  /* { dg-final { scan-tree-dump-times "#pragma omp interop use\\(obj7\\) 
destroy\\(obj6\\) init\\(obj5\\) destroy\\(obj4\\) use\\(obj3\\) init\\(obj2\\) 
init\\(obj1\\)\[\r\n\]" 1 "original" } }  */
+#pragma omp interop init (target: obj1, obj2) use (obj3) destroy(obj4) 
init(targetsync: obj5) destroy(obj6) use(obj7)
+  /* { dg-final { scan-tree-dump-times "#pragma omp interop use\\(obj7\\) 
destroy\\(obj6\\) init\\(targetsync: obj5\\) destroy\\(obj4\\) use\\(obj3\\) 
init\\(target: obj2\\) init\\(target: obj1\\)\[\r\n\]" 1 "original" } }  */
 
   #pragma omp interop nowait init (targetsync : obj1, obj2) use (obj3) 
destroy(obj4) init(target, targetsync : obj5) destroy(obj6) use(obj7) 
depend(inout: x)  
   /* { dg-final { scan-tree-dump-times "#pragma omp interop 
depend\\(inout:x\\) use\\(obj7\\) destroy\\(obj6\\) init\\(target, targetsync: 
obj5\\) destroy\\(obj4\\) use\\(obj3\\) init\\(targetsync: obj2\\) 
init\\(targetsync: obj1\\) nowait\[\r\n\]" 1 "original" } }  */
 
-  #pragma omp interop init ( obj1, obj2) init (target: obj3) init(targetsync : 
obj4) init(target,targetsync: obj5)  
-  /* { dg-final { scan-tree-dump-times "#pragma omp interop init\\(target, 
targetsync: obj5\\) init\\(targetsync: obj4\\) init\\(target: obj3\\) 
init\\(obj2\\) init\\(obj1\\)\[\r\n\]" 1 "original" } }  */
+#pragma omp interop init (target: obj1, obj2) init (target: obj3) 
init(targetsync : obj4) init(target,targetsync: obj5)  
+  /* { dg-final { scan-tree-dump-times "#pragma omp interop init\\(target, 
targetsync: obj5\\) init\\(targetsync: obj4\\) init\\(target: obj3\\) 
init\\(target: obj2\\) init\\(target: obj1\\)\[\r\n\]" 1 "original" } }  */
 
   /* --------------------------------------------  */
 
diff --git a/gcc/testsuite/c-c++-common/gomp/pr118965-1.c 
b/gcc/testsuite/c-c++-common/gomp/pr118965-1.c
new file mode 100644
index 000000000000..2014b9444378
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr118965-1.c
@@ -0,0 +1,57 @@
+/* { dg-do compile } */
+
+/* At least one of the target and/or targetsync modifiers must be provided.
+   This implies that there are always modifiers required, and the parser
+   should reject e.g. "init (var1, var2)"; the first thing in the list is
+   always an init_modifier in valid code.  */
+
+/* The following definitions are in omp_lib, which cannot be included
+   in gcc/testsuite/  */
+
+#if __cplusplus >= 201103L
+# define __GOMP_UINTPTR_T_ENUM : __UINTPTR_TYPE__
+#else
+# define __GOMP_UINTPTR_T_ENUM
+#endif
+
+typedef enum omp_interop_t __GOMP_UINTPTR_T_ENUM
+{
+  omp_interop_none = 0,
+  __omp_interop_t_max__ = __UINTPTR_MAX__
+} omp_interop_t;
+
+typedef enum omp_interop_fr_t
+{
+  omp_ifr_cuda = 1,
+  omp_ifr_cuda_driver = 2,
+  omp_ifr_opencl = 3,
+  omp_ifr_sycl = 4,
+  omp_ifr_hip = 5,
+  omp_ifr_level_zero = 6,
+  omp_ifr_hsa = 7,
+  omp_ifr_last = omp_ifr_hsa
+} omp_interop_fr_t;
+
+// ---------------------------------
+
+void f()
+{
+  omp_interop_t obj1, obj2;
+
+  #pragma omp interop init (obj1) // { dg-error "expected 'prefer_type', 
'target', or 'targetsync'" }
+  #pragma omp interop init (obj1, obj2) // { dg-error "expected 'prefer_type', 
'target', or 'targetsync'" }
+  #pragma omp interop init (obj1, target) // { dg-error "expected 
'prefer_type', 'target', or 'targetsync'" }
+  #pragma omp interop init (target, obj1) // { dg-error "expected 
'prefer_type', 'target', or 'targetsync'" }
+  #pragma omp interop init (obj1, targetsync) // { dg-error "expected 
'prefer_type', 'target', or 'targetsync'" }
+  #pragma omp interop init (targetsync, obj1) // { dg-error "expected 
'prefer_type', 'target', or 'targetsync'" }
+  #pragma omp interop init (targetsync, target) // { dg-error "expected ':' 
before '\\)' token" }
+
+  #pragma omp interop init (target, prefer_type( {fr(4 ) }) : obj1) // OK
+  #pragma omp interop init (targetsync, prefer_type( {fr(4 ) }) : obj1) // OK
+  #pragma omp interop init (prefer_type( {fr(4 ) }), target : obj1) // OK
+
+  #pragma omp interop init (prefer_type( {fr(4 ) }) : obj1) // { dg-error 
"missing required 'target' and/or 'targetsync' modifier" }
+  #pragma omp interop init (prefer_type( {fr(4 ) }) : foobar) // { dg-error 
"missing required 'target' and/or 'targetsync' modifier" }  
+  // { dg-error "'foobar' undeclared" "" { target c } .-1 }
+  // { dg-error "'foobar' has not been declared" "" { target c++ } .-2 }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/pr118965-2.c 
b/gcc/testsuite/c-c++-common/gomp/pr118965-2.c
new file mode 100644
index 000000000000..6e27179b85db
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr118965-2.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+
+/* At least one of the target and/or targetsync modifiers must be provided.  */
+
+#if __cplusplus >= 201103L
+# define __GOMP_UINTPTR_T_ENUM : __UINTPTR_TYPE__
+#else
+# define __GOMP_UINTPTR_T_ENUM
+#endif
+
+typedef enum omp_interop_t __GOMP_UINTPTR_T_ENUM
+{
+  omp_interop_none = 0,
+  __omp_interop_t_max__ = __UINTPTR_MAX__
+} omp_interop_t;
+
+void f1(omp_interop_t) { }
+#pragma omp declare variant(f1) match(construct={dispatch}) \
+  append_args(interop(prefer_type({attr("ompx_fun")})))
+// { dg-error "missing required 'target' and/or 'targetsync' modifier" ""  { 
target *-*-* } .-1 }
+void g1(void);
+
+
+int f2(omp_interop_t, omp_interop_t);
+#pragma omp declare variant(f2) \
+  append_args(interop(prefer_type("cuda")),                    \
+             interop(prefer_type({fr("hsa")})))                        \
+  match(construct={dispatch})
+// { dg-error "missing required 'target' and/or 'targetsync' modifier" ""  { 
target *-*-* } .-3 }
+// { dg-error "missing required 'target' and/or 'targetsync' modifier" ""  { 
target *-*-* } .-3 }
+int g2(void) { return 5; }
diff --git a/gcc/testsuite/g++.dg/gomp/append-args-1.C 
b/gcc/testsuite/g++.dg/gomp/append-args-1.C
index dd52fb90fc1c..3392293e0846 100644
--- a/gcc/testsuite/g++.dg/gomp/append-args-1.C
+++ b/gcc/testsuite/g++.dg/gomp/append-args-1.C
@@ -49,7 +49,7 @@ template<typename T, typename T2, typename T3>
 void repl2(T, T2, T3, T3);
 #pragma omp declare variant(repl2) match(construct={dispatch}) 
adjust_args(need_device_ptr : y) \
         append_args(interop(target, targetsync, prefer_type(1)), \
-                    interop(prefer_type({fr(3), 
attr("ompx_nop")},{fr(2)},{attr("ompx_all")})))
+                    interop(target, prefer_type({fr(3), 
attr("ompx_nop")},{fr(2)},{attr("ompx_all")})))
 template<typename T, typename T2>
 void base2(T x, T2 y);
 
@@ -58,7 +58,7 @@ template<typename T,typename T3>
 void tooFewRepl(T, T, T3);
 #pragma omp declare variant(tooFewRepl) match(construct={dispatch}) \
         append_args(interop(target, targetsync, prefer_type(1)), \
-                    interop(prefer_type({fr(3), 
attr("ompx_nop")},{fr(2)},{attr("ompx_all")})))
+                    interop(target, prefer_type({fr(3), 
attr("ompx_nop")},{fr(2)},{attr("ompx_all")})))
 template<typename T, typename T2>
 void tooFewBase(T x, T2 y);
 
@@ -72,7 +72,7 @@ void tooFewBase(T x, T2 y);
 template<typename T, typename T2>
 void repl3(T, T2, ...);
 #pragma omp declare variant(repl3) match(construct={dispatch}) \
-        append_args(interop(prefer_type("cuda", "hsa")))
+       append_args(interop(target, prefer_type("cuda", "hsa")))
 template<typename T>
 void base3(T, ...);
 
diff --git a/gcc/testsuite/g++.dg/gomp/append-args-2.C 
b/gcc/testsuite/g++.dg/gomp/append-args-2.C
index 33cd268e7992..62f01771eef9 100644
--- a/gcc/testsuite/g++.dg/gomp/append-args-2.C
+++ b/gcc/testsuite/g++.dg/gomp/append-args-2.C
@@ -30,7 +30,7 @@ template<typename T, typename T2, typename T3>
 void repl2(T, T2, T3, T3);  /* { dg-error "argument 3 of 'repl2' must be of 
'omp_interop_t'" }  */
 #pragma omp declare variant(repl2) match(construct={dispatch}) 
adjust_args(need_device_ptr : y) \
         append_args(interop(target, targetsync, prefer_type(1)),  /* { dg-note 
"'append_args' specified here" }  */ \
-                    interop(prefer_type({fr(3), 
attr("ompx_nop")},{fr(2)},{attr("ompx_all")})))
+                    interop(target, prefer_type({fr(3), 
attr("ompx_nop")},{fr(2)},{attr("ompx_all")})))
 template<typename T, typename T2>
 void base2(T x, T2 y);
 
@@ -39,7 +39,7 @@ template<typename T,typename T3>
 void tooFewRepl(T, T, T3);  /* { dg-error "argument 3 of 'tooFewRepl' must be 
of 'omp_interop_t'" }  */
 #pragma omp declare variant(tooFewRepl) match(construct={dispatch}) \
         append_args(interop(target, targetsync, prefer_type(1)),  /* { dg-note 
"'append_args' specified here" }  */ \
-                    interop(prefer_type({fr(3), 
attr("ompx_nop")},{fr(2)},{attr("ompx_all")})))
+                    interop(target, prefer_type({fr(3), 
attr("ompx_nop")},{fr(2)},{attr("ompx_all")})))
 template<typename T, typename T2>
 void tooFewBase(T x, T2 y);
 
@@ -48,6 +48,6 @@ void tooFewBase(T x, T2 y);
 template<typename T, typename T2>
 void repl3(T, T2, ...);  /* { dg-error "argument 2 of 'repl3' must be of 
'omp_interop_t'" }  */
 #pragma omp declare variant(repl3) match(construct={dispatch}) \
-        append_args(interop(prefer_type("cuda", "hsa")))  /* { dg-note 
"'append_args' specified here" }  */
+       append_args(interop(target, prefer_type("cuda", "hsa")))  /* { dg-note 
"'append_args' specified here" }  */
 template<typename T>
 void base3(T, ...);
diff --git a/gcc/testsuite/g++.dg/gomp/append-args-6.C 
b/gcc/testsuite/g++.dg/gomp/append-args-6.C
index 039d9faaf04d..a97a01575732 100644
--- a/gcc/testsuite/g++.dg/gomp/append-args-6.C
+++ b/gcc/testsuite/g++.dg/gomp/append-args-6.C
@@ -14,13 +14,13 @@ void f1(omp_interop_t &) { }
 /* { dg-error "argument 1 of 'f1' must be of 'omp_interop_t'" "" { target c } 
.-1 }  */
 /* { dg-note "initializing argument 1 of 'void f1\\(omp_interop_t&\\)'" "" { 
target c++ } .-2 }  */
 #pragma omp declare variant(f1) match(construct={dispatch}) \
-                                
append_args(interop(prefer_type({attr("ompx_fun")})))
+       append_args(interop(targetsync, prefer_type({attr("ompx_fun")})))
 void g1(void);
 /* { dg-note "'append_args' specified here" "" { target c } .-2 }  */
 /* { dg-error "cannot bind non-const lvalue reference of type 'omp_interop_t&' 
to an rvalue of type 'omp_interop_t'" "" { target c++ } .-4 }  */
 
 int f2(omp_interop_t);
-#pragma omp declare variant(f2) append_args(interop(prefer_type("cuda"))) \
+#pragma omp declare variant(f2) append_args(interop(targetsync, 
prefer_type("cuda"))) \
                                 match(construct={dispatch})
 int g2(void) { return 5; }
 
diff --git a/gcc/testsuite/g++.dg/gomp/append-args-7.C 
b/gcc/testsuite/g++.dg/gomp/append-args-7.C
index 97df32ea2475..7c70731da752 100644
--- a/gcc/testsuite/g++.dg/gomp/append-args-7.C
+++ b/gcc/testsuite/g++.dg/gomp/append-args-7.C
@@ -64,7 +64,7 @@ template<typename T, typename T2, typename T3>
 void repl2(T, T2, T3, T3);
 #pragma omp declare variant(repl2) match(construct={dispatch}) 
adjust_args(need_device_ptr : y) \
         append_args(interop(target, targetsync, prefer_type(1)), \
-                    interop(prefer_type({fr(3), 
attr("ompx_nop")},{fr(2)},{attr("ompx_all")})))
+                    interop(target, targetsync, prefer_type({fr(3), 
attr("ompx_nop")},{fr(2)},{attr("ompx_all")})))
 template<typename T, typename T2>
 void base2(T x, T2 y);
 
diff --git a/gcc/testsuite/g++.dg/gomp/append-args-8.C 
b/gcc/testsuite/g++.dg/gomp/append-args-8.C
index 786a2b3dc57c..379c7677c95a 100644
--- a/gcc/testsuite/g++.dg/gomp/append-args-8.C
+++ b/gcc/testsuite/g++.dg/gomp/append-args-8.C
@@ -20,7 +20,7 @@ template<typename T, typename T2, typename T3>
 void repl2(T, T2, T3, T3);
 #pragma omp declare variant(repl2) match(construct={dispatch}) 
adjust_args(need_device_ptr : y) \
         append_args(interop(target, targetsync, prefer_type(1)), \
-                    interop(prefer_type({fr(3), 
attr("ompx_nop")},{fr(2)},{attr("ompx_all")})))
+                    interop(target, prefer_type({fr(3), 
attr("ompx_nop")},{fr(2)},{attr("ompx_all")})))
 template<typename T, typename T2>
 void base2(T x, T2 y);
 
@@ -31,7 +31,7 @@ void repl3(T, T2, T2, T2, ...);
 #pragma omp declare variant(repl3) match(construct={dispatch}) \
         append_args( interop(target, prefer_type("cuda", "hsa")), \
                      interop(targetsync), \
-                     interop(prefer_type({attr("ompx_nop")})) )
+                     interop(target, prefer_type({attr("ompx_nop")})) )
 template<typename T>
 void base3(T, ...);
 
@@ -68,10 +68,9 @@ test (int *a, int *b)
 /* { dg-final { scan-tree-dump-times "interopobjs.\[0-9\]+\\\[0\\\] = 
&interop\\.\[0-9\]+;" 2 "gimple" } }  */
 /* { dg-final { scan-tree-dump-times "interopobjs.\[0-9\]+\\\[1\\\] = 
&interop\\.\[0-9\]+;" 1 "gimple" } }  */
 /* { dg-final { scan-tree-dump-times "interopobjs.\[0-9\]+\\\[2\\\] = 
&interop\\.\[0-9\]+;" 1 "gimple" } }  */
-/* { dg-final { scan-tree-dump-times "tgt_tgtsync.\[0-9\]+\\\[0\\\] = 0;" 1 
"gimple" } }  */
-/* { dg-final { scan-tree-dump-times "tgt_tgtsync.\[0-9\]+\\\[0\\\] = 1;" 1 
"gimple" } }  */
+/* { dg-final { scan-tree-dump-times "tgt_tgtsync.\[0-9\]+\\\[0\\\] = 1;" 2 
"gimple" } }  */
 /* { dg-final { scan-tree-dump-times "tgt_tgtsync.\[0-9\]+\\\[1\\\] = 2;" 1 
"gimple" } }  */
-/* { dg-final { scan-tree-dump-times "tgt_tgtsync.\[0-9\]+\\\[2\\\] = 0;" 1 
"gimple" } }  */
+/* { dg-final { scan-tree-dump-times "tgt_tgtsync.\[0-9\]+\\\[2\\\] = 1;" 1 
"gimple" } }  */
 /* { dg-final { scan-tree-dump-times "pref_type.\[0-9\]+\\\[0\\\] = 
\"\\\\x80\\\\x03\\\\x80ompx_nop\\\\x00\\\\x00\\\\x80\\\\x02\\\\x80\\\\x00\\\\x80\\\\x80ompx_all\\\\x00\\\\x00\";"
 1 "gimple" } }  */
 /* { dg-final { scan-tree-dump-times "pref_type.\[0-9\]+\\\[0\\\] = 
\"\\\\x80\\\\x01\\\\x80\\\\x00\\\\x80\\\\x07\\\\x80\\\\x00\";" 1 "gimple" } }  
*/
 /* { dg-final { scan-tree-dump-times "pref_type.\[0-9\]+\\\[1\\\] = 0B;" 1 
"gimple" } }  */
diff --git a/gcc/testsuite/g++.dg/gomp/interop-5.C 
b/gcc/testsuite/g++.dg/gomp/interop-5.C
index 89396cf54379..0c65f83e32d9 100644
--- a/gcc/testsuite/g++.dg/gomp/interop-5.C
+++ b/gcc/testsuite/g++.dg/gomp/interop-5.C
@@ -41,14 +41,14 @@ f ()
   constexpr T3 ifr_level_zero = (T3) (omp_ifr_sycl + 2);
   constexpr T3 ifr_invalid = (T3) 99;
 
-  #pragma omp interop init ( obj1, obj2) use (obj3) destroy(obj4) init(obj5) 
destroy(obj6) use(obj7)   
-  /* { dg-final { scan-tree-dump-times "#pragma omp interop use\\(obj7\\) 
destroy\\(obj6\\) init\\(obj5\\) destroy\\(obj4\\) use\\(obj3\\) init\\(obj2\\) 
init\\(obj1\\)\[\r\n\]" 2 "original" } }  */
+#pragma omp interop init (target: obj1, obj2) use (obj3) destroy(obj4) 
init(targetsync:obj5) destroy(obj6) use(obj7)   
+  /* { dg-final { scan-tree-dump-times "#pragma omp interop use\\(obj7\\) 
destroy\\(obj6\\) init\\(targetsync: obj5\\) destroy\\(obj4\\) use\\(obj3\\) 
init\\(target: obj2\\) init\\(target: obj1\\)\[\r\n\]" 2 "original" } }  */
 
   #pragma omp interop nowait init (targetsync : obj1, obj2) use (obj3) 
destroy(obj4) init(target, targetsync : obj5) destroy(obj6) use(obj7) 
depend(inout: x)  
   /* { dg-final { scan-tree-dump-times "#pragma omp interop 
depend\\(inout:x\\) use\\(obj7\\) destroy\\(obj6\\) init\\(target, targetsync: 
obj5\\) destroy\\(obj4\\) use\\(obj3\\) init\\(targetsync: obj2\\) 
init\\(targetsync: obj1\\) nowait\[\r\n\]" 2 "original" } }  */
 
-  #pragma omp interop init ( obj1, obj2) init (target: obj3) init(targetsync : 
obj4) init(target,targetsync: obj5)  
-  /* { dg-final { scan-tree-dump-times "#pragma omp interop init\\(target, 
targetsync: obj5\\) init\\(targetsync: obj4\\) init\\(target: obj3\\) 
init\\(obj2\\) init\\(obj1\\)\[\r\n\]" 2 "original" } }  */
+#pragma omp interop init (target: obj1, obj2) init (target: obj3) 
init(targetsync : obj4) init(target,targetsync: obj5)  
+  /* { dg-final { scan-tree-dump-times "#pragma omp interop init\\(target, 
targetsync: obj5\\) init\\(targetsync: obj4\\) init\\(target: obj3\\) 
init\\(target: obj2\\) init\\(target: obj1\\)\[\r\n\]" 2 "original" } }  */
 
   /* --------------------------------------------  */
 
diff --git a/gcc/testsuite/gfortran.dg/gomp/append_args-1.f90 
b/gcc/testsuite/gfortran.dg/gomp/append_args-1.f90
index c994b555c97f..7e4f74d281c5 100644
--- a/gcc/testsuite/gfortran.dg/gomp/append_args-1.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/append_args-1.f90
@@ -49,7 +49,7 @@ contains
   end subroutine
 
   subroutine f2a ()
-    !$omp declare variant (f1b) append_args ( interop ( prefer_type ( "cuda", 
"hip" ) ) , interop(target)) &
+    !$omp declare variant (f1b) append_args ( interop ( target, prefer_type ( 
"cuda", "hip" ) ) , interop(target)) &
     !$omp&     append_args ( interop ( target , targetsync) ) 
match(construct={dispatch})   ! { dg-error "'append_args' clause at .1. 
specified more than once" }
   end subroutine
 
@@ -60,17 +60,17 @@ contains
   end subroutine
 
   subroutine f2c (x,y)
-    !$omp declare variant (fop) , append_args ( interop ( prefer_type ( 
"cuda", "hip" ) ) , interop(target)) , &
+    !$omp declare variant (fop) , append_args ( interop ( target, prefer_type 
( "cuda", "hip" ) ) , interop(target)) , &
     !$omp&     adjust_args (need_device_ptr : x, y )   ! { dg-error "the 
'adjust_args' clause at .1. can only be specified if the 'dispatch' selector of 
the construct selector set appears in the 'match' clause" } 
     type(c_ptr) :: x, y
     value :: y
   end subroutine
 
   subroutine f2d ()
-    !$omp declare variant (f1d) append_args ( interop ( prefer_type ( "cuda", 
"hip" ) ) , interop(target)) ,  ! { dg-error "111: expected 'match', 
'adjust_args' or 'append_args' at .1." }
+    !$omp declare variant (f1d) append_args ( interop ( target, prefer_type ( 
"cuda", "hip" ) ) , interop(target)) ,  ! { dg-error "119: expected 'match', 
'adjust_args' or 'append_args' at .1." }
   end subroutine
 
   subroutine f2e ()
-    !$omp declare variant (f1e) append_args ( interop ( prefer_type ( "cuda", 
"hip" ) ) , interop(target) interop(targetsync))  ! { dg-error "Expected ',' or 
'\\)' at .1." }
+    !$omp declare variant (f1e) append_args ( interop ( target, prefer_type ( 
"cuda", "hip" ) ) , interop(target) interop(targetsync))  ! { dg-error 
"Expected ',' or '\\)' at .1." }
   end subroutine
 end
diff --git a/gcc/testsuite/gfortran.dg/gomp/append_args-2.f90 
b/gcc/testsuite/gfortran.dg/gomp/append_args-2.f90
index 7a68977ed4d0..63a6934a0bd0 100644
--- a/gcc/testsuite/gfortran.dg/gomp/append_args-2.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/append_args-2.f90
@@ -56,7 +56,7 @@ contains
     integer(omp_interop_kind),value :: obj2
   end
   subroutine g1a (obj)
-    !$omp declare variant (g1 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
+    !$omp declare variant (g1 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( target, prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
     integer(omp_interop_kind),value :: obj
   end
 
@@ -75,7 +75,7 @@ contains
     integer(omp_interop_kind) :: obj2
   end
   subroutine g3a (obj)
-    !$omp declare variant (g3 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
+    !$omp declare variant (g3 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( target, prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
     integer(omp_interop_kind),value :: obj
   end
 
@@ -84,7 +84,7 @@ contains
     integer(omp_interop_kind) :: obj2
   end
   subroutine g4a (obj)
-    !$omp declare variant (g4 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
+    !$omp declare variant (g4 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( target, prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
     integer(omp_interop_kind),value :: obj
   end
 
@@ -95,7 +95,7 @@ contains
     optional :: obj3
   end
   subroutine g5a (obj)
-    !$omp declare variant (g5 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
+    !$omp declare variant (g5 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( target, prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
     ! { dg-error "'obj3' at .1. with OPTIONAL attribute not support when 
utilized with the 'append_args' clause at .2." "" { target *-*-* } .-1 }
     integer(omp_interop_kind),value :: obj
   end
@@ -108,7 +108,7 @@ contains
     optional :: obj3
   end
   subroutine g5avar (obj)
-    !$omp declare variant (g5var ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
+    !$omp declare variant (g5var ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( target, prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
     ! { dg-error "'obj3' at .1. with OPTIONAL attribute not support when 
utilized with the 'append_args' clause at .2." "" { target *-*-* } .-1 }
     integer(omp_interop_kind),value :: obj
   end
@@ -120,7 +120,7 @@ contains
     integer(omp_interop_kind) :: obj2
   end
   subroutine g6a (obj)
-    !$omp declare variant (g6 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
+    !$omp declare variant (g6 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( target, prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
     ! { dg-error "'obj3' at .1. must be a nonpointer, nonallocatable scalar 
integer dummy argument of 'omp_interop_kind' kind as it utilized with the 
'append_args' clause at .2." "" { target *-*-* } .-1 }
     integer(omp_interop_kind),value :: obj
   end
@@ -132,7 +132,7 @@ contains
     integer(omp_interop_kind),allocatable :: obj2
   end
   subroutine g7a (obj)
-    !$omp declare variant (g7 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
+    !$omp declare variant (g7 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( target, prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
     ! { dg-error "'obj2' at .1. must be a nonpointer, nonallocatable scalar 
integer dummy argument of 'omp_interop_kind' kind as it utilized with the 
'append_args' clause at .2." "" { target *-*-* } .-1 }
     integer(omp_interop_kind),value :: obj
   end
@@ -144,7 +144,7 @@ contains
     integer(omp_interop_kind) :: obj2(:)
   end
   subroutine g8a (obj)
-    !$omp declare variant (g8 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
+    !$omp declare variant (g8 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( target, prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
     ! { dg-error "'obj2' at .1. must be a nonpointer, nonallocatable scalar 
integer dummy argument of 'omp_interop_kind' kind as it utilized with the 
'append_args' clause at .2." "" { target *-*-* } .-1 }
     integer(omp_interop_kind),value :: obj
   end
@@ -156,7 +156,7 @@ contains
     integer(omp_interop_kind) :: obj2(2)
   end
   subroutine g9a (obj)
-    !$omp declare variant (g9 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
+    !$omp declare variant (g9 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( target, prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
     ! { dg-error "'obj2' at .1. must be a nonpointer, nonallocatable scalar 
integer dummy argument of 'omp_interop_kind' kind as it utilized with the 
'append_args' clause at .2." "" { target *-*-* } .-1 }
     integer(omp_interop_kind),value :: obj
   end
@@ -168,7 +168,7 @@ contains
     integer(1) :: obj2
   end
   subroutine g10a (obj)
-    !$omp declare variant (g10 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
+    !$omp declare variant (g10 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( target, prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
     ! { dg-error "'obj2' at .1. must be a nonpointer, nonallocatable scalar 
integer dummy argument of 'omp_interop_kind' kind as it utilized with the 
'append_args' clause at .2." "" { target *-*-* } .-1 }
     integer(omp_interop_kind),value :: obj
   end
@@ -180,7 +180,7 @@ contains
     real(omp_interop_kind) :: obj2  ! { dg-warning "C kind type parameter is 
for type INTEGER but type at .1. is REAL" }
   end
   subroutine g11a (obj)
-    !$omp declare variant (g11 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
+    !$omp declare variant (g11 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( target, prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
     ! { dg-error "'obj2' at .1. must be a nonpointer, nonallocatable scalar 
integer dummy argument of 'omp_interop_kind' kind as it utilized with the 
'append_args' clause at .2." "" { target *-*-* } .-1 }
     integer(omp_interop_kind),value :: obj
   end
@@ -192,7 +192,7 @@ contains
     integer(omp_interop_kind) :: obj2[*]
   end
   subroutine g12a (obj)
-    !$omp declare variant (g12 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
+    !$omp declare variant (g12 ) match(construct={dispatch}) append_args ( 
interop ( target , targetsync), interop( target, prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
     ! { dg-error "'obj2' at .1. must be a nonpointer, nonallocatable scalar 
integer dummy argument of 'omp_interop_kind' kind as it utilized with the 
'append_args' clause at .2." "" { target *-*-* } .-1 }
     integer(omp_interop_kind),value :: obj
   end
diff --git a/gcc/testsuite/gfortran.dg/gomp/append_args-3.f90 
b/gcc/testsuite/gfortran.dg/gomp/append_args-3.f90
index 5dbc246fc537..3b5d3f82fa96 100644
--- a/gcc/testsuite/gfortran.dg/gomp/append_args-3.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/append_args-3.f90
@@ -33,7 +33,7 @@ contains
     integer(omp_interop_kind), value :: o_value
   end
   subroutine sub_no_arg ()
-    !$omp declare variant (vsub_no_arg ) match(construct={dispatch}) 
append_args (interop(targetsync), interop( prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
+    !$omp declare variant (vsub_no_arg ) match(construct={dispatch}) 
append_args (interop(targetsync), interop( target, prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
   end
 
   integer(c_int) function vfun_cbind(arg2_int, arg2_str, o2_dummy, o2_value) 
bind(C)
diff --git a/gcc/testsuite/gfortran.dg/gomp/append_args-4.f90 
b/gcc/testsuite/gfortran.dg/gomp/append_args-4.f90
index 6f550842ca97..f07e3ab4b859 100644
--- a/gcc/testsuite/gfortran.dg/gomp/append_args-4.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/append_args-4.f90
@@ -40,7 +40,7 @@ contains
     character(len=*) :: str
     integer, optional, value :: int_opt
     character(len=:), allocatable :: alloc_str
-    !$omp declare variant (vifun ) match(construct={dispatch}) append_args 
(interop(targetsync), interop( prefer_type ( {fr("cuda"), attr("ompx_xx")}, 
{attr("ompx_yy")} )))
+    !$omp declare variant (vifun ) match(construct={dispatch}) append_args 
(interop(targetsync), interop( target, prefer_type ( {fr("cuda"), 
attr("ompx_xx")}, {attr("ompx_yy")} )))
     ifun = 0
   end
 
diff --git a/gcc/testsuite/gfortran.dg/gomp/interop-1.f90 
b/gcc/testsuite/gfortran.dg/gomp/interop-1.f90
index a16c3845afdd..eae0cb3ae16a 100644
--- a/gcc/testsuite/gfortran.dg/gomp/interop-1.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/interop-1.f90
@@ -33,12 +33,12 @@ integer(omp_interop_fr_kind), parameter :: ifr_array(2) = 
[omp_ifr_cuda, omp_ifr
 integer(omp_interop_kind) :: obj1, obj2, obj3, obj4, obj5
 integer :: x
 
-!$omp interop init(obj1) init(target,targetsync : obj2, obj3) nowait ! OK
-!$omp interop init(obj1) init (targetsync  : obj2, obj3) nowait ! OK
-!$omp interop init(obj1) init (targetsync , target : obj2, obj3) nowait ! OK
+!$omp interop init(target: obj1) init(target,targetsync : obj2, obj3) nowait ! 
OK
+!$omp interop init(target: obj1) init (targetsync  : obj2, obj3) nowait ! OK
+!$omp interop init(target: obj1) init (targetsync , target : obj2, obj3) 
nowait ! OK
 
-!$omp interop init(obj1) init(target,targetsync,target: obj2, obj3) nowait ! { 
dg-error "Duplicate 'target'" }
-!$omp interop init(obj1) init(target,targetsync, targetsync : obj2, obj3) 
nowait ! { dg-error "Duplicate 'targetsync'" }
+!$omp interop init(target: obj1) init(target,targetsync,target: obj2, obj3) 
nowait ! { dg-error "Duplicate 'target'" }
+!$omp interop init(target: obj1) init(target,targetsync, targetsync : obj2, 
obj3) nowait ! { dg-error "Duplicate 'targetsync'" }
 
 !$omp interop init(prefer_type("cuda", omp_ifr_opencl, omp_ifr_level_zero, 
"hsa"), targetsync : obj1) &
 !$omp&        destroy(obj2, obj3) depend(inout: x) use(obj4, obj5) 
device(device_num: 0)
@@ -47,7 +47,7 @@ integer :: x
 ! { dg-warning "Unknown foreign runtime identifier 'cu' at \\(1\\) 
\\\[-Wopenmp\\\]" "" { target *-*-* } .-1 }
 
 !$omp assume contains(interop)
-  !$omp interop init(prefer_type("cuða") : obj3)  ! { dg-warning "Unknown 
foreign runtime identifier 'cu\[^'\]*a'" }
+  !$omp interop init(target, prefer_type("cuða") : obj3)  ! { dg-warning 
"Unknown foreign runtime identifier 'cu\[^'\]*a'" }
 !$omp end assume
 
 !$omp interop init(prefer_type("cu"//char(0)//"da") : obj3) ! { dg-error "36: 
Expected ',' or '\\)'" }
@@ -63,35 +63,35 @@ integer :: x
 
 !$omp interop init ( target , prefer_type( { fr("hsa"), attr("ompx_nothing") , 
fr("hsa" ) }) :obj1) ! { dg-error "Duplicated 'fr' preference-selector-name" }
 
-!$omp interop init ( prefer_type( 4, omp_ifr_hip*4) : obj1)  ! { dg-warning 
"Unknown foreign runtime identifier '20'" }
-!$omp interop init ( prefer_type( sin(3.3) : obj1)  ! { dg-error "Expected 
constant scalar integer expression or non-empty default-kind character literal" 
}
-!$omp interop init ( prefer_type( {fr(4 ) }) : obj1) ! OK
-!$omp interop init ( prefer_type( {fr(4_"cuda" ) }) : obj1) ! { dg-error 
"Expected constant scalar integer expression or non-empty default-kind 
character literal" }
-!$omp interop init ( prefer_type( {fr(c_char_"cuda") }) : obj1) ! OK
-!$omp interop init ( prefer_type( {fr(1_"cuda" ) }) : obj1) ! OK
-!$omp interop init ( prefer_type( {fr(omp_ifr_level_zero ) }, 
{fr(omp_ifr_hip)}) : obj1) ! OK
-!$omp interop init ( prefer_type( {fr("cuda" // "_driver") }) : obj1) ! { 
dg-error "46: Expected '\\)'" }
-!$omp interop init ( prefer_type( {fr(trim("cuda" // "_driver")) }) : obj1) ! 
{ dg-error "38: Expected constant scalar integer expression or non-empty 
default-kind character literal" }
-!$omp interop init ( prefer_type( {fr("hello" }) : obj1) ! { dg-error "47: 
Expected '\\)'" }
+!$omp interop init ( target, prefer_type( 4, omp_ifr_hip*4) : obj1)  ! { 
dg-warning "Unknown foreign runtime identifier '20'" }
+!$omp interop init ( target, prefer_type( sin(3.3) : obj1)  ! { dg-error 
"Expected constant scalar integer expression or non-empty default-kind 
character literal" }
+!$omp interop init ( target, prefer_type( {fr(4 ) }) : obj1) ! OK
+!$omp interop init ( target, prefer_type( {fr(4_"cuda" ) }) : obj1) ! { 
dg-error "Expected constant scalar integer expression or non-empty default-kind 
character literal" }
+!$omp interop init ( target, prefer_type( {fr(c_char_"cuda") }) : obj1) ! OK
+!$omp interop init ( target, prefer_type( {fr(1_"cuda" ) }) : obj1) ! OK
+!$omp interop init ( target, prefer_type( {fr(omp_ifr_level_zero ) }, 
{fr(omp_ifr_hip)}) : obj1) ! OK
+!$omp interop init ( target, prefer_type( {fr("cuda" // "_driver") }) : obj1) 
! { dg-error "54: Expected '\\)'" }
+!$omp interop init ( target, prefer_type( {fr(trim("cuda" // "_driver")) }) : 
obj1) ! { dg-error "46: Expected constant scalar integer expression or 
non-empty default-kind character literal" }
+!$omp interop init ( target, prefer_type( {fr("hello" }) : obj1) ! { dg-error 
"55: Expected '\\)'" }
 ! { dg-warning "Unknown foreign runtime identifier 'hello' at \\(1\\) 
\\\[-Wopenmp\\\]" "" { target *-*-* } .-1 }
 
-!$omp interop init ( prefer_type( {fr(x) }) : obj1) ! { dg-error "Expected 
constant scalar integer expression or non-empty default-kind character literal" 
}
-!$omp interop init ( prefer_type( {fr(ifr_array ) }) : obj1) ! { dg-error 
"Expected constant scalar integer expression or non-empty default-kind 
character literal" }
-!$omp interop init ( prefer_type( {fr(ifr_array(1) ) }) : obj1)
+!$omp interop init ( target, prefer_type( {fr(x) }) : obj1) ! { dg-error 
"Expected constant scalar integer expression or non-empty default-kind 
character literal" }
+!$omp interop init ( target, prefer_type( {fr(ifr_array ) }) : obj1) ! { 
dg-error "Expected constant scalar integer expression or non-empty default-kind 
character literal" }
+!$omp interop init ( target, prefer_type( {fr(ifr_array(1) ) }) : obj1)
 
-!$omp interop init ( prefer_type( omp_ifr_level_zero, omp_ifr_hip ) : obj1) ! 
OK
-!$omp interop init ( prefer_type( omp_ifr_level_zero +1 ) : obj1) ! OK
-!$omp interop init ( prefer_type( x ) : obj1) ! { dg-error "Expected constant 
scalar integer expression or non-empty default-kind character literal" }
-!$omp interop init ( prefer_type( ifr_array ) : obj1) ! { dg-error "Expected 
constant scalar integer expression or non-empty default-kind character literal" 
}
-!$omp interop init ( prefer_type( ifr_array(2) ) : obj1) ! OK
+!$omp interop init ( target, prefer_type( omp_ifr_level_zero, omp_ifr_hip ) : 
obj1) ! OK
+!$omp interop init ( target, prefer_type( omp_ifr_level_zero +1 ) : obj1) ! OK
+!$omp interop init ( target, prefer_type( x ) : obj1) ! { dg-error "Expected 
constant scalar integer expression or non-empty default-kind character literal" 
}
+!$omp interop init ( target, prefer_type( ifr_array ) : obj1) ! { dg-error 
"Expected constant scalar integer expression or non-empty default-kind 
character literal" }
+!$omp interop init ( target, prefer_type( ifr_array(2) ) : obj1) ! OK
 
-!$omp interop init ( prefer_type( 4, omp_ifr_hip*4) : obj1) ! { dg-warning 
"Unknown foreign runtime identifier '20'" }
-!$omp interop init ( prefer_type( 4, 1, 3) : obj1)
+!$omp interop init ( target, prefer_type( 4, omp_ifr_hip*4) : obj1) ! { 
dg-warning "Unknown foreign runtime identifier '20'" }
+!$omp interop init ( target, prefer_type( 4, 1, 3) : obj1)
 
-!$omp interop init ( prefer_type( {fr("cuda") }, {fr(omp_ifr_hsa)} , 
{attr("ompx_a") } , {fr(omp_ifr_hip) }) : obj1)
-!$omp interop init ( prefer_type( {fr("cuda") }, 
{fr(omp_ifr_hsa,omp_ifr_level_zero)} , {attr("ompx_a") } , {fr(omp_ifr_hip) }) 
: obj1) ! { dg-error "65: Expected '\\)'" }
-!$omp interop init ( prefer_type( {fr("cuda",5) }, 
{fr(omp_ifr_hsa,omp_ifr_level_zero)} , {attr("ompx_a") } , {fr(omp_ifr_hip) }) 
: obj1) ! { dg-error "45: Expected '\\)' at" }
-!$omp interop init ( prefer_type( {fr("sycl"), attr("ompx_1", "ompx_2"), 
attr("ompx_3") }, {attr("ompx_4", "ompx_5"),fr(omp_ifr_level_zero)} ) : obj1)
-!$omp interop init ( prefer_type( { fr(5), attr("ompx_1") }, {fr(omp_ifr_hsa)} 
, {attr("ompx_a") } ) : obj1)
+!$omp interop init ( target, prefer_type( {fr("cuda") }, {fr(omp_ifr_hsa)} , 
{attr("ompx_a") } , {fr(omp_ifr_hip) }) : obj1)
+!$omp interop init ( target, prefer_type( {fr("cuda") }, 
{fr(omp_ifr_hsa,omp_ifr_level_zero)} , {attr("ompx_a") } , {fr(omp_ifr_hip) }) 
: obj1) ! { dg-error "73: Expected '\\)'" }
+!$omp interop init ( target, prefer_type( {fr("cuda",5) }, 
{fr(omp_ifr_hsa,omp_ifr_level_zero)} , {attr("ompx_a") } , {fr(omp_ifr_hip) }) 
: obj1) ! { dg-error "53: Expected '\\)' at" }
+!$omp interop init ( target, prefer_type( {fr("sycl"), attr("ompx_1", 
"ompx_2"), attr("ompx_3") }, {attr("ompx_4", "ompx_5"),fr(omp_ifr_level_zero)} 
) : obj1)
+!$omp interop init ( target, prefer_type( { fr(5), attr("ompx_1") }, 
{fr(omp_ifr_hsa)} , {attr("ompx_a") } ) : obj1)
 
 end
diff --git a/gcc/testsuite/gfortran.dg/gomp/interop-2.f90 
b/gcc/testsuite/gfortran.dg/gomp/interop-2.f90
index b3130117fb2b..a8fc9204223d 100644
--- a/gcc/testsuite/gfortran.dg/gomp/interop-2.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/interop-2.f90
@@ -27,13 +27,13 @@ integer(1) :: o1
 integer, parameter :: mykind = mod (omp_interop_kind, 100) ! remove saving the 
'comes from c_int' info
 real(mykind) :: or
 
-!$omp interop init (op)      ! { dg-error "'op' at \\(1\\) in 'INIT' clause 
must be a scalar integer variable of 'omp_interop_kind' kind" }
+!$omp interop init (target : op)      ! { dg-error "'op' at \\(1\\) in 'INIT' 
clause must be a scalar integer variable of 'omp_interop_kind' kind" }
                              ! { dg-error "Object 'op' is not a variable at 
\\(1\\)" "" { target *-*-* } .-1 }
-!$omp interop init (ointent) ! { dg-error "'ointent' at \\(1\\) in 'INIT' 
clause must be definable" }
-!$omp interop init (od)      ! { dg-error "'od' at \\(1\\) in 'INIT' clause 
must be a scalar integer variable of 'omp_interop_kind' kind" }
-!$omp interop init (od(1))   ! { dg-error "Syntax error in OpenMP variable 
list" }
-!$omp interop init (o1)      ! { dg-error "'o1' at \\(1\\) in 'INIT' clause 
must be a scalar integer variable of 'omp_interop_kind' kind" }
-!$omp interop init (or)      ! { dg-error "'or' at \\(1\\) in 'INIT' clause 
must be a scalar integer variable of 'omp_interop_kind' kind" }
+!$omp interop init (target : ointent) ! { dg-error "'ointent' at \\(1\\) in 
'INIT' clause must be definable" }
+!$omp interop init (target : od)      ! { dg-error "'od' at \\(1\\) in 'INIT' 
clause must be a scalar integer variable of 'omp_interop_kind' kind" }
+!$omp interop init (target : od(1))   ! { dg-error "Syntax error in OpenMP 
variable list" }
+!$omp interop init (target: o1)      ! { dg-error "'o1' at \\(1\\) in 'INIT' 
clause must be a scalar integer variable of 'omp_interop_kind' kind" }
+!$omp interop init (target: or)      ! { dg-error "'or' at \\(1\\) in 'INIT' 
clause must be a scalar integer variable of 'omp_interop_kind' kind" }
 
 !$omp interop use (op)      ! { dg-error "'op' at \\(1\\) in 'USE' clause must 
be a scalar integer variable of 'omp_interop_kind' kind" }
                             ! { dg-error "Object 'op' is not a variable at 
\\(1\\)" "" { target *-*-* } .-1 }
@@ -60,21 +60,21 @@ implicit none
 integer(omp_interop_kind) :: obj1, obj2, obj3, obj4, obj5
 integer :: x
 
-!$omp interop init ( prefer_type( {fr(1_"") }) : obj1) ! { dg-error "Expected 
constant scalar integer expression or non-empty default-kind character literal" 
}
-!$omp interop init ( prefer_type( {fr(1_"hip") , attr(omp_ifr_cuda) }) : obj1) 
! { dg-error "Expected default-kind character literal" }
+!$omp interop init ( target, prefer_type( {fr(1_"") }) : obj1) ! { dg-error 
"Expected constant scalar integer expression or non-empty default-kind 
character literal" }
+!$omp interop init ( target, prefer_type( {fr(1_"hip") , attr(omp_ifr_cuda) }) 
: obj1) ! { dg-error "Expected default-kind character literal" }
 
-!$omp interop init ( prefer_type( {fr(1_"hip") , attr("myooption") }) : obj1) 
! { dg-error "Character literal at .1. must start with 'ompx_'" }
-!$omp interop init ( prefer_type( {fr(1_"hip") , attr("ompx_option") , 
attr("ompx_") } ) : obj1)
-!$omp interop init ( prefer_type( {fr(1_"hip") , attr("ompx_option") }, { 
attr("ompx_") } ) : obj1)
-!$omp interop init ( prefer_type( {fr(1_"hip") , attr("ompx_option") }  { 
attr("ompx_") } ) : obj1) ! { dg-error "Expected ',' or '\\)'" }
-!$omp interop init ( prefer_type( {fr(1_"hip") , attr("ompx_option")   ) : 
obj1) ! { dg-error "Expected ',' or '\}'" }
+!$omp interop init ( target, prefer_type( {fr(1_"hip") , attr("myooption") }) 
: obj1) ! { dg-error "Character literal at .1. must start with 'ompx_'" }
+!$omp interop init ( target, prefer_type( {fr(1_"hip") , attr("ompx_option") , 
attr("ompx_") } ) : obj1)
+!$omp interop init ( target, prefer_type( {fr(1_"hip") , attr("ompx_option") 
}, { attr("ompx_") } ) : obj1)
+!$omp interop init ( target, prefer_type( {fr(1_"hip") , attr("ompx_option") } 
 { attr("ompx_") } ) : obj1) ! { dg-error "Expected ',' or '\\)'" }
+!$omp interop init ( target, prefer_type( {fr(1_"hip") , attr("ompx_option")   
) : obj1) ! { dg-error "Expected ',' or '\}'" }
 
-!$omp interop init ( prefer_type( {fr(1_"hip") attr("ompx_option")   ) : obj1) 
! { dg-error "Expected ',' or '\}'" }
-!$omp interop init ( prefer_type( {fr(1_"hip")}), prefer_type("cuda") : obj1) 
! { dg-error "Duplicate 'prefer_type' modifier" }
+!$omp interop init ( target, prefer_type( {fr(1_"hip") attr("ompx_option")   ) 
: obj1) ! { dg-error "Expected ',' or '\}'" }
+!$omp interop init ( target, prefer_type( {fr(1_"hip")}), prefer_type("cuda") 
: obj1) ! { dg-error "Duplicate 'prefer_type' modifier" }
 
-!$omp interop init ( prefer_type( {attr("ompx_option1,ompx_option2")   ) : 
obj1) ! { dg-error "Unexpected null or ',' character in character literal" }
+!$omp interop init ( target, prefer_type( {attr("ompx_option1,ompx_option2")   
) : obj1) ! { dg-error "Unexpected null or ',' character in character literal" }
 
 !$omp interop init ( targetsync other ) : obj1)  ! { dg-error "Expected ',' or 
':'" }
-!$omp interop init ( prefer_type( {fr(1_"cuda") } ), other : obj1)  ! { 
dg-error "Expected 'target' or 'targetsync'" }
-!$omp interop init ( prefer_type( {fr(1_"cuda") } ), obj1)  ! { dg-error 
"Expected 'target' or 'targetsync'" }
+!$omp interop init ( target, prefer_type( {fr(1_"cuda") } ), other : obj1)  ! 
{ dg-error "Expected 'prefer_type', 'target', or 'targetsync'" }
+!$omp interop init ( target, prefer_type( {fr(1_"cuda") } ), obj1)  ! { 
dg-error "Expected 'prefer_type', 'target', or 'targetsync'" }
 end
diff --git a/gcc/testsuite/gfortran.dg/gomp/interop-3.f90 
b/gcc/testsuite/gfortran.dg/gomp/interop-3.f90
index a3bbfcaf2ca5..04015de35e06 100644
--- a/gcc/testsuite/gfortran.dg/gomp/interop-3.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/interop-3.f90
@@ -25,16 +25,16 @@ integer(omp_interop_kind) :: obj1, obj2, obj3, obj4, obj5
 integer(omp_interop_kind) :: target, targetsync,prefer_type
 integer :: x
 
-!$omp interop init(obj1) init(target,targetsync : obj2, obj3) nowait
+!$omp interop init(target: obj1) init(target,targetsync : obj2, obj3) nowait
 
 !$omp interop init(prefer_type(1_"cuda", omp_ifr_opencl, omp_ifr_level_zero, 
"hsa"), targetsync : obj1) &
 !$omp&        destroy(obj2, obj3) depend(inout: x) use(obj4, obj5) 
device(device_num: 0)
 
 !$omp assume contains(interop)
-  !$omp interop init(prefer_type("cu da") : obj3)  ! { dg-warning "Unknown 
foreign runtime identifier 'cu da'" }
+  !$omp interop init(target, prefer_type("cu da") : obj3)  ! { dg-warning 
"Unknown foreign runtime identifier 'cu da'" }
 !$omp end assume
 
-!$omp interop init(obj1, obj2, obj1), use(obj4) destroy(obj4)
+!$omp interop init(target: obj1, obj2, obj1), use(obj4) destroy(obj4)
 ! { dg-error "Symbol 'obj1' present on multiple clauses" "" { target *-*-* } 
.-1 }
 ! { dg-error "Symbol 'obj4' present on multiple clauses" "" { target *-*-* } 
.-2 }
 
@@ -44,13 +44,13 @@ integer :: x
 
 !$omp interop depend(inout: x) use(obj2), destroy(obj3) !  Likewise
 
-!$omp interop depend(inout: x) use(obj2), destroy(obj3) init(obj4) ! { 
dg-error "DEPEND clause at .1. requires 'targetsync' interop-type, lacking it 
for 'obj4' at .2." }
+!$omp interop depend(inout: x) use(obj2), destroy(obj3) init(target: obj4) ! { 
dg-error "DEPEND clause at .1. requires 'targetsync' interop-type, lacking it 
for 'obj4' at .2." }
 
-!$omp interop depend(inout: x) init(targetsync : obj5)  use(obj2), 
destroy(obj3) init(obj4) ! { dg-error "DEPEND clause at .1. requires 
'targetsync' interop-type, lacking it for 'obj4' at .2." } 
+!$omp interop depend(inout: x) init(targetsync : obj5)  use(obj2), 
destroy(obj3) init(target: obj4) ! { dg-error "DEPEND clause at .1. requires 
'targetsync' interop-type, lacking it for 'obj4' at .2." } 
 !$omp interop depend(inout: x) init(targetsync : obj5)  use(obj2), 
destroy(obj3) init(prefer_type("cuda"), targetsync : obj4) ! OK
 
-!$omp interop init(target, targetsync, prefer_type, obj1)
-!$omp interop init(prefer_type, obj1, target, targetsync)
+!$omp interop init(target, targetsync, prefer_type, obj1) ! { dg-error "51: 
Expected '\\(' after 'prefer_type'" }
+!$omp interop init(target, prefer_type, obj1, targetsync) ! { dg-error "39: 
Expected '\\(' after 'prefer_type'" }
 
 ! Duplicated variable name or duplicated modifier:
 !$omp interop init(target, targetsync,target : obj1)  ! { dg-error "Duplicate 
'target' at \\(1\\)" }
@@ -62,5 +62,5 @@ integer :: x
 !$omp interop init(target : target, targetsync,targetsync)  ! { dg-error 
"Symbol 'targetsync' present on multiple clauses" }
 
 
-!$omp interop init(, targetsync, prefer_type, obj1, target)  ! { dg-error 
"Syntax error in OpenMP variable list" }
+!$omp interop init(, targetsync, prefer_type, obj1, target)  ! { dg-error "20: 
Expected 'prefer_type', 'target', or 'targetsync'" }
 end
diff --git a/gcc/testsuite/gfortran.dg/gomp/interop-4.f90 
b/gcc/testsuite/gfortran.dg/gomp/interop-4.f90
index 43c28d696689..742288127cd3 100644
--- a/gcc/testsuite/gfortran.dg/gomp/interop-4.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/interop-4.f90
@@ -26,14 +26,14 @@ implicit none
 integer(omp_interop_kind) :: obj1, obj2, obj3, obj4, obj5, obj6, obj7
 integer :: x(6)
 
-!$omp interop init ( obj1, obj2) use (obj3) destroy(obj4) init(obj5) 
destroy(obj6) use(obj7) 
-! { dg-final { scan-tree-dump-times "#pragma omp interop init\\(obj1\\) 
init\\(obj2\\) init\\(obj5\\) use\\(obj3\\) use\\(obj7\\) destroy\\(obj4\\) 
destroy\\(obj6\\)\[\r\n\]" 1 "original" } }
+!$omp interop init ( target: obj1, obj2) use (obj3) destroy(obj4) init(target: 
obj5) destroy(obj6) use(obj7) 
+! { dg-final { scan-tree-dump-times "#pragma omp interop init\\(target: 
obj1\\) init\\(target: obj2\\) init\\(target: obj5\\) use\\(obj3\\) 
use\\(obj7\\) destroy\\(obj4\\) destroy\\(obj6\\)\[\r\n\]" 1 "original" } }
 
 !$omp interop nowait init (targetsync : obj1, obj2) use (obj3) destroy(obj4) 
init(target, targetsync : obj5) destroy(obj6) use(obj7) depend(inout: x) 
 ! { dg-final { scan-tree-dump-times "#pragma omp interop depend\\(inout:x\\) 
init\\(targetsync: obj1\\) init\\(targetsync: obj2\\) init\\(target, 
targetsync: obj5\\) use\\(obj3\\) use\\(obj7\\) destroy\\(obj4\\) 
destroy\\(obj6\\) nowait\[\r\n\]" 1 "original" } }
 
-!$omp interop init ( obj1, obj2) init (target: obj3) init(targetsync : obj4) 
init(target,targetsync: obj5)  
-! { dg-final { scan-tree-dump-times "#pragma omp interop init\\(obj1\\) 
init\\(obj2\\) init\\(target: obj3\\) init\\(targetsync: obj4\\) init\\(target, 
targetsync: obj5\\)\[\r\n\]" 1 "original" } }
+!$omp interop init ( target: obj1, obj2) init (target: obj3) init(targetsync : 
obj4) init(target,targetsync: obj5)  
+! { dg-final { scan-tree-dump-times "#pragma omp interop init\\(target: 
obj1\\) init\\(target: obj2\\) init\\(target: obj3\\) init\\(targetsync: 
obj4\\) init\\(target, targetsync: obj5\\)\[\r\n\]" 1 "original" } }
 
 ! --------------------------------------------
 
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr118965-1.f90 
b/gcc/testsuite/gfortran.dg/gomp/pr118965-1.f90
new file mode 100644
index 000000000000..c9b1eca3cba9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/pr118965-1.f90
@@ -0,0 +1,48 @@
+! At least one of the target and/or targetsync modifiers must be provided.
+! This implies that there are always modifiers required, and the parser
+! should reject e.g. "init (var1, var2)"; the first thing in the list is
+! always an init_modifier in valid code.
+
+module m
+ use iso_c_binding
+ implicit none
+
+ ! The following definitions are in omp_lib, which cannot be included
+ ! in gcc/testsuite/
+ integer, parameter :: omp_interop_kind = c_intptr_t
+ integer, parameter :: omp_interop_fr_kind = c_int
+
+ integer (omp_interop_kind), parameter :: omp_interop_none = 0_omp_interop_kind
+ integer (omp_interop_fr_kind), parameter :: omp_ifr_cuda = 1
+ integer (omp_interop_fr_kind), parameter :: omp_ifr_cuda_driver = 2
+ integer (omp_interop_fr_kind), parameter :: omp_ifr_opencl = 3
+ integer (omp_interop_fr_kind), parameter :: omp_ifr_sycl = 4
+ integer (omp_interop_fr_kind), parameter :: omp_ifr_hip = 5
+ integer (omp_interop_fr_kind), parameter :: omp_ifr_level_zero = 6
+ integer (omp_interop_fr_kind), parameter :: omp_ifr_hsa = 7
+end module m
+
+program main
+use m
+implicit none
+integer(omp_interop_kind) :: obj1, obj2
+
+  !$omp interop init (obj1) ! { dg-error "Expected 'prefer_type', 'target', or 
'targetsync'" }
+  !$omp interop init (obj1, obj2) ! { dg-error "Expected 'prefer_type', 
'target', or 'targetsync'" }
+  !$omp interop init (obj1, target) ! { dg-error "Expected 'prefer_type', 
'target', or 'targetsync'" }
+  !$omp interop init (target, obj1) ! { dg-error "Expected 'prefer_type', 
'target', or 'targetsync'" }
+  !$omp interop init (obj1, targetsync) ! { dg-error "Expected 'prefer_type', 
'target', or 'targetsync'" }
+  !$omp interop init (targetsync, obj1) ! { dg-error "Expected 'prefer_type', 
'target', or 'targetsync'" }
+  !$omp interop init (targetsync, target) ! { dg-error "Expected ',' or ':'" }
+
+  !$omp interop init (target, prefer_type( {fr(4 ) }) : obj1) ! OK
+  !$omp interop init (targetsync, prefer_type( {fr(4 ) }) : obj1) ! OK
+  !$omp interop init (prefer_type( {fr(4 ) }), target : obj1) ! OK
+
+  !$omp interop init (prefer_type( {fr(4 ) }) : obj1) ! { dg-error "Missing 
required 'target' and/or 'targetsync' modifier" }
+
+  ! This does not complain about foobar not being declared because
+  ! Fortran parser error handling eats the whole rest of the statement.
+  !$omp interop init (prefer_type( {fr(4 ) }) : foobar) ! { dg-error "Missing 
required 'target' and/or 'targetsync' modifier" }
+
+end
\ No newline at end of file
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr118965-2.f90 
b/gcc/testsuite/gfortran.dg/gomp/pr118965-2.f90
new file mode 100644
index 000000000000..0b3015aeb541
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/pr118965-2.f90
@@ -0,0 +1,57 @@
+! At least one of the target and/or targetsync modifiers must be provided.
+
+module my_omp_lib
+ use iso_c_binding
+ implicit none
+
+ ! The following definitions are in omp_lib, which cannot be included
+ ! in gcc/testsuite/
+ integer, parameter :: omp_interop_kind = c_intptr_t
+ integer, parameter :: omp_interop_fr_kind = c_int
+
+ integer (omp_interop_kind), parameter :: omp_interop_none = 0_omp_interop_kind
+ integer (omp_interop_fr_kind), parameter :: omp_ifr_cuda = 1
+ integer (omp_interop_fr_kind), parameter :: omp_ifr_cuda_driver = 2
+ integer (omp_interop_fr_kind), parameter :: omp_ifr_opencl = 3
+ integer (omp_interop_fr_kind), parameter :: omp_ifr_sycl = 4
+ integer (omp_interop_fr_kind), parameter :: omp_ifr_hip = 5
+ integer (omp_interop_fr_kind), parameter :: omp_ifr_level_zero = 6
+ integer (omp_interop_fr_kind), parameter :: omp_ifr_hsa = 7
+end module my_omp_lib
+
+module m
+  use my_omp_lib
+  implicit none
+  logical, parameter :: flag = .true.
+contains
+
+  subroutine f1 (i)
+    integer(omp_interop_kind) :: i
+  end
+
+  subroutine g1 ()
+    !$omp declare variant (f1) match(user={condition(flag)}) &
+    !$omp&    append_args(interop(prefer_type({attr("ompx_fun")})))
+    ! { dg-error "Missing required 'target' and/or 'targetsync' modifier" ""  
{ target *-*-* } .-1 }
+  end
+
+  function f2 (a1, a2)
+    integer(omp_interop_kind) :: a1
+    integer(omp_interop_kind) :: a2
+    integer :: f2
+    f2 = 0
+  end
+
+  function g2 ()
+    !$omp declare variant(f2) &
+    !$omp&    append_args(interop(prefer_type("cuda")), &
+    !$omp&    interop(prefer_type({fr("hsa")}))) &
+    !$omp&    match(construct={dispatch})
+    ! { dg-error "Missing required 'target' and/or 'targetsync' modifier" ""  
{ target *-*-* } .-3 }
+    ! There is no diagnostic for the second interop arg because Fortran
+    ! error recovery skips to the end of the statement after diagnosing the
+    ! first one.
+    integer :: g2
+    g2 = 5
+  end
+end

Reply via email to