https://gcc.gnu.org/g:61f2dff87339b642e132b30845b928117b514896

commit r17-2538-g61f2dff87339b642e132b30845b928117b514896
Author: Tobias Burnus <[email protected]>
Date:   Mon Jul 20 09:19:04 2026 +0200

    Fortran/OpenMP: Add parsing support for spatial dimensions
    
    Adds 'dim(...)' modifier parsing for spatial dimensions to the num_teams,
    thread_limit, and num_threads clauses.
    
    Add strict + relaxed modifier support to the thread_limit and num_threads
    clauses. [For teams, the effect of strict/relaxed is provided by the
    lower_bound feature.]
    
    For num_threads, support specifying multiple values - to be applicable
    for nested parallel constructs.
    
    NOTE: All added features (but 'relaxed') will fail after parsing with
    a 'sorry, unimplemented' as only the parsing support has been added and
    not the actual feature.
    
    gcc/fortran/ChangeLog:
    
            * dump-parse-tree.cc (show_omp_clauses): Handle spatial dimension
            in num_teams and it and strict/relaxed in thread_limits and
            num_threads.
            * trans-openmp.cc (gfc_trans_omp_clauses, gfc_split_omp_clauses,
            gfc_trans_omp_target): Likewise.
            * openmp.cc (gfc_free_omp_clauses, gfc_match_omp_clauses,
            resolve_omp_clauses): Likewise.
            (match_omp_oacc_expr_list): Return current locus for a parse
            fail instead of resetting the locus.
            * gfortran.h (gfc_omp_clauses): Changed gfc_expr num_threads,
            num_teams_lower, num_teams_upper, and thread_limit to
            gfc_expr_list num_threads_list, num_teams_list, and 
thread_limit_list.
            Add thread_limit_strict, num_threads_strict, num_teams_dims,
            thread_limit_dims, and num_threads_dims.
            * frontend-passes.cc (gfc_code_walker): Update for this change.
    
    gcc/testsuite/ChangeLog:
    
            * gfortran.dg/gomp/spatial-dimensions-1.f90: New test.
            * gfortran.dg/gomp/spatial-dimensions-2.f90: New test.
            * gfortran.dg/gomp/spatial-dimensions-3.f90: New test.

Diff:
---
 gcc/fortran/dump-parse-tree.cc                     |  60 +++-
 gcc/fortran/frontend-passes.cc                     |  13 +-
 gcc/fortran/gfortran.h                             |   9 +-
 gcc/fortran/openmp.cc                              | 301 ++++++++++++++++++---
 gcc/fortran/trans-openmp.cc                        | 106 +++++---
 .../gfortran.dg/gomp/spatial-dimensions-1.f90      | 116 ++++++++
 .../gfortran.dg/gomp/spatial-dimensions-2.f90      |  22 ++
 .../gfortran.dg/gomp/spatial-dimensions-3.f90      | 252 +++++++++++++++++
 8 files changed, 794 insertions(+), 85 deletions(-)

diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc
index 5f058cdc8300..3f1b35b715a5 100644
--- a/gcc/fortran/dump-parse-tree.cc
+++ b/gcc/fortran/dump-parse-tree.cc
@@ -1898,10 +1898,24 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
       show_expr (omp_clauses->final_expr);
       fputc (')', dumpfile);
     }
-  if (omp_clauses->num_threads)
+  if (omp_clauses->num_threads_list)
     {
       fputs (" NUM_THREADS(", dumpfile);
-      show_expr (omp_clauses->num_threads);
+      if (omp_clauses->num_threads_strict)
+       fputs ("STRICT", dumpfile);
+      if (omp_clauses->num_threads_strict && omp_clauses->num_threads_dims)
+       fputc (',', dumpfile);
+      if (omp_clauses->num_threads_dims)
+       fputs ("DIMS()", dumpfile);
+      if (omp_clauses->num_threads_strict || omp_clauses->num_threads_dims)
+       fputc (':', dumpfile);
+      gfc_expr_list *nt;
+      for (nt = omp_clauses->num_threads_list; nt; nt = nt->next)
+       {
+         show_expr (nt->expr);
+         if (nt->next)
+           fputs (", ", dumpfile);
+       }
       fputc (')', dumpfile);
     }
   if (omp_clauses->async)
@@ -2199,15 +2213,29 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
        }
       fprintf (dumpfile, " BIND(%s)", type);
     }
-  if (omp_clauses->num_teams_upper)
+  if (omp_clauses->num_teams_list)
     {
       fputs (" NUM_TEAMS(", dumpfile);
-      if (omp_clauses->num_teams_lower)
+      if (omp_clauses->num_teams_dims)
        {
-         show_expr (omp_clauses->num_teams_lower);
-         fputc (':', dumpfile);
+         fputs ("DIMS():", dumpfile);
+         gfc_expr_list *nt;
+         for (nt = omp_clauses->num_teams_list; nt; nt = nt->next)
+          {
+            show_expr (nt->expr);
+            if (nt->next)
+              fputs (", ", dumpfile);
+          }
+       }
+      else
+       {
+         show_expr (omp_clauses->num_teams_list->expr);
+         if (omp_clauses->num_teams_list->next)
+           {
+             fputc (':', dumpfile);
+             show_expr (omp_clauses->num_teams_list->next->expr);
+           }
        }
-      show_expr (omp_clauses->num_teams_upper);
       fputc (')', dumpfile);
     }
   if (omp_clauses->device)
@@ -2218,10 +2246,24 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
       show_expr (omp_clauses->device);
       fputc (')', dumpfile);
     }
-  if (omp_clauses->thread_limit)
+  if (omp_clauses->thread_limit_list)
     {
       fputs (" THREAD_LIMIT(", dumpfile);
-      show_expr (omp_clauses->thread_limit);
+      if (omp_clauses->thread_limit_strict)
+       fputs ("STRICT", dumpfile);
+      if (omp_clauses->thread_limit_strict && omp_clauses->thread_limit_dims)
+       fputc (',', dumpfile);
+      if (omp_clauses->thread_limit_dims)
+       fputs ("DIMS()", dumpfile);
+      if (omp_clauses->thread_limit_strict || omp_clauses->thread_limit_dims)
+       fputc (':', dumpfile);
+      gfc_expr_list *nt;
+      for (nt = omp_clauses->thread_limit_list; nt; nt = nt->next)
+       {
+         show_expr (nt->expr);
+         if (nt->next)
+           fputs (", ", dumpfile);
+       }
       fputc (')', dumpfile);
     }
   if (omp_clauses->dist_sched_kind != OMP_SCHED_NONE)
diff --git a/gcc/fortran/frontend-passes.cc b/gcc/fortran/frontend-passes.cc
index 92678310ffd3..fd34f0c19121 100644
--- a/gcc/fortran/frontend-passes.cc
+++ b/gcc/fortran/frontend-passes.cc
@@ -5709,14 +5709,10 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, 
walk_expr_fn_t exprfn,
                  for (idx = 0; idx < OMP_IF_LAST; idx++)
                    WALK_SUBEXPR (co->ext.omp_clauses->if_exprs[idx]);
                  WALK_SUBEXPR (co->ext.omp_clauses->final_expr);
-                 WALK_SUBEXPR (co->ext.omp_clauses->num_threads);
                  WALK_SUBEXPR (co->ext.omp_clauses->chunk_size);
                  WALK_SUBEXPR (co->ext.omp_clauses->safelen_expr);
                  WALK_SUBEXPR (co->ext.omp_clauses->simdlen_expr);
-                 WALK_SUBEXPR (co->ext.omp_clauses->num_teams_lower);
-                 WALK_SUBEXPR (co->ext.omp_clauses->num_teams_upper);
                  WALK_SUBEXPR (co->ext.omp_clauses->device);
-                 WALK_SUBEXPR (co->ext.omp_clauses->thread_limit);
                  WALK_SUBEXPR (co->ext.omp_clauses->dist_chunk_size);
                  WALK_SUBEXPR (co->ext.omp_clauses->grainsize);
                  WALK_SUBEXPR (co->ext.omp_clauses->hint);
@@ -5726,6 +5722,15 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, 
walk_expr_fn_t exprfn,
                  WALK_SUBEXPR (co->ext.omp_clauses->dyn_groupprivate);
                  WALK_SUBEXPR (co->ext.omp_clauses->novariants);
                  WALK_SUBEXPR (co->ext.omp_clauses->nocontext);
+                 gfc_expr_list *el = co->ext.omp_clauses->num_teams_list;
+                 for ( ; el; el = el->next)
+                   WALK_SUBEXPR (el->expr);
+                 el = co->ext.omp_clauses->thread_limit_list;
+                 for ( ; el; el = el->next)
+                   WALK_SUBEXPR (el->expr);
+                 el = co->ext.omp_clauses->num_threads_list;
+                 for ( ; el; el = el->next)
+                   WALK_SUBEXPR (el->expr);
                  for (idx = 0; idx < ARRAY_SIZE (list_types); idx++)
                    for (n = co->ext.omp_clauses->lists[list_types[idx]];
                         n; n = n->next)
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index df987576fffb..48ddd9a72d5e 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1709,14 +1709,13 @@ typedef struct gfc_omp_clauses
   struct gfc_expr *if_exprs[OMP_IF_LAST];
   struct gfc_expr *self_expr;
   struct gfc_expr *final_expr;
-  struct gfc_expr *num_threads;
+  struct gfc_expr_list *num_threads_list;
   struct gfc_expr *chunk_size;
   struct gfc_expr *safelen_expr;
   struct gfc_expr *simdlen_expr;
-  struct gfc_expr *num_teams_lower;
-  struct gfc_expr *num_teams_upper;
+  struct gfc_expr_list *num_teams_list;
   struct gfc_expr *device;
-  struct gfc_expr *thread_limit;
+  struct gfc_expr_list *thread_limit_list;
   struct gfc_expr *grainsize;
   struct gfc_expr *filter;
   struct gfc_expr *hint;
@@ -1747,6 +1746,8 @@ typedef struct gfc_omp_clauses
   unsigned contains_teams_construct:1, target_first_st_is_teams_or_meta:1;
   unsigned contained_in_target_construct:1, indirect:1;
   unsigned full:1, erroneous:1;
+  unsigned thread_limit_strict:1, num_threads_strict:1;
+  unsigned num_teams_dims:1, thread_limit_dims:1, num_threads_dims:1;
   ENUM_BITFIELD (gfc_omp_sched_kind) sched_kind:3;
   ENUM_BITFIELD (gfc_omp_device_type) device_type:2;
   ENUM_BITFIELD (gfc_omp_memorder) memorder:3;
diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index 64355971d9e1..d151aff8a452 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -188,15 +188,11 @@ gfc_free_omp_clauses (gfc_omp_clauses *c)
     gfc_free_expr (c->if_exprs[i]);
   gfc_free_expr (c->self_expr);
   gfc_free_expr (c->final_expr);
-  gfc_free_expr (c->num_threads);
   gfc_free_expr (c->chunk_size);
   gfc_free_expr (c->safelen_expr);
   gfc_free_expr (c->simdlen_expr);
-  gfc_free_expr (c->num_teams_lower);
-  gfc_free_expr (c->num_teams_upper);
   gfc_free_expr (c->device);
   gfc_free_expr (c->dyn_groupprivate);
-  gfc_free_expr (c->thread_limit);
   gfc_free_expr (c->dist_chunk_size);
   gfc_free_expr (c->grainsize);
   gfc_free_expr (c->hint);
@@ -216,6 +212,9 @@ gfc_free_omp_clauses (gfc_omp_clauses *c)
   for (enum gfc_omp_list_type t = OMP_LIST_FIRST; t < OMP_LIST_NUM;
        t = gfc_omp_list_type (t + 1))
     gfc_free_omp_namelist (c->lists[t], t);
+  gfc_free_expr_list (c->num_teams_list);
+  gfc_free_expr_list (c->thread_limit_list);
+  gfc_free_expr_list (c->num_threads_list);
   gfc_free_expr_list (c->wait_list);
   gfc_free_expr_list (c->tile_list);
   gfc_free_expr_list (c->sizes_list);
@@ -846,8 +845,7 @@ match_omp_oacc_expr_list (const char *str, gfc_expr_list 
**list,
 
   old_loc = gfc_current_locus;
 
-  m = gfc_match (str);
-  if (m != MATCH_YES)
+  if (str && (m = gfc_match (str)) != MATCH_YES)
     return m;
 
   for (;;)
@@ -4105,30 +4103,161 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const 
omp_mask mask,
              continue;
            }
          if ((mask & OMP_CLAUSE_NUM_TEAMS)
-             && (m = gfc_match_dupl_check (!c->num_teams_upper, "num_teams",
-                                           true)) != MATCH_NO)
+             && (m = gfc_match_dupl_check (!c->num_teams_list,
+                                           "num_teams", true)) != MATCH_NO)
            {
              if (m == MATCH_ERROR)
                goto error;
-             if (gfc_match ("%e ", &c->num_teams_upper) != MATCH_YES)
-               goto error;
-             if (gfc_peek_ascii_char () == ':')
+             gfc_expr *expr;
+             if (gfc_match ("dims ( %e ) : ", &expr) == MATCH_YES
+                 && match_omp_oacc_expr_list (NULL, &c->num_teams_list,
+                                              false, true) == MATCH_YES)
+               {
+                 int num = 0;
+                 gfc_expr_list *el;
+                 for (el = c->num_teams_list; el; el = el->next)
+                   ++num;
+                 if (!gfc_resolve_expr (expr)
+                     || expr->ts.type != BT_INTEGER
+                     || expr->rank != 0
+                     || expr->expr_type != EXPR_CONSTANT
+                     || mpz_sgn (expr->value.integer) <= 0)
+                   {
+                     gfc_error ("DIMS must be a constant positive integer "
+                                "at %L", &expr->where);
+                     goto error;
+                   }
+                 if (mpz_cmp_si (expr->value.integer, num) != 0)
+                   {
+                     gfc_error ("The number of arguments (%d) must be the same"
+                                " as specified for DIMS at %L", num,
+                                &expr->where);
+                     goto error;
+                   }
+                 c->num_teams_dims = true;
+               }
+             else if (gfc_match ("%e ", &expr) == MATCH_YES)
                {
-                 c->num_teams_lower = c->num_teams_upper;
-                 c->num_teams_upper = NULL;
-                 if (gfc_match (": %e ", &c->num_teams_upper) != MATCH_YES)
+                 c->num_teams_list = gfc_get_expr_list();
+                 c->num_teams_list->expr = expr;
+                 if (gfc_peek_ascii_char () == ':')
+                   {
+                     expr = NULL;
+                     if (gfc_match (": %e ", &expr) != MATCH_YES)
+                       goto error;
+                     c->num_teams_list->next = gfc_get_expr_list();
+                     c->num_teams_list->next->expr = expr;
+                   }
+                 if (gfc_match (") ") != MATCH_YES)
                    goto error;
                }
-             if (gfc_match (") ") != MATCH_YES)
-               goto error;
+             else
+               {
+                 gfc_error ("Expected either %<[lower-expr : ] upper-expr%> or 
"
+                            "%<dims(N): expr-list%> at %C");
+                 goto error;
+               }
              continue;
            }
          if ((mask & OMP_CLAUSE_NUM_THREADS)
-             && (m = gfc_match_dupl_check (!c->num_threads, "num_threads", 
true,
-                                           &c->num_threads)) != MATCH_NO)
+             && (m = gfc_match_dupl_check (!c->num_threads_list,
+                                           "num_threads", true, NULL))
+                 != MATCH_NO)
            {
+             int nstrict = 0, nrelaxed = 0, ndims = 0;
+             bool fail = false;
+             gfc_expr *dims = NULL;
+             locus old_loc = gfc_current_locus;
+
              if (m == MATCH_ERROR)
                goto error;
+             while (true)
+               {
+                 if (gfc_match ("strict ") == MATCH_YES)
+                   nstrict++;
+                 else if (gfc_match ("relaxed ") == MATCH_YES)
+                   nrelaxed++;
+                 else if (gfc_match ("dims ") == MATCH_YES)
+                   {
+                     ndims++;
+                     if (dims)
+                       gfc_free_expr (dims);
+                     if (gfc_match ("( %e ) ", &dims) != MATCH_YES)
+                       break;
+                   }
+                 else
+                   {
+                     fail = true;
+                     break;
+                   }
+                 if (gfc_match (", ") == MATCH_YES)
+                   continue;
+                 break;
+               }
+             if (gfc_match (" : ") == MATCH_YES)
+               {
+                 if (nstrict + nrelaxed + ndims == 0 || fail)
+                   {
+                     gfc_error ("Expected STRICT, RELAXED or DIMS modifier at "
+                                "%C");
+                     goto error;
+                   }
+                 else if (nstrict + nrelaxed > 1)
+                   {
+                     gfc_error ("Only one STRICT or RELAXED modifier permitted"
+                                " at %L", &old_loc);
+                     goto error;
+                   }
+                 if (ndims > 1)
+                   {
+                     gfc_error ("Duplicated DIMS expression at %L",
+                                &dims->where);
+                     goto error;
+                   }
+                 if (nstrict || (dims && !nrelaxed))
+                   c->num_threads_strict = true;
+               }
+             else
+               {
+                 gfc_free_expr (dims);
+                 dims = NULL;
+                 gfc_current_locus = old_loc;
+               }
+
+             m = match_omp_oacc_expr_list (NULL, &c->num_threads_list, false,
+                                           true);
+             if (m != MATCH_YES)
+               {
+                 gfc_error ("Expected a list of integer expressions followed "
+                            "by a %<)%> and optionally preceded by the STRICT,"
+                            " RELAXED, or DIMS as modifiers and a colon at 
%C");
+                 goto error;
+               }
+             if (dims)
+               {
+                 int num = 0;
+                 gfc_expr_list *el;
+                 for (el = c->num_threads_list; el; el = el->next)
+                   ++num;
+                 if (!gfc_resolve_expr (dims)
+                     || dims->ts.type != BT_INTEGER
+                     || dims->rank != 0
+                     || dims->expr_type != EXPR_CONSTANT
+                     || mpz_sgn (dims->value.integer) <= 0)
+                   {
+                     gfc_error ("DIMS must be a constant positive integer "
+                                "at %L", &dims->where);
+                     goto error;
+                   }
+                 if (mpz_cmp_si (dims->value.integer, num) != 0)
+                   {
+                     gfc_error ("The number of arguments (%d) must be the same"
+                                " as specified for DIMS at %L", num,
+                                &dims->where);
+                     goto error;
+                   }
+                 c->num_threads_dims = true;
+               }
              continue;
            }
          if ((mask & OMP_CLAUSE_NUM_WORKERS)
@@ -4520,12 +4649,110 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const 
omp_mask mask,
                                                 allow_derived) == MATCH_YES)
            continue;
          if ((mask & OMP_CLAUSE_THREAD_LIMIT)
-             && (m = gfc_match_dupl_check (!c->thread_limit, "thread_limit",
-                                           true, &c->thread_limit))
-                != MATCH_NO)
+             && (m = gfc_match_dupl_check (!c->thread_limit_list, 
"thread_limit",
+                                           true, NULL)) != MATCH_NO)
            {
+             int nstrict = 0, nrelaxed = 0, ndims = 0;
+             bool fail = false;
+             gfc_expr *dims = NULL;
+             locus old_loc = gfc_current_locus;
+
              if (m == MATCH_ERROR)
                goto error;
+             while (true)
+               {
+                 if (gfc_match ("strict ") == MATCH_YES)
+                   nstrict++;
+                 else if (gfc_match ("relaxed ") == MATCH_YES)
+                   nrelaxed++;
+                 else if (gfc_match ("dims ") == MATCH_YES)
+                   {
+                     ndims++;
+                     if (dims)
+                       gfc_free_expr (dims);
+                     if (gfc_match ("( %e ) ", &dims) != MATCH_YES)
+                       break;
+                   }
+                 else
+                   {
+                     fail = true;
+                     break;
+                   }
+                 if (gfc_match (", ") == MATCH_YES)
+                   continue;
+                 break;
+               }
+             if (gfc_match (" : ") == MATCH_YES)
+               {
+                 if (nstrict + nrelaxed + ndims == 0 || fail)
+                   {
+                     gfc_error ("Expected STRICT, RELAXED or DIMS modifier at "
+                                "%C");
+                     goto error;
+                   }
+                 else if (nstrict + nrelaxed > 1)
+                   {
+                     gfc_error ("Only one STRICT or RELAXED modifier permitted"
+                                " at %L", &old_loc);
+                     goto error;
+                   }
+                 if (ndims > 1)
+                   {
+                     gfc_error ("Duplicated DIMS expression at %L",
+                                &dims->where);
+                     goto error;
+                   }
+               }
+             else
+               {
+                 gfc_free_expr (dims);
+                 dims = NULL;
+                 gfc_current_locus = old_loc;
+               }
+
+             m = match_omp_oacc_expr_list (NULL, &c->thread_limit_list,
+                                           false, true);
+             if (m != MATCH_YES)
+               {
+                 gfc_error ("Expected a list of integer expressions followed "
+                            "by a %<)%> and optionally preceded by the STRICT,"
+                            " RELAXED, or DIMS as modifiers and a colon at 
%C");
+                 goto error;
+               }
+             c->thread_limit_strict = (nstrict != 0) || (dims && !nrelaxed);
+
+             if (!dims && c->thread_limit_list->next)
+               {
+                 gfc_error ("Without the DIM modifier, only a single integer "
+                            "expression may be specified at %L",
+                            &c->thread_limit_list->next->expr->where);
+                 goto error;
+               }
+             else if (dims)
+               {
+                 int num = 0;
+                 gfc_expr_list *el;
+                 for (el = c->thread_limit_list; el; el = el->next)
+                   ++num;
+                 if (!gfc_resolve_expr (dims)
+                     || dims->ts.type != BT_INTEGER
+                     || dims->rank != 0
+                     || dims->expr_type != EXPR_CONSTANT
+                     || mpz_sgn (dims->value.integer) <= 0)
+                   {
+                     gfc_error ("DIMS must be a constant positive integer "
+                                "at %L", &dims->where);
+                     goto error;
+                   }
+                 if (mpz_cmp_si (dims->value.integer, num) != 0)
+                   {
+                     gfc_error ("The number of arguments (%d) must be the same"
+                                " as specified for DIMS at %L", num,
+                                &dims->where);
+                     goto error;
+                   }
+                 c->thread_limit_dims = true;
+               }
              continue;
            }
          if ((mask & OMP_CLAUSE_THREADS)
@@ -10296,8 +10523,10 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses 
*omp_clauses,
          &expr->where);
       if_without_mod = true;
     }
-  if (omp_clauses->num_threads)
-    resolve_positive_int_expr (omp_clauses->num_threads, "NUM_THREADS");
+
+  for (el = omp_clauses->num_threads_list; el; el = el->next)
+    resolve_positive_int_expr (el->expr, "NUM_THREADS");
+
   if (omp_clauses->dyn_groupprivate)
     resolve_nonnegative_int_expr (omp_clauses->dyn_groupprivate,
                                  "DYN_GROUPPRIVATE");
@@ -11100,18 +11329,18 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses 
*omp_clauses,
     resolve_positive_int_expr (omp_clauses->safelen_expr, "SAFELEN");
   if (omp_clauses->simdlen_expr)
     resolve_positive_int_expr (omp_clauses->simdlen_expr, "SIMDLEN");
-  if (omp_clauses->num_teams_lower)
-    resolve_positive_int_expr (omp_clauses->num_teams_lower, "NUM_TEAMS");
-  if (omp_clauses->num_teams_upper)
-    resolve_positive_int_expr (omp_clauses->num_teams_upper, "NUM_TEAMS");
-  if (omp_clauses->num_teams_lower
-      && omp_clauses->num_teams_lower->expr_type == EXPR_CONSTANT
-      && omp_clauses->num_teams_upper->expr_type == EXPR_CONSTANT
-      && mpz_cmp (omp_clauses->num_teams_lower->value.integer,
-                 omp_clauses->num_teams_upper->value.integer) > 0)
+  for (el = omp_clauses->num_teams_list; el; el = el->next)
+    resolve_positive_int_expr (el->expr, "NUM_TEAMS");
+  if (omp_clauses->num_teams_list
+      && omp_clauses->num_teams_list->next
+      && !omp_clauses->num_teams_dims
+      && omp_clauses->num_teams_list->expr->expr_type == EXPR_CONSTANT
+      && omp_clauses->num_teams_list->next->expr->expr_type == EXPR_CONSTANT
+      && mpz_cmp (omp_clauses->num_teams_list->expr->value.integer,
+                 omp_clauses->num_teams_list->next->expr->value.integer) > 0)
     gfc_warning (OPT_Wopenmp, "NUM_TEAMS lower bound at %L larger than upper "
-                "bound at %L", &omp_clauses->num_teams_lower->where,
-                &omp_clauses->num_teams_upper->where);
+                "bound at %L", &omp_clauses->num_teams_list->expr->where,
+                &omp_clauses->num_teams_list->next->expr->where);
   if (omp_clauses->device)
     resolve_scalar_int_expr (omp_clauses->device, "DEVICE");
   if (omp_clauses->filter)
@@ -11135,8 +11364,8 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses 
*omp_clauses,
        gfc_error ("DIST_SCHEDULE clause's chunk_size at %L requires "
                   "a scalar INTEGER expression", &expr->where);
     }
-  if (omp_clauses->thread_limit)
-    resolve_positive_int_expr (omp_clauses->thread_limit, "THREAD_LIMIT");
+  for (el = omp_clauses->thread_limit_list; el; el = el->next)
+    resolve_positive_int_expr (el->expr, "THREAD_LIMIT");
   if (omp_clauses->grainsize)
     resolve_positive_int_expr (omp_clauses->grainsize, "GRAINSIZE");
   if (omp_clauses->num_tasks)
diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index aa4e8ebfa239..381fb48d008c 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -5660,12 +5660,25 @@ gfc_trans_omp_clauses (stmtblock_t *block, 
gfc_omp_clauses *clauses,
       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
     }
 
-  if (clauses->num_threads)
+  if (clauses->num_threads_list)
     {
       tree num_threads;
 
+      if (clauses->num_threads_dims)
+       sorry_at (gfc_get_location (&clauses->num_threads_list->expr->where),
+                 "%<num_threads%> with %<dims%> modifier");
+      else if (clauses->num_threads_strict)
+       sorry_at (gfc_get_location (&clauses->num_threads_list->expr->where),
+                 "%<num_threads%> with %<strict%> modifier");
+      else if (clauses->num_threads_list->next)
+       {
+         gfc_expr *expr = clauses->num_threads_list->next->expr;
+         sorry_at (gfc_get_location (&expr->where),
+                   "%<num_threads%> with more than one argument");
+       }
+
       gfc_init_se (&se, NULL);
-      gfc_conv_expr (&se, clauses->num_threads);
+      gfc_conv_expr (&se, clauses->num_threads_list->expr);
       gfc_add_block_to_block (block, &se.pre);
       num_threads = gfc_evaluate_now (se.expr, block);
       gfc_add_block_to_block (block, &se.post);
@@ -5970,24 +5983,31 @@ gfc_trans_omp_clauses (stmtblock_t *block, 
gfc_omp_clauses *clauses,
        }
     }
 
-  if (clauses->num_teams_upper)
+  if (clauses->num_teams_list)
     {
       tree num_teams_lower = NULL_TREE, num_teams_upper;
 
-      gfc_init_se (&se, NULL);
-      gfc_conv_expr (&se, clauses->num_teams_upper);
-      gfc_add_block_to_block (block, &se.pre);
-      num_teams_upper = gfc_evaluate_now (se.expr, block);
-      gfc_add_block_to_block (block, &se.post);
+      if (clauses->num_teams_dims)
+       sorry_at (gfc_get_location (&clauses->num_teams_list->expr->where),
+                   "%<num_teams%> with %<dims%> modifier");
 
-      if (clauses->num_teams_lower)
+      gfc_expr_list *el = clauses->num_teams_list;
+      if (el->next)
        {
          gfc_init_se (&se, NULL);
-         gfc_conv_expr (&se, clauses->num_teams_lower);
+         gfc_conv_expr (&se, el->expr);
          gfc_add_block_to_block (block, &se.pre);
          num_teams_lower = gfc_evaluate_now (se.expr, block);
          gfc_add_block_to_block (block, &se.post);
+         el = el->next;
        }
+
+      gfc_init_se (&se, NULL);
+      gfc_conv_expr (&se, el->expr);
+      gfc_add_block_to_block (block, &se.pre);
+      num_teams_upper = gfc_evaluate_now (se.expr, block);
+      gfc_add_block_to_block (block, &se.post);
+
       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TEAMS);
       OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = num_teams_lower;
       OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = num_teams_upper;
@@ -6013,12 +6033,18 @@ gfc_trans_omp_clauses (stmtblock_t *block, 
gfc_omp_clauses *clauses,
       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
     }
 
-  if (clauses->thread_limit)
+  if (clauses->thread_limit_list)
     {
       tree thread_limit;
 
+      if (clauses->thread_limit_dims)
+       sorry_at (gfc_get_location (&clauses->thread_limit_list->expr->where),
+                   "%<thread_limit%> with %<dims%> modifier");
+      else if (clauses->thread_limit_strict)
+       sorry_at (gfc_get_location (&clauses->thread_limit_list->expr->where),
+                   "%<thread_limit%> with %<strict%> modifier");
       gfc_init_se (&se, NULL);
-      gfc_conv_expr (&se, clauses->thread_limit);
+      gfc_conv_expr (&se, clauses->thread_limit_list->expr);
       gfc_add_block_to_block (block, &se.pre);
       thread_limit = gfc_evaluate_now (se.expr, block);
       gfc_add_block_to_block (block, &se.post);
@@ -8471,8 +8497,12 @@ gfc_split_omp_clauses (gfc_code *code,
            = code->ext.omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR];
          clausesa[GFC_OMP_SPLIT_TARGET].device
            = code->ext.omp_clauses->device;
-         clausesa[GFC_OMP_SPLIT_TARGET].thread_limit
-           = code->ext.omp_clauses->thread_limit;
+         clausesa[GFC_OMP_SPLIT_TARGET].thread_limit_list
+           = code->ext.omp_clauses->thread_limit_list;
+         clausesa[GFC_OMP_SPLIT_TARGET].thread_limit_strict
+           = code->ext.omp_clauses->thread_limit_strict;
+         clausesa[GFC_OMP_SPLIT_TARGET].thread_limit_dims
+           = code->ext.omp_clauses->thread_limit_dims;
          clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_USES_ALLOCATORS]
            = code->ext.omp_clauses->lists[OMP_LIST_USES_ALLOCATORS];
          for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; i++)
@@ -8491,12 +8521,16 @@ gfc_split_omp_clauses (gfc_code *code,
       if (mask & GFC_OMP_MASK_TEAMS)
        {
          /* First the clauses that are unique to some constructs.  */
-         clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower
-           = code->ext.omp_clauses->num_teams_lower;
-         clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper
-           = code->ext.omp_clauses->num_teams_upper;
-         clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit
-           = code->ext.omp_clauses->thread_limit;
+         clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_list
+           = code->ext.omp_clauses->num_teams_list;
+         clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_dims
+           = code->ext.omp_clauses->num_teams_dims;
+         clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_list
+           = code->ext.omp_clauses->thread_limit_list;
+         clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_strict
+           = code->ext.omp_clauses->thread_limit_strict;
+         clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_dims
+           = code->ext.omp_clauses->thread_limit_dims;
          /* Shared and default clauses are allowed on parallel, teams
             and taskloop.  */
          clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_SHARED]
@@ -8526,8 +8560,12 @@ gfc_split_omp_clauses (gfc_code *code,
          /* First the clauses that are unique to some constructs.  */
          clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_COPYIN]
            = code->ext.omp_clauses->lists[OMP_LIST_COPYIN];
-         clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads
-           = code->ext.omp_clauses->num_threads;
+         clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads_list
+           = code->ext.omp_clauses->num_threads_list;
+         clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads_strict
+           = code->ext.omp_clauses->num_threads_strict;
+         clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads_dims
+           = code->ext.omp_clauses->num_threads_dims;
          clausesa[GFC_OMP_SPLIT_PARALLEL].proc_bind
            = code->ext.omp_clauses->proc_bind;
          /* Shared and default clauses are allowed on parallel, teams
@@ -9344,8 +9382,8 @@ gfc_trans_omp_target (gfc_code *code)
       break;
     default:
       if (flag_openmp
-         && (clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper
-             || clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit))
+         && (clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_list
+             || clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit_list))
        {
          gfc_omp_clauses clausesb;
          tree teams_clauses;
@@ -9353,14 +9391,18 @@ gfc_trans_omp_target (gfc_code *code)
             thread_limit clauses are evaluated before entering the
             target construct.  */
          memset (&clausesb, '\0', sizeof (clausesb));
-         clausesb.num_teams_lower
-           = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower;
-         clausesb.num_teams_upper
-           = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper;
-         clausesb.thread_limit = clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit;
-         clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower = NULL;
-         clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper = NULL;
-         clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit = NULL;
+         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 ();
diff --git a/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-1.f90 
b/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-1.f90
new file mode 100644
index 000000000000..94349180f5e1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-1.f90
@@ -0,0 +1,116 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+
+subroutine one_a
+!$omp teams num_teams(dims(3) : 1,2,3) &            ! { dg-message "sorry, 
unimplemented: 'num_teams' with 'dims' modifier" }
+!$omp&      thread_limit ( dims ( 4 ) : 1, 2, 3, 4) ! { dg-message "sorry, 
unimplemented: 'thread_limit' with 'dims' modifier" }
+!$omp   parallel num_threads(dims(3): 1,2,3)        ! { dg-message "sorry, 
unimplemented: 'num_threads' with 'dims' modifier" }
+!$omp   end parallel
+!$omp end teams
+end
+
+subroutine one_b
+!$omp teams num_teams(dims(3) : 1,2,3) &                      ! { dg-message 
"sorry, unimplemented: 'num_teams' with 'dims' modifier" }
+!$omp&      thread_limit ( dims ( 4 ) , relaxed : 1, 2, 3, 4) ! { dg-message 
"sorry, unimplemented: 'thread_limit' with 'dims' modifier" }
+!$omp   parallel num_threads(dims(3) , relaxed : 1,2,3)       ! { dg-message 
"sorry, unimplemented: 'num_threads' with 'dims' modifier" }
+!$omp   end parallel
+!$omp end teams
+end
+
+subroutine one_c
+!$omp teams num_teams(dims(3) : 1,2,3) &                     ! { dg-message 
"sorry, unimplemented: 'num_teams' with 'dims' modifier" }
+!$omp&      thread_limit ( dims ( 4 ) , strict : 1, 2, 3, 4) ! { dg-message 
"sorry, unimplemented: 'thread_limit' with 'dims' modifier" }
+!$omp   parallel num_threads(dims(3) , strict : 1,2,3)       ! { dg-message 
"sorry, unimplemented: 'num_threads' with 'dims' modifier" }
+!$omp   end parallel
+!$omp end teams
+end
+
+subroutine one_d
+!$omp teams num_teams ( dims(3) : 1,2,3) &                     ! { dg-message 
"sorry, unimplemented: 'num_teams' with 'dims' modifier" }
+!$omp&      thread_limit ( relaxed ,  dims ( 4 ) : 1, 2, 3, 4) ! { dg-message 
"sorry, unimplemented: 'thread_limit' with 'dims' modifier" }
+!$omp   parallel num_threads( relaxed , dims(3) : 1,2,3)       ! { dg-message 
"sorry, unimplemented: 'num_threads' with 'dims' modifier" }
+!$omp   end parallel
+!$omp end teams
+end
+
+subroutine one_e
+!$omp teams num_teams ( dims(3) : 1,2,3) &                    ! { dg-message 
"sorry, unimplemented: 'num_teams' with 'dims' modifier" }
+!$omp&      thread_limit ( strict ,  dims ( 4 ) : 1, 2, 3, 4) ! { dg-message 
"sorry, unimplemented: 'thread_limit' with 'dims' modifier" }
+!$omp   parallel num_threads( strict , dims(3) : 1,2,3)       ! { dg-message 
"sorry, unimplemented: 'num_threads' with 'dims' modifier" }
+!$omp   end parallel
+!$omp end teams
+end
+
+
+subroutine two
+!$omp teams thread_limit (strict : 4)          ! { dg-message "sorry, 
unimplemented: 'thread_limit' with 'strict' modifier" }
+!$omp   parallel num_threads(strict : 2)       ! { dg-message "sorry, 
unimplemented: 'num_threads' with 'strict' modifier" }
+!$omp   end parallel
+!$omp end teams
+end
+
+subroutine zero
+!$omp teams num_teams(1234) thread_limit ( 2345)  ! OK
+!$omp   parallel num_threads( 3456)            ! OK
+!$omp   end parallel
+!$omp end teams
+
+!$omp teams num_teams(123:456)
+!$omp end teams
+end
+
+subroutine three
+!$omp teams num_teams(4567) thread_limit (relaxed : 5678)  ! OK
+!$omp   parallel num_threads(relaxed : 6789)            ! OK
+!$omp   end parallel
+!$omp end teams
+end
+
+subroutine four
+!$omp parallel num_threads(1 , 2 , 3 )  ! { dg-message "sorry, unimplemented: 
'num_threads' with more than one argument" }
+!$omp end parallel
+end
+
+subroutine five
+!$omp parallel num_threads(relaxed : 1,2,3)  ! { dg-message "sorry, 
unimplemented: 'num_threads' with more than one argument" }
+!$omp end parallel
+end
+
+subroutine six
+!$omp parallel num_threads(strict : 1,2,3)  ! { dg-message "sorry, 
unimplemented: 'num_threads' with 'strict' modifier" }
+!$omp end parallel
+end
+
+
+subroutine seven
+  integer :: static, relaxed, dims(2)
+  !$omp teams num_teams(static) thread_limit (static)  ! OK
+  !$omp   parallel num_threads(static)                 ! OK
+  !$omp   end parallel
+  !$omp end teams
+
+  !$omp teams num_teams(relaxed) thread_limit (relaxed)  ! OK
+  !$omp   parallel num_threads(relaxed)                  ! OK
+  !$omp   end parallel
+  !$omp end teams
+
+  !$omp teams num_teams(dims(2)) thread_limit (dims(2))  ! OK
+  !$omp   parallel num_threads(dims(2))                  ! OK
+  !$omp   end parallel
+  !$omp end teams
+
+end subroutine
+
+! Check that the tree is correctly generated:
+
+! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(1234\\) 
thread_limit\\(2345\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel 
num_threads\\(3456\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(4567\\) 
thread_limit\\(5678\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel 
num_threads\\(6789\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams num_teams\\(123:456\\)" 
1 "original" } }
+
+! { dg-final { scan-tree-dump-times "D\\.\[0-9\]+ = static;" 3 "original" } }
+! { dg-final { scan-tree-dump-times "D\\.\[0-9\]+ = relaxed;" 3 "original" } }
+! { dg-final { scan-tree-dump-times "D\\.\[0-9\]+ = dims\\\[1\\\];" 3 
"original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams 
num_teams\\(D\\.\[0-9\]+\\) thread_limit\\(D\\.\[0-9\]+\\)" 3 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel 
num_threads\\(D\\.\[0-9\]+\\)" 3 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-2.f90 
b/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-2.f90
new file mode 100644
index 000000000000..db570df86f98
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-2.f90
@@ -0,0 +1,22 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+
+! This testcase is ambigous in Fortran
+! cf. OpenMP Spec Issues 4998
+! Unresolved when this testcase was written
+
+! FIXME: Check what's the outcome of the discussion
+
+! NOTE: GCC currently implements this as spatial dimension
+! and not as lower bound ...
+
+subroutine sub
+  integer, parameter :: dims(2) = [11,22]
+!...
+  !$omp teams  num_teams( dims(1) : 256 )  ! { dg-message "sorry, 
unimplemented: 'num_teams' with 'dims' modifier" }
+  !$omp end teams
+end
+
+! ... hence: 'num_teams(256)' and not 'num_teams(11:256)'
+
+! { dg-final { scan-tree-dump "#pragma omp teams num_teams\\(256\\)" 
"original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-3.f90 
b/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-3.f90
new file mode 100644
index 000000000000..22b9f23f6402
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/spatial-dimensions-3.f90
@@ -0,0 +1,252 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+
+subroutine one
+  !$omp teams num_teams(1) num_teams(2)  ! { dg-error "Duplicated 'num_teams' 
clause" }
+  block; end block
+
+  !$omp teams thread_limit(1) thread_limit(2)  ! { dg-error "Duplicated 
'thread_limit' clause" }
+  block; end block
+
+  !$omp parallel num_threads(1) num_threads(2)  ! { dg-error "Duplicated 
'num_threads' clause" }
+  block; end block
+
+
+  !$omp teams num_teams(dims([1,1]) : 1)  ! { dg-error "DIMS must be a 
constant positive integer" }
+  block; end block
+
+  !$omp teams num_teams(dims(1.0) : 1)  ! { dg-error "DIMS must be a constant 
positive integer" }
+  block; end block
+
+  !$omp teams num_teams(dims(i) : 1)  ! { dg-error "DIMS must be a constant 
positive integer" }
+  block; end block
+
+  !$omp teams num_teams(dims(i) : 1)  ! { dg-error "DIMS must be a constant 
positive integer" }
+  block; end block
+
+  !$omp teams num_teams(dims( 1 - 2) : 1)  ! { dg-error "DIMS must be a 
constant positive integer" }
+  block; end block
+
+  !$omp teams num_teams(dims( int ( cos(0.0) )) : 1)  ! OK
+  block; end block
+
+
+  !$omp teams thread_limit(dims([1,1]) : 1)  ! { dg-error "DIMS must be a 
constant positive integer" }
+  block; end block
+
+  !$omp teams thread_limit(dims(1.0) : 1)  ! { dg-error "DIMS must be a 
constant positive integer" }
+  block; end block
+
+  !$omp teams thread_limit(dims(i) : 1)  ! { dg-error "DIMS must be a constant 
positive integer" }
+  block; end block
+
+  !$omp teams thread_limit(dims(i) : 1)  ! { dg-error "DIMS must be a constant 
positive integer" }
+  block; end block
+
+  !$omp teams thread_limit(dims( 1 - 2) : 1)  ! { dg-error "DIMS must be a 
constant positive integer" }
+  block; end block
+
+  !$omp teams thread_limit(dims( int ( cos(0.0) )) : 1)  ! OK
+  block; end block
+
+
+  !$omp parallel num_threads(dims([1,1]) : 1)  ! { dg-error "DIMS must be a 
constant positive integer" }
+  block; end block
+
+  !$omp parallel num_threads(dims(1.0) : 1)  ! { dg-error "DIMS must be a 
constant positive integer" }
+  block; end block
+
+  !$omp parallel num_threads(dims(i) : 1)  ! { dg-error "DIMS must be a 
constant positive integer" }
+  block; end block
+
+  !$omp parallel num_threads(dims(i) : 1)  ! { dg-error "DIMS must be a 
constant positive integer" }
+  block; end block
+
+  !$omp parallel num_threads(dims( 1 - 2) : 1)  ! { dg-error "DIMS must be a 
constant positive integer" }
+  block; end block
+
+  !$omp parallel num_threads(dims( int ( cos(0.0) )) : 1)  ! OK
+  block; end block
+end
+
+subroutine two
+  !$omp parallel num_threads(dims( int ( cos(0.0) ) + 1 ) : 1)  ! { dg-error 
"The number of arguments \\(1\\) must be the same as specified for DIMS" }
+  block; end block
+
+  !$omp teams num_teams(dims( 3 )  : 1, 2, 3 , 4)  ! { dg-error "The number of 
arguments \\(4\\) must be the same as specified for DIMS" }
+  block; end block
+
+  !$omp teams thread_limit(dims( 3 ) : 1, 4)  ! { dg-error "The number of 
arguments \\(2\\) must be the same as specified for DIMS" }
+  block; end block
+end
+
+subroutine three
+  !$omp teams num_teams  ! { dg-error "Expected '\\(' after 'num_teams'" }
+  block; end block
+
+  !$omp teams num_teams( :  ! { dg-error "Expected either '\\\[lower-expr : 
\\\] upper-expr' or 'dims\\(N\\): expr-list'" }
+  block; end block
+
+  !$omp teams num_teams(  ! { dg-error "Expected either '\\\[lower-expr : \\\] 
upper-expr' or 'dims\\(N\\): expr-list'" }
+  block; end block
+
+  !$omp teams num_teams( dims ! { dg-error "Failed to match clause" }
+  block; end block
+
+  !$omp teams num_teams( dims(1) ! { dg-error "Invalid character in name" }
+  block; end block
+
+  !$omp teams num_teams( dims(1) : ! { dg-error "Expected either 
'\\\[lower-expr : \\\] upper-expr' or 'dims\\(N\\): expr-list'" }
+  block; end block
+
+  !$omp teams num_teams( dims(1) : 1 ! { dg-error "Syntax error in OpenMP 
expression" }
+  block; end block
+
+  !$omp teams num_teams( 5 : ! { dg-error "Invalid character in name" }
+  block; end block
+
+  !$omp teams num_teams( 5 : 5 ! { dg-error "Failed to match clause" }
+  block; end block
+end
+
+subroutine four
+  !$omp teams thread_limit  ! { dg-error "Expected '\\(' after 'thread_limit'" 
}
+  block; end block
+
+  !$omp teams thread_limit( :  ! { dg-error "Expected STRICT, RELAXED or DIMS 
modifier" }
+  block; end block
+
+  !$omp teams thread_limit(  ! { dg-error "Expected a list of integer 
expressions followed by a '\\)' and optionally preceded by the STRICT, RELAXED, 
or DIMS as modifiers and a colon at .1." }
+  block; end block
+
+  !$omp teams thread_limit( dims ! { dg-error "Expected a list of integer 
expressions followed by a '\\)' and optionally preceded by the STRICT, RELAXED, 
or DIMS as modifiers and a colon at .1." }
+  block; end block
+
+  !$omp teams thread_limit( dims(1) ! { dg-error "Expected a list of integer 
expressions followed by a '\\)' and optionally preceded by the STRICT, RELAXED, 
or DIMS as modifiers and a colon at .1." }
+  block; end block
+
+  !$omp teams thread_limit( dims(1) : ! { dg-error "Expected a list of integer 
expressions followed by a '\\)' and optionally preceded by the STRICT, RELAXED, 
or DIMS as modifiers and a colon at .1." }
+  block; end block
+
+  !$omp teams thread_limit( dims(1) : 1 ! { dg-error "Expected a list of 
integer expressions followed by a '\\)' and optionally preceded by the STRICT, 
RELAXED, or DIMS as modifiers and a colon at .1." }
+  block; end block
+
+  !$omp teams thread_limit( 5 : ! { dg-error "Expected a list of integer 
expressions followed by a '\\)' and optionally preceded by the STRICT, RELAXED, 
or DIMS as modifiers and a colon at .1." }
+  block; end block
+
+  !$omp teams thread_limit( 5 : 5 ! { dg-error "Expected a list of integer 
expressions followed by a '\\)' and optionally preceded by the STRICT, RELAXED, 
or DIMS as modifiers and a colon at .1." }
+  block; end block
+end
+
+subroutine five
+  !$omp parallel num_threads  ! { dg-error "Expected '\\(' after 
'num_threads'" }
+  block; end block
+
+  !$omp parallel num_threads( :  ! { dg-error "Expected STRICT, RELAXED or 
DIMS modifier" }
+  block; end block
+
+  !$omp parallel num_threads(  ! { dg-error "Expected a list of integer 
expressions followed by a '\\)' and optionally preceded by the STRICT, RELAXED, 
or DIMS as modifiers and a colon at .1." }
+  block; end block
+
+  !$omp parallel num_threads( dims ! { dg-error "Expected a list of integer 
expressions followed by a '\\)' and optionally preceded by the STRICT, RELAXED, 
or DIMS as modifiers and a colon at .1." }
+  block; end block
+
+  !$omp parallel num_threads( dims(1) ! { dg-error "Expected a list of integer 
expressions followed by a '\\)' and optionally preceded by the STRICT, RELAXED, 
or DIMS as modifiers and a colon at .1." }
+  block; end block
+
+  !$omp parallel num_threads( dims(1) : ! { dg-error "Expected a list of 
integer expressions followed by a '\\)' and optionally preceded by the STRICT, 
RELAXED, or DIMS as modifiers and a colon at .1." }
+  block; end block
+
+  !$omp parallel num_threads( dims(1) : 1 ! { dg-error "Expected a list of 
integer expressions followed by a '\\)' and optionally preceded by the STRICT, 
RELAXED, or DIMS as modifiers and a colon at .1." }
+  block; end block
+
+  !$omp parallel num_threads( 5 : ! { dg-error "Expected a list of integer 
expressions followed by a '\\)' and optionally preceded by the STRICT, RELAXED, 
or DIMS as modifiers and a colon at .1." }
+  block; end block
+
+  !$omp parallel num_threads( 5 : 5 ! { dg-error "Expected a list of integer 
expressions followed by a '\\)' and optionally preceded by the STRICT, RELAXED, 
or DIMS as modifiers and a colon at .1." }
+  block; end block
+end
+
+subroutine six
+  !$omp teams num_teams (dims(1), dims(1) : 1) ! { dg-error "Invalid character 
in name" }
+  block; end block
+
+
+  !$omp teams thread_limit (dims(1), dims(1) : 1) ! { dg-error "Duplicated 
DIMS expression" }
+  block; end block
+
+  !$omp teams thread_limit (dims(1), relaxed, dims(1) : 1) ! { dg-error 
"Duplicated DIMS expression" }
+  block; end block
+
+  !$omp teams thread_limit (dims(1), strict, dims(1) : 1) ! { dg-error 
"Duplicated DIMS expression" }
+  block; end block
+
+  !$omp teams thread_limit (strict, relaxed, dims(1) : 1) ! { dg-error "Only 
one STRICT or RELAXED modifier permitted" }
+  block; end block
+
+  !$omp teams thread_limit (relaxed, strict, dims(1) : 1) ! { dg-error "Only 
one STRICT or RELAXED modifier permitted" }
+  block; end block
+
+  !$omp teams thread_limit (strict, relaxed : 1) ! { dg-error "Only one STRICT 
or RELAXED modifier permitted" }
+  block; end block
+
+  !$omp teams thread_limit (relaxed, strict : 1) ! { dg-error "Only one STRICT 
or RELAXED modifier permitted" }
+  block; end block
+
+  !$omp teams thread_limit (strict, dims(1), strict : 1) ! { dg-error "Only 
one STRICT or RELAXED modifier permitted" }
+  block; end block
+
+  !$omp teams thread_limit (relaxed, dims(1), relaxed : 1) ! { dg-error "Only 
one STRICT or RELAXED modifier permitted" }
+  block; end block
+
+  !$omp teams thread_limit (strict, strict : 1) ! { dg-error "Only one STRICT 
or RELAXED modifier permitted" }
+  block; end block
+
+  !$omp teams thread_limit (relaxed, relaxed : 1) ! { dg-error "Only one 
STRICT or RELAXED modifier permitted" }
+  block; end block
+
+
+  !$omp parallel num_threads (dims(1), dims(1) : 1) ! { dg-error "Duplicated 
DIMS expression" }
+  block; end block
+
+  !$omp parallel num_threads (dims(1), relaxed, dims(1) : 1) ! { dg-error 
"Duplicated DIMS expression" }
+  block; end block
+
+  !$omp parallel num_threads (dims(1), strict, dims(1) : 1) ! { dg-error 
"Duplicated DIMS expression" }
+  block; end block
+
+  !$omp parallel num_threads (strict, relaxed, dims(1) : 1) ! { dg-error "Only 
one STRICT or RELAXED modifier permitted" }
+  block; end block
+
+  !$omp parallel num_threads (relaxed, strict, dims(1) : 1) ! { dg-error "Only 
one STRICT or RELAXED modifier permitted" }
+  block; end block
+
+  !$omp parallel num_threads (strict, relaxed : 1) ! { dg-error "Only one 
STRICT or RELAXED modifier permitted" }
+  block; end block
+
+  !$omp parallel num_threads (relaxed, strict : 1) ! { dg-error "Only one 
STRICT or RELAXED modifier permitted" }
+  block; end block
+
+  !$omp parallel num_threads (strict, dims(1), strict : 1) ! { dg-error "Only 
one STRICT or RELAXED modifier permitted" }
+  block; end block
+
+  !$omp parallel num_threads (relaxed, dims(1), relaxed : 1) ! { dg-error 
"Only one STRICT or RELAXED modifier permitted" }
+  block; end block
+
+  !$omp parallel num_threads (strict, strict : 1) ! { dg-error "Only one 
STRICT or RELAXED modifier permitted" }
+  block; end block
+
+  !$omp parallel num_threads (relaxed, relaxed : 1) ! { dg-error "Only one 
STRICT or RELAXED modifier permitted" }
+  block; end block
+end subroutine
+
+subroutine seven
+  !$omp teams num_teams (2,2)  ! { dg-error "Failed to match clause" }
+  block; end block
+
+  !$omp teams thread_limit (2,2)  ! { dg-error "Without the DIM modifier, only 
a single integer expression may be specified" }
+  block; end block
+
+  !$omp parallel num_threads (2,2)  ! OK
+  block; end block
+end

Reply via email to