]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
OpenMP: C/C++ parser support for dyn_groupprivate
authorTobias Burnus <tburnus@baylibre.com>
Fri, 5 Dec 2025 08:08:06 +0000 (09:08 +0100)
committerTobias Burnus <tburnus@baylibre.com>
Fri, 5 Dec 2025 08:08:06 +0000 (09:08 +0100)
Follow-up to the Fortran patch r16-5633-g26d41e245dbba3, which (besides
other changes) added parser support for the 'dyn_groupprivate' clause to
the target directive.
This commit adds now the parser support to C/C++ and moves the
not-yet-implemented 'sorry' to the early middle end.

gcc/c-family/ChangeLog:

* c-omp.cc (c_omp_split_clauses): Handle
OMP_CLAUSE_DYN_GROUPPRIVATE, sort target clauses
alphabetically.
* c-pragma.h (enum pragma_omp_clause): Add
PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE.

gcc/c/ChangeLog:

* c-parser.cc (c_parser_omp_clause_dyn_groupprivate): New.
(OMP_TARGET_CLAUSE_MASK): Add PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE;
sort clauses alphabetically.
(c_parser_omp_clause_name, c_parser_omp_all_clauses):
Handle 'dyn_groupprivate' clause.
* c-typeck.cc (c_finish_omp_clauses): Likewise.

gcc/cp/ChangeLog:

* pt.cc (tsubst_omp_clauses): Handle OMP_CLAUSE_DYN_GROUPPRIVATE.
* semantics.cc (finish_omp_clauses): Likewise.
* parser.cc (cp_parser_omp_clause_dyn_groupprivate): New.
(cp_parser_omp_clause_name, cp_parser_omp_all_clauses):
Handle 'dyn_groupprivate' clause.
(OMP_TARGET_CLAUSE_MASK): Add PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE;
sort clauses alphabetically.

gcc/fortran/ChangeLog:

* openmp.cc (resolve_omp_clauses): Permit zero with
DYN_GROUPPRIVATE clause.
* trans-openmp.cc (fallback): Generate TREE code
for DYN_GROUPPRIVATE and remove 'sorry'.

gcc/ChangeLog:

* gimplify.cc (gimplify_scan_omp_clauses): Handle
OMP_CLAUSE_DYN_GROUPPRIVATE by printing 'sorry, unimplemented'.
* tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_DYN_GROUPPRIVATE.
(enum omp_clause_fallback_kind): New.
(struct tree_omp_clause): Add fallback_kind union member.
* tree-nested.cc (convert_nonlocal_omp_clauses,
convert_local_omp_clauses): Handle OMP_CLAUSE_DYN_GROUPPRIVATE.
* tree.cc (omp_clause_num_ops, omp_clause_code_name): Add
OMP_CLAUSE_DYN_GROUPPRIVATE.
* tree-pretty-print.cc (dump_omp_clause): Handle
OMP_CLAUSE_DYN_GROUPPRIVATE.
* tree.h (OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR,
OMP_CLAUSE_DYN_GROUPPRIVATE_KIND): New #define.

gcc/testsuite/ChangeLog:

* gfortran.dg/gomp/dyn_groupprivate-1.f90: Add scan-dump test.
* gfortran.dg/gomp/dyn_groupprivate-2.f90: Extend and update.
* c-c++-common/gomp/dyn_groupprivate-1.c: New test.
* c-c++-common/gomp/dyn_groupprivate-2.c: New test.

19 files changed:
gcc/c-family/c-omp.cc
gcc/c-family/c-pragma.h
gcc/c/c-parser.cc
gcc/c/c-typeck.cc
gcc/cp/parser.cc
gcc/cp/pt.cc
gcc/cp/semantics.cc
gcc/fortran/openmp.cc
gcc/fortran/trans-openmp.cc
gcc/gimplify.cc
gcc/testsuite/c-c++-common/gomp/dyn_groupprivate-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/gomp/dyn_groupprivate-2.c [new file with mode: 0644]
gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-1.f90
gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-2.f90
gcc/tree-core.h
gcc/tree-nested.cc
gcc/tree-pretty-print.cc
gcc/tree.cc
gcc/tree.h

index c80d2de6deb837bf977fea03e411ed4714aba7ca..e183c400652d9cf3112b485b2051ef07279d40c9 100644 (file)
@@ -2176,11 +2176,12 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
        {
        /* First the clauses that are unique to some constructs.  */
        case OMP_CLAUSE_DEVICE:
-       case OMP_CLAUSE_MAP:
-       case OMP_CLAUSE_IS_DEVICE_PTR:
-       case OMP_CLAUSE_HAS_DEVICE_ADDR:
        case OMP_CLAUSE_DEFAULTMAP:
        case OMP_CLAUSE_DEPEND:
+       case OMP_CLAUSE_DYN_GROUPPRIVATE:
+       case OMP_CLAUSE_IS_DEVICE_PTR:
+       case OMP_CLAUSE_HAS_DEVICE_ADDR:
+       case OMP_CLAUSE_MAP:
          s = C_OMP_CLAUSE_SPLIT_TARGET;
          break;
        case OMP_CLAUSE_DOACROSS:
index 13df9ea490ec14e924170c378f31e6f7c3356f36..a61a2c7bec36c63af453a535c86e07754c9f33d8 100644 (file)
@@ -119,6 +119,7 @@ enum pragma_omp_clause {
   PRAGMA_OMP_CLAUSE_DEVICE_TYPE,
   PRAGMA_OMP_CLAUSE_DIST_SCHEDULE,
   PRAGMA_OMP_CLAUSE_DOACROSS,
+  PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE,
   PRAGMA_OMP_CLAUSE_ENTER,
   PRAGMA_OMP_CLAUSE_FILTER,
   PRAGMA_OMP_CLAUSE_FINAL,
index b4dc741c6fd4fba9dcf7ccfda31db477ef07dac1..15bfd0dc3f4c85cc0f4cc0e7d9247711c81445d9 100644 (file)
@@ -16411,6 +16411,8 @@ c_parser_omp_clause_name (c_parser *parser)
            result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
          else if (!strcmp ("doacross", p))
            result = PRAGMA_OMP_CLAUSE_DOACROSS;
+         else if (!strcmp ("dyn_groupprivate", p))
+           result = PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE;
          break;
        case 'e':
          if (!strcmp ("enter", p))
@@ -20262,6 +20264,96 @@ c_parser_omp_clause_doacross (c_parser *parser, tree list)
   return list;
 }
 
+/* OpenMP 6.1:
+   dyn_groupprivate ( [fallback-modifier : ] integer-expression )
+
+   fallback-modifier
+      fallback( abort | default_mem | null )  */
+
+static tree
+c_parser_omp_clause_dyn_groupprivate (c_parser *parser, tree list)
+{
+  location_t clause_loc = c_parser_peek_token (parser)->location;
+  matching_parens parens;
+  if (!parens.require_open (parser))
+    return list;
+
+  enum omp_clause_fallback_kind kind = OMP_CLAUSE_FALLBACK_UNSPECIFIED;
+
+  unsigned n = 3;
+  if (c_parser_next_token_is (parser, CPP_NAME)
+      && (c_parser_peek_2nd_token (parser)->type == CPP_COLON
+         || (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN
+             && c_parser_check_balanced_raw_token_sequence (parser, &n)
+             && (c_parser_peek_nth_token_raw (parser, n)->type
+                 == CPP_CLOSE_PAREN)
+             && (c_parser_peek_nth_token_raw (parser, n + 1)->type
+                 == CPP_COLON))))
+    {
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (strcmp (p, "fallback") != 0)
+       {
+         c_parser_error (parser, "expected %<fallback%> modifier");
+         return list;
+       }
+      c_parser_consume_token (parser);
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+       return list;
+      p = "";
+      if (c_parser_next_token_is (parser, CPP_NAME))
+       p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (strcmp (p, "abort") == 0)
+       kind = OMP_CLAUSE_FALLBACK_ABORT;
+      else if (strcmp (p, "default_mem") == 0)
+       kind = OMP_CLAUSE_FALLBACK_DEFAULT_MEM;
+      else if (strcmp (p, "null") == 0)
+       kind = OMP_CLAUSE_FALLBACK_NULL;
+      else
+       {
+         c_parser_error (parser, "expected %<abort%>, %<default_mem%>, or "
+                                 "%<null%> as fallback mode");
+         return list;
+       }
+      c_parser_consume_token (parser);
+      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+       return list;
+      if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+       return list;
+    }
+  location_t expr_loc = c_parser_peek_token (parser)->location;
+  c_expr expr = c_parser_expr_no_commas (parser, NULL);
+  expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+  tree size = c_fully_fold (expr.value, false, NULL);
+  parens.skip_until_found_close (parser);
+
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (size)))
+    {
+      error_at (expr_loc, "expected integer expression");
+      return list;
+    }
+
+  /* Attempt to statically determine when the number is negative.  */
+  tree c = fold_build2_loc (expr_loc, LT_EXPR, boolean_type_node, size,
+                           build_int_cst (TREE_TYPE (size), 0));
+  protected_set_expr_location (c, expr_loc);
+  if (c == boolean_true_node)
+    {
+      warning_at (expr_loc, OPT_Wopenmp,
+                 "%<dyn_groupprivate%> value must be non-negative");
+      size = integer_zero_node;
+    }
+  check_no_duplicate_clause (list, OMP_CLAUSE_DYN_GROUPPRIVATE,
+                            "dyn_groupprivate");
+
+  c = build_omp_clause (clause_loc, OMP_CLAUSE_DYN_GROUPPRIVATE);
+  OMP_CLAUSE_DYN_GROUPPRIVATE_KIND (c) = kind;
+  OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (c) = size;
+  OMP_CLAUSE_CHAIN (c) = list;
+  list = c;
+
+  return list;
+}
+
 /* OpenMP 4.0:
    map ( map-kind: variable-list )
    map ( variable-list )
@@ -21982,6 +22074,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
          clauses = c_parser_omp_clause_destroy (parser, clauses);
          c_name = "destroy";
          break;
+       case PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE:
+         clauses = c_parser_omp_clause_dyn_groupprivate (parser, clauses);
+         c_name = "dyn_groupprivate";
+         break;
        case PRAGMA_OMP_CLAUSE_INIT:
          clauses = c_parser_omp_clause_init (parser, clauses);
          c_name = "init";
@@ -26796,19 +26892,20 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
      structured-block  */
 
 #define OMP_TARGET_CLAUSE_MASK                                 \
-       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE)       \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)          \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)           \
+       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE)     \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP)   \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)       \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)       \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE)      \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE)       \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE) \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE)     \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP)   \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR) \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)           \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR)\
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR))
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)          \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)       \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE)      \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT))
 
 static bool
 c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
index a34ca2ab97c4443c0472ef0bd953da465437cda6..d7c9a324d7ae81faf9498a2578a6bb0ceb873430 100644 (file)
@@ -17879,6 +17879,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
        case OMP_CLAUSE_FINAL:
        case OMP_CLAUSE_DEVICE:
        case OMP_CLAUSE_DIST_SCHEDULE:
+       case OMP_CLAUSE_DYN_GROUPPRIVATE:
        case OMP_CLAUSE_PARALLEL:
        case OMP_CLAUSE_FOR:
        case OMP_CLAUSE_SECTIONS:
index 4289f47e1b233fe11f2f54361e6192d6f305f3af..cdfa8f0122d367540409de52c2e5a5dc6ee6576c 100644 (file)
@@ -40047,6 +40047,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
            result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
          else if (!strcmp ("doacross", p))
            result = PRAGMA_OMP_CLAUSE_DOACROSS;
+         else if (!strcmp ("dyn_groupprivate", p))
+           result = PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE;
          break;
        case 'e':
          if (!strcmp ("enter", p))
@@ -43743,6 +43745,91 @@ cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind,
   return nl;
 }
 
+/* OpenMP 6.1:
+   dyn_groupprivate ( [fallback-modifier : ] integer-expression )
+
+   fallback-modifier
+      fallback( abort | default_mem | null )  */
+
+static tree
+cp_parser_omp_clause_dyn_groupprivate (cp_parser *parser, tree list,
+                                      location_t location)
+{
+  matching_parens parens;
+  if (!parens.require_open (parser))
+    return list;
+
+  enum omp_clause_fallback_kind kind = OMP_CLAUSE_FALLBACK_UNSPECIFIED;
+
+  size_t n;
+  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+      && (cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON)
+         || (cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN)
+             && (n = cp_parser_skip_balanced_tokens (parser, 2)) != 3
+             && cp_lexer_nth_token_is (parser->lexer, n, CPP_COLON))))
+    {
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+      if (strcmp (IDENTIFIER_POINTER (id), "fallback") != 0)
+       {
+         cp_parser_error (parser, "expected %<fallback%> modifier");
+         cp_parser_skip_to_closing_parenthesis (parser,
+                                                /*recovering=*/true,
+                                                /*or_comma=*/false,
+                                                /*consume_paren=*/true);
+         return list;
+       }
+      cp_lexer_consume_token (parser->lexer);
+      if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+       return list;
+      const char *p = "";
+      if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+       {
+         id = cp_lexer_peek_token (parser->lexer)->u.value;
+         p = IDENTIFIER_POINTER (id);
+       }
+      if (strcmp (p, "abort") == 0)
+       kind = OMP_CLAUSE_FALLBACK_ABORT;
+      else if (strcmp (p, "default_mem") == 0)
+       kind = OMP_CLAUSE_FALLBACK_DEFAULT_MEM;
+      else if (strcmp (p, "null") == 0)
+       kind = OMP_CLAUSE_FALLBACK_NULL;
+      else
+       {
+         cp_parser_error (parser, "expected %<abort%>, %<default_mem%>, or "
+                                  "%<null%> as fallback mode");
+         cp_parser_skip_to_closing_parenthesis (parser,
+                                                /*recovering=*/true,
+                                                /*or_comma=*/false,
+                                                /*consume_paren=*/true);
+         return list;
+       }
+      cp_lexer_consume_token (parser->lexer);
+      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+       return list;
+      if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+       return list;
+    }
+
+  tree size = cp_parser_assignment_expression (parser);
+
+  if (size == error_mark_node
+      || !parens.require_close (parser))
+    cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                          /*or_comma=*/false,
+                                          /*consume_paren=*/true);
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_DYN_GROUPPRIVATE,
+                            "dyn_groupprivate", location);
+
+  tree c = build_omp_clause (location, OMP_CLAUSE_DYN_GROUPPRIVATE);
+  OMP_CLAUSE_DYN_GROUPPRIVATE_KIND (c) = kind;
+  OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (c) = size;
+  OMP_CLAUSE_CHAIN (c) = list;
+  list = c;
+
+  return list;
+}
+
 /* OpenMP 4.0:
    map ( map-kind : variable-list )
    map ( variable-list )
@@ -45352,6 +45439,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
                                            clauses);
          c_name = "destroy";
          break;
+       case PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE:
+         clauses = cp_parser_omp_clause_dyn_groupprivate (parser, clauses,
+                                                          token->location);
+         c_name = "dyn_groupprivate";
+         break;
        case PRAGMA_OMP_CLAUSE_INIT:
          {
            /* prefer_type parsing fails often such that many follow-up errors
@@ -50230,19 +50322,20 @@ cp_parser_omp_target_update (cp_parser *parser, cp_token *pragma_tok,
      structured-block  */
 
 #define OMP_TARGET_CLAUSE_MASK                                 \
-       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE)       \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)          \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)           \
+       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE)     \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP)   \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)       \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)       \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE)      \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE)       \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE) \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP)   \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE)     \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR) \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)           \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR)\
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR))
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)          \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)       \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE)      \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT))
 
 static bool
 cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
index cd66aeafd86ef67db23e1dd9ef6c092dcde05efc..7a019d33bda1d335830892dba59e0f20850d5cc9 100644 (file)
@@ -18214,6 +18214,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
        case OMP_CLAUSE_ASYNC:
        case OMP_CLAUSE_WAIT:
        case OMP_CLAUSE_DETACH:
+       case OMP_CLAUSE_DYN_GROUPPRIVATE:
          OMP_CLAUSE_OPERAND (nc, 0)
            = tsubst_stmt (OMP_CLAUSE_OPERAND (oc, 0), args, complain, in_decl);
          break;
index f472be21c4bbdb89841cd5c06b98f408cb6bfdf7..331db16f76dee08a6132c0e27ff71cf4de99d749 100644 (file)
@@ -8356,6 +8356,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
        case OMP_CLAUSE_NUM_THREADS:
        case OMP_CLAUSE_NUM_GANGS:
        case OMP_CLAUSE_NUM_WORKERS:
+       case OMP_CLAUSE_DYN_GROUPPRIVATE:
        case OMP_CLAUSE_VECTOR_LENGTH:
          t = OMP_CLAUSE_OPERAND (c, 0);
          if (t == error_mark_node)
@@ -8389,7 +8390,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
              if (!processing_template_decl)
                {
                  t = maybe_constant_value (t);
-                 if (TREE_CODE (t) == INTEGER_CST
+                 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DYN_GROUPPRIVATE
+                     && TREE_CODE (t) == INTEGER_CST
                      && tree_int_cst_sgn (t) != 1)
                    {
                      switch (OMP_CLAUSE_CODE (c))
@@ -8418,6 +8420,15 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                        }
                      t = integer_one_node;
                    }
+                 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DYN_GROUPPRIVATE
+                          && TREE_CODE (t) == INTEGER_CST
+                          && tree_int_cst_sgn (t) < 0)
+                   {
+                     warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
+                                 "%<dyn_groupprivate%> value must be "
+                                 "non-negative");
+                     t = integer_zero_node;
+                   }
                  t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
                }
              OMP_CLAUSE_OPERAND (c, 0) = t;
index e847c1c0c0846d3c3b35fc59ce9d5e7631b36953..abc27d59a0c5cfe0c9f49616e0a3abff02128724 100644 (file)
@@ -8977,8 +8977,8 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
   if (omp_clauses->num_threads)
     resolve_positive_int_expr (omp_clauses->num_threads, "NUM_THREADS");
   if (omp_clauses->dyn_groupprivate)
-    resolve_positive_int_expr (omp_clauses->dyn_groupprivate,
-                              "DYN_GROUPPRIVATE");
+    resolve_nonnegative_int_expr (omp_clauses->dyn_groupprivate,
+                                 "DYN_GROUPPRIVATE");
   if (omp_clauses->chunk_size)
     {
       gfc_expr *expr = omp_clauses->chunk_size;
index c0a8ed927d9d470e233c6f9cecbfdbe1fdf648b0..8eb4fc4bcc6610dd4da309639826229e92710d85 100644 (file)
@@ -5267,21 +5267,33 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
 
   if (clauses->dyn_groupprivate)
     {
-      sorry_at (gfc_get_location (&where), "%<dyn_groupprivate%> clause");
-#if 0  /* FIXME: Handle it, including 'fallback(abort/default_mem/null)'  */
-      tree dyn_groupprivate;
-
       gfc_init_se (&se, NULL);
       gfc_conv_expr (&se, clauses->dyn_groupprivate);
       gfc_add_block_to_block (block, &se.pre);
-      dyn_groupprivate = gfc_evaluate_now (se.expr, block);
+      tree expr = (CONSTANT_CLASS_P (se.expr) || DECL_P (se.expr)
+                  ? se.expr : gfc_evaluate_now (se.expr, block));
       gfc_add_block_to_block (block, &se.post);
 
+      enum omp_clause_fallback_kind kind = OMP_CLAUSE_FALLBACK_UNSPECIFIED;
+      switch (clauses->fallback)
+       {
+       case OMP_FALLBACK_ABORT:
+         kind = OMP_CLAUSE_FALLBACK_ABORT;
+         break;
+       case OMP_FALLBACK_DEFAULT_MEM:
+         kind = OMP_CLAUSE_FALLBACK_DEFAULT_MEM;
+         break;
+       case OMP_FALLBACK_NULL:
+         kind = OMP_CLAUSE_FALLBACK_NULL;
+         break;
+       case OMP_FALLBACK_NONE:
+         break;
+       }
       c = build_omp_clause (gfc_get_location (&where),
                            OMP_CLAUSE_DYN_GROUPPRIVATE);
-      OMP_CLAUSE_NUM_THREADS_EXPR (c) = num_threads;
+      OMP_CLAUSE_DYN_GROUPPRIVATE_KIND (c) = kind;
+      OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (c) = expr;
       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
-#endif
     }
 
   chunk_size = NULL_TREE;
index 9371195fa01db107abd3f57980e2c85bc16bba48..0023728ad8eb5f1f333611670bfb801f297a271d 100644 (file)
@@ -14881,6 +14881,11 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
        case OMP_CLAUSE_DESTROY:
          break;
 
+       case OMP_CLAUSE_DYN_GROUPPRIVATE:
+         remove = true;
+         sorry_at (OMP_CLAUSE_LOCATION (c),"%<dyn_groupprivate%> clause");
+         break;
+
        case OMP_CLAUSE_ORDER:
          ctx->order_concurrent = true;
          break;
diff --git a/gcc/testsuite/c-c++-common/gomp/dyn_groupprivate-1.c b/gcc/testsuite/c-c++-common/gomp/dyn_groupprivate-1.c
new file mode 100644 (file)
index 0000000..c49189d
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do compile }  */
+/* { dg-additional-options "-fdump-tree-original" }  */
+
+void f()
+{
+  int N = 1024;
+
+  #pragma omp target dyn_groupprivate(1024)  // { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+    ;
+
+  #pragma omp target dyn_groupprivate (1024 * N)  // { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+    ;
+
+  #pragma omp target dyn_groupprivate ( fallback ( abort ) : N)  // { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+    ;
+
+  #pragma omp target dyn_groupprivate ( fallback ( null ) : N)  // { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+    ;
+
+  #pragma omp target dyn_groupprivate ( fallback ( default_mem ) : N)  // { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+    ;
+}
+
+/* { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(1024\\)" 1 "original" } }  */
+/* { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(N \\* 1024\\)" 1 "original" } }  */
+/* { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(fallback\\(abort\\):N\\)" 1 "original" } }  */
+/* { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(fallback\\(null\\):N\\)" 1 "original" } }  */
+/* { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(fallback\\(default_mem\\):N\\)" 1 "original" } }  */
diff --git a/gcc/testsuite/c-c++-common/gomp/dyn_groupprivate-2.c b/gcc/testsuite/c-c++-common/gomp/dyn_groupprivate-2.c
new file mode 100644 (file)
index 0000000..f12ff7b
--- /dev/null
@@ -0,0 +1,72 @@
+/* { dg-do compile }  */
+
+void f()
+{
+#if !defined(__cplusplus) || __cplusplus >= 201103L
+  constexpr int M = 1024; // C20 + C++11
+#endif
+  int N, A[1];
+  N = 1024;
+
+  #pragma omp target dyn_groupprivate(0)
+    ;
+
+  #pragma omp target dyn_groupprivate(0) dyn_groupprivate(0)  // { dg-error "too many 'dyn_groupprivate' clauses" }
+    ;
+
+  #pragma omp target dyn_groupprivate(1,)  // { dg-error "expected '\\)' before ',' token" }
+    ;
+
+  #pragma omp target dyn_groupprivate(-123)  // { dg-warning "'dyn_groupprivate' value must be non-negative \\\[-Wopenmp\\\]" }
+    ;
+
+#if !defined(__cplusplus) || __cplusplus >= 201103L
+  #pragma omp target dyn_groupprivate (0 * M - 1)  // { dg-warning "'dyn_groupprivate' value must be non-negative \\\[-Wopenmp\\\]" "" { target { ! c++98_only } } }
+#endif
+    ;
+
+  #pragma omp target dyn_groupprivate (- 4)  // { dg-warning "'dyn_groupprivate' value must be non-negative \\\[-Wopenmp\\\]" }
+    ;
+
+  #pragma omp target dyn_groupprivate ( fallback ( other ) : N)  // { dg-error "expected 'abort', 'default_mem', or 'null' as fallback mode before 'other'" }
+    // { dg-error "expected an OpenMP clause before ':' token" "" { target c++ } .-1 }
+    ;
+
+  #pragma omp target dyn_groupprivate ( A )
+  // { dg-error "expected integer expression" "" { target c } .-1 }
+  // { dg-error "'dyn_groupprivate' expression must be integral" "" { target c++ } .-2 }
+    ;
+
+  #pragma omp target dyn_groupprivate ( 1024. )
+  // { dg-error "expected integer expression" "" { target c } .-1 }
+  // { dg-error "'dyn_groupprivate' expression must be integral" "" { target c++ } .-2 }
+    ;
+
+  #pragma omp target dyn_groupprivate ( foo ( 4 ) : 10 )  // { dg-error "expected 'fallback' modifier before 'foo'" }
+    ;
+
+  #pragma omp target dyn_groupprivate ( foo2 (  ) : 10 )  // { dg-error "expected 'fallback' modifier before 'foo2'" }
+    ;
+
+  #pragma omp target dyn_groupprivate ( fallback (  ) : 10 )  // { dg-error "expected 'abort', 'default_mem', or 'null' as fallback mode before '\\)'" }
+    // { dg-error "expected an OpenMP clause before ':' token" "" { target c++ } .-1 }
+    ;
+
+  #pragma omp target dyn_groupprivate ( bar : 10 )  // { dg-error "expected 'fallback' modifier before 'bar'" }
+    ;
+
+  #pragma omp target dyn_groupprivate ( fallback : 10 )  // { dg-error "expected '\\(' before ':' token" }
+    // { dg-error "expected an OpenMP clause before ':' token" "" { target c++ } .-1 }
+    ;
+
+  #pragma omp target dyn_groupprivate ( fallback ( null,) : 10 )  // { dg-error "expected '\\)' before ',' token" }
+    // { dg-error "expected an OpenMP clause before '\\)' token" "" { target c++ } .-1 }
+    ;
+}
+
+// { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" "" { target *-*-* } 11 }
+// { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" "" { target *-*-* } 14 }
+// { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" "" { target *-*-* } 17 }
+// { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" "" { target *-*-* } 20 }
+// { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" "" { target { ! c++98_only } } 24 }
+// { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" "" { target *-*-* } 28 }
index 2e09febe18c262935bdb0f6ff08f0d2a3d148adb..3661f142ca50ccd4da4a6b6ece5905fb3f5aa957 100644 (file)
@@ -1,3 +1,6 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+
 implicit none
 
 integer :: N
@@ -18,3 +21,9 @@ N = 1024
 !$omp target dyn_groupprivate ( fallback ( default_mem ) : N)  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
 !$omp end target
 end
+
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(1024\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(D.4680\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(fallback\\(abort\\):n\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(fallback\\(null\\):n\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(fallback\\(default_mem\\):n\\)" 1 "original" } }
index 0a5a644b9f40c1ff1333f2fb61f193192a6f1772..8410334f4f5dc4e1e3f72a164b7b70757e09b677 100644 (file)
@@ -1,3 +1,5 @@
+! { dg-do compile }
+
 implicit none
 
 integer, parameter :: M = 1024
@@ -5,10 +7,16 @@ integer :: N, A(1)
 
 N = 1024
 
-!$omp target dyn_groupprivate(-123)  ! { dg-warning "INTEGER expression of DYN_GROUPPRIVATE clause at .1. must be positive \\\[-Wopenmp\\\]" }
+!$omp target dyn_groupprivate(0)  ! OK, zero is permitted
+block; end block
+
+!$omp target dyn_groupprivate(0)  dyn_groupprivate(0)  ! { dg-error "Duplicated 'dyn_groupprivate' clause" }
+block; end block
+
+!$omp target dyn_groupprivate(-123)  ! { dg-warning "INTEGER expression of DYN_GROUPPRIVATE clause at .1. must be non-negative \\\[-Wopenmp\\\]" }
 block; end block
 
-!$omp target dyn_groupprivate (0 * M)  ! { dg-warning "INTEGER expression of DYN_GROUPPRIVATE clause at .1. must be positive \\\[-Wopenmp\\\]" }
+!$omp target dyn_groupprivate (0 * M-1)  ! { dg-warning "INTEGER expression of DYN_GROUPPRIVATE clause at .1. must be non-negative \\\[-Wopenmp\\\]" }
 block; end block
 
 !$omp target dyn_groupprivate ( fallback ( other ) : N)  ! { dg-error "Failed to match clause" }
index 88627ac938161b5d930d99fa6fa24d8491aa1a28..674d6ec8c7fbe23343ff837b85f679b223bf3b97 100644 (file)
@@ -596,6 +596,8 @@ enum omp_clause_code {
   /* OpenMP clause: nocontext (scalar-expression).  */
   OMP_CLAUSE_NOCONTEXT,
 
+  /* OpenMP clause: dyn_groupprivate ( [fallback (...)] : integer-expression).  */
+  OMP_CLAUSE_DYN_GROUPPRIVATE,
 };
 
 #undef DEFTREESTRUCT
@@ -655,6 +657,14 @@ enum omp_clause_bind_kind {
   OMP_CLAUSE_BIND_THREAD
 };
 
+enum omp_clause_fallback_kind {
+  OMP_CLAUSE_FALLBACK_UNSPECIFIED,
+  OMP_CLAUSE_FALLBACK_ABORT,
+  OMP_CLAUSE_FALLBACK_DEFAULT_MEM,
+  OMP_CLAUSE_FALLBACK_NULL
+};
+
+
 /* memory-order-clause on OpenMP atomic/flush constructs or
    argument of atomic_default_mem_order clause.  */
 enum omp_memory_order {
@@ -1747,6 +1757,7 @@ struct GTY(()) tree_omp_clause {
     enum omp_clause_defaultmap_kind defaultmap_kind;
     enum omp_clause_bind_kind      bind_kind;
     enum omp_clause_device_type_kind device_type_kind;
+    enum omp_clause_fallback_kind fallback_kind;
   } GTY ((skip)) subcode;
 
   /* The gimplification of OMP_CLAUSE_REDUCTION_{INIT,MERGE} for omp-low's
index 813334b5c92049d1722925695edefa368ac63add..21a289b086063b902f8da6d27376c24388c3d1d9 100644 (file)
@@ -1411,6 +1411,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_DEPEND:
        case OMP_CLAUSE_DOACROSS:
        case OMP_CLAUSE_DEVICE:
+       case OMP_CLAUSE_DYN_GROUPPRIVATE:
        case OMP_CLAUSE_NUM_TEAMS:
        case OMP_CLAUSE_THREAD_LIMIT:
        case OMP_CLAUSE_SAFELEN:
@@ -2192,6 +2193,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_DEPEND:
        case OMP_CLAUSE_DOACROSS:
        case OMP_CLAUSE_DEVICE:
+       case OMP_CLAUSE_DYN_GROUPPRIVATE:
        case OMP_CLAUSE_NUM_TEAMS:
        case OMP_CLAUSE_THREAD_LIMIT:
        case OMP_CLAUSE_SAFELEN:
index c19babadeadee73a063dfd46660e3a97b18cfdb9..ba04911ae905c7bdf7702ece3184f4e152cd1a45 100644 (file)
@@ -1327,6 +1327,27 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
       pp_right_paren (pp);
       break;
 
+    case OMP_CLAUSE_DYN_GROUPPRIVATE:
+      pp_string (pp, "dyn_groupprivate(");
+      switch (OMP_CLAUSE_DYN_GROUPPRIVATE_KIND (clause))
+       {
+       case OMP_CLAUSE_FALLBACK_ABORT:
+         pp_string (pp, "fallback(abort):");
+         break;
+       case OMP_CLAUSE_FALLBACK_DEFAULT_MEM:
+         pp_string (pp, "fallback(default_mem):");
+         break;
+       case OMP_CLAUSE_FALLBACK_NULL:
+         pp_string (pp, "fallback(null):");
+         break;
+       case OMP_CLAUSE_FALLBACK_UNSPECIFIED:
+         break;
+       }
+      dump_generic_node (pp, OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (clause),
+                        spc, flags, false);
+      pp_right_paren (pp);
+      break;
+
     case OMP_CLAUSE_SAFELEN:
       pp_string (pp, "safelen(");
       dump_generic_node (pp, OMP_CLAUSE_SAFELEN_EXPR (clause),
index e8376dd04bd761b9f4839fd579567b5e2ecbc653..52fc83e3c07d86770d5b4dda8ec0347b105d8fc9 100644 (file)
@@ -398,6 +398,7 @@ unsigned const char omp_clause_num_ops[] =
   0, /* OMP_CLAUSE_NOHOST */
   1, /* OMP_CLAUSE_NOVARIANTS */
   1, /* OMP_CLAUSE_NOCONTEXT */
+  1, /* OMP_CLAUSE_DYN_GROUPPRIVATE  */
 };
 
 const char * const omp_clause_code_name[] =
@@ -501,6 +502,7 @@ const char * const omp_clause_code_name[] =
   "nohost",
   "novariants",
   "nocontext",
+  "dyn_groupprivate",
 };
 
 /* Unless specific to OpenACC, we tend to internally maintain OpenMP-centric
index 762228c336fbff75a5fc1b9ee110e8f6db4ab30a..56f4fc16dcd198e56a709f639768f7a1251bfc5c 100644 (file)
@@ -2116,6 +2116,11 @@ class auto_suppress_location_wrappers
 #define OMP_CLAUSE_BIND_KIND(NODE) \
   (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_BIND)->omp_clause.subcode.bind_kind)
 
+#define OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR(NODE)                                        \
+  OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DYN_GROUPPRIVATE), 0)
+#define OMP_CLAUSE_DYN_GROUPPRIVATE_KIND(NODE) \
+  (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DYN_GROUPPRIVATE)->omp_clause.subcode.fallback_kind)
+
 /* True if ENTER clause is spelled as TO.  */
 #define OMP_CLAUSE_ENTER_TO(NODE) \
   (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ENTER)->base.public_flag)