The attached patch adds parsing support for the following features:
* strict/relaxed modifiers to thread_limit and num_threads clauses
(default is 'relaxed')
* supporting a list of arguments for num_threads
This is to set the number of threads also for nested parallels;
the OMP_NUM_THREADS env var already supports this.
* Spatial dimension support, e.g. 'num_teams(dim(3) : 32, 32, 32)',
with the num_teams, thread_limit, and num_threads clauses.
(this implies 'strict', unless overridden).
When using any of the new features (but the relaxed modifier),
a 'sorry, unimplemented' is printed.
Comments before I commit this?
Tobias
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 specifiying 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.
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 5f058cdc830..3f1b35b715a 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 92678310ffd..fd34f0c1912 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 df987576fff..48ddd9a72d5 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 64355971d9e..ff021a60fe0 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 preceeded 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 preceeded 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 aa4e8ebfa23..381fb48d008 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 00000000000..94349180f5e
--- /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 00000000000..db570df86f9
--- /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 00000000000..74e76795085
--- /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 preceeded 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 preceeded 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 preceeded 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 preceeded 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 preceeded 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 preceeded 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 preceeded 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 preceeded 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 preceeded 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 preceeded 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 preceeded 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 preceeded 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 preceeded 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 preceeded 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