Short version:
* dyn_groupprivate clause - valid on target and on teams
  Fixed: was not accepted on 'teams'
  Fixed: on combined directives, the clause was lost.

* target + teams (two directives or in one combined directive):
  For the dyn_groupprivate, num_teams, thread_limit clauses:
  - now evaluated on the host
  - clauses are put on 'target' (also num_teams, which only
    accepts this clause internally)
  - for dyn_groupprivate/thread_limit, the value on 'teams' wins
    if both target and teams such a clause
  - there will be no dyn_groupprivate on teams
  - num_teams + thread_limit: temp variable will be firstprivate
    on 'target' and clauses are also on 'teams'

Background: for all three clauses, the host code launching a
GPU kernel should know the value at launch time. If not, it
the value has to be guesses. - OpenMP 5.0 and then 6.0 added
wording to make it possible to evaluate it on the host, in time
for the kernel launch.

(Currently, num_teams/num_threads == -1 is used in the call to
GOMP_target_ext to indicate that a teams with a clause exists
but the value is unknown when GOMP_target_ext is called.
With this patch, gfortran code shall never yield '-1' any more.)

Any comments before I commit this later today?

Tobias

* * *

Long version for the second change:

When launching a GPU kernel, the host code needs to know how many
teams and threads have to be created. That's not that trivial for
code like:

  !$omp target
     !$omp teams num_teams(f()) thread_limit(n[0])

as f() on the host or on the device might return different values
and 'n' might be mapped on the target - such that evaluation on
host and device can be again have different values.

Since 5.0, OpenMP has clarified that on 'target teams' the evaluation
is always on the host - and, since 6.0, also for code like above,
OpenMP requires the user that evaluation on the host and on the device
will yield the same result (target-consistent expression).
[No sane person will code with non-target-consistent expressions.]


There is code in the middle end which is supposed to handle code as
above in simple cases like:

  integer :: n
  n = 16
  !$omp target
    !$omp teams num_teams(n)
or even
  !$omp target teams num_teams(n)

However, before this patch is turned into:

  #pragma omp target num_teams(-1) firstprivate(n)
  {
     int D.123 = n;  // expanded by the front end
     #pragma teams num_teams(D.123)

as the middle end expects the full expression in the clause
(as common with C) and fails due to the temporary.

Now the result with this patch is the front-end code:

  int D.123 = n;
  #pragma omp target num_teams(D.123) firstprivate(D.123)
  {
     #pragma teams num_teams(D.123)

and the middle change of this patch ensures that this
remains such after gimplification without adding a
second num_teams(-1) to 'target'.

Tobias

PS: For C/C++, the situation is better; for the combined directive,
the host expansion and firstprivate already happens (5.0 semantic)
and the gimplify.cc code will also help with the common cases when
using two directives. - Still, a similar change for C/C++ should
be done in lockstep with supporting spatial dimensions to completely
avoid the '-1' case.  (target teams without clauses is '0' and target
without teams is '-2'.)
OpenMP/Fortran: Fixes to target-consistent clauses and dyn_groupprivate

num_teams and thread_limit clauses on teams inside target can be evaluated
on the host (and must be the same as on the device: target consistent).
As those values are relevant when launching a GPU kernel, it very much
makes sense to do so.  This commit ensures that this happens (gimplify.cc's
optimize_target_teams comes too late as the expanded expression has been
converted to assignment statements - likewise for combined directives
and for immediately nested directives.)

Note: Since 5.0, the evaluation of the num_teams and thread_limit on a
combined directive of target and teams must be evaluated on the host,
since 6.0 this is expanded to also cover a teams construct that is
immediately nested in target. - This is is a breaking change as before
a function call to a device function instead to a host function or a
mapped variable instead of the corresponding host function could yield
other results when evaluated on the host or on the device. However,
this is extremely unlikely to occur in real-world code.

This commit evaluates the expression of those two clauses and of
dyn_groupprivate on the host; dyn_groupprivate will only be put on
target, the other clauses are on both target and teams and the
temporary clause will also be put into a firstprivate clause on target.
(num_teams is not permitted on target by the standard but internally,
GCC puts it there, too.)
For dyn_groupprivate and thread_limit, the clause on teams wins
as it overrides the settings of target - such that it can be used directly.

NOTE: 'if' and 'allocate' are also target consistent; for 'allocate',
this is no restriction due to other restrictions - and 'if' on teams
is not yet supported.

gcc/fortran/ChangeLog:

	* openmp.cc (OMP_TEAMS_CLAUSES): Add OMP_CLAUSE_DYN_GROUPPRIVATE.
	* trans-openmp.cc (gfc_trans_omp_clauses): Use expression and not
	directive line for the location.
	(gfc_split_omp_clauses): Handle dyn_groupprivate.
	(gfc_trans_omp_target): Handle target-consistent clauses.

gcc/ChangeLog:

	* gimplify.cc (optimize_target_teams): SKip if there is already a
	'num_teams' (i.e. already optimized by the front end).

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/spatial-dimensions-1.f90: Update scan-tree-dump.
	* gfortran.dg/gomp/spatial-dimensions-4.f90: Likewise.
	* gfortran.dg/gomp/spatial-dimensions-5.f90: Likewise.
	* gfortran.dg/gomp/dyn_groupprivate-3.f90: New test.
	* gfortran.dg/gomp/dyn_groupprivate-4.f90: New test.
	* gfortran.dg/gomp/target-teams-1.f90: New test.
	* gfortran.dg/gomp/target-teams-2.f90: New test.

 gcc/fortran/openmp.cc                              |   2 +-
 gcc/fortran/trans-openmp.cc                        | 233 +++++++++++++++++----
 gcc/gimplify.cc                                    |   6 +
 .../gfortran.dg/gomp/dyn_groupprivate-3.f90        |  24 +++
 .../gfortran.dg/gomp/dyn_groupprivate-4.f90        | 184 ++++++++++++++++
 .../gfortran.dg/gomp/spatial-dimensions-1.f90      |   2 +-
 .../gfortran.dg/gomp/spatial-dimensions-4.f90      |  15 +-
 .../gfortran.dg/gomp/spatial-dimensions-5.f90      |  12 +-
 gcc/testsuite/gfortran.dg/gomp/target-teams-1.f90  |  65 ++++++
 gcc/testsuite/gfortran.dg/gomp/target-teams-2.f90  |  17 ++
 10 files changed, 504 insertions(+), 56 deletions(-)

diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index ba7f3c5ea24..670e4af1399 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -5995,7 +5995,7 @@ cleanup:
   (omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT		\
    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE	\
    | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE	\
-   | OMP_CLAUSE_MESSAGE)
+   | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_DYN_GROUPPRIVATE)
 #define OMP_DISTRIBUTE_CLAUSES \
   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE		\
    | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE \
diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index bee9fd608ec..e64aba9aef7 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -5760,8 +5760,8 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
 	case OMP_FALLBACK_NONE:
 	  break;
 	}
-      c = build_omp_clause (gfc_get_location (&where),
-			    OMP_CLAUSE_DYN_GROUPPRIVATE);
+      location_t loc = gfc_get_location (&clauses->dyn_groupprivate->where);
+      c = build_omp_clause (loc, OMP_CLAUSE_DYN_GROUPPRIVATE);
       OMP_CLAUSE_DYN_GROUPPRIVATE_KIND (c) = kind;
       OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (c) = expr;
       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
@@ -6016,9 +6016,19 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
 			       gfc_convert_expr_to_tree (block, el->expr),
 			       num_teams);
       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TEAMS);
-      OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = NULL_TREE;
-      OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = nreverse (num_teams);
-      OMP_CLAUSE_NUM_TEAMS_DIMS (c) = clauses->num_teams_dims;
+      if (clauses->num_teams_dims)
+	{
+	  OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = NULL_TREE;
+	  OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = nreverse (num_teams);
+	  OMP_CLAUSE_NUM_TEAMS_DIMS (c) = clauses->num_teams_dims;
+	}
+      else
+	{
+	  OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = TREE_VALUE (num_teams);
+	  if (TREE_CHAIN(num_teams))
+	    OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
+	      = TREE_VALUE (TREE_CHAIN (num_teams));
+	}
       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
     }
 
@@ -8565,6 +8575,10 @@ gfc_split_omp_clauses (gfc_code *code,
 	    = code->ext.omp_clauses->lists[OMP_LIST_IS_DEVICE_PTR];
 	  clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_HAS_DEVICE_ADDR]
 	    = code->ext.omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR];
+	  clausesa[GFC_OMP_SPLIT_TARGET].dyn_groupprivate
+	    = code->ext.omp_clauses->dyn_groupprivate;
+	  clausesa[GFC_OMP_SPLIT_TARGET].fallback
+	    = code->ext.omp_clauses->fallback;
 	  clausesa[GFC_OMP_SPLIT_TARGET].device
 	    = code->ext.omp_clauses->device;
 	  clausesa[GFC_OMP_SPLIT_TARGET].thread_limit_list
@@ -8603,6 +8617,10 @@ gfc_split_omp_clauses (gfc_code *code,
 	    = code->ext.omp_clauses->thread_limit_strict;
 	  clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_dims
 	    = code->ext.omp_clauses->thread_limit_dims;
+	  clausesa[GFC_OMP_SPLIT_TEAMS].dyn_groupprivate
+	    = code->ext.omp_clauses->dyn_groupprivate;
+	  clausesa[GFC_OMP_SPLIT_TEAMS].fallback
+	    = code->ext.omp_clauses->fallback;
 	  /* Shared and default clauses are allowed on parallel, teams
 	     and taskloop.  */
 	  clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_SHARED]
@@ -9405,16 +9423,181 @@ gfc_trans_omp_target (gfc_code *code)
   tree stmt, omp_clauses = NULL_TREE;
 
   gfc_start_block (&block);
+
+  /* For target + teams, evaluate some clauses on the host; as for those their
+     expressions must be target consistent, this is also permitted when
+     nested and not only for combined directives.  */
+  bool combined_teams_dir = false;
+  if (flag_openmp)
+    switch (code->op)
+      {
+      case EXEC_OMP_TARGET_TEAMS:
+      case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
+      case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
+      case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+      case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
+      case EXEC_OMP_TARGET_TEAMS_LOOP:
+	combined_teams_dir = true;
+	break;
+      default:
+	combined_teams_dir = false;
+	break;
+      }
+  tree tree_tgt_clauses = NULL_TREE, tree_teams_clauses = NULL_TREE;
+  gfc_omp_clauses *teams_clauses = NULL;
+  if (flag_openmp && code->op == EXEC_OMP_TARGET && code->block->next)
+    {
+      gfc_code *code2 = (code->block->next->op == EXEC_BLOCK
+			 ? code->block->next->ext.block.ns->code
+			 : code->block->next);
+      if (code2)
+	switch (code2->op)
+	  {
+	  case EXEC_OMP_TEAMS:
+	  case EXEC_OMP_TEAMS_DISTRIBUTE:
+	  case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
+	  case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+	  case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
+	  case EXEC_OMP_TEAMS_LOOP:
+	    teams_clauses = code2->ext.omp_clauses;
+	    break;
+	  default:
+	    break;
+	  }
+     }
+  if ((teams_clauses && teams_clauses->num_teams_list)
+       || (combined_teams_dir && code->ext.omp_clauses->num_teams_list))
+    {
+      gfc_omp_clauses *num_teams_clauses
+	= teams_clauses ? teams_clauses : code->ext.omp_clauses;
+      tree c, t, num_teams = NULL_TREE;
+      for (gfc_expr_list *el = num_teams_clauses->num_teams_list;
+	   el; el = el->next)
+	{
+	  t = gfc_convert_expr_to_tree (&block, el->expr);
+	  if (DECL_P (t))
+	    {
+	      c = build_omp_clause (gfc_get_location (&el->expr->where),
+				    OMP_CLAUSE_FIRSTPRIVATE);
+	      OMP_CLAUSE_DECL (c) = t;
+	      tree_tgt_clauses = gfc_trans_add_clause (c, tree_tgt_clauses);
+	    }
+	  num_teams = tree_cons (NULL_TREE, t, num_teams);
+	}
+      locus *loc = &num_teams_clauses->num_teams_list->expr->where;
+      c = build_omp_clause (gfc_get_location (loc), OMP_CLAUSE_NUM_TEAMS);
+      if (num_teams_clauses->num_teams_dims)
+	{
+	  OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = NULL_TREE;
+	  OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = nreverse (num_teams);
+	  OMP_CLAUSE_NUM_TEAMS_DIMS (c) = num_teams_clauses->num_teams_dims;
+	}
+      else
+	{
+	  OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = TREE_VALUE (num_teams);
+	  if (TREE_CHAIN (num_teams))
+	    OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
+	      = TREE_VALUE (TREE_CHAIN (num_teams));
+	}
+      tree_tgt_clauses = gfc_trans_add_clause (c, tree_tgt_clauses);
+      tree_teams_clauses = gfc_trans_add_clause (unshare_expr (c),
+						 tree_teams_clauses);
+      gfc_free_expr_list (num_teams_clauses->num_teams_list);
+      num_teams_clauses->num_teams_list = NULL;
+    }
+  if ((teams_clauses && teams_clauses->thread_limit_list)
+      || (combined_teams_dir && code->ext.omp_clauses->thread_limit_list))
+    {
+      /* thread_limit can be put on target and on teams, use the team one as
+	 having higher precedence.  */
+      gfc_omp_clauses *thread_limit_clauses
+	= (teams_clauses && teams_clauses->thread_limit_list
+	   ? teams_clauses : code->ext.omp_clauses);
+      tree c, t, thread_limit = NULL_TREE;
+      for (gfc_expr_list *el = thread_limit_clauses->thread_limit_list;
+	   el; el = el->next)
+	{
+	  t = gfc_convert_expr_to_tree (&block, el->expr);
+	  if (DECL_P (t))
+	    {
+	      c = build_omp_clause (gfc_get_location (&el->expr->where),
+				    OMP_CLAUSE_FIRSTPRIVATE);
+	      OMP_CLAUSE_DECL (c) = t;
+	      tree_tgt_clauses = gfc_trans_add_clause (c, tree_tgt_clauses);
+	    }
+	  thread_limit = tree_cons (NULL_TREE, t, thread_limit);
+	}
+      locus *loc = &thread_limit_clauses->thread_limit_list->expr->where;
+      c = build_omp_clause (gfc_get_location (loc), OMP_CLAUSE_THREAD_LIMIT);
+      OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = nreverse (thread_limit);
+      OMP_CLAUSE_THREAD_LIMIT_STRICT (c)
+	= thread_limit_clauses->thread_limit_strict;
+      OMP_CLAUSE_THREAD_LIMIT_DIMS (c)
+	= thread_limit_clauses->thread_limit_dims;
+      tree_tgt_clauses = gfc_trans_add_clause (c, tree_tgt_clauses);
+      tree_teams_clauses = gfc_trans_add_clause (unshare_expr (c),
+						 tree_teams_clauses);
+      gfc_free_expr_list (thread_limit_clauses->thread_limit_list);
+      thread_limit_clauses->thread_limit_list = NULL;
+      gfc_free_expr_list (code->ext.omp_clauses->thread_limit_list);
+      code->ext.omp_clauses->thread_limit_list = NULL;
+    }
+  if ((teams_clauses && teams_clauses->dyn_groupprivate)
+      || (combined_teams_dir && code->ext.omp_clauses->dyn_groupprivate))
+    {
+      /* dyn_groupprivate can be put on target and on teams, use the team one as
+	 having higher precedence.  */
+      gfc_omp_clauses *dyn_gp_clauses
+	= (teams_clauses && teams_clauses->dyn_groupprivate
+	   ? teams_clauses : code->ext.omp_clauses);
+      gfc_omp_clauses tmp = {};
+      tmp.dyn_groupprivate = dyn_gp_clauses->dyn_groupprivate;
+      tmp.fallback = dyn_gp_clauses->fallback;
+      tree c = gfc_trans_omp_clauses (&block, &tmp, code->loc);
+      if (DECL_P (OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (c)))
+	{
+	  tree c2;
+	  OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (c)
+	    = gfc_evaluate_now (OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (c), &block);
+	  c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+				 OMP_CLAUSE_FIRSTPRIVATE);
+	  OMP_CLAUSE_DECL (c2) = OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (c);
+	  tree_tgt_clauses = gfc_trans_add_clause (c2, tree_tgt_clauses);
+	}
+      /* There is no need to put the clause also on teams.  */
+      tree_tgt_clauses = gfc_trans_add_clause (c, tree_tgt_clauses);
+      gfc_free_expr (dyn_gp_clauses->dyn_groupprivate);
+      dyn_gp_clauses->dyn_groupprivate = NULL;
+      gfc_free_expr (code->ext.omp_clauses->dyn_groupprivate);
+      code->ext.omp_clauses->dyn_groupprivate = NULL;
+    }
+  /* FIXME: also 'if' and 'allocate' are target consistent.  */
+
   gfc_split_omp_clauses (code, clausesa);
   if (flag_openmp)
     omp_clauses
-      = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET],
-			       code->loc);
+      = chainon (gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET],
+					code->loc), tree_tgt_clauses);
   switch (code->op)
     {
     case EXEC_OMP_TARGET:
       pushlevel ();
-      stmt = gfc_trans_omp_code (code->block->next, true);
+      if (tree_teams_clauses)
+	{
+	  gfc_code *code2 = code->block->next;
+	  if (code2->op == EXEC_BLOCK)
+	    {
+	      gcc_checking_assert (!code2->ext.block.ns->sym_root->left
+				   && !code2->ext.block.ns->sym_root->right);
+	      code2 = code2->ext.block.ns->code;
+	    }
+	  gcc_checking_assert (code2->next == NULL);
+	  stmt = gfc_trans_omp_teams (code2,
+				      combined_teams_dir ? clausesa : NULL,
+				      tree_teams_clauses);
+	}
+      else
+	stmt = gfc_trans_omp_code (code->block->next, true);
       stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
       break;
     case EXEC_OMP_TARGET_PARALLEL:
@@ -9464,38 +9647,8 @@ gfc_trans_omp_target (gfc_code *code)
 	poplevel (0, 0);
       break;
     default:
-      if (flag_openmp
-	  && (clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_list
-	      || clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_list))
-	{
-	  gfc_omp_clauses clausesb;
-	  tree teams_clauses;
-	  /* For combined !$omp target teams, the num_teams and
-	     thread_limit clauses are evaluated before entering the
-	     target construct.  */
-	  memset (&clausesb, '\0', sizeof (clausesb));
-	  clausesb.num_teams_list
-	    = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_list;
-	  clausesb.num_teams_dims
-	    = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_dims;
-	  clausesb.thread_limit_list
-	    = clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_list;
-	  clausesb.thread_limit_strict
-	    = clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_strict;
-	  clausesb.thread_limit_dims
-	    = clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_dims;
-	  clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_list = NULL;
-	  clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_list = NULL;
-	  teams_clauses
-	    = gfc_trans_omp_clauses (&block, &clausesb, code->loc);
-	  pushlevel ();
-	  stmt = gfc_trans_omp_teams (code, clausesa, teams_clauses);
-	}
-      else
-	{
-	  pushlevel ();
-	  stmt = gfc_trans_omp_teams (code, clausesa, NULL_TREE);
-	}
+      pushlevel ();
+      stmt = gfc_trans_omp_teams (code, clausesa, tree_teams_clauses);
       if (TREE_CODE (stmt) != BIND_EXPR)
 	stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
       else
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 94d71d71fc2..d521bda8186 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -18790,6 +18790,12 @@ computable_teams_clause (tree *tp, int *walk_subtrees, void *)
 static void
 optimize_target_teams (tree target, gimple_seq *pre_p)
 {
+  /* If the NUM_TEAMS clause is on TARGET, assume that the front end already
+     took care of the target-consistent clauses.  Note that user code cannot
+     specify 'num_teams' on 'target', only on 'teams'.  */
+  if (omp_find_clause (OMP_TARGET_CLAUSES (target), OMP_CLAUSE_NUM_TEAMS))
+    return;
+
   tree body = OMP_BODY (target);
   tree teams = walk_tree (&body, find_omp_teams, NULL, NULL);
   tree num_teams_lower = NULL_TREE;
diff --git a/gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-3.f90 b/gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-3.f90
new file mode 100644
index 00000000000..2df14a2c1c9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-3.f90
@@ -0,0 +1,24 @@
+! { dg-additional-options "-fdump-tree-original" }
+subroutine foo
+  implicit none
+
+  !$omp teams dyn_groupprivate(fallback(abort) : 123)  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+  !$omp end teams
+
+  !$omp target
+    !$omp teams dyn_groupprivate(fallback(null) : 234)  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+    !$omp end teams
+  !$omp end target
+
+  !$omp teams dyn_groupprivate(fallback(default_mem) : 345)  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+  !$omp end teams
+
+  !$omp target teams  dyn_groupprivate(cgroup: 567)  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+  !$omp end target teams
+end
+
+! { dg-final { scan-tree-dump-times "#pragma omp teams dyn_groupprivate\\(fallback\\(abort\\):123\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(fallback\\(null\\):234\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams dyn_groupprivate\\(fallback\\(default_mem\\):345\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(567\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams\[\\n\\r\]" 2 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-4.f90 b/gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-4.f90
new file mode 100644
index 00000000000..0a767c8bec9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-4.f90
@@ -0,0 +1,184 @@
+! { dg-additional-options "-fdump-tree-original" }
+
+subroutine f(n)
+ integer, value :: n
+ integer :: i
+
+ ! Clauses only on target (parallel also accepts 'severity')
+
+ !$omp target parallel do simd thread_limit(dims(2), strict : 1,2) dyn_groupprivate(fallback(null), cgroup : 123) message("one") severity(warning) ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(\"one\" \\\[len:3\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(fallback\\(null\\):123\\) thread_limit\\(strict,dims\\(\\):1, 2\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel message\\(\"one\" \\\[len:3\\\]\\) severity\\(warning\\)" 1 "original" } }
+
+ !$omp target parallel do thread_limit(dims(2), relaxed : 2,3) dyn_groupprivate(fallback(abort), cgroup : 234) message("two") severity(warning)  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(\"two\" \\\[len:3\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(fallback\\(abort\\):234\\) thread_limit\\(dims\\(\\):2, 3\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel message\\(\"two\" \\\[len:3\\\]\\) severity\\(warning\\)" 1 "original" } }
+
+ !$omp target parallel loop thread_limit(relaxed: 34) dyn_groupprivate(fallback(default_mem), cgroup : 345) message("three") severity(warning)  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(\"three\" \\\[len:5\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(fallback\\(default_mem\\):345\\) thread_limit\\(34\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel message\\(\"three\" \\\[len:5\\\]\\) severity\\(warning\\)" 1 "original" } }
+
+ !$omp target parallel thread_limit(strict : 45) dyn_groupprivate(cgroup : 456) message("four") severity(warning)  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ block
+ end block
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(\"four\" \\\[len:4\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(456\\) thread_limit\\(strict:45\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel message\\(\"four\" \\\[len:4\\\]\\) severity\\(warning\\)" 1 "original" } }
+
+ !$omp target simd thread_limit(dims(1) : 67) dyn_groupprivate(fallback(abort), cgroup : 678) message("five")  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(\"five\" \\\[len:4\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(fallback\\(abort\\):678\\) thread_limit\\(strict,dims\\(\\):67\\)" 1 "original" } }
+
+ ! Clauses on target teams (additionally with num_teams)
+
+ !$omp target teams distribute parallel do simd num_teams(11:22) thread_limit(strict : 331) dyn_groupprivate( cgroup ,fallback(null) : 243) message("seven") severity(warning)  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(\"seven\" \\\[len:5\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(fallback\\(null\\):243\\) thread_limit\\(strict:331\\) num_teams\\(11:22\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams thread_limit\\(strict:331\\) num_teams\\(11:22\\) message\\(\"seven\" \\\[len:5\\\]\\) severity\\(fatal\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel message\\(\"seven\" \\\[len:5\\\]\\) severity\\(warning\\)" 1 "original" } }
+
+ !$omp target teams distribute parallel do num_teams(dims(1):1343) thread_limit(relaxed : 1452) dyn_groupprivate( cgroup ,fallback(default_mem) : 1248) message("nine") severity(warning)  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(\"nine\" \\\[len:4\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(fallback\\(default_mem\\):1248\\) thread_limit\\(1452\\) num_teams\\(dims\\(\\):1343\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams thread_limit\\(1452\\) num_teams\\(dims\\(\\):1343\\) message\\(\"nine\" \\\[len:4\\\]\\) severity\\(fatal\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel message\\(\"nine\" \\\[len:4\\\]\\) severity\\(warning\\)" 1 "original" } }
+
+ !$omp target teams distribute simd num_teams(dims(2):3,3) thread_limit(938) dyn_groupprivate( 1458) message("ten")  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(\"ten\" \\\[len:3\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(1458\\) thread_limit\\(938\\) num_teams\\(dims\\(\\):3, 3\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams thread_limit\\(938\\) num_teams\\(dims\\(\\):3, 3\\) message\\(\"ten\" \\\[len:3\\\]\\) severity\\(fatal\\)" 1 "original" } }
+
+ !$omp target teams distribute num_teams(4223) thread_limit(729) dyn_groupprivate( 803) message("eleven")  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(\"eleven\" \\\[len:6\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(803\\) thread_limit\\(729\\) num_teams\\(4223\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams thread_limit\\(729\\) num_teams\\(4223\\) message\\(\"eleven\" \\\[len:6\\\]\\) severity\\(fatal\\)" 1 "original" } }
+!
+ !$omp target teams loop num_teams(444) thread_limit(451) dyn_groupprivate( 842) message("twelf")  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(\"twelf\" \\\[len:5\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(842\\) thread_limit\\(451\\) num_teams\\(444\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams thread_limit\\(451\\) num_teams\\(444\\) message\\(\"twelf\" \\\[len:5\\\]\\) severity\\(fatal\\)" 1 "original" } }
+
+
+ ! Same, but in two directives - put on 'teams'
+
+ !$omp target
+ !$omp teams distribute parallel do simd num_teams(11:22) thread_limit(strict : 331) dyn_groupprivate( cgroup ,fallback(null) : 243) message("13") severity(warning)  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+ !$omp end target
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(fallback\\(null\\):243\\) thread_limit\\(strict:331\\) num_teams\\(11:22\\)\[\\n\\r\{ \]+#pragma omp teams thread_limit\\(strict:331\\) num_teams\\(11:22\\) message\\(\"13\" \\\[len:2\\\]\\) severity\\(fatal\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel message\\(\"13\" \\\[len:2\\\]\\) severity\\(warning\\)" 1 "original" } }
+
+ !$omp target
+ !$omp teams distribute parallel do num_teams(dims(1):1343) thread_limit(relaxed : 1452) dyn_groupprivate( cgroup ,fallback(default_mem) : 1248) message("14") severity(warning)  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+ !$omp end target
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(fallback\\(default_mem\\):1248\\) thread_limit\\(1452\\) num_teams\\(dims\\(\\):1343\\)\[\\n\\r\{ \]+#pragma omp teams thread_limit\\(1452\\) num_teams\\(dims\\(\\):1343\\) message\\(\"14\" \\\[len:2\\\]\\) severity\\(fatal\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel message\\(\"14\" \\\[len:2\\\]\\) severity\\(warning\\)" 1 "original" } }
+
+ !$omp target
+ !$omp teams distribute simd num_teams(dims(2):3,3) thread_limit(938) dyn_groupprivate( 1458) message("15")  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+ !$omp end target
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(1458\\) thread_limit\\(938\\) num_teams\\(dims\\(\\):3, 3\\)\[\\n\\r\{ \]+#pragma omp teams thread_limit\\(938\\) num_teams\\(dims\\(\\):3, 3\\) message\\(\"15\" \\\[len:2\\\]\\) severity\\(fatal\\)" 1 "original" } }
+
+ !$omp target
+ !$omp teams distribute num_teams(4223) thread_limit(729) dyn_groupprivate( 803) message("16")  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+ !$omp end target
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(803\\) thread_limit\\(729\\) num_teams\\(4223\\)\[\\n\\r\{ \]+#pragma omp teams thread_limit\\(729\\) num_teams\\(4223\\) message\\(\"16\" \\\[len:2\\\]\\) severity\\(fatal\\)" 1 "original" } }
+
+ !$omp target
+ !$omp teams loop num_teams(444) thread_limit(451) dyn_groupprivate( 842) message("17")  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+ !$omp end target
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(842\\) thread_limit\\(451\\) num_teams\\(444\\)\[\\n\\r\{ \]+#pragma omp teams thread_limit\\(451\\) num_teams\\(444\\) message\\(\"17\" \\\[len:2\\\]\\) severity\\(fatal\\)" 1 "original" } }
+
+
+ ! Same but in two directives, put on target, except for num_teams
+
+ !$omp target thread_limit(strict : 331) dyn_groupprivate( cgroup ,fallback(null) : 243) message("18")  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ !$omp teams distribute parallel do simd num_teams(11:22) severity(warning)
+ do i = 1, n
+ end do
+ !$omp end target
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(\"18\" \\\[len:2\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(fallback\\(null\\):243\\) thread_limit\\(strict:331\\) num_teams\\(11:22\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(11:22\\)" 1 "original" } }
+
+ !$omp target thread_limit(relaxed : 1452) dyn_groupprivate( cgroup ,fallback(default_mem) : 1248) message("19")  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ !$omp teams distribute parallel do num_teams(dims(1):1343) severity(warning)
+ do i = 1, n
+ end do
+ !$omp end target
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(\"19\" \\\[len:2\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(fallback\\(default_mem\\):1248\\) thread_limit\\(1452\\) num_teams\\(dims\\(\\):1343\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(dims\\(\\):1343\\)" 1 "original" } }
+
+ !$omp target thread_limit(938) dyn_groupprivate( 1458) message("20")  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ !$omp teams distribute simd num_teams(dims(2):3,3)
+ do i = 1, n
+ end do
+ !$omp end target
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(\"20\" \\\[len:2\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(1458\\) thread_limit\\(938\\) num_teams\\(dims\\(\\):3, 3\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(dims\\(\\):3, 3\\)" 1 "original" } }
+
+ !$omp target thread_limit(729) dyn_groupprivate( 803) message("21")  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ !$omp teams distribute num_teams(4223)
+ do i = 1, n
+ end do
+ !$omp end target
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(\"21\" \\\[len:2\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(803\\) thread_limit\\(729\\) num_teams\\(4223\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(4223\\)" 1 "original" } }
+
+ !$omp target thread_limit(451) dyn_groupprivate( 842) message("22")  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ !$omp teams loop num_teams(444)
+ do i = 1, n
+ end do
+ !$omp end target
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(\"22\" \\\[len:2\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(842\\) thread_limit\\(451\\) num_teams\\(444\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(444\\)" 1 "original" } }
+
+
+ ! No 'target', just teams
+
+ !$omp teams distribute parallel do simd num_teams(11:22) thread_limit(strict : 331) dyn_groupprivate( cgroup ,fallback(null) : 243) message("23") severity(warning)  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+! { dg-final { scan-tree-dump-times "#pragma omp teams message\\(\"23\" \\\[len:2\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(fallback\\(null\\):243\\) num_teams\\(11:22\\) thread_limit\\(strict:331\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel message\\(\"23\" \\\[len:2\\\]\\) severity\\(warning\\)" 1 "original" } }
+
+ !$omp teams distribute parallel do num_teams(11:22) thread_limit(strict : 331) dyn_groupprivate( cgroup ,fallback(null) : 243) message("24") severity(warning)  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+! { dg-final { scan-tree-dump-times "#pragma omp teams message\\(\"24\" \\\[len:2\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(fallback\\(null\\):243\\) num_teams\\(11:22\\) thread_limit\\(strict:331\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel message\\(\"24\" \\\[len:2\\\]\\) severity\\(warning\\)" 1 "original" } }
+
+ !$omp teams distribute simd num_teams(11:22) thread_limit(strict : 331) dyn_groupprivate( cgroup ,fallback(null) : 243) message("25")  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+! { dg-final { scan-tree-dump-times "#pragma omp teams message\\(\"25\" \\\[len:2\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(fallback\\(null\\):243\\) num_teams\\(11:22\\) thread_limit\\(strict:331\\)" 1 "original" } }
+
+ !$omp teams distribute num_teams(11:22) thread_limit(strict : 331) dyn_groupprivate( cgroup ,fallback(null) : 243) message("26")  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+! { dg-final { scan-tree-dump-times "#pragma omp teams message\\(\"26\" \\\[len:2\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(fallback\\(null\\):243\\) num_teams\\(11:22\\) thread_limit\\(strict:331\\)" 1 "original" } }
+
+ !$omp teams loop num_teams(11:22) thread_limit(strict : 331) dyn_groupprivate( cgroup ,fallback(null) : 243) message("27")  ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ do i = 1, n
+ end do
+! { dg-final { scan-tree-dump-times "#pragma omp teams message\\(\"27\" \\\[len:2\\\]\\) severity\\(fatal\\) dyn_groupprivate\\(fallback\\(null\\):243\\) num_teams\\(11:22\\) thread_limit\\(strict:331\\)" 1 "original" } }
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-1.f90 b/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-1.f90
index 6e000cb49c4..83d3201a215 100644
--- a/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-1.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-1.f90
@@ -165,7 +165,7 @@ end subroutine
 ! { dg-final { scan-tree-dump-times "#pragma omp parallel num_threads\\(strict:2\\) shared\\(x\\)" 1 "gimple" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(1234\\) thread_limit\\(2345\\) shared\\(x\\)" 1 "gimple" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp parallel num_threads\\(3456\\) shared\\(x\\)" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(123, 456\\) shared\\(x\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(123:456\\) shared\\(x\\)" 1 "gimple" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(4567\\) thread_limit\\(5678\\) shared\\(x\\)" 1 "gimple" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp parallel num_threads\\(6789\\) shared\\(x\\)" 1 "gimple" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp parallel num_threads\\(1, 2, 3\\) shared\\(x\\)" 1 "gimple" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-4.f90 b/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-4.f90
index 3abca5248f3..059ecb5976d 100644
--- a/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-4.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-4.f90
@@ -32,17 +32,16 @@ end do
 block
   x = 1
 end block
-! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(-1\\) thread_limit\\(31\\) firstprivate\\(x\\) \\\[child fn" 1 "omplower" } }
-! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(dims\\(\\):33\\) thread_limit\\(31\\) shared\\(x\\)" 1 "omplower" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target thread_limit\\(31\\) num_teams\\(dims\\(\\):33\\) firstprivate\\(x\\) \\\[child fn" 1 "omplower" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams thread_limit\\(31\\) num_teams\\(dims\\(\\):33\\) shared\\(x\\)" 1 "omplower" } }
 ! { dg-final { scan-tree-dump-times "__builtin_GOMP_teams4 \\(33, 33, 31, D.\[0-9]+\\);" 1 "ompexp" } }
 
-
 !$omp target teams distribute parallel do simd thread_limit(relaxed : 41) num_teams(dims(1) : 43) num_threads( dims ( 1 ) , relaxed : 44)
 do i = 1, 1
   x = 1
 end do
-! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(-1\\) thread_limit\\(41\\) map\\(tofrom:i \\\[len: 4\\\] \\\[runtime_implicit\\\]\\) firstprivate\\(x\\) \\\[child fn" 1 "omplower" } }
-! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(dims\\(\\):43\\) thread_limit\\(41\\) shared\\(i\\) shared\\(x\\)" 1 "omplower" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target thread_limit\\(41\\) num_teams\\(dims\\(\\):43\\) map\\(tofrom:i \\\[len: 4\\\] \\\[runtime_implicit\\\]\\) firstprivate\\(x\\) \\\[child fn" 1 "omplower" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams thread_limit\\(41\\) num_teams\\(dims\\(\\):43\\) shared\\(i\\) shared\\(x\\)" 1 "omplower" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp parallel _looptemp_\\(D.\[0-9\]+\\) _looptemp_\\(D.\[0-9\]+\\) num_threads\\(dims\\(\\):44\\) lastprivate\\(i\\) shared\\(x\\) \\\[child fn" 1 "omplower" } }
 ! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel \\(sub_._omp_fn.\[0-9]+, &.omp_data_o.\[0-9]+, 44, 0\\);" 1 "ompexp" } }
 
@@ -80,15 +79,15 @@ end block
 block
   x = 1
 end block
-! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(1, 93\\) thread_limit\\(91\\) shared\\(x\\)" 1 "omplower" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(1:93\\) thread_limit\\(91\\) shared\\(x\\)" 1 "omplower" } }
 ! { dg-final { scan-tree-dump-times "__builtin_GOMP_teams_reg \\(sub_._omp_fn.\[0-9\]+, &.omp_data_o.\[0-9\]+, 93, 91, 0\\);" 1 "ompexp" } }
 
 !$omp target teams thread_limit(relaxed : 991) num_teams(191 : 993)
 block
   x = 1
 end block
-! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(-1\\) thread_limit\\(991\\) firstprivate\\(x\\) \\\[child fn" 1 "omplower" } }
-! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(191, 993\\) thread_limit\\(991\\) shared\\(x\\)" 1 "omplower" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target thread_limit\\(991\\) num_teams\\(191:993\\) firstprivate\\(x\\) \\\[child fn" 1 "omplower" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams thread_limit\\(991\\) num_teams\\(191:993\\) shared\\(x\\)" 1 "omplower" } }
 
 !$omp teams thread_limit(relaxed : 1231) message("my1234")
 block
diff --git a/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-5.f90 b/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-5.f90
index 9cde28a76ef..f43678f8ae0 100644
--- a/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-5.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-5.f90
@@ -9,8 +9,8 @@ integer :: x, i
 do i = 1,1
   x = 0
 end do
-! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(-1\\) message\\(.first. \\\[len:5\\\]\\) severity\\(fatal\\) thread_limit\\(strict,dims\\(\\):11, 12, 13\\) firstprivate\\(x\\)" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(11, 22\\) thread_limit\\(strict,dims\\(\\):11, 12, 13\\) message\\(.first. \\\[len:5\\\]\\) severity\\(fatal\\) shared\\(x\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(.first. \\\[len:5\\\]\\) severity\\(fatal\\) thread_limit\\(strict,dims\\(\\):11, 12, 13\\) num_teams\\(11:22\\) firstprivate\\(x\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams thread_limit\\(strict,dims\\(\\):11, 12, 13\\) num_teams\\(11:22\\) message\\(.first. \\\[len:5\\\]\\) severity\\(fatal\\) shared\\(x\\)" 1 "gimple" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp parallel message\\(.first. \\\[len:5\\\]\\) severity\\(warning\\) num_threads\\(23, 45, 53\\) shared\\(x\\)" 1 "gimple" } }
 end
 
@@ -27,15 +27,15 @@ integer :: x, i
 do i = 1,1
   x = 0
 end do
-! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(-1\\) message\\(.second. \\\[len:6\\\]\\) severity\\(fatal\\) thread_limit\\(11\\) firstprivate\\(x\\)" 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(dims\\(\\):111, 222, 333, 324\\) thread_limit\\(11\\) message\\(.second. \\\[len:6\\\]\\) severity\\(fatal\\) shared\\(x\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target message\\(.second. \\\[len:6\\\]\\) severity\\(fatal\\) thread_limit\\(11\\) num_teams\\(dims\\(\\):111, 222, 333, 324\\) firstprivate\\(x\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams thread_limit\\(11\\) num_teams\\(dims\\(\\):111, 222, 333, 324\\) message\\(.second. \\\[len:6\\\]\\) severity\\(fatal\\) shared\\(x\\)" 1 "gimple" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp parallel message\\(.second. \\\[len:6\\\]\\) severity\\(fatal\\) num_threads\\(strict:445, 553\\) shared\\(x\\)" 1 "gimple" } }
 
 !$omp teams distribute parallel do num_teams(11 : 55) thread_limit(strict : 11) num_threads(relaxed: 23,45,53) message("third") severity(warning)
 do i = 1,1
   x = 0
 end do
-! { dg-final { scan-tree-dump-times "#pragma omp teams message\\(.third. \\\[len:5\\\]\\) severity\\(fatal\\) num_teams\\(11, 55\\) thread_limit\\(strict:11\\) shared\\(x\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams message\\(.third. \\\[len:5\\\]\\) severity\\(fatal\\) num_teams\\(11:55\\) thread_limit\\(strict:11\\) shared\\(x\\)" 1 "gimple" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp parallel message\\(.third. \\\[len:5\\\]\\) severity\\(warning\\) num_threads\\(23, 45, 53\\) shared\\(x\\)" 1 "gimple" } }
 
 !$omp teams distribute parallel do num_teams(dims(2): 1111,33) thread_limit(dims(3) : 11,3,480) num_threads(strict, dims(2): 445,553) message("fourth") severity(fatal)
@@ -61,7 +61,7 @@ end block
 block
   x = 0
 end block
-! { dg-final { scan-tree-dump-times "#pragma omp teams message\\(.teams. \\\[len:5\\\]\\) severity\\(fatal\\) num_teams\\(14, 34\\) shared\\(x\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams message\\(.teams. \\\[len:5\\\]\\) severity\\(fatal\\) num_teams\\(14:34\\) shared\\(x\\)" 1 "gimple" } }
 
 !$omp teams thread_limit(relaxed, dims(2): 514 , 384)
 block
diff --git a/gcc/testsuite/gfortran.dg/gomp/target-teams-1.f90 b/gcc/testsuite/gfortran.dg/gomp/target-teams-1.f90
new file mode 100644
index 00000000000..39387a9878a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/target-teams-1.f90
@@ -0,0 +1,65 @@
+! { dg-additional-options "-fdump-tree-omplower" }
+
+subroutine foo
+  implicit none
+
+  !$omp target teams num_teams(dims(2) : 1,2)  ! { dg-message "sorry, unimplemented: 'num_teams' clause with 'dims' modifier" }
+  !$omp end target teams
+
+  !$omp target
+    !$omp teams num_teams(dims(2) : 2,3)  ! { dg-message "sorry, unimplemented: 'num_teams' clause with 'dims' modifier" }
+    !$omp end teams
+  !$omp end target
+
+  !$omp teams num_teams(dims(2) : 4,5)  ! { dg-message "sorry, unimplemented: 'num_teams' clause with 'dims' modifier" }
+  !$omp end teams
+
+  !$omp target teams num_teams(dims(2) : 5,6)  ! { dg-message "sorry, unimplemented: 'num_teams' clause with 'dims' modifier" }
+  !$omp end target teams
+
+  ! -----
+
+  !$omp target thread_limit(dims(3), relaxed : 1,2,3)  ! { dg-message "sorry, unimplemented: 'thread_limit' clause with 'dims' modifier" }
+  !$omp end target
+
+  !$omp target thread_limit(dims(3), strict : 2,3,4)  ! { dg-message "sorry, unimplemented: 'thread_limit' clause with 'dims' modifier" }
+    !$omp teams
+    !$omp end teams
+  !$omp end target 
+
+  !$omp target teams thread_limit(dims(3), strict : 3,4,5)  ! { dg-message "sorry, unimplemented: 'thread_limit' clause with 'dims' modifier" }
+  !$omp end target teams
+
+  !$omp target
+   !$omp teams thread_limit(strict : 456)  ! { dg-message "sorry, unimplemented: 'thread_limit' clause with 'strict' modifier" }
+   !$omp end teams
+  !$omp end target
+
+  !$omp teams thread_limit(strict : 567)  ! { dg-message "sorry, unimplemented: 'thread_limit' clause with 'strict' modifier" }
+  !$omp end teams
+end
+
+! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(dims\\(\\):1, 2\\) \\\[child fn:" 1 "omplower" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(dims\\(\\):1, 2\\)" 1 "omplower" } }
+
+! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(dims\\(\\):2, 3\\) \\\[child fn:" 1 "omplower" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(dims\\(\\):2, 3\\)" 1 "omplower" } }
+
+! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(dims\\(\\):4, 5\\)" 1 "omplower" } }
+
+! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(dims\\(\\):5, 6\\) \\\[child fn:" 1 "omplower" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(dims\\(\\):5, 6\\)" 1 "omplower" } }
+
+! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(-2\\) thread_limit\\(dims\\(\\):1, 2, 3\\) \\\[child fn:" 1 "omplower" } }
+
+! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(0\\) thread_limit\\(strict,dims\\(\\):2, 3, 4\\) \\\[child fn:" 1 "omplower" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams\[\\n\\r\]" 1 "omplower" } }
+
+! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(0\\) thread_limit\\(strict,dims\\(\\):3, 4, 5\\) \\\[child fn:" 1 "omplower" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams thread_limit\\(strict,dims\\(\\):3, 4, 5\\)" 1 "omplower" } }
+
+! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(0\\) thread_limit\\(strict:456\\) \\\[child fn:" 1 "omplower" } }
+
+! { dg-final { scan-tree-dump-times "#pragma omp teams thread_limit\\(strict:456\\)" 1 "omplower" } }
+
+! { dg-final { scan-tree-dump-times "#pragma omp teams thread_limit\\(strict:567\\)" 1 "omplower" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/target-teams-2.f90 b/gcc/testsuite/gfortran.dg/gomp/target-teams-2.f90
new file mode 100644
index 00000000000..8098f5c82df
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/target-teams-2.f90
@@ -0,0 +1,17 @@
+! { dg-additional-options "-fdump-tree-original -fdump-tree-gimple" }
+
+! Check that the expression is evaluated before the target region
+
+subroutine sub(n)
+implicit none
+integer, value :: n
+
+!$omp target
+!$omp teams thread_limit(n+1)
+!$omp end teams
+!$omp end target
+end
+! { dg-final { scan-tree-dump "D\.\[0-9\]+ = n \\+ 1;\[\\n\\r\]+ *#pragma omp target thread_limit\\(D\.\[0-9\]+\\) firstprivate\\(D\.\[0-9\]+\\)\[\\n\\r\{ \]+#pragma omp teams thread_limit\\(D\.\[0-9\]+\\)" "original" } }
+
+! { dg-final { scan-tree-dump "D\.\[0-9\]+ = n \\+ 1;\[\\n\\r\]+ *_\[0-9\]+ = D\.\[0-9\]+;\[\\n\\r\]+ *#pragma omp target num_teams\\(0\\) thread_limit\\(_\[0-9\]+\\) firstprivate\\(D\.\[0-9\]+\\)\[\\n\\r\{ \]+integer\\(kind=4\\) D\.\[0-9\]+;\[\\n\\r \]+D\.\[0-9\]+ = D\.\[0-9\]+;\[\\n\\r \]+#pragma omp teams thread_limit\\(D\.\[0-9\]+\\)" "gimple" } }
+

Reply via email to