The attached patch adds parser support for the 'groupprivate' directive
with 'device_type(any|host|nohost)' clause - but then stops immediately
with a 'sorry, unimplemented'.

Comments before I push the patch?

Note: The groupprivate directive implies
  declare target local(...) device_type(...)
but the 'local' clause is not yet implemented.

Still to be done (implementation plan):
* Add C/C++ FE support for the 'local' clause and then
* add the restriction checking for 'groupprivate'.
* Once 'local' can be parsed, middle end support for 'local' can be
  added and a bug with 'requires self_maps' fixed: for static
  variables with explicit/implicit 'declare target enter(...)', the
  'enter' clause must be changed to 'link'.
* Otherwise: 'device_type(nohost/host)' for 'declare target' should
  have (better) middle-end support: Don't enable offload support for
  'host' - and remove the node on the host for 'nohost'.
* Once, everything mention is done, adding nvptx/gcn support for
  'groupprivate device_type(nohost)' should be trivial.
* Handle device_type(host/nohost) support for 'target'
  [Implementation wise similar 'declare target', but for 'nohost'
  requires stub version on the host to find the device version and
  for error diagnostic if actually invoked.]

Tobias

PS: My main motivation is actually only to avoid wrong-code issues
with 'omp requires self_maps' for declare-target static variables as
OpenMP requires that device and host access the same variable.
That works with the 'link' clause (there is code in libgomp for it),
but not for the 'enter'/'to' clause. [Solution, as mentioned: use
'link' internally if self_maps [or USM?] is in 'omp requires'.]
However, implementation wise it makes sense to add parser support
for 'local' and 'groupprivate' first - and both features are also
useful themselves.
PPS: Fortran parser support for local and groupprivate is already
in mainline.
OpenMP: Add early C/C++ parser support for 'groupprivate' directive

After parsing the directive, 'sorry, unimplemented' is printed.
Note that restriction checks still have to be implemented, but this
depends on parser support for the 'local' clause of 'omp declare target',
which still has to be implemented.

gcc/c-family/ChangeLog:

	* c-omp.cc (c_omp_directives): Uncomment 'groupprivate'.
	* c-pragma.cc (omp_pragmas): Add PRAGMA_OMP_GROUPPRIVATE.
	* c-pragma.h (enum pragma_kind): Likewise.

gcc/c/ChangeLog:

	* c-parser.ccS (OMP_GROUPPRIVATE_CLAUSE_MASK,
	c_parser_omp_groupprivate): New.
	(c_parser_pragma): Call it.
	(c_maybe_parse_omp_decl): Uncomment PRAGMA_OMP_GROUPPRIVATE
	check.

gcc/cp/ChangeLog:

	* parser.cc (OMP_GROUPPRIVATE_CLAUSE_MASK,
	cp_parser_omp_groupprivate): New.
	(cp_parser_pragma): Call it.
	(cp_maybe_parse_omp_decl): Uncomment PRAGMA_OMP_GROUPPRIVATE
	check.

gcc/testsuite/ChangeLog:

	* c-c++-common/gomp/groupprivate-1.c: New test.

 gcc/c-family/c-omp.cc                            |  4 ++--
 gcc/c-family/c-pragma.cc                         |  1 +
 gcc/c-family/c-pragma.h                          |  1 +
 gcc/c/c-parser.cc                                | 27 +++++++++++++++++++++++-
 gcc/cp/parser.cc                                 | 25 +++++++++++++++++++++-
 gcc/testsuite/c-c++-common/gomp/groupprivate-1.c | 12 +++++++++++
 6 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc
index bd92da9a86c..bb121ede06b 100644
--- a/gcc/c-family/c-omp.cc
+++ b/gcc/c-family/c-omp.cc
@@ -4655,8 +4655,8 @@ const struct c_omp_directive c_omp_directives[] = {
     C_OMP_DIR_CONSTRUCT, true },
   /* { "fuse", nullptr, nullptr, PRAGMA_OMP_FUSE,
     C_OMP_DIR_CONSTRUCT, true },  */
-  /* { "groupprivate", nullptr, nullptr, PRAGMA_OMP_GROUPPRIVATE,
-    C_OMP_DIR_DECLARATIVE, false },  */
+  { "groupprivate", nullptr, nullptr, PRAGMA_OMP_GROUPPRIVATE,
+    C_OMP_DIR_DECLARATIVE, false },
   /* { "interchange", nullptr, nullptr, PRAGMA_OMP_INTERCHANGE,
     C_OMP_DIR_CONSTRUCT, true },  */
   { "interop", nullptr, nullptr, PRAGMA_OMP_INTEROP,
diff --git a/gcc/c-family/c-pragma.cc b/gcc/c-family/c-pragma.cc
index 4502a3b86f8..4903dcaa082 100644
--- a/gcc/c-family/c-pragma.cc
+++ b/gcc/c-family/c-pragma.cc
@@ -1529,6 +1529,7 @@ static const struct omp_pragma_def omp_pragmas[] = {
   { "error", PRAGMA_OMP_ERROR },
   { "end", PRAGMA_OMP_END },
   { "flush", PRAGMA_OMP_FLUSH },
+  { "groupprivate", PRAGMA_OMP_GROUPPRIVATE },
   { "interop", PRAGMA_OMP_INTEROP },
   { "metadirective", PRAGMA_OMP_METADIRECTIVE },
   { "nothing", PRAGMA_OMP_NOTHING },
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 568620c34a6..ff299f4e1a7 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -61,6 +61,7 @@ enum pragma_kind {
   PRAGMA_OMP_END,
   PRAGMA_OMP_FLUSH,
   PRAGMA_OMP_FOR,
+  PRAGMA_OMP_GROUPPRIVATE,
   PRAGMA_OMP_INTEROP,
   PRAGMA_OMP_LOOP,
   PRAGMA_OMP_NOTHING,
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 30398be4f41..0cc8be10eb0 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -1889,6 +1889,7 @@ static void c_parser_oacc_declare (c_parser *);
 static void c_parser_oacc_enter_exit_data (c_parser *, bool);
 static void c_parser_oacc_update (c_parser *);
 static void c_parser_omp_construct (c_parser *, bool *);
+static void c_parser_omp_groupprivate (c_parser *);
 static void c_parser_omp_threadprivate (c_parser *);
 static void c_parser_omp_barrier (c_parser *);
 static void c_parser_omp_depobj (c_parser *);
@@ -16094,6 +16095,10 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p,
     case PRAGMA_OMP_CANCELLATION_POINT:
       return c_parser_omp_cancellation_point (parser, context);
 
+    case PRAGMA_OMP_GROUPPRIVATE:
+      c_parser_omp_groupprivate (parser);
+      return false;
+
     case PRAGMA_OMP_THREADPRIVATE:
       c_parser_omp_threadprivate (parser);
       return false;
@@ -28599,7 +28604,7 @@ c_maybe_parse_omp_decl (tree decl, tree d)
       return false;
     }
   if (dir->id != PRAGMA_OMP_THREADPRIVATE
-      /* && dir->id != PRAGMA_OMP_GROUPPRIVATE */
+      && dir->id != PRAGMA_OMP_GROUPPRIVATE
       && dir->id != PRAGMA_OMP_ALLOCATE
       && (dir->id != PRAGMA_OMP_DECLARE
 	  || strcmp (directive[1], "target") != 0))
@@ -30960,6 +30965,26 @@ c_parser_omp_construct (c_parser *parser, bool *if_p)
     gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
 }
 
+/* OpenMP 6.0:
+   # pragma omp groupprivate (variable-list) [device_type(...)]  */
+
+#define OMP_GROUPPRIVATE_CLAUSE_MASK					\
+	( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) )
+
+static void
+c_parser_omp_groupprivate (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_pragma (parser);
+  tree vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
+  tree clauses = c_parser_omp_all_clauses (parser, OMP_GROUPPRIVATE_CLAUSE_MASK,
+					   "#pragma omp groupprivate");
+  /* TODO: Implies 'declare target local' with specified device_type, check for
+     conflicts.  Check for other restrictions.  */
+  (void) vars;
+  (void) clauses;
+  sorry_at (loc, "%<omp groupprivate%>");
+}
 
 /* OpenMP 2.5:
    # pragma omp threadprivate (variable-list) */
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index e48868eedbd..c02bd1a3fce 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -50025,6 +50025,25 @@ cp_parser_omp_taskgroup (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
 				 clauses);
 }
 
+/* OpenMP 6.0:
+   # pragma omp groupprivate (variable-list) [device_type(...)]  */
+
+#define OMP_GROUPPRIVATE_CLAUSE_MASK					\
+	( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) )
+
+static void
+cp_parser_omp_groupprivate (cp_parser *parser, cp_token *pragma_tok)
+{
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+  tree vars = cp_parser_omp_var_list (parser, OMP_CLAUSE_ERROR, NULL);
+  tree clauses = cp_parser_omp_all_clauses (parser, OMP_GROUPPRIVATE_CLAUSE_MASK,
+					    "#pragma omp groupprivate", pragma_tok);
+  /* TODO: Implies 'declare target local' with specified device_type, check for
+     conflicts.  Check for other restrictions.  */
+  (void) vars;
+  (void) clauses;
+  sorry_at (loc, "%<omp groupprivate%>");
+}
 
 /* OpenMP 2.5:
    # pragma omp threadprivate (variable-list) */
@@ -52952,7 +52971,7 @@ cp_maybe_parse_omp_decl (tree decl, tree d)
       return false;
     }
   if (dir->id != PRAGMA_OMP_THREADPRIVATE
-      /* && dir->id != PRAGMA_OMP_GROUPPRIVATE */
+      && dir->id != PRAGMA_OMP_GROUPPRIVATE
       && dir->id != PRAGMA_OMP_ALLOCATE
       && (dir->id != PRAGMA_OMP_DECLARE
 	  || strcmp (directive[1], "target") != 0))
@@ -55952,6 +55971,10 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
     case PRAGMA_OMP_CANCELLATION_POINT:
       return cp_parser_omp_cancellation_point (parser, pragma_tok, context);
 
+    case PRAGMA_OMP_GROUPPRIVATE:
+      cp_parser_omp_groupprivate (parser, pragma_tok);
+      return false;
+
     case PRAGMA_OMP_THREADPRIVATE:
       cp_parser_omp_threadprivate (parser, pragma_tok);
       return false;
diff --git a/gcc/testsuite/c-c++-common/gomp/groupprivate-1.c b/gcc/testsuite/c-c++-common/gomp/groupprivate-1.c
new file mode 100644
index 00000000000..280b66fe24d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/groupprivate-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile }  */
+
+int x, y, z, a, b;
+#pragma omp groupprivate(a,b)  // { dg-message "sorry, unimplemented: 'omp groupprivate'" }
+#pragma omp groupprivate(x) device_type(any)     // { dg-message "sorry, unimplemented: 'omp groupprivate'" }
+#pragma omp groupprivate(y) device_type(host)    // { dg-message "sorry, unimplemented: 'omp groupprivate'" }
+#pragma omp groupprivate(z) device_type(nohost)  // { dg-message "sorry, unimplemented: 'omp groupprivate'" }
+
+[[omp::decl (groupprivate)]] int d, e;  // { dg-message "sorry, unimplemented: 'omp groupprivate'" }
+[[omp::decl (groupprivate,device_type(any))]] int f1;     // { dg-message "sorry, unimplemented: 'omp groupprivate'" }
+[[omp::decl (groupprivate,device_type(host))]] int f2;    // { dg-message "sorry, unimplemented: 'omp groupprivate'" }
+[[omp::decl (groupprivate,device_type(nohost))]] int f3;  // { dg-message "sorry, unimplemented: 'omp groupprivate'" }

Reply via email to