summaryrefslogtreecommitdiff
path: root/gcc/fortran/openmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/openmp.c')
-rw-r--r--gcc/fortran/openmp.c3002
1 files changed, 2001 insertions, 1001 deletions
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index de9a4ad47a..89eecfa2ed 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -1,5 +1,5 @@
/* OpenMP directive matching and resolving.
- Copyright (C) 2005-2016 Free Software Foundation, Inc.
+ Copyright (C) 2005-2017 Free Software Foundation, Inc.
Contributed by Jakub Jelinek
This file is part of GCC.
@@ -76,6 +76,12 @@ gfc_free_omp_clauses (gfc_omp_clauses *c)
gfc_free_expr (c->device);
gfc_free_expr (c->thread_limit);
gfc_free_expr (c->dist_chunk_size);
+ gfc_free_expr (c->grainsize);
+ gfc_free_expr (c->hint);
+ gfc_free_expr (c->num_tasks);
+ gfc_free_expr (c->priority);
+ for (i = 0; i < OMP_IF_LAST; i++)
+ gfc_free_expr (c->if_exprs[i]);
gfc_free_expr (c->async_expr);
gfc_free_expr (c->gang_num_expr);
gfc_free_expr (c->gang_static_expr);
@@ -88,6 +94,7 @@ gfc_free_omp_clauses (gfc_omp_clauses *c)
gfc_free_omp_namelist (c->lists[i]);
gfc_free_expr_list (c->wait_list);
gfc_free_expr_list (c->tile_list);
+ free (CONST_CAST (char *, c->critical_name));
free (c);
}
@@ -333,6 +340,170 @@ cleanup:
return MATCH_ERROR;
}
+/* Match a variable/procedure/common block list and construct a namelist
+ from it. */
+
+static match
+gfc_match_omp_to_link (const char *str, gfc_omp_namelist **list)
+{
+ gfc_omp_namelist *head, *tail, *p;
+ locus old_loc, cur_loc;
+ char n[GFC_MAX_SYMBOL_LEN+1];
+ gfc_symbol *sym;
+ match m;
+ gfc_symtree *st;
+
+ head = tail = NULL;
+
+ old_loc = gfc_current_locus;
+
+ m = gfc_match (str);
+ if (m != MATCH_YES)
+ return m;
+
+ for (;;)
+ {
+ cur_loc = gfc_current_locus;
+ m = gfc_match_symbol (&sym, 1);
+ switch (m)
+ {
+ case MATCH_YES:
+ p = gfc_get_omp_namelist ();
+ if (head == NULL)
+ head = tail = p;
+ else
+ {
+ tail->next = p;
+ tail = tail->next;
+ }
+ tail->sym = sym;
+ tail->where = cur_loc;
+ goto next_item;
+ case MATCH_NO:
+ break;
+ case MATCH_ERROR:
+ goto cleanup;
+ }
+
+ m = gfc_match (" / %n /", n);
+ if (m == MATCH_ERROR)
+ goto cleanup;
+ if (m == MATCH_NO)
+ goto syntax;
+
+ st = gfc_find_symtree (gfc_current_ns->common_root, n);
+ if (st == NULL)
+ {
+ gfc_error ("COMMON block /%s/ not found at %C", n);
+ goto cleanup;
+ }
+ p = gfc_get_omp_namelist ();
+ if (head == NULL)
+ head = tail = p;
+ else
+ {
+ tail->next = p;
+ tail = tail->next;
+ }
+ tail->u.common = st->n.common;
+ tail->where = cur_loc;
+
+ next_item:
+ if (gfc_match_char (')') == MATCH_YES)
+ break;
+ if (gfc_match_char (',') != MATCH_YES)
+ goto syntax;
+ }
+
+ while (*list)
+ list = &(*list)->next;
+
+ *list = head;
+ return MATCH_YES;
+
+syntax:
+ gfc_error ("Syntax error in OpenMP variable list at %C");
+
+cleanup:
+ gfc_free_omp_namelist (head);
+ gfc_current_locus = old_loc;
+ return MATCH_ERROR;
+}
+
+/* Match depend(sink : ...) construct a namelist from it. */
+
+static match
+gfc_match_omp_depend_sink (gfc_omp_namelist **list)
+{
+ gfc_omp_namelist *head, *tail, *p;
+ locus old_loc, cur_loc;
+ gfc_symbol *sym;
+
+ head = tail = NULL;
+
+ old_loc = gfc_current_locus;
+
+ for (;;)
+ {
+ cur_loc = gfc_current_locus;
+ switch (gfc_match_symbol (&sym, 1))
+ {
+ case MATCH_YES:
+ gfc_set_sym_referenced (sym);
+ p = gfc_get_omp_namelist ();
+ if (head == NULL)
+ {
+ head = tail = p;
+ head->u.depend_op = OMP_DEPEND_SINK_FIRST;
+ }
+ else
+ {
+ tail->next = p;
+ tail = tail->next;
+ tail->u.depend_op = OMP_DEPEND_SINK;
+ }
+ tail->sym = sym;
+ tail->expr = NULL;
+ tail->where = cur_loc;
+ if (gfc_match_char ('+') == MATCH_YES)
+ {
+ if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
+ goto syntax;
+ }
+ else if (gfc_match_char ('-') == MATCH_YES)
+ {
+ if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
+ goto syntax;
+ tail->expr = gfc_uminus (tail->expr);
+ }
+ break;
+ case MATCH_NO:
+ goto syntax;
+ case MATCH_ERROR:
+ goto cleanup;
+ }
+
+ if (gfc_match_char (')') == MATCH_YES)
+ break;
+ if (gfc_match_char (',') != MATCH_YES)
+ goto syntax;
+ }
+
+ while (*list)
+ list = &(*list)->next;
+
+ *list = head;
+ return MATCH_YES;
+
+syntax:
+ gfc_error ("Syntax error in OpenMP DEPEND SINK list at %C");
+
+cleanup:
+ gfc_free_omp_namelist (head);
+ gfc_current_locus = old_loc;
+ return MATCH_ERROR;
+}
+
static match
match_oacc_expr_list (const char *str, gfc_expr_list **list,
bool allow_asterisk)
@@ -563,67 +734,183 @@ cleanup:
return MATCH_ERROR;
}
-#define OMP_CLAUSE_PRIVATE ((uint64_t) 1 << 0)
-#define OMP_CLAUSE_FIRSTPRIVATE ((uint64_t) 1 << 1)
-#define OMP_CLAUSE_LASTPRIVATE ((uint64_t) 1 << 2)
-#define OMP_CLAUSE_COPYPRIVATE ((uint64_t) 1 << 3)
-#define OMP_CLAUSE_SHARED ((uint64_t) 1 << 4)
-#define OMP_CLAUSE_COPYIN ((uint64_t) 1 << 5)
-#define OMP_CLAUSE_REDUCTION ((uint64_t) 1 << 6)
-#define OMP_CLAUSE_IF ((uint64_t) 1 << 7)
-#define OMP_CLAUSE_NUM_THREADS ((uint64_t) 1 << 8)
-#define OMP_CLAUSE_SCHEDULE ((uint64_t) 1 << 9)
-#define OMP_CLAUSE_DEFAULT ((uint64_t) 1 << 10)
-#define OMP_CLAUSE_ORDERED ((uint64_t) 1 << 11)
-#define OMP_CLAUSE_COLLAPSE ((uint64_t) 1 << 12)
-#define OMP_CLAUSE_UNTIED ((uint64_t) 1 << 13)
-#define OMP_CLAUSE_FINAL ((uint64_t) 1 << 14)
-#define OMP_CLAUSE_MERGEABLE ((uint64_t) 1 << 15)
-#define OMP_CLAUSE_ALIGNED ((uint64_t) 1 << 16)
-#define OMP_CLAUSE_DEPEND ((uint64_t) 1 << 17)
-#define OMP_CLAUSE_INBRANCH ((uint64_t) 1 << 18)
-#define OMP_CLAUSE_LINEAR ((uint64_t) 1 << 19)
-#define OMP_CLAUSE_NOTINBRANCH ((uint64_t) 1 << 20)
-#define OMP_CLAUSE_PROC_BIND ((uint64_t) 1 << 21)
-#define OMP_CLAUSE_SAFELEN ((uint64_t) 1 << 22)
-#define OMP_CLAUSE_SIMDLEN ((uint64_t) 1 << 23)
-#define OMP_CLAUSE_UNIFORM ((uint64_t) 1 << 24)
-#define OMP_CLAUSE_DEVICE ((uint64_t) 1 << 25)
-#define OMP_CLAUSE_MAP ((uint64_t) 1 << 26)
-#define OMP_CLAUSE_TO ((uint64_t) 1 << 27)
-#define OMP_CLAUSE_FROM ((uint64_t) 1 << 28)
-#define OMP_CLAUSE_NUM_TEAMS ((uint64_t) 1 << 29)
-#define OMP_CLAUSE_THREAD_LIMIT ((uint64_t) 1 << 30)
-#define OMP_CLAUSE_DIST_SCHEDULE ((uint64_t) 1 << 31)
-
-/* OpenACC 2.0 clauses. */
-#define OMP_CLAUSE_ASYNC ((uint64_t) 1 << 32)
-#define OMP_CLAUSE_NUM_GANGS ((uint64_t) 1 << 33)
-#define OMP_CLAUSE_NUM_WORKERS ((uint64_t) 1 << 34)
-#define OMP_CLAUSE_VECTOR_LENGTH ((uint64_t) 1 << 35)
-#define OMP_CLAUSE_COPY ((uint64_t) 1 << 36)
-#define OMP_CLAUSE_COPYOUT ((uint64_t) 1 << 37)
-#define OMP_CLAUSE_CREATE ((uint64_t) 1 << 38)
-#define OMP_CLAUSE_PRESENT ((uint64_t) 1 << 39)
-#define OMP_CLAUSE_PRESENT_OR_COPY ((uint64_t) 1 << 40)
-#define OMP_CLAUSE_PRESENT_OR_COPYIN ((uint64_t) 1 << 41)
-#define OMP_CLAUSE_PRESENT_OR_COPYOUT ((uint64_t) 1 << 42)
-#define OMP_CLAUSE_PRESENT_OR_CREATE ((uint64_t) 1 << 43)
-#define OMP_CLAUSE_DEVICEPTR ((uint64_t) 1 << 44)
-#define OMP_CLAUSE_GANG ((uint64_t) 1 << 45)
-#define OMP_CLAUSE_WORKER ((uint64_t) 1 << 46)
-#define OMP_CLAUSE_VECTOR ((uint64_t) 1 << 47)
-#define OMP_CLAUSE_SEQ ((uint64_t) 1 << 48)
-#define OMP_CLAUSE_INDEPENDENT ((uint64_t) 1 << 49)
-#define OMP_CLAUSE_USE_DEVICE ((uint64_t) 1 << 50)
-#define OMP_CLAUSE_DEVICE_RESIDENT ((uint64_t) 1 << 51)
-#define OMP_CLAUSE_HOST_SELF ((uint64_t) 1 << 52)
-#define OMP_CLAUSE_OACC_DEVICE ((uint64_t) 1 << 53)
-#define OMP_CLAUSE_WAIT ((uint64_t) 1 << 54)
-#define OMP_CLAUSE_DELETE ((uint64_t) 1 << 55)
-#define OMP_CLAUSE_AUTO ((uint64_t) 1 << 56)
-#define OMP_CLAUSE_TILE ((uint64_t) 1 << 57)
-#define OMP_CLAUSE_LINK ((uint64_t) 1 << 58)
+/* OpenMP 4.5 clauses. */
+enum omp_mask1
+{
+ OMP_CLAUSE_PRIVATE,
+ OMP_CLAUSE_FIRSTPRIVATE,
+ OMP_CLAUSE_LASTPRIVATE,
+ OMP_CLAUSE_COPYPRIVATE,
+ OMP_CLAUSE_SHARED,
+ OMP_CLAUSE_COPYIN,
+ OMP_CLAUSE_REDUCTION,
+ OMP_CLAUSE_IF,
+ OMP_CLAUSE_NUM_THREADS,
+ OMP_CLAUSE_SCHEDULE,
+ OMP_CLAUSE_DEFAULT,
+ OMP_CLAUSE_ORDERED,
+ OMP_CLAUSE_COLLAPSE,
+ OMP_CLAUSE_UNTIED,
+ OMP_CLAUSE_FINAL,
+ OMP_CLAUSE_MERGEABLE,
+ OMP_CLAUSE_ALIGNED,
+ OMP_CLAUSE_DEPEND,
+ OMP_CLAUSE_INBRANCH,
+ OMP_CLAUSE_LINEAR,
+ OMP_CLAUSE_NOTINBRANCH,
+ OMP_CLAUSE_PROC_BIND,
+ OMP_CLAUSE_SAFELEN,
+ OMP_CLAUSE_SIMDLEN,
+ OMP_CLAUSE_UNIFORM,
+ OMP_CLAUSE_DEVICE,
+ OMP_CLAUSE_MAP,
+ OMP_CLAUSE_TO,
+ OMP_CLAUSE_FROM,
+ OMP_CLAUSE_NUM_TEAMS,
+ OMP_CLAUSE_THREAD_LIMIT,
+ OMP_CLAUSE_DIST_SCHEDULE,
+ OMP_CLAUSE_DEFAULTMAP,
+ OMP_CLAUSE_GRAINSIZE,
+ OMP_CLAUSE_HINT,
+ OMP_CLAUSE_IS_DEVICE_PTR,
+ OMP_CLAUSE_LINK,
+ OMP_CLAUSE_NOGROUP,
+ OMP_CLAUSE_NUM_TASKS,
+ OMP_CLAUSE_PRIORITY,
+ OMP_CLAUSE_SIMD,
+ OMP_CLAUSE_THREADS,
+ OMP_CLAUSE_USE_DEVICE_PTR,
+ OMP_CLAUSE_NOWAIT,
+ /* This must come last. */
+ OMP_MASK1_LAST
+};
+
+/* OpenACC 2.0 specific clauses. */
+enum omp_mask2
+{
+ OMP_CLAUSE_ASYNC,
+ OMP_CLAUSE_NUM_GANGS,
+ OMP_CLAUSE_NUM_WORKERS,
+ OMP_CLAUSE_VECTOR_LENGTH,
+ OMP_CLAUSE_COPY,
+ OMP_CLAUSE_COPYOUT,
+ OMP_CLAUSE_CREATE,
+ OMP_CLAUSE_PRESENT,
+ OMP_CLAUSE_PRESENT_OR_COPY,
+ OMP_CLAUSE_PRESENT_OR_COPYIN,
+ OMP_CLAUSE_PRESENT_OR_COPYOUT,
+ OMP_CLAUSE_PRESENT_OR_CREATE,
+ OMP_CLAUSE_DEVICEPTR,
+ OMP_CLAUSE_GANG,
+ OMP_CLAUSE_WORKER,
+ OMP_CLAUSE_VECTOR,
+ OMP_CLAUSE_SEQ,
+ OMP_CLAUSE_INDEPENDENT,
+ OMP_CLAUSE_USE_DEVICE,
+ OMP_CLAUSE_DEVICE_RESIDENT,
+ OMP_CLAUSE_HOST_SELF,
+ OMP_CLAUSE_WAIT,
+ OMP_CLAUSE_DELETE,
+ OMP_CLAUSE_AUTO,
+ OMP_CLAUSE_TILE,
+ /* This must come last. */
+ OMP_MASK2_LAST
+};
+
+struct omp_inv_mask;
+
+/* Customized bitset for up to 128-bits.
+ The two enums above provide bit numbers to use, and which of the
+ two enums it is determines which of the two mask fields is used.
+ Supported operations are defining a mask, like:
+ #define XXX_CLAUSES \
+ (omp_mask (OMP_CLAUSE_XXX) | OMP_CLAUSE_YYY | OMP_CLAUSE_ZZZ)
+ oring such bitsets together or removing selected bits:
+ (XXX_CLAUSES | YYY_CLAUSES) & ~(omp_mask (OMP_CLAUSE_VVV))
+ and testing individual bits:
+ if (mask & OMP_CLAUSE_UUU) */
+
+struct omp_mask {
+ const uint64_t mask1;
+ const uint64_t mask2;
+ inline omp_mask ();
+ inline omp_mask (omp_mask1);
+ inline omp_mask (omp_mask2);
+ inline omp_mask (uint64_t, uint64_t);
+ inline omp_mask operator| (omp_mask1) const;
+ inline omp_mask operator| (omp_mask2) const;
+ inline omp_mask operator| (omp_mask) const;
+ inline omp_mask operator& (const omp_inv_mask &) const;
+ inline bool operator& (omp_mask1) const;
+ inline bool operator& (omp_mask2) const;
+ inline omp_inv_mask operator~ () const;
+};
+
+struct omp_inv_mask : public omp_mask {
+ inline omp_inv_mask (const omp_mask &);
+};
+
+omp_mask::omp_mask () : mask1 (0), mask2 (0)
+{
+}
+
+omp_mask::omp_mask (omp_mask1 m) : mask1 (((uint64_t) 1) << m), mask2 (0)
+{
+}
+
+omp_mask::omp_mask (omp_mask2 m) : mask1 (0), mask2 (((uint64_t) 1) << m)
+{
+}
+
+omp_mask::omp_mask (uint64_t m1, uint64_t m2) : mask1 (m1), mask2 (m2)
+{
+}
+
+omp_mask
+omp_mask::operator| (omp_mask1 m) const
+{
+ return omp_mask (mask1 | (((uint64_t) 1) << m), mask2);
+}
+
+omp_mask
+omp_mask::operator| (omp_mask2 m) const
+{
+ return omp_mask (mask1, mask2 | (((uint64_t) 1) << m));
+}
+
+omp_mask
+omp_mask::operator| (omp_mask m) const
+{
+ return omp_mask (mask1 | m.mask1, mask2 | m.mask2);
+}
+
+omp_mask
+omp_mask::operator& (const omp_inv_mask &m) const
+{
+ return omp_mask (mask1 & ~m.mask1, mask2 & ~m.mask2);
+}
+
+bool
+omp_mask::operator& (omp_mask1 m) const
+{
+ return (mask1 & (((uint64_t) 1) << m)) != 0;
+}
+
+bool
+omp_mask::operator& (omp_mask2 m) const
+{
+ return (mask2 & (((uint64_t) 1) << m)) != 0;
+}
+
+omp_inv_mask
+omp_mask::operator~ () const
+{
+ return omp_inv_mask (*this);
+}
+
+omp_inv_mask::omp_inv_mask (const omp_mask &m) : omp_mask (m)
+{
+}
/* Helper function for OpenACC and OpenMP clauses involving memory
mapping. */
@@ -648,13 +935,14 @@ gfc_match_omp_map_clause (gfc_omp_namelist **list, gfc_omp_map_op map_op)
clauses that are allowed for a particular directive. */
static match
-gfc_match_omp_clauses (gfc_omp_clauses **cp, uint64_t mask,
+gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
bool first = true, bool needs_space = true,
bool openacc = false)
{
gfc_omp_clauses *c = gfc_get_omp_clauses ();
locus old_loc;
+ gcc_checking_assert (OMP_MASK1_LAST <= 64 && OMP_MASK2_LAST <= 64);
*cp = NULL;
while (1)
{
@@ -664,670 +952,957 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, uint64_t mask,
needs_space = false;
first = false;
gfc_gobble_whitespace ();
+ bool end_colon;
+ gfc_omp_namelist **head;
old_loc = gfc_current_locus;
- if ((mask & OMP_CLAUSE_ASYNC) && !c->async)
- if (gfc_match ("async") == MATCH_YES)
- {
- c->async = true;
- match m = gfc_match (" ( %e )", &c->async_expr);
- if (m == MATCH_ERROR)
- {
- gfc_current_locus = old_loc;
- break;
- }
- else if (m == MATCH_NO)
- {
- c->async_expr
- = gfc_get_constant_expr (BT_INTEGER,
- gfc_default_integer_kind,
- &gfc_current_locus);
- mpz_set_si (c->async_expr->value.integer, GOMP_ASYNC_NOVAL);
- needs_space = true;
- }
- continue;
- }
- if ((mask & OMP_CLAUSE_GANG) && !c->gang)
- if (gfc_match ("gang") == MATCH_YES)
- {
- c->gang = true;
- match m = match_oacc_clause_gwv (c, GOMP_DIM_GANG);
- if (m == MATCH_ERROR)
- {
- gfc_current_locus = old_loc;
- break;
- }
- else if (m == MATCH_NO)
+ char pc = gfc_peek_ascii_char ();
+ switch (pc)
+ {
+ case 'a':
+ end_colon = false;
+ head = NULL;
+ if ((mask & OMP_CLAUSE_ALIGNED)
+ && gfc_match_omp_variable_list ("aligned (",
+ &c->lists[OMP_LIST_ALIGNED],
+ false, &end_colon,
+ &head) == MATCH_YES)
+ {
+ gfc_expr *alignment = NULL;
+ gfc_omp_namelist *n;
+
+ if (end_colon && gfc_match (" %e )", &alignment) != MATCH_YES)
+ {
+ gfc_free_omp_namelist (*head);
+ gfc_current_locus = old_loc;
+ *head = NULL;
+ break;
+ }
+ for (n = *head; n; n = n->next)
+ if (n->next && alignment)
+ n->expr = gfc_copy_expr (alignment);
+ else
+ n->expr = alignment;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_ASYNC)
+ && !c->async
+ && gfc_match ("async") == MATCH_YES)
+ {
+ c->async = true;
+ match m = gfc_match (" ( %e )", &c->async_expr);
+ if (m == MATCH_ERROR)
+ {
+ gfc_current_locus = old_loc;
+ break;
+ }
+ else if (m == MATCH_NO)
+ {
+ c->async_expr
+ = gfc_get_constant_expr (BT_INTEGER,
+ gfc_default_integer_kind,
+ &gfc_current_locus);
+ mpz_set_si (c->async_expr->value.integer, GOMP_ASYNC_NOVAL);
+ needs_space = true;
+ }
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_AUTO)
+ && !c->par_auto
+ && gfc_match ("auto") == MATCH_YES)
+ {
+ c->par_auto = true;
needs_space = true;
+ continue;
+ }
+ break;
+ case 'c':
+ if ((mask & OMP_CLAUSE_COLLAPSE)
+ && !c->collapse)
+ {
+ gfc_expr *cexpr = NULL;
+ match m = gfc_match ("collapse ( %e )", &cexpr);
+
+ if (m == MATCH_YES)
+ {
+ int collapse;
+ if (gfc_extract_int (cexpr, &collapse, -1))
+ collapse = 1;
+ else if (collapse <= 0)
+ {
+ gfc_error_now ("COLLAPSE clause argument not"
+ " constant positive integer at %C");
+ collapse = 1;
+ }
+ c->collapse = collapse;
+ gfc_free_expr (cexpr);
+ continue;
+ }
+ }
+ if ((mask & OMP_CLAUSE_COPY)
+ && gfc_match ("copy ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_FORCE_TOFROM))
continue;
- }
- if ((mask & OMP_CLAUSE_WORKER) && !c->worker)
- if (gfc_match ("worker") == MATCH_YES)
- {
- c->worker = true;
- match m = match_oacc_clause_gwv (c, GOMP_DIM_WORKER);
- if (m == MATCH_ERROR)
- {
- gfc_current_locus = old_loc;
- break;
- }
- else if (m == MATCH_NO)
- needs_space = true;
+ if (mask & OMP_CLAUSE_COPYIN)
+ {
+ if (openacc)
+ {
+ if (gfc_match ("copyin ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_FORCE_TO))
+ continue;
+ }
+ else if (gfc_match_omp_variable_list ("copyin (",
+ &c->lists[OMP_LIST_COPYIN],
+ true) == MATCH_YES)
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_COPYOUT)
+ && gfc_match ("copyout ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_FORCE_FROM))
continue;
- }
- if ((mask & OMP_CLAUSE_VECTOR_LENGTH) && c->vector_length_expr == NULL
- && gfc_match ("vector_length ( %e )", &c->vector_length_expr)
- == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_VECTOR) && !c->vector)
- if (gfc_match ("vector") == MATCH_YES)
- {
- c->vector = true;
- match m = match_oacc_clause_gwv (c, GOMP_DIM_VECTOR);
- if (m == MATCH_ERROR)
- {
+ if ((mask & OMP_CLAUSE_COPYPRIVATE)
+ && gfc_match_omp_variable_list ("copyprivate (",
+ &c->lists[OMP_LIST_COPYPRIVATE],
+ true) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_CREATE)
+ && gfc_match ("create ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_FORCE_ALLOC))
+ continue;
+ break;
+ case 'd':
+ if ((mask & OMP_CLAUSE_DEFAULT)
+ && c->default_sharing == OMP_DEFAULT_UNKNOWN)
+ {
+ if (gfc_match ("default ( none )") == MATCH_YES)
+ c->default_sharing = OMP_DEFAULT_NONE;
+ else if (openacc)
+ /* c->default_sharing = OMP_DEFAULT_UNKNOWN */;
+ else if (gfc_match ("default ( shared )") == MATCH_YES)
+ c->default_sharing = OMP_DEFAULT_SHARED;
+ else if (gfc_match ("default ( private )") == MATCH_YES)
+ c->default_sharing = OMP_DEFAULT_PRIVATE;
+ else if (gfc_match ("default ( firstprivate )") == MATCH_YES)
+ c->default_sharing = OMP_DEFAULT_FIRSTPRIVATE;
+ if (c->default_sharing != OMP_DEFAULT_UNKNOWN)
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_DEFAULTMAP)
+ && !c->defaultmap
+ && gfc_match ("defaultmap ( tofrom : scalar )") == MATCH_YES)
+ {
+ c->defaultmap = true;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_DELETE)
+ && gfc_match ("delete ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_DELETE))
+ continue;
+ if ((mask & OMP_CLAUSE_DEPEND)
+ && gfc_match ("depend ( ") == MATCH_YES)
+ {
+ match m = MATCH_YES;
+ gfc_omp_depend_op depend_op = OMP_DEPEND_OUT;
+ if (gfc_match ("inout") == MATCH_YES)
+ depend_op = OMP_DEPEND_INOUT;
+ else if (gfc_match ("in") == MATCH_YES)
+ depend_op = OMP_DEPEND_IN;
+ else if (gfc_match ("out") == MATCH_YES)
+ depend_op = OMP_DEPEND_OUT;
+ else if (!c->depend_source
+ && gfc_match ("source )") == MATCH_YES)
+ {
+ c->depend_source = true;
+ continue;
+ }
+ else if (gfc_match ("sink : ") == MATCH_YES)
+ {
+ if (gfc_match_omp_depend_sink (&c->lists[OMP_LIST_DEPEND])
+ == MATCH_YES)
+ continue;
+ m = MATCH_NO;
+ }
+ else
+ m = MATCH_NO;
+ head = NULL;
+ if (m == MATCH_YES
+ && gfc_match_omp_variable_list (" : ",
+ &c->lists[OMP_LIST_DEPEND],
+ false, NULL, &head,
+ true) == MATCH_YES)
+ {
+ gfc_omp_namelist *n;
+ for (n = *head; n; n = n->next)
+ n->u.depend_op = depend_op;
+ continue;
+ }
+ else
gfc_current_locus = old_loc;
- break;
- }
- if (m == MATCH_NO)
- needs_space = true;
+ }
+ if ((mask & OMP_CLAUSE_DEVICE)
+ && !openacc
+ && c->device == NULL
+ && gfc_match ("device ( %e )", &c->device) == MATCH_YES)
continue;
- }
- if ((mask & OMP_CLAUSE_IF) && c->if_expr == NULL
- && gfc_match ("if ( %e )", &c->if_expr) == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_FINAL) && c->final_expr == NULL
- && gfc_match ("final ( %e )", &c->final_expr) == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_NUM_THREADS) && c->num_threads == NULL
- && gfc_match ("num_threads ( %e )", &c->num_threads) == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_PRIVATE)
- && gfc_match_omp_variable_list ("private (",
- &c->lists[OMP_LIST_PRIVATE], true)
- == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_FIRSTPRIVATE)
- && gfc_match_omp_variable_list ("firstprivate (",
- &c->lists[OMP_LIST_FIRSTPRIVATE],
- true)
- == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_LASTPRIVATE)
- && gfc_match_omp_variable_list ("lastprivate (",
- &c->lists[OMP_LIST_LASTPRIVATE],
- true)
- == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_COPYPRIVATE)
- && gfc_match_omp_variable_list ("copyprivate (",
- &c->lists[OMP_LIST_COPYPRIVATE],
- true)
- == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_SHARED)
- && gfc_match_omp_variable_list ("shared (",
- &c->lists[OMP_LIST_SHARED], true)
- == MATCH_YES)
- continue;
- if (mask & OMP_CLAUSE_COPYIN)
- {
- if (openacc)
+ if ((mask & OMP_CLAUSE_DEVICE)
+ && openacc
+ && gfc_match ("device ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_FORCE_TO))
+ continue;
+ if ((mask & OMP_CLAUSE_DEVICEPTR)
+ && gfc_match ("deviceptr ( ") == MATCH_YES)
+ {
+ gfc_omp_namelist **list = &c->lists[OMP_LIST_MAP];
+ gfc_omp_namelist **head = NULL;
+ if (gfc_match_omp_variable_list ("", list, true, NULL,
+ &head, false) == MATCH_YES)
+ {
+ gfc_omp_namelist *n;
+ for (n = *head; n; n = n->next)
+ n->u.map_op = OMP_MAP_FORCE_DEVICEPTR;
+ continue;
+ }
+ }
+ if ((mask & OMP_CLAUSE_DEVICE_RESIDENT)
+ && gfc_match_omp_variable_list
+ ("device_resident (",
+ &c->lists[OMP_LIST_DEVICE_RESIDENT], true) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_DIST_SCHEDULE)
+ && c->dist_sched_kind == OMP_SCHED_NONE
+ && gfc_match ("dist_schedule ( static") == MATCH_YES)
{
- if (gfc_match ("copyin ( ") == MATCH_YES
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_FORCE_TO))
+ match m = MATCH_NO;
+ c->dist_sched_kind = OMP_SCHED_STATIC;
+ m = gfc_match (" , %e )", &c->dist_chunk_size);
+ if (m != MATCH_YES)
+ m = gfc_match_char (')');
+ if (m != MATCH_YES)
+ {
+ c->dist_sched_kind = OMP_SCHED_NONE;
+ gfc_current_locus = old_loc;
+ }
+ else
continue;
}
- else if (gfc_match_omp_variable_list ("copyin (",
- &c->lists[OMP_LIST_COPYIN],
- true) == MATCH_YES)
+ break;
+ case 'f':
+ if ((mask & OMP_CLAUSE_FINAL)
+ && c->final_expr == NULL
+ && gfc_match ("final ( %e )", &c->final_expr) == MATCH_YES)
continue;
- }
- if ((mask & OMP_CLAUSE_NUM_GANGS) && c->num_gangs_expr == NULL
- && gfc_match ("num_gangs ( %e )", &c->num_gangs_expr) == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_NUM_WORKERS) && c->num_workers_expr == NULL
- && gfc_match ("num_workers ( %e )", &c->num_workers_expr)
- == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_COPY)
- && gfc_match ("copy ( ") == MATCH_YES
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_FORCE_TOFROM))
- continue;
- if ((mask & OMP_CLAUSE_COPYOUT)
- && gfc_match ("copyout ( ") == MATCH_YES
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_FORCE_FROM))
- continue;
- if ((mask & OMP_CLAUSE_CREATE)
- && gfc_match ("create ( ") == MATCH_YES
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_FORCE_ALLOC))
- continue;
- if ((mask & OMP_CLAUSE_DELETE)
- && gfc_match ("delete ( ") == MATCH_YES
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_DELETE))
- continue;
- if ((mask & OMP_CLAUSE_PRESENT)
- && gfc_match ("present ( ") == MATCH_YES
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_FORCE_PRESENT))
- continue;
- if ((mask & OMP_CLAUSE_PRESENT_OR_COPY)
- && gfc_match ("present_or_copy ( ") == MATCH_YES
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_TOFROM))
- continue;
- if ((mask & OMP_CLAUSE_PRESENT_OR_COPY)
- && gfc_match ("pcopy ( ") == MATCH_YES
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_TOFROM))
- continue;
- if ((mask & OMP_CLAUSE_PRESENT_OR_COPYIN)
- && gfc_match ("present_or_copyin ( ") == MATCH_YES
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_TO))
- continue;
- if ((mask & OMP_CLAUSE_PRESENT_OR_COPYIN)
- && gfc_match ("pcopyin ( ") == MATCH_YES
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_TO))
- continue;
- if ((mask & OMP_CLAUSE_PRESENT_OR_COPYOUT)
- && gfc_match ("present_or_copyout ( ") == MATCH_YES
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_FROM))
- continue;
- if ((mask & OMP_CLAUSE_PRESENT_OR_COPYOUT)
- && gfc_match ("pcopyout ( ") == MATCH_YES
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_FROM))
- continue;
- if ((mask & OMP_CLAUSE_PRESENT_OR_CREATE)
- && gfc_match ("present_or_create ( ") == MATCH_YES
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_ALLOC))
- continue;
- if ((mask & OMP_CLAUSE_PRESENT_OR_CREATE)
- && gfc_match ("pcreate ( ") == MATCH_YES
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_ALLOC))
- continue;
- if ((mask & OMP_CLAUSE_DEVICEPTR)
- && gfc_match ("deviceptr ( ") == MATCH_YES)
- {
- gfc_omp_namelist **list = &c->lists[OMP_LIST_MAP];
- gfc_omp_namelist **head = NULL;
- if (gfc_match_omp_variable_list ("", list, true, NULL, &head, false)
- == MATCH_YES)
+ if ((mask & OMP_CLAUSE_FIRSTPRIVATE)
+ && gfc_match_omp_variable_list ("firstprivate (",
+ &c->lists[OMP_LIST_FIRSTPRIVATE],
+ true) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_FROM)
+ && gfc_match_omp_variable_list ("from (",
+ &c->lists[OMP_LIST_FROM], false,
+ NULL, &head, true) == MATCH_YES)
+ continue;
+ break;
+ case 'g':
+ if ((mask & OMP_CLAUSE_GANG)
+ && !c->gang
+ && gfc_match ("gang") == MATCH_YES)
{
- gfc_omp_namelist *n;
- for (n = *head; n; n = n->next)
- n->u.map_op = OMP_MAP_FORCE_DEVICEPTR;
+ c->gang = true;
+ match m = match_oacc_clause_gwv (c, GOMP_DIM_GANG);
+ if (m == MATCH_ERROR)
+ {
+ gfc_current_locus = old_loc;
+ break;
+ }
+ else if (m == MATCH_NO)
+ needs_space = true;
continue;
}
- }
- if ((mask & OMP_CLAUSE_USE_DEVICE)
- && gfc_match_omp_variable_list ("use_device (",
- &c->lists[OMP_LIST_USE_DEVICE], true)
- == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_DEVICE_RESIDENT)
- && gfc_match_omp_variable_list ("device_resident (",
- &c->lists[OMP_LIST_DEVICE_RESIDENT],
- true)
- == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_LINK)
- && gfc_match_oacc_clause_link ("link (",
- &c->lists[OMP_LIST_LINK])
- == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_OACC_DEVICE)
- && gfc_match ("device ( ") == MATCH_YES
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_FORCE_TO))
- continue;
- if ((mask & OMP_CLAUSE_HOST_SELF)
- && (gfc_match ("host ( ") == MATCH_YES
- || gfc_match ("self ( ") == MATCH_YES)
- && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
- OMP_MAP_FORCE_FROM))
- continue;
- if ((mask & OMP_CLAUSE_TILE)
- && !c->tile_list
- && match_oacc_expr_list ("tile (", &c->tile_list, true) == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_SEQ) && !c->seq
- && gfc_match ("seq") == MATCH_YES)
- {
- c->seq = true;
- needs_space = true;
- continue;
- }
- if ((mask & OMP_CLAUSE_INDEPENDENT) && !c->independent
- && gfc_match ("independent") == MATCH_YES)
- {
- c->independent = true;
- needs_space = true;
- continue;
- }
- if ((mask & OMP_CLAUSE_AUTO) && !c->par_auto
- && gfc_match ("auto") == MATCH_YES)
- {
- c->par_auto = true;
- needs_space = true;
- continue;
- }
- if ((mask & OMP_CLAUSE_WAIT) && !c->wait
- && gfc_match ("wait") == MATCH_YES)
- {
- c->wait = true;
- match m = match_oacc_expr_list (" (", &c->wait_list, false);
- if (m == MATCH_ERROR)
+ if ((mask & OMP_CLAUSE_GRAINSIZE)
+ && c->grainsize == NULL
+ && gfc_match ("grainsize ( %e )", &c->grainsize) == MATCH_YES)
+ continue;
+ break;
+ case 'h':
+ if ((mask & OMP_CLAUSE_HINT)
+ && c->hint == NULL
+ && gfc_match ("hint ( %e )", &c->hint) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_HOST_SELF)
+ && gfc_match ("host ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_FORCE_FROM))
+ continue;
+ break;
+ case 'i':
+ if ((mask & OMP_CLAUSE_IF)
+ && c->if_expr == NULL
+ && gfc_match ("if ( ") == MATCH_YES)
{
+ if (gfc_match ("%e )", &c->if_expr) == MATCH_YES)
+ continue;
+ if (!openacc)
+ {
+ /* This should match the enum gfc_omp_if_kind order. */
+ static const char *ifs[OMP_IF_LAST] = {
+ " parallel : %e )",
+ " task : %e )",
+ " taskloop : %e )",
+ " target : %e )",
+ " target data : %e )",
+ " target update : %e )",
+ " target enter data : %e )",
+ " target exit data : %e )" };
+ int i;
+ for (i = 0; i < OMP_IF_LAST; i++)
+ if (c->if_exprs[i] == NULL
+ && gfc_match (ifs[i], &c->if_exprs[i]) == MATCH_YES)
+ break;
+ if (i < OMP_IF_LAST)
+ continue;
+ }
gfc_current_locus = old_loc;
- break;
}
- else if (m == MATCH_NO)
- needs_space = true;
- continue;
- }
- if ((mask & OMP_CLAUSE_REDUCTION)
- && gfc_match ("reduction ( ") == MATCH_YES)
- {
- gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
- char buffer[GFC_MAX_SYMBOL_LEN + 3];
- if (gfc_match_char ('+') == MATCH_YES)
- rop = OMP_REDUCTION_PLUS;
- else if (gfc_match_char ('*') == MATCH_YES)
- rop = OMP_REDUCTION_TIMES;
- else if (gfc_match_char ('-') == MATCH_YES)
- rop = OMP_REDUCTION_MINUS;
- else if (gfc_match (".and.") == MATCH_YES)
- rop = OMP_REDUCTION_AND;
- else if (gfc_match (".or.") == MATCH_YES)
- rop = OMP_REDUCTION_OR;
- else if (gfc_match (".eqv.") == MATCH_YES)
- rop = OMP_REDUCTION_EQV;
- else if (gfc_match (".neqv.") == MATCH_YES)
- rop = OMP_REDUCTION_NEQV;
- if (rop != OMP_REDUCTION_NONE)
- snprintf (buffer, sizeof buffer,
- "operator %s", gfc_op2string ((gfc_intrinsic_op) rop));
- else if (gfc_match_defined_op_name (buffer + 1, 1) == MATCH_YES)
+ if ((mask & OMP_CLAUSE_INBRANCH)
+ && !c->inbranch
+ && !c->notinbranch
+ && gfc_match ("inbranch") == MATCH_YES)
{
- buffer[0] = '.';
- strcat (buffer, ".");
+ c->inbranch = needs_space = true;
+ continue;
}
- else if (gfc_match_name (buffer) == MATCH_YES)
+ if ((mask & OMP_CLAUSE_INDEPENDENT)
+ && !c->independent
+ && gfc_match ("independent") == MATCH_YES)
{
- gfc_symbol *sym;
- const char *n = buffer;
-
- gfc_find_symbol (buffer, NULL, 1, &sym);
- if (sym != NULL)
+ c->independent = true;
+ needs_space = true;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_IS_DEVICE_PTR)
+ && gfc_match_omp_variable_list
+ ("is_device_ptr (",
+ &c->lists[OMP_LIST_IS_DEVICE_PTR], false) == MATCH_YES)
+ continue;
+ break;
+ case 'l':
+ if ((mask & OMP_CLAUSE_LASTPRIVATE)
+ && gfc_match_omp_variable_list ("lastprivate (",
+ &c->lists[OMP_LIST_LASTPRIVATE],
+ true) == MATCH_YES)
+ continue;
+ end_colon = false;
+ head = NULL;
+ if ((mask & OMP_CLAUSE_LINEAR)
+ && gfc_match ("linear (") == MATCH_YES)
+ {
+ gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
+ gfc_expr *step = NULL;
+
+ if (gfc_match_omp_variable_list (" ref (",
+ &c->lists[OMP_LIST_LINEAR],
+ false, NULL, &head)
+ == MATCH_YES)
+ linear_op = OMP_LINEAR_REF;
+ else if (gfc_match_omp_variable_list (" val (",
+ &c->lists[OMP_LIST_LINEAR],
+ false, NULL, &head)
+ == MATCH_YES)
+ linear_op = OMP_LINEAR_VAL;
+ else if (gfc_match_omp_variable_list (" uval (",
+ &c->lists[OMP_LIST_LINEAR],
+ false, NULL, &head)
+ == MATCH_YES)
+ linear_op = OMP_LINEAR_UVAL;
+ else if (gfc_match_omp_variable_list ("",
+ &c->lists[OMP_LIST_LINEAR],
+ false, &end_colon, &head)
+ == MATCH_YES)
+ linear_op = OMP_LINEAR_DEFAULT;
+ else
{
- if (sym->attr.intrinsic)
- n = sym->name;
- else if ((sym->attr.flavor != FL_UNKNOWN
- && sym->attr.flavor != FL_PROCEDURE)
- || sym->attr.external
- || sym->attr.generic
- || sym->attr.entry
- || sym->attr.result
- || sym->attr.dummy
- || sym->attr.subroutine
- || sym->attr.pointer
- || sym->attr.target
- || sym->attr.cray_pointer
- || sym->attr.cray_pointee
- || (sym->attr.proc != PROC_UNKNOWN
- && sym->attr.proc != PROC_INTRINSIC)
- || sym->attr.if_source != IFSRC_UNKNOWN
- || sym == sym->ns->proc_name)
+ gfc_free_omp_namelist (*head);
+ gfc_current_locus = old_loc;
+ *head = NULL;
+ break;
+ }
+ if (linear_op != OMP_LINEAR_DEFAULT)
+ {
+ if (gfc_match (" :") == MATCH_YES)
+ end_colon = true;
+ else if (gfc_match (" )") != MATCH_YES)
{
- sym = NULL;
- n = NULL;
+ gfc_free_omp_namelist (*head);
+ gfc_current_locus = old_loc;
+ *head = NULL;
+ break;
}
- else
- n = sym->name;
}
- if (n == NULL)
- rop = OMP_REDUCTION_NONE;
- else if (strcmp (n, "max") == 0)
- rop = OMP_REDUCTION_MAX;
- else if (strcmp (n, "min") == 0)
- rop = OMP_REDUCTION_MIN;
- else if (strcmp (n, "iand") == 0)
- rop = OMP_REDUCTION_IAND;
- else if (strcmp (n, "ior") == 0)
- rop = OMP_REDUCTION_IOR;
- else if (strcmp (n, "ieor") == 0)
- rop = OMP_REDUCTION_IEOR;
- if (rop != OMP_REDUCTION_NONE
- && sym != NULL
- && ! sym->attr.intrinsic
- && ! sym->attr.use_assoc
- && ((sym->attr.flavor == FL_UNKNOWN
- && !gfc_add_flavor (&sym->attr, FL_PROCEDURE,
- sym->name, NULL))
- || !gfc_add_intrinsic (&sym->attr, NULL)))
- rop = OMP_REDUCTION_NONE;
+ if (end_colon && gfc_match (" %e )", &step) != MATCH_YES)
+ {
+ gfc_free_omp_namelist (*head);
+ gfc_current_locus = old_loc;
+ *head = NULL;
+ break;
+ }
+ else if (!end_colon)
+ {
+ step = gfc_get_constant_expr (BT_INTEGER,
+ gfc_default_integer_kind,
+ &old_loc);
+ mpz_set_si (step->value.integer, 1);
+ }
+ (*head)->expr = step;
+ if (linear_op != OMP_LINEAR_DEFAULT)
+ for (gfc_omp_namelist *n = *head; n; n = n->next)
+ n->u.linear_op = linear_op;
+ continue;
}
- else
- buffer[0] = '\0';
- gfc_omp_udr *udr
- = (buffer[0]
- ? gfc_find_omp_udr (gfc_current_ns, buffer, NULL) : NULL);
- gfc_omp_namelist **head = NULL;
- if (rop == OMP_REDUCTION_NONE && udr)
- rop = OMP_REDUCTION_USER;
-
- if (gfc_match_omp_variable_list (" :",
- &c->lists[OMP_LIST_REDUCTION],
- false, NULL, &head, openacc)
- == MATCH_YES)
+ if ((mask & OMP_CLAUSE_LINK)
+ && openacc
+ && (gfc_match_oacc_clause_link ("link (",
+ &c->lists[OMP_LIST_LINK])
+ == MATCH_YES))
+ continue;
+ else if ((mask & OMP_CLAUSE_LINK)
+ && !openacc
+ && (gfc_match_omp_to_link ("link (",
+ &c->lists[OMP_LIST_LINK])
+ == MATCH_YES))
+ continue;
+ break;
+ case 'm':
+ if ((mask & OMP_CLAUSE_MAP)
+ && gfc_match ("map ( ") == MATCH_YES)
{
- gfc_omp_namelist *n;
- if (rop == OMP_REDUCTION_NONE)
+ locus old_loc2 = gfc_current_locus;
+ bool always = false;
+ gfc_omp_map_op map_op = OMP_MAP_TOFROM;
+ if (gfc_match ("always , ") == MATCH_YES)
+ always = true;
+ if (gfc_match ("alloc : ") == MATCH_YES)
+ map_op = OMP_MAP_ALLOC;
+ else if (gfc_match ("tofrom : ") == MATCH_YES)
+ map_op = always ? OMP_MAP_ALWAYS_TOFROM : OMP_MAP_TOFROM;
+ else if (gfc_match ("to : ") == MATCH_YES)
+ map_op = always ? OMP_MAP_ALWAYS_TO : OMP_MAP_TO;
+ else if (gfc_match ("from : ") == MATCH_YES)
+ map_op = always ? OMP_MAP_ALWAYS_FROM : OMP_MAP_FROM;
+ else if (gfc_match ("release : ") == MATCH_YES)
+ map_op = OMP_MAP_RELEASE;
+ else if (gfc_match ("delete : ") == MATCH_YES)
+ map_op = OMP_MAP_DELETE;
+ else if (always)
{
- n = *head;
- *head = NULL;
- gfc_error_now ("!$OMP DECLARE REDUCTION %s not found "
- "at %L", buffer, &old_loc);
- gfc_free_omp_namelist (n);
+ gfc_current_locus = old_loc2;
+ always = false;
+ }
+ head = NULL;
+ if (gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_MAP],
+ false, NULL, &head,
+ true) == MATCH_YES)
+ {
+ gfc_omp_namelist *n;
+ for (n = *head; n; n = n->next)
+ n->u.map_op = map_op;
+ continue;
}
else
- for (n = *head; n; n = n->next)
- {
- n->u.reduction_op = rop;
- if (udr)
- {
- n->udr = gfc_get_omp_namelist_udr ();
- n->udr->udr = udr;
- }
- }
+ gfc_current_locus = old_loc;
+ }
+ if ((mask & OMP_CLAUSE_MERGEABLE) && !c->mergeable
+ && gfc_match ("mergeable") == MATCH_YES)
+ {
+ c->mergeable = needs_space = true;
continue;
}
- else
- gfc_current_locus = old_loc;
- }
- if ((mask & OMP_CLAUSE_DEFAULT)
- && c->default_sharing == OMP_DEFAULT_UNKNOWN)
- {
- if (gfc_match ("default ( none )") == MATCH_YES)
- c->default_sharing = OMP_DEFAULT_NONE;
- else if (openacc)
- /* c->default_sharing = OMP_DEFAULT_UNKNOWN */;
- else if (gfc_match ("default ( shared )") == MATCH_YES)
- c->default_sharing = OMP_DEFAULT_SHARED;
- else if (gfc_match ("default ( private )") == MATCH_YES)
- c->default_sharing = OMP_DEFAULT_PRIVATE;
- else if (gfc_match ("default ( firstprivate )") == MATCH_YES)
- c->default_sharing = OMP_DEFAULT_FIRSTPRIVATE;
- if (c->default_sharing != OMP_DEFAULT_UNKNOWN)
+ break;
+ case 'n':
+ if ((mask & OMP_CLAUSE_NOGROUP)
+ && !c->nogroup
+ && gfc_match ("nogroup") == MATCH_YES)
+ {
+ c->nogroup = needs_space = true;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_NOTINBRANCH)
+ && !c->notinbranch
+ && !c->inbranch
+ && gfc_match ("notinbranch") == MATCH_YES)
+ {
+ c->notinbranch = needs_space = true;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_NOWAIT)
+ && !c->nowait
+ && gfc_match ("nowait") == MATCH_YES)
+ {
+ c->nowait = needs_space = true;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_NUM_GANGS)
+ && c->num_gangs_expr == NULL
+ && gfc_match ("num_gangs ( %e )",
+ &c->num_gangs_expr) == MATCH_YES)
continue;
- }
- old_loc = gfc_current_locus;
- if ((mask & OMP_CLAUSE_SCHEDULE)
- && c->sched_kind == OMP_SCHED_NONE
- && gfc_match ("schedule ( ") == MATCH_YES)
- {
- if (gfc_match ("static") == MATCH_YES)
- c->sched_kind = OMP_SCHED_STATIC;
- else if (gfc_match ("dynamic") == MATCH_YES)
- c->sched_kind = OMP_SCHED_DYNAMIC;
- else if (gfc_match ("guided") == MATCH_YES)
- c->sched_kind = OMP_SCHED_GUIDED;
- else if (gfc_match ("runtime") == MATCH_YES)
- c->sched_kind = OMP_SCHED_RUNTIME;
- else if (gfc_match ("auto") == MATCH_YES)
- c->sched_kind = OMP_SCHED_AUTO;
- if (c->sched_kind != OMP_SCHED_NONE)
+ if ((mask & OMP_CLAUSE_NUM_TASKS)
+ && c->num_tasks == NULL
+ && gfc_match ("num_tasks ( %e )", &c->num_tasks) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_NUM_TEAMS)
+ && c->num_teams == NULL
+ && gfc_match ("num_teams ( %e )", &c->num_teams) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_NUM_THREADS)
+ && c->num_threads == NULL
+ && (gfc_match ("num_threads ( %e )", &c->num_threads)
+ == MATCH_YES))
+ continue;
+ if ((mask & OMP_CLAUSE_NUM_WORKERS)
+ && c->num_workers_expr == NULL
+ && gfc_match ("num_workers ( %e )",
+ &c->num_workers_expr) == MATCH_YES)
+ continue;
+ break;
+ case 'o':
+ if ((mask & OMP_CLAUSE_ORDERED)
+ && !c->ordered
+ && gfc_match ("ordered") == MATCH_YES)
{
- match m = MATCH_NO;
- if (c->sched_kind != OMP_SCHED_RUNTIME
- && c->sched_kind != OMP_SCHED_AUTO)
- m = gfc_match (" , %e )", &c->chunk_size);
- if (m != MATCH_YES)
- m = gfc_match_char (')');
- if (m != MATCH_YES)
- c->sched_kind = OMP_SCHED_NONE;
+ gfc_expr *cexpr = NULL;
+ match m = gfc_match (" ( %e )", &cexpr);
+
+ c->ordered = true;
+ if (m == MATCH_YES)
+ {
+ int ordered = 0;
+ if (gfc_extract_int (cexpr, &ordered, -1))
+ ordered = 0;
+ else if (ordered <= 0)
+ {
+ gfc_error_now ("ORDERED clause argument not"
+ " constant positive integer at %C");
+ ordered = 0;
+ }
+ c->orderedc = ordered;
+ gfc_free_expr (cexpr);
+ continue;
+ }
+
+ needs_space = true;
+ continue;
}
- if (c->sched_kind != OMP_SCHED_NONE)
+ break;
+ case 'p':
+ if ((mask & OMP_CLAUSE_PRESENT_OR_COPY)
+ && gfc_match ("pcopy ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_TOFROM))
continue;
- else
- gfc_current_locus = old_loc;
- }
- if ((mask & OMP_CLAUSE_ORDERED) && !c->ordered
- && gfc_match ("ordered") == MATCH_YES)
- {
- c->ordered = needs_space = true;
- continue;
- }
- if ((mask & OMP_CLAUSE_UNTIED) && !c->untied
- && gfc_match ("untied") == MATCH_YES)
- {
- c->untied = needs_space = true;
- continue;
- }
- if ((mask & OMP_CLAUSE_MERGEABLE) && !c->mergeable
- && gfc_match ("mergeable") == MATCH_YES)
- {
- c->mergeable = needs_space = true;
- continue;
- }
- if ((mask & OMP_CLAUSE_COLLAPSE) && !c->collapse)
- {
- gfc_expr *cexpr = NULL;
- match m = gfc_match ("collapse ( %e )", &cexpr);
+ if ((mask & OMP_CLAUSE_PRESENT_OR_COPYIN)
+ && gfc_match ("pcopyin ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_TO))
+ continue;
+ if ((mask & OMP_CLAUSE_PRESENT_OR_COPYOUT)
+ && gfc_match ("pcopyout ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_FROM))
+ continue;
+ if ((mask & OMP_CLAUSE_PRESENT_OR_CREATE)
+ && gfc_match ("pcreate ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_ALLOC))
+ continue;
+ if ((mask & OMP_CLAUSE_PRESENT)
+ && gfc_match ("present ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_FORCE_PRESENT))
+ continue;
+ if ((mask & OMP_CLAUSE_PRESENT_OR_COPY)
+ && gfc_match ("present_or_copy ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_TOFROM))
+ continue;
+ if ((mask & OMP_CLAUSE_PRESENT_OR_COPYIN)
+ && gfc_match ("present_or_copyin ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_TO))
+ continue;
+ if ((mask & OMP_CLAUSE_PRESENT_OR_COPYOUT)
+ && gfc_match ("present_or_copyout ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_FROM))
+ continue;
+ if ((mask & OMP_CLAUSE_PRESENT_OR_CREATE)
+ && gfc_match ("present_or_create ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_ALLOC))
+ continue;
+ if ((mask & OMP_CLAUSE_PRIORITY)
+ && c->priority == NULL
+ && gfc_match ("priority ( %e )", &c->priority) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_PRIVATE)
+ && gfc_match_omp_variable_list ("private (",
+ &c->lists[OMP_LIST_PRIVATE],
+ true) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_PROC_BIND)
+ && c->proc_bind == OMP_PROC_BIND_UNKNOWN)
+ {
+ if (gfc_match ("proc_bind ( master )") == MATCH_YES)
+ c->proc_bind = OMP_PROC_BIND_MASTER;
+ else if (gfc_match ("proc_bind ( spread )") == MATCH_YES)
+ c->proc_bind = OMP_PROC_BIND_SPREAD;
+ else if (gfc_match ("proc_bind ( close )") == MATCH_YES)
+ c->proc_bind = OMP_PROC_BIND_CLOSE;
+ if (c->proc_bind != OMP_PROC_BIND_UNKNOWN)
+ continue;
+ }
+ break;
+ case 'r':
+ if ((mask & OMP_CLAUSE_REDUCTION)
+ && gfc_match ("reduction ( ") == MATCH_YES)
+ {
+ gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
+ char buffer[GFC_MAX_SYMBOL_LEN + 3];
+ if (gfc_match_char ('+') == MATCH_YES)
+ rop = OMP_REDUCTION_PLUS;
+ else if (gfc_match_char ('*') == MATCH_YES)
+ rop = OMP_REDUCTION_TIMES;
+ else if (gfc_match_char ('-') == MATCH_YES)
+ rop = OMP_REDUCTION_MINUS;
+ else if (gfc_match (".and.") == MATCH_YES)
+ rop = OMP_REDUCTION_AND;
+ else if (gfc_match (".or.") == MATCH_YES)
+ rop = OMP_REDUCTION_OR;
+ else if (gfc_match (".eqv.") == MATCH_YES)
+ rop = OMP_REDUCTION_EQV;
+ else if (gfc_match (".neqv.") == MATCH_YES)
+ rop = OMP_REDUCTION_NEQV;
+ if (rop != OMP_REDUCTION_NONE)
+ snprintf (buffer, sizeof buffer, "operator %s",
+ gfc_op2string ((gfc_intrinsic_op) rop));
+ else if (gfc_match_defined_op_name (buffer + 1, 1) == MATCH_YES)
+ {
+ buffer[0] = '.';
+ strcat (buffer, ".");
+ }
+ else if (gfc_match_name (buffer) == MATCH_YES)
+ {
+ gfc_symbol *sym;
+ const char *n = buffer;
- if (m == MATCH_YES)
+ gfc_find_symbol (buffer, NULL, 1, &sym);
+ if (sym != NULL)
+ {
+ if (sym->attr.intrinsic)
+ n = sym->name;
+ else if ((sym->attr.flavor != FL_UNKNOWN
+ && sym->attr.flavor != FL_PROCEDURE)
+ || sym->attr.external
+ || sym->attr.generic
+ || sym->attr.entry
+ || sym->attr.result
+ || sym->attr.dummy
+ || sym->attr.subroutine
+ || sym->attr.pointer
+ || sym->attr.target
+ || sym->attr.cray_pointer
+ || sym->attr.cray_pointee
+ || (sym->attr.proc != PROC_UNKNOWN
+ && sym->attr.proc != PROC_INTRINSIC)
+ || sym->attr.if_source != IFSRC_UNKNOWN
+ || sym == sym->ns->proc_name)
+ {
+ sym = NULL;
+ n = NULL;
+ }
+ else
+ n = sym->name;
+ }
+ if (n == NULL)
+ rop = OMP_REDUCTION_NONE;
+ else if (strcmp (n, "max") == 0)
+ rop = OMP_REDUCTION_MAX;
+ else if (strcmp (n, "min") == 0)
+ rop = OMP_REDUCTION_MIN;
+ else if (strcmp (n, "iand") == 0)
+ rop = OMP_REDUCTION_IAND;
+ else if (strcmp (n, "ior") == 0)
+ rop = OMP_REDUCTION_IOR;
+ else if (strcmp (n, "ieor") == 0)
+ rop = OMP_REDUCTION_IEOR;
+ if (rop != OMP_REDUCTION_NONE
+ && sym != NULL
+ && ! sym->attr.intrinsic
+ && ! sym->attr.use_assoc
+ && ((sym->attr.flavor == FL_UNKNOWN
+ && !gfc_add_flavor (&sym->attr, FL_PROCEDURE,
+ sym->name, NULL))
+ || !gfc_add_intrinsic (&sym->attr, NULL)))
+ rop = OMP_REDUCTION_NONE;
+ }
+ else
+ buffer[0] = '\0';
+ gfc_omp_udr *udr
+ = (buffer[0]
+ ? gfc_find_omp_udr (gfc_current_ns, buffer, NULL) : NULL);
+ gfc_omp_namelist **head = NULL;
+ if (rop == OMP_REDUCTION_NONE && udr)
+ rop = OMP_REDUCTION_USER;
+
+ if (gfc_match_omp_variable_list (" :",
+ &c->lists[OMP_LIST_REDUCTION],
+ false, NULL, &head,
+ openacc) == MATCH_YES)
+ {
+ gfc_omp_namelist *n;
+ if (rop == OMP_REDUCTION_NONE)
+ {
+ n = *head;
+ *head = NULL;
+ gfc_error_now ("!$OMP DECLARE REDUCTION %s not found "
+ "at %L", buffer, &old_loc);
+ gfc_free_omp_namelist (n);
+ }
+ else
+ for (n = *head; n; n = n->next)
+ {
+ n->u.reduction_op = rop;
+ if (udr)
+ {
+ n->udr = gfc_get_omp_namelist_udr ();
+ n->udr->udr = udr;
+ }
+ }
+ continue;
+ }
+ else
+ gfc_current_locus = old_loc;
+ }
+ break;
+ case 's':
+ if ((mask & OMP_CLAUSE_SAFELEN)
+ && c->safelen_expr == NULL
+ && gfc_match ("safelen ( %e )", &c->safelen_expr) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_SCHEDULE)
+ && c->sched_kind == OMP_SCHED_NONE
+ && gfc_match ("schedule ( ") == MATCH_YES)
{
- int collapse;
- const char *p = gfc_extract_int (cexpr, &collapse);
- if (p)
+ int nmodifiers = 0;
+ locus old_loc2 = gfc_current_locus;
+ do
{
- gfc_error_now (p);
- collapse = 1;
+ if (!c->sched_simd
+ && gfc_match ("simd") == MATCH_YES)
+ {
+ c->sched_simd = true;
+ nmodifiers++;
+ }
+ else if (!c->sched_monotonic
+ && !c->sched_nonmonotonic
+ && gfc_match ("monotonic") == MATCH_YES)
+ {
+ c->sched_monotonic = true;
+ nmodifiers++;
+ }
+ else if (!c->sched_monotonic
+ && !c->sched_nonmonotonic
+ && gfc_match ("nonmonotonic") == MATCH_YES)
+ {
+ c->sched_nonmonotonic = true;
+ nmodifiers++;
+ }
+ else
+ {
+ if (nmodifiers)
+ gfc_current_locus = old_loc2;
+ break;
+ }
+ if (nmodifiers == 0
+ && gfc_match (" , ") == MATCH_YES)
+ continue;
+ else if (gfc_match (" : ") == MATCH_YES)
+ break;
+ gfc_current_locus = old_loc2;
+ break;
}
- else if (collapse <= 0)
+ while (1);
+ if (gfc_match ("static") == MATCH_YES)
+ c->sched_kind = OMP_SCHED_STATIC;
+ else if (gfc_match ("dynamic") == MATCH_YES)
+ c->sched_kind = OMP_SCHED_DYNAMIC;
+ else if (gfc_match ("guided") == MATCH_YES)
+ c->sched_kind = OMP_SCHED_GUIDED;
+ else if (gfc_match ("runtime") == MATCH_YES)
+ c->sched_kind = OMP_SCHED_RUNTIME;
+ else if (gfc_match ("auto") == MATCH_YES)
+ c->sched_kind = OMP_SCHED_AUTO;
+ if (c->sched_kind != OMP_SCHED_NONE)
{
- gfc_error_now ("COLLAPSE clause argument not"
- " constant positive integer at %C");
- collapse = 1;
+ match m = MATCH_NO;
+ if (c->sched_kind != OMP_SCHED_RUNTIME
+ && c->sched_kind != OMP_SCHED_AUTO)
+ m = gfc_match (" , %e )", &c->chunk_size);
+ if (m != MATCH_YES)
+ m = gfc_match_char (')');
+ if (m != MATCH_YES)
+ c->sched_kind = OMP_SCHED_NONE;
}
- c->collapse = collapse;
- gfc_free_expr (cexpr);
+ if (c->sched_kind != OMP_SCHED_NONE)
+ continue;
+ else
+ gfc_current_locus = old_loc;
+ }
+ if ((mask & OMP_CLAUSE_HOST_SELF)
+ && gfc_match ("self ( ") == MATCH_YES
+ && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
+ OMP_MAP_FORCE_FROM))
+ continue;
+ if ((mask & OMP_CLAUSE_SEQ)
+ && !c->seq
+ && gfc_match ("seq") == MATCH_YES)
+ {
+ c->seq = true;
+ needs_space = true;
continue;
}
- }
- if ((mask & OMP_CLAUSE_INBRANCH) && !c->inbranch && !c->notinbranch
- && gfc_match ("inbranch") == MATCH_YES)
- {
- c->inbranch = needs_space = true;
- continue;
- }
- if ((mask & OMP_CLAUSE_NOTINBRANCH) && !c->notinbranch && !c->inbranch
- && gfc_match ("notinbranch") == MATCH_YES)
- {
- c->notinbranch = needs_space = true;
- continue;
- }
- if ((mask & OMP_CLAUSE_PROC_BIND)
- && c->proc_bind == OMP_PROC_BIND_UNKNOWN)
- {
- if (gfc_match ("proc_bind ( master )") == MATCH_YES)
- c->proc_bind = OMP_PROC_BIND_MASTER;
- else if (gfc_match ("proc_bind ( spread )") == MATCH_YES)
- c->proc_bind = OMP_PROC_BIND_SPREAD;
- else if (gfc_match ("proc_bind ( close )") == MATCH_YES)
- c->proc_bind = OMP_PROC_BIND_CLOSE;
- if (c->proc_bind != OMP_PROC_BIND_UNKNOWN)
+ if ((mask & OMP_CLAUSE_SHARED)
+ && gfc_match_omp_variable_list ("shared (",
+ &c->lists[OMP_LIST_SHARED],
+ true) == MATCH_YES)
continue;
- }
- if ((mask & OMP_CLAUSE_SAFELEN) && c->safelen_expr == NULL
- && gfc_match ("safelen ( %e )", &c->safelen_expr) == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_SIMDLEN) && c->simdlen_expr == NULL
- && gfc_match ("simdlen ( %e )", &c->simdlen_expr) == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_UNIFORM)
- && gfc_match_omp_variable_list ("uniform (",
- &c->lists[OMP_LIST_UNIFORM], false)
- == MATCH_YES)
- continue;
- bool end_colon = false;
- gfc_omp_namelist **head = NULL;
- old_loc = gfc_current_locus;
- if ((mask & OMP_CLAUSE_ALIGNED)
- && gfc_match_omp_variable_list ("aligned (",
- &c->lists[OMP_LIST_ALIGNED], false,
- &end_colon, &head)
- == MATCH_YES)
- {
- gfc_expr *alignment = NULL;
- gfc_omp_namelist *n;
-
- if (end_colon
- && gfc_match (" %e )", &alignment) != MATCH_YES)
+ if ((mask & OMP_CLAUSE_SIMDLEN)
+ && c->simdlen_expr == NULL
+ && gfc_match ("simdlen ( %e )", &c->simdlen_expr) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_SIMD)
+ && !c->simd
+ && gfc_match ("simd") == MATCH_YES)
{
- gfc_free_omp_namelist (*head);
- gfc_current_locus = old_loc;
- *head = NULL;
- break;
+ c->simd = needs_space = true;
+ continue;
}
- for (n = *head; n; n = n->next)
- if (n->next && alignment)
- n->expr = gfc_copy_expr (alignment);
- else
- n->expr = alignment;
- continue;
- }
- end_colon = false;
- head = NULL;
- old_loc = gfc_current_locus;
- if ((mask & OMP_CLAUSE_LINEAR)
- && gfc_match_omp_variable_list ("linear (",
- &c->lists[OMP_LIST_LINEAR], false,
- &end_colon, &head)
- == MATCH_YES)
- {
- gfc_expr *step = NULL;
-
- if (end_colon
- && gfc_match (" %e )", &step) != MATCH_YES)
+ break;
+ case 't':
+ if ((mask & OMP_CLAUSE_THREAD_LIMIT)
+ && c->thread_limit == NULL
+ && gfc_match ("thread_limit ( %e )",
+ &c->thread_limit) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_THREADS)
+ && !c->threads
+ && gfc_match ("threads") == MATCH_YES)
{
- gfc_free_omp_namelist (*head);
- gfc_current_locus = old_loc;
- *head = NULL;
- break;
+ c->threads = needs_space = true;
+ continue;
}
- else if (!end_colon)
+ if ((mask & OMP_CLAUSE_TILE)
+ && !c->tile_list
+ && match_oacc_expr_list ("tile (", &c->tile_list,
+ true) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_TO) && (mask & OMP_CLAUSE_LINK))
{
- step = gfc_get_constant_expr (BT_INTEGER,
- gfc_default_integer_kind,
- &old_loc);
- mpz_set_si (step->value.integer, 1);
+ if (gfc_match_omp_to_link ("to (", &c->lists[OMP_LIST_TO])
+ == MATCH_YES)
+ continue;
}
- (*head)->expr = step;
- continue;
- }
- if ((mask & OMP_CLAUSE_DEPEND)
- && gfc_match ("depend ( ") == MATCH_YES)
- {
- match m = MATCH_YES;
- gfc_omp_depend_op depend_op = OMP_DEPEND_OUT;
- if (gfc_match ("inout") == MATCH_YES)
- depend_op = OMP_DEPEND_INOUT;
- else if (gfc_match ("in") == MATCH_YES)
- depend_op = OMP_DEPEND_IN;
- else if (gfc_match ("out") == MATCH_YES)
- depend_op = OMP_DEPEND_OUT;
- else
- m = MATCH_NO;
- head = NULL;
- if (m == MATCH_YES
- && gfc_match_omp_variable_list (" : ",
- &c->lists[OMP_LIST_DEPEND],
- false, NULL, &head, true)
- == MATCH_YES)
+ else if ((mask & OMP_CLAUSE_TO)
+ && gfc_match_omp_variable_list ("to (",
+ &c->lists[OMP_LIST_TO], false,
+ NULL, &head, true) == MATCH_YES)
+ continue;
+ break;
+ case 'u':
+ if ((mask & OMP_CLAUSE_UNIFORM)
+ && gfc_match_omp_variable_list ("uniform (",
+ &c->lists[OMP_LIST_UNIFORM],
+ false) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_UNTIED)
+ && !c->untied
+ && gfc_match ("untied") == MATCH_YES)
{
- gfc_omp_namelist *n;
- for (n = *head; n; n = n->next)
- n->u.depend_op = depend_op;
+ c->untied = needs_space = true;
continue;
}
- else
- gfc_current_locus = old_loc;
- }
- if ((mask & OMP_CLAUSE_DIST_SCHEDULE)
- && c->dist_sched_kind == OMP_SCHED_NONE
- && gfc_match ("dist_schedule ( static") == MATCH_YES)
- {
- match m = MATCH_NO;
- c->dist_sched_kind = OMP_SCHED_STATIC;
- m = gfc_match (" , %e )", &c->dist_chunk_size);
- if (m != MATCH_YES)
- m = gfc_match_char (')');
- if (m != MATCH_YES)
+ if ((mask & OMP_CLAUSE_USE_DEVICE)
+ && gfc_match_omp_variable_list ("use_device (",
+ &c->lists[OMP_LIST_USE_DEVICE],
+ true) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_USE_DEVICE_PTR)
+ && gfc_match_omp_variable_list
+ ("use_device_ptr (",
+ &c->lists[OMP_LIST_USE_DEVICE_PTR], false) == MATCH_YES)
+ continue;
+ break;
+ case 'v':
+ /* VECTOR_LENGTH must be matched before VECTOR, because the latter
+ doesn't unconditionally match '('. */
+ if ((mask & OMP_CLAUSE_VECTOR_LENGTH)
+ && c->vector_length_expr == NULL
+ && (gfc_match ("vector_length ( %e )", &c->vector_length_expr)
+ == MATCH_YES))
+ continue;
+ if ((mask & OMP_CLAUSE_VECTOR)
+ && !c->vector
+ && gfc_match ("vector") == MATCH_YES)
{
- c->dist_sched_kind = OMP_SCHED_NONE;
- gfc_current_locus = old_loc;
+ c->vector = true;
+ match m = match_oacc_clause_gwv (c, GOMP_DIM_VECTOR);
+ if (m == MATCH_ERROR)
+ {
+ gfc_current_locus = old_loc;
+ break;
+ }
+ if (m == MATCH_NO)
+ needs_space = true;
+ continue;
}
- else
- continue;
- }
- if ((mask & OMP_CLAUSE_NUM_TEAMS) && c->num_teams == NULL
- && gfc_match ("num_teams ( %e )", &c->num_teams) == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_DEVICE) && c->device == NULL
- && gfc_match ("device ( %e )", &c->device) == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_THREAD_LIMIT) && c->thread_limit == NULL
- && gfc_match ("thread_limit ( %e )", &c->thread_limit) == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_MAP)
- && gfc_match ("map ( ") == MATCH_YES)
- {
- gfc_omp_map_op map_op = OMP_MAP_TOFROM;
- if (gfc_match ("alloc : ") == MATCH_YES)
- map_op = OMP_MAP_ALLOC;
- else if (gfc_match ("tofrom : ") == MATCH_YES)
- map_op = OMP_MAP_TOFROM;
- else if (gfc_match ("to : ") == MATCH_YES)
- map_op = OMP_MAP_TO;
- else if (gfc_match ("from : ") == MATCH_YES)
- map_op = OMP_MAP_FROM;
- head = NULL;
- if (gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_MAP],
- false, NULL, &head, true)
- == MATCH_YES)
+ break;
+ case 'w':
+ if ((mask & OMP_CLAUSE_WAIT)
+ && !c->wait
+ && gfc_match ("wait") == MATCH_YES)
{
- gfc_omp_namelist *n;
- for (n = *head; n; n = n->next)
- n->u.map_op = map_op;
+ c->wait = true;
+ match m = match_oacc_expr_list (" (", &c->wait_list, false);
+ if (m == MATCH_ERROR)
+ {
+ gfc_current_locus = old_loc;
+ break;
+ }
+ else if (m == MATCH_NO)
+ needs_space = true;
continue;
}
- else
- gfc_current_locus = old_loc;
+ if ((mask & OMP_CLAUSE_WORKER)
+ && !c->worker
+ && gfc_match ("worker") == MATCH_YES)
+ {
+ c->worker = true;
+ match m = match_oacc_clause_gwv (c, GOMP_DIM_WORKER);
+ if (m == MATCH_ERROR)
+ {
+ gfc_current_locus = old_loc;
+ break;
+ }
+ else if (m == MATCH_NO)
+ needs_space = true;
+ continue;
+ }
+ break;
}
- if ((mask & OMP_CLAUSE_TO)
- && gfc_match_omp_variable_list ("to (",
- &c->lists[OMP_LIST_TO], false,
- NULL, &head, true)
- == MATCH_YES)
- continue;
- if ((mask & OMP_CLAUSE_FROM)
- && gfc_match_omp_variable_list ("from (",
- &c->lists[OMP_LIST_FROM], false,
- NULL, &head, true)
- == MATCH_YES)
- continue;
-
break;
}
@@ -1343,152 +1918,115 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, uint64_t mask,
#define OACC_PARALLEL_CLAUSES \
- (OMP_CLAUSE_IF | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \
+ (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \
| OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION \
- | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
+ | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
| OMP_CLAUSE_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_PRESENT_OR_COPY \
- | OMP_CLAUSE_PRESENT_OR_COPYIN | OMP_CLAUSE_PRESENT_OR_COPYOUT \
+ | OMP_CLAUSE_PRESENT_OR_COPYIN | OMP_CLAUSE_PRESENT_OR_COPYOUT \
| OMP_CLAUSE_PRESENT_OR_CREATE | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE \
| OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT)
#define OACC_KERNELS_CLAUSES \
- (OMP_CLAUSE_IF | OMP_CLAUSE_ASYNC | OMP_CLAUSE_DEVICEPTR \
- | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
+ (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_DEVICEPTR \
+ | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
| OMP_CLAUSE_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_PRESENT_OR_COPY \
- | OMP_CLAUSE_PRESENT_OR_COPYIN | OMP_CLAUSE_PRESENT_OR_COPYOUT \
+ | OMP_CLAUSE_PRESENT_OR_COPYIN | OMP_CLAUSE_PRESENT_OR_COPYOUT \
| OMP_CLAUSE_PRESENT_OR_CREATE | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT)
#define OACC_DATA_CLAUSES \
- (OMP_CLAUSE_IF | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY \
- | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE \
- | OMP_CLAUSE_PRESENT | OMP_CLAUSE_PRESENT_OR_COPY \
- | OMP_CLAUSE_PRESENT_OR_COPYIN | OMP_CLAUSE_PRESENT_OR_COPYOUT \
+ (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY \
+ | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE \
+ | OMP_CLAUSE_PRESENT | OMP_CLAUSE_PRESENT_OR_COPY \
+ | OMP_CLAUSE_PRESENT_OR_COPYIN | OMP_CLAUSE_PRESENT_OR_COPYOUT \
| OMP_CLAUSE_PRESENT_OR_CREATE)
#define OACC_LOOP_CLAUSES \
- (OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER \
- | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT \
- | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO \
+ (omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER \
+ | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT \
+ | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO \
| OMP_CLAUSE_TILE)
#define OACC_PARALLEL_LOOP_CLAUSES \
(OACC_LOOP_CLAUSES | OACC_PARALLEL_CLAUSES)
#define OACC_KERNELS_LOOP_CLAUSES \
(OACC_LOOP_CLAUSES | OACC_KERNELS_CLAUSES)
-#define OACC_HOST_DATA_CLAUSES OMP_CLAUSE_USE_DEVICE
+#define OACC_HOST_DATA_CLAUSES omp_mask (OMP_CLAUSE_USE_DEVICE)
#define OACC_DECLARE_CLAUSES \
- (OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
+ (omp_mask (OMP_CLAUSE_COPY) | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
| OMP_CLAUSE_CREATE | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_DEVICE_RESIDENT \
- | OMP_CLAUSE_PRESENT | OMP_CLAUSE_PRESENT_OR_COPY \
- | OMP_CLAUSE_PRESENT_OR_COPYIN | OMP_CLAUSE_PRESENT_OR_COPYOUT \
+ | OMP_CLAUSE_PRESENT | OMP_CLAUSE_PRESENT_OR_COPY \
+ | OMP_CLAUSE_PRESENT_OR_COPYIN | OMP_CLAUSE_PRESENT_OR_COPYOUT \
| OMP_CLAUSE_PRESENT_OR_CREATE | OMP_CLAUSE_LINK)
#define OACC_UPDATE_CLAUSES \
- (OMP_CLAUSE_IF | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST_SELF \
- | OMP_CLAUSE_OACC_DEVICE | OMP_CLAUSE_WAIT)
+ (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST_SELF \
+ | OMP_CLAUSE_DEVICE | OMP_CLAUSE_WAIT)
#define OACC_ENTER_DATA_CLAUSES \
- (OMP_CLAUSE_IF | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT | OMP_CLAUSE_COPYIN \
- | OMP_CLAUSE_CREATE | OMP_CLAUSE_PRESENT_OR_COPYIN \
+ (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \
+ | OMP_CLAUSE_COPYIN | OMP_CLAUSE_CREATE | OMP_CLAUSE_PRESENT_OR_COPYIN \
| OMP_CLAUSE_PRESENT_OR_CREATE)
#define OACC_EXIT_DATA_CLAUSES \
- (OMP_CLAUSE_IF | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT | OMP_CLAUSE_COPYOUT \
- | OMP_CLAUSE_DELETE)
+ (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \
+ | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_DELETE)
#define OACC_WAIT_CLAUSES \
- (OMP_CLAUSE_ASYNC)
+ omp_mask (OMP_CLAUSE_ASYNC)
#define OACC_ROUTINE_CLAUSES \
- (OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ)
+ (omp_mask (OMP_CLAUSE_GANG) | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR \
+ | OMP_CLAUSE_SEQ)
-match
-gfc_match_oacc_parallel_loop (void)
+static match
+match_acc (gfc_exec_op op, const omp_mask mask)
{
gfc_omp_clauses *c;
- if (gfc_match_omp_clauses (&c, OACC_PARALLEL_LOOP_CLAUSES, false, false,
- true) != MATCH_YES)
+ if (gfc_match_omp_clauses (&c, mask, false, false, true) != MATCH_YES)
return MATCH_ERROR;
-
- new_st.op = EXEC_OACC_PARALLEL_LOOP;
+ new_st.op = op;
new_st.ext.omp_clauses = c;
return MATCH_YES;
}
+match
+gfc_match_oacc_parallel_loop (void)
+{
+ return match_acc (EXEC_OACC_PARALLEL_LOOP, OACC_PARALLEL_LOOP_CLAUSES);
+}
+
match
gfc_match_oacc_parallel (void)
{
- gfc_omp_clauses *c;
- if (gfc_match_omp_clauses (&c, OACC_PARALLEL_CLAUSES, false, false, true)
- != MATCH_YES)
- return MATCH_ERROR;
-
- new_st.op = EXEC_OACC_PARALLEL;
- new_st.ext.omp_clauses = c;
- return MATCH_YES;
+ return match_acc (EXEC_OACC_PARALLEL, OACC_PARALLEL_CLAUSES);
}
match
gfc_match_oacc_kernels_loop (void)
{
- gfc_omp_clauses *c;
- if (gfc_match_omp_clauses (&c, OACC_KERNELS_LOOP_CLAUSES, false, false,
- true) != MATCH_YES)
- return MATCH_ERROR;
-
- new_st.op = EXEC_OACC_KERNELS_LOOP;
- new_st.ext.omp_clauses = c;
- return MATCH_YES;
+ return match_acc (EXEC_OACC_KERNELS_LOOP, OACC_KERNELS_LOOP_CLAUSES);
}
match
gfc_match_oacc_kernels (void)
{
- gfc_omp_clauses *c;
- if (gfc_match_omp_clauses (&c, OACC_KERNELS_CLAUSES, false, false, true)
- != MATCH_YES)
- return MATCH_ERROR;
-
- new_st.op = EXEC_OACC_KERNELS;
- new_st.ext.omp_clauses = c;
- return MATCH_YES;
+ return match_acc (EXEC_OACC_KERNELS, OACC_KERNELS_CLAUSES);
}
match
gfc_match_oacc_data (void)
{
- gfc_omp_clauses *c;
- if (gfc_match_omp_clauses (&c, OACC_DATA_CLAUSES, false, false, true)
- != MATCH_YES)
- return MATCH_ERROR;
-
- new_st.op = EXEC_OACC_DATA;
- new_st.ext.omp_clauses = c;
- return MATCH_YES;
+ return match_acc (EXEC_OACC_DATA, OACC_DATA_CLAUSES);
}
match
gfc_match_oacc_host_data (void)
{
- gfc_omp_clauses *c;
- if (gfc_match_omp_clauses (&c, OACC_HOST_DATA_CLAUSES, false, false, true)
- != MATCH_YES)
- return MATCH_ERROR;
-
- new_st.op = EXEC_OACC_HOST_DATA;
- new_st.ext.omp_clauses = c;
- return MATCH_YES;
+ return match_acc (EXEC_OACC_HOST_DATA, OACC_HOST_DATA_CLAUSES);
}
match
gfc_match_oacc_loop (void)
{
- gfc_omp_clauses *c;
- if (gfc_match_omp_clauses (&c, OACC_LOOP_CLAUSES, false, false, true)
- != MATCH_YES)
- return MATCH_ERROR;
-
- new_st.op = EXEC_OACC_LOOP;
- new_st.ext.omp_clauses = c;
- return MATCH_YES;
+ return match_acc (EXEC_OACC_LOOP, OACC_LOOP_CLAUSES);
}
@@ -1521,7 +2059,7 @@ gfc_match_oacc_declare (void)
if (n->u.map_op != OMP_MAP_FORCE_ALLOC
&& n->u.map_op != OMP_MAP_FORCE_TO)
{
- gfc_error ("Invalid clause in module with $!ACC DECLARE at %L",
+ gfc_error ("Invalid clause in module with !$ACC DECLARE at %L",
&where);
return MATCH_ERROR;
}
@@ -1531,7 +2069,7 @@ gfc_match_oacc_declare (void)
if (s->attr.use_assoc)
{
- gfc_error ("Variable is USE-associated with $!ACC DECLARE at %L",
+ gfc_error ("Variable is USE-associated with !$ACC DECLARE at %L",
&where);
return MATCH_ERROR;
}
@@ -1539,7 +2077,7 @@ gfc_match_oacc_declare (void)
if ((s->attr.dimension || s->attr.codimension)
&& s->attr.dummy && s->as->type != AS_EXPLICIT)
{
- gfc_error ("Assumed-size dummy array with $!ACC DECLARE at %L",
+ gfc_error ("Assumed-size dummy array with !$ACC DECLARE at %L",
&where);
return MATCH_ERROR;
}
@@ -1600,28 +2138,14 @@ gfc_match_oacc_update (void)
match
gfc_match_oacc_enter_data (void)
{
- gfc_omp_clauses *c;
- if (gfc_match_omp_clauses (&c, OACC_ENTER_DATA_CLAUSES, false, false, true)
- != MATCH_YES)
- return MATCH_ERROR;
-
- new_st.op = EXEC_OACC_ENTER_DATA;
- new_st.ext.omp_clauses = c;
- return MATCH_YES;
+ return match_acc (EXEC_OACC_ENTER_DATA, OACC_ENTER_DATA_CLAUSES);
}
match
gfc_match_oacc_exit_data (void)
{
- gfc_omp_clauses *c;
- if (gfc_match_omp_clauses (&c, OACC_EXIT_DATA_CLAUSES, false, false, true)
- != MATCH_YES)
- return MATCH_ERROR;
-
- new_st.op = EXEC_OACC_EXIT_DATA;
- new_st.ext.omp_clauses = c;
- return MATCH_YES;
+ return match_acc (EXEC_OACC_EXIT_DATA, OACC_EXIT_DATA_CLAUSES);
}
@@ -1648,7 +2172,7 @@ gfc_match_oacc_wait (void)
{
if (el->expr == NULL)
{
- gfc_error ("Invalid argument to $!ACC WAIT at %L",
+ gfc_error ("Invalid argument to !$ACC WAIT at %L",
&wait_list->expr->where);
return MATCH_ERROR;
}
@@ -1839,44 +2363,71 @@ cleanup:
#define OMP_PARALLEL_CLAUSES \
- (OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED \
- | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF \
- | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND)
+ (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
+ | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION \
+ | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT \
+ | OMP_CLAUSE_PROC_BIND)
#define OMP_DECLARE_SIMD_CLAUSES \
- (OMP_CLAUSE_SIMDLEN | OMP_CLAUSE_LINEAR | OMP_CLAUSE_UNIFORM \
- | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_INBRANCH | OMP_CLAUSE_NOTINBRANCH)
+ (omp_mask (OMP_CLAUSE_SIMDLEN) | OMP_CLAUSE_LINEAR \
+ | OMP_CLAUSE_UNIFORM | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_INBRANCH \
+ | OMP_CLAUSE_NOTINBRANCH)
#define OMP_DO_CLAUSES \
- (OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
+ (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
| OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
- | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE)
+ | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE \
+ | OMP_CLAUSE_LINEAR)
#define OMP_SECTIONS_CLAUSES \
- (OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
+ (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
| OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
#define OMP_SIMD_CLAUSES \
- (OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
- | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN | OMP_CLAUSE_LINEAR \
- | OMP_CLAUSE_ALIGNED)
+ (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE \
+ | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN \
+ | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN)
#define OMP_TASK_CLAUSES \
- (OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED \
- | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED \
- | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_DEPEND)
+ (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
+ | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT \
+ | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE \
+ | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY)
+#define OMP_TASKLOOP_CLAUSES \
+ (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
+ | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF \
+ | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL \
+ | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE \
+ | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP)
#define OMP_TARGET_CLAUSES \
- (OMP_CLAUSE_DEVICE | OMP_CLAUSE_MAP | OMP_CLAUSE_IF)
+ (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
+ | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE \
+ | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP \
+ | OMP_CLAUSE_IS_DEVICE_PTR)
#define OMP_TARGET_DATA_CLAUSES \
- (OMP_CLAUSE_DEVICE | OMP_CLAUSE_MAP | OMP_CLAUSE_IF)
+ (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
+ | OMP_CLAUSE_USE_DEVICE_PTR)
+#define OMP_TARGET_ENTER_DATA_CLAUSES \
+ (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
+ | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
+#define OMP_TARGET_EXIT_DATA_CLAUSES \
+ (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
+ | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
#define OMP_TARGET_UPDATE_CLAUSES \
- (OMP_CLAUSE_DEVICE | OMP_CLAUSE_IF | OMP_CLAUSE_TO | OMP_CLAUSE_FROM)
+ (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_TO \
+ | OMP_CLAUSE_FROM | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
#define OMP_TEAMS_CLAUSES \
- (OMP_CLAUSE_NUM_TEAMS | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_DEFAULT \
- | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED \
- | OMP_CLAUSE_REDUCTION)
+ (omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT \
+ | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
+ | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION)
#define OMP_DISTRIBUTE_CLAUSES \
- (OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_COLLAPSE \
- | OMP_CLAUSE_DIST_SCHEDULE)
+ (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
+ | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE)
+#define OMP_SINGLE_CLAUSES \
+ (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE)
+#define OMP_ORDERED_CLAUSES \
+ (omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD)
+#define OMP_DECLARE_TARGET_CLAUSES \
+ (omp_mask (OMP_CLAUSE_TO) | OMP_CLAUSE_LINK)
static match
-match_omp (gfc_exec_op op, unsigned int mask)
+match_omp (gfc_exec_op op, const omp_mask mask)
{
gfc_omp_clauses *c;
if (gfc_match_omp_clauses (&c, mask) != MATCH_YES)
@@ -1891,6 +2442,32 @@ match
gfc_match_omp_critical (void)
{
char n[GFC_MAX_SYMBOL_LEN+1];
+ gfc_omp_clauses *c = NULL;
+
+ if (gfc_match (" ( %n )", n) != MATCH_YES)
+ {
+ n[0] = '\0';
+ if (gfc_match_omp_eos () != MATCH_YES)
+ {
+ gfc_error ("Unexpected junk after $OMP CRITICAL statement at %C");
+ return MATCH_ERROR;
+ }
+ }
+ else if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_HINT)) != MATCH_YES)
+ return MATCH_ERROR;
+
+ new_st.op = EXEC_OMP_CRITICAL;
+ new_st.ext.omp_clauses = c;
+ if (n[0])
+ c->critical_name = xstrdup (n);
+ return MATCH_YES;
+}
+
+
+match
+gfc_match_omp_end_critical (void)
+{
+ char n[GFC_MAX_SYMBOL_LEN+1];
if (gfc_match (" ( %n )", n) != MATCH_YES)
n[0] = '\0';
@@ -1899,7 +2476,8 @@ gfc_match_omp_critical (void)
gfc_error ("Unexpected junk after $OMP CRITICAL statement at %C");
return MATCH_ERROR;
}
- new_st.op = EXEC_OMP_CRITICAL;
+
+ new_st.op = EXEC_OMP_END_CRITICAL;
new_st.ext.omp_name = n[0] ? xstrdup (n) : NULL;
return MATCH_YES;
}
@@ -1916,8 +2494,10 @@ match
gfc_match_omp_distribute_parallel_do (void)
{
return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO,
- OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
- | OMP_DO_CLAUSES);
+ (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
+ | OMP_DO_CLAUSES)
+ & ~(omp_mask (OMP_CLAUSE_ORDERED))
+ & ~(omp_mask (OMP_CLAUSE_LINEAR)));
}
@@ -1927,7 +2507,7 @@ gfc_match_omp_distribute_parallel_do_simd (void)
return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD,
(OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
| OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
- & ~OMP_CLAUSE_ORDERED);
+ & ~(omp_mask (OMP_CLAUSE_ORDERED)));
}
@@ -1949,8 +2529,7 @@ gfc_match_omp_do (void)
match
gfc_match_omp_do_simd (void)
{
- return match_omp (EXEC_OMP_DO_SIMD, ((OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
- & ~OMP_CLAUSE_ORDERED));
+ return match_omp (EXEC_OMP_DO_SIMD, OMP_DO_CLAUSES | OMP_SIMD_CLAUSES);
}
@@ -1978,14 +2557,25 @@ gfc_match_omp_declare_simd (void)
gfc_symbol *proc_name;
gfc_omp_clauses *c;
gfc_omp_declare_simd *ods;
+ bool needs_space = false;
- if (gfc_match (" ( %s ) ", &proc_name) != MATCH_YES)
- return MATCH_ERROR;
+ switch (gfc_match (" ( %s ) ", &proc_name))
+ {
+ case MATCH_YES: break;
+ case MATCH_NO: proc_name = NULL; needs_space = true; break;
+ case MATCH_ERROR: return MATCH_ERROR;
+ }
if (gfc_match_omp_clauses (&c, OMP_DECLARE_SIMD_CLAUSES, true,
- false) != MATCH_YES)
+ needs_space) != MATCH_YES)
return MATCH_ERROR;
+ if (gfc_current_ns->is_block_data)
+ {
+ gfc_free_omp_clauses (c);
+ return MATCH_YES;
+ }
+
ods = gfc_get_omp_declare_simd ();
ods->where = where;
ods->proc_name = proc_name;
@@ -2268,7 +2858,7 @@ gfc_match_omp_declare_reduction (void)
const char *predef_name = NULL;
omp_udr = gfc_get_omp_udr ();
- omp_udr->name = gfc_get_string (name);
+ omp_udr->name = gfc_get_string ("%s", name);
omp_udr->rop = rop;
omp_udr->ts = tss[i];
omp_udr->where = where;
@@ -2391,26 +2981,15 @@ match
gfc_match_omp_declare_target (void)
{
locus old_loc;
- char n[GFC_MAX_SYMBOL_LEN+1];
- gfc_symbol *sym;
match m;
- gfc_symtree *st;
+ gfc_omp_clauses *c = NULL;
+ int list;
+ gfc_omp_namelist *n;
+ gfc_symbol *s;
old_loc = gfc_current_locus;
- m = gfc_match (" (");
-
if (gfc_current_ns->proc_name
- && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY
- && m == MATCH_YES)
- {
- gfc_error ("Only the !$OMP DECLARE TARGET form without "
- "list is allowed in interface block at %C");
- goto cleanup;
- }
-
- if (m == MATCH_NO
- && gfc_current_ns->proc_name
&& gfc_match_omp_eos () == MATCH_YES)
{
if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
@@ -2420,58 +2999,111 @@ gfc_match_omp_declare_target (void)
return MATCH_YES;
}
- if (m != MATCH_YES)
- return m;
+ if (gfc_current_ns->proc_name
+ && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY)
+ {
+ gfc_error ("Only the !$OMP DECLARE TARGET form without "
+ "clauses is allowed in interface block at %C");
+ goto cleanup;
+ }
- for (;;)
+ m = gfc_match (" (");
+ if (m == MATCH_YES)
{
- m = gfc_match_symbol (&sym, 0);
- switch (m)
+ c = gfc_get_omp_clauses ();
+ gfc_current_locus = old_loc;
+ m = gfc_match_omp_to_link (" (", &c->lists[OMP_LIST_TO]);
+ if (m != MATCH_YES)
+ goto syntax;
+ if (gfc_match_omp_eos () != MATCH_YES)
{
- case MATCH_YES:
- if (sym->attr.in_common)
- gfc_error_now ("OMP DECLARE TARGET on a variable at %C is an "
- "element of a COMMON block");
- else if (!gfc_add_omp_declare_target (&sym->attr, sym->name,
- &sym->declared_at))
- goto cleanup;
- goto next_item;
- case MATCH_NO:
- break;
- case MATCH_ERROR:
+ gfc_error ("Unexpected junk after !$OMP DECLARE TARGET at %C");
goto cleanup;
}
+ }
+ else if (gfc_match_omp_clauses (&c, OMP_DECLARE_TARGET_CLAUSES) != MATCH_YES)
+ return MATCH_ERROR;
- m = gfc_match (" / %n /", n);
- if (m == MATCH_ERROR)
- goto cleanup;
- if (m == MATCH_NO || n[0] == '\0')
- goto syntax;
+ gfc_buffer_error (false);
- st = gfc_find_symtree (gfc_current_ns->common_root, n);
- if (st == NULL)
+ for (list = OMP_LIST_TO; list != OMP_LIST_NUM;
+ list = (list == OMP_LIST_TO ? OMP_LIST_LINK : OMP_LIST_NUM))
+ for (n = c->lists[list]; n; n = n->next)
+ if (n->sym)
+ n->sym->mark = 0;
+ else if (n->u.common->head)
+ n->u.common->head->mark = 0;
+
+ for (list = OMP_LIST_TO; list != OMP_LIST_NUM;
+ list = (list == OMP_LIST_TO ? OMP_LIST_LINK : OMP_LIST_NUM))
+ for (n = c->lists[list]; n; n = n->next)
+ if (n->sym)
{
- gfc_error ("COMMON block /%s/ not found at %C", n);
- goto cleanup;
+ if (n->sym->attr.in_common)
+ gfc_error_now ("OMP DECLARE TARGET variable at %L is an "
+ "element of a COMMON block", &n->where);
+ else if (n->sym->attr.omp_declare_target
+ && n->sym->attr.omp_declare_target_link
+ && list != OMP_LIST_LINK)
+ gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
+ "mentioned in LINK clause and later in TO clause",
+ &n->where);
+ else if (n->sym->attr.omp_declare_target
+ && !n->sym->attr.omp_declare_target_link
+ && list == OMP_LIST_LINK)
+ gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
+ "mentioned in TO clause and later in LINK clause",
+ &n->where);
+ else if (n->sym->mark)
+ gfc_error_now ("Variable at %L mentioned multiple times in "
+ "clauses of the same OMP DECLARE TARGET directive",
+ &n->where);
+ else if (gfc_add_omp_declare_target (&n->sym->attr, n->sym->name,
+ &n->sym->declared_at))
+ {
+ if (list == OMP_LIST_LINK)
+ gfc_add_omp_declare_target_link (&n->sym->attr, n->sym->name,
+ &n->sym->declared_at);
+ }
+ n->sym->mark = 1;
+ }
+ else if (n->u.common->omp_declare_target
+ && n->u.common->omp_declare_target_link
+ && list != OMP_LIST_LINK)
+ gfc_error_now ("OMP DECLARE TARGET COMMON at %L previously "
+ "mentioned in LINK clause and later in TO clause",
+ &n->where);
+ else if (n->u.common->omp_declare_target
+ && !n->u.common->omp_declare_target_link
+ && list == OMP_LIST_LINK)
+ gfc_error_now ("OMP DECLARE TARGET COMMON at %L previously "
+ "mentioned in TO clause and later in LINK clause",
+ &n->where);
+ else if (n->u.common->head && n->u.common->head->mark)
+ gfc_error_now ("COMMON at %L mentioned multiple times in "
+ "clauses of the same OMP DECLARE TARGET directive",
+ &n->where);
+ else
+ {
+ n->u.common->omp_declare_target = 1;
+ n->u.common->omp_declare_target_link = (list == OMP_LIST_LINK);
+ for (s = n->u.common->head; s; s = s->common_next)
+ {
+ s->mark = 1;
+ if (gfc_add_omp_declare_target (&s->attr, s->name,
+ &s->declared_at))
+ {
+ if (list == OMP_LIST_LINK)
+ gfc_add_omp_declare_target_link (&s->attr, s->name,
+ &s->declared_at);
+ }
+ }
}
- st->n.common->omp_declare_target = 1;
- for (sym = st->n.common->head; sym; sym = sym->common_next)
- if (!gfc_add_omp_declare_target (&sym->attr, sym->name,
- &sym->declared_at))
- goto cleanup;
- next_item:
- if (gfc_match_char (')') == MATCH_YES)
- break;
- if (gfc_match_char (',') != MATCH_YES)
- goto syntax;
- }
+ gfc_buffer_error (true);
- if (gfc_match_omp_eos () != MATCH_YES)
- {
- gfc_error ("Unexpected junk after !$OMP DECLARE TARGET at %C");
- goto cleanup;
- }
+ if (c)
+ gfc_free_omp_clauses (c);
return MATCH_YES;
syntax:
@@ -2479,6 +3111,8 @@ syntax:
cleanup:
gfc_current_locus = old_loc;
+ if (c)
+ gfc_free_omp_clauses (c);
return MATCH_ERROR;
}
@@ -2576,8 +3210,7 @@ match
gfc_match_omp_parallel_do_simd (void)
{
return match_omp (EXEC_OMP_PARALLEL_DO_SIMD,
- (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
- & ~OMP_CLAUSE_ORDERED);
+ OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES);
}
@@ -2613,57 +3246,70 @@ gfc_match_omp_simd (void)
match
gfc_match_omp_single (void)
{
- return match_omp (EXEC_OMP_SINGLE,
- OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE);
+ return match_omp (EXEC_OMP_SINGLE, OMP_SINGLE_CLAUSES);
}
match
-gfc_match_omp_task (void)
+gfc_match_omp_target (void)
{
- return match_omp (EXEC_OMP_TASK, OMP_TASK_CLAUSES);
+ return match_omp (EXEC_OMP_TARGET, OMP_TARGET_CLAUSES);
}
match
-gfc_match_omp_taskwait (void)
+gfc_match_omp_target_data (void)
{
- if (gfc_match_omp_eos () != MATCH_YES)
- {
- gfc_error ("Unexpected junk after TASKWAIT clause at %C");
- return MATCH_ERROR;
- }
- new_st.op = EXEC_OMP_TASKWAIT;
- new_st.ext.omp_clauses = NULL;
- return MATCH_YES;
+ return match_omp (EXEC_OMP_TARGET_DATA, OMP_TARGET_DATA_CLAUSES);
}
match
-gfc_match_omp_taskyield (void)
+gfc_match_omp_target_enter_data (void)
{
- if (gfc_match_omp_eos () != MATCH_YES)
- {
- gfc_error ("Unexpected junk after TASKYIELD clause at %C");
- return MATCH_ERROR;
- }
- new_st.op = EXEC_OMP_TASKYIELD;
- new_st.ext.omp_clauses = NULL;
- return MATCH_YES;
+ return match_omp (EXEC_OMP_TARGET_ENTER_DATA, OMP_TARGET_ENTER_DATA_CLAUSES);
}
match
-gfc_match_omp_target (void)
+gfc_match_omp_target_exit_data (void)
{
- return match_omp (EXEC_OMP_TARGET, OMP_TARGET_CLAUSES);
+ return match_omp (EXEC_OMP_TARGET_EXIT_DATA, OMP_TARGET_EXIT_DATA_CLAUSES);
}
match
-gfc_match_omp_target_data (void)
+gfc_match_omp_target_parallel (void)
{
- return match_omp (EXEC_OMP_TARGET_DATA, OMP_TARGET_DATA_CLAUSES);
+ return match_omp (EXEC_OMP_TARGET_PARALLEL,
+ (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES)
+ & ~(omp_mask (OMP_CLAUSE_COPYIN)));
+}
+
+
+match
+gfc_match_omp_target_parallel_do (void)
+{
+ return match_omp (EXEC_OMP_TARGET_PARALLEL_DO,
+ (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
+ | OMP_DO_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
+}
+
+
+match
+gfc_match_omp_target_parallel_do_simd (void)
+{
+ return match_omp (EXEC_OMP_TARGET_PARALLEL_DO_SIMD,
+ (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
+ | OMP_SIMD_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
+}
+
+
+match
+gfc_match_omp_target_simd (void)
+{
+ return match_omp (EXEC_OMP_TARGET_SIMD,
+ OMP_TARGET_CLAUSES | OMP_SIMD_CLAUSES);
}
@@ -2688,9 +3334,11 @@ match
gfc_match_omp_target_teams_distribute_parallel_do (void)
{
return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
- OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
- | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
- | OMP_DO_CLAUSES);
+ (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
+ | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
+ | OMP_DO_CLAUSES)
+ & ~(omp_mask (OMP_CLAUSE_ORDERED))
+ & ~(omp_mask (OMP_CLAUSE_LINEAR)));
}
@@ -2701,7 +3349,7 @@ gfc_match_omp_target_teams_distribute_parallel_do_simd (void)
(OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
| OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
| OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
- & ~OMP_CLAUSE_ORDERED);
+ & ~(omp_mask (OMP_CLAUSE_ORDERED)));
}
@@ -2722,6 +3370,57 @@ gfc_match_omp_target_update (void)
match
+gfc_match_omp_task (void)
+{
+ return match_omp (EXEC_OMP_TASK, OMP_TASK_CLAUSES);
+}
+
+
+match
+gfc_match_omp_taskloop (void)
+{
+ return match_omp (EXEC_OMP_TASKLOOP, OMP_TASKLOOP_CLAUSES);
+}
+
+
+match
+gfc_match_omp_taskloop_simd (void)
+{
+ return match_omp (EXEC_OMP_TASKLOOP_SIMD,
+ (OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES)
+ & ~(omp_mask (OMP_CLAUSE_REDUCTION)));
+}
+
+
+match
+gfc_match_omp_taskwait (void)
+{
+ if (gfc_match_omp_eos () != MATCH_YES)
+ {
+ gfc_error ("Unexpected junk after TASKWAIT clause at %C");
+ return MATCH_ERROR;
+ }
+ new_st.op = EXEC_OMP_TASKWAIT;
+ new_st.ext.omp_clauses = NULL;
+ return MATCH_YES;
+}
+
+
+match
+gfc_match_omp_taskyield (void)
+{
+ if (gfc_match_omp_eos () != MATCH_YES)
+ {
+ gfc_error ("Unexpected junk after TASKYIELD clause at %C");
+ return MATCH_ERROR;
+ }
+ new_st.op = EXEC_OMP_TASKYIELD;
+ new_st.ext.omp_clauses = NULL;
+ return MATCH_YES;
+}
+
+
+match
gfc_match_omp_teams (void)
{
return match_omp (EXEC_OMP_TEAMS, OMP_TEAMS_CLAUSES);
@@ -2740,8 +3439,10 @@ match
gfc_match_omp_teams_distribute_parallel_do (void)
{
return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO,
- OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
- | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES);
+ (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
+ | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
+ & ~(omp_mask (OMP_CLAUSE_ORDERED))
+ & ~(omp_mask (OMP_CLAUSE_LINEAR)));
}
@@ -2751,7 +3452,7 @@ gfc_match_omp_teams_distribute_parallel_do_simd (void)
return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
(OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
| OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
- | OMP_SIMD_CLAUSES) & ~OMP_CLAUSE_ORDERED);
+ | OMP_SIMD_CLAUSES) & ~(omp_mask (OMP_CLAUSE_ORDERED)));
}
@@ -2795,14 +3496,14 @@ gfc_match_omp_master (void)
match
gfc_match_omp_ordered (void)
{
- if (gfc_match_omp_eos () != MATCH_YES)
- {
- gfc_error ("Unexpected junk after $OMP ORDERED statement at %C");
- return MATCH_ERROR;
- }
- new_st.op = EXEC_OMP_ORDERED;
- new_st.ext.omp_clauses = NULL;
- return MATCH_YES;
+ return match_omp (EXEC_OMP_ORDERED, OMP_ORDERED_CLAUSES);
+}
+
+
+match
+gfc_match_omp_ordered_depend (void)
+{
+ return match_omp (EXEC_OMP_ORDERED, omp_mask (OMP_CLAUSE_DEPEND));
}
@@ -2915,7 +3616,7 @@ gfc_match_omp_cancel (void)
enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
if (kind == OMP_CANCEL_UNKNOWN)
return MATCH_ERROR;
- if (gfc_match_omp_clauses (&c, OMP_CLAUSE_IF, false) != MATCH_YES)
+ if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_IF), false) != MATCH_YES)
return MATCH_ERROR;
c->cancel = kind;
new_st.op = EXEC_OMP_CANCEL;
@@ -2972,7 +3673,8 @@ gfc_match_omp_end_single (void)
new_st.ext.omp_bool = true;
return MATCH_YES;
}
- if (gfc_match_omp_clauses (&c, OMP_CLAUSE_COPYPRIVATE) != MATCH_YES)
+ if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_COPYPRIVATE))
+ != MATCH_YES)
return MATCH_ERROR;
new_st.op = EXEC_OMP_END_SINGLE;
new_st.ext.omp_clauses = c;
@@ -2989,23 +3691,35 @@ oacc_is_loop (gfc_code *code)
}
static void
-resolve_oacc_scalar_int_expr (gfc_expr *expr, const char *clause)
+resolve_scalar_int_expr (gfc_expr *expr, const char *clause)
{
if (!gfc_resolve_expr (expr)
- || expr->ts.type != BT_INTEGER || expr->rank != 0)
+ || expr->ts.type != BT_INTEGER
+ || expr->rank != 0)
gfc_error ("%s clause at %L requires a scalar INTEGER expression",
- clause, &expr->where);
+ clause, &expr->where);
}
-
static void
-resolve_oacc_positive_int_expr (gfc_expr *expr, const char *clause)
+resolve_positive_int_expr (gfc_expr *expr, const char *clause)
{
- resolve_oacc_scalar_int_expr (expr, clause);
- if (expr->expr_type == EXPR_CONSTANT && expr->ts.type == BT_INTEGER
- && mpz_sgn(expr->value.integer) <= 0)
+ resolve_scalar_int_expr (expr, clause);
+ if (expr->expr_type == EXPR_CONSTANT
+ && expr->ts.type == BT_INTEGER
+ && mpz_sgn (expr->value.integer) <= 0)
gfc_warning (0, "INTEGER expression of %s clause at %L must be positive",
- clause, &expr->where);
+ clause, &expr->where);
+}
+
+static void
+resolve_nonnegative_int_expr (gfc_expr *expr, const char *clause)
+{
+ resolve_scalar_int_expr (expr, clause);
+ if (expr->expr_type == EXPR_CONSTANT
+ && expr->ts.type == BT_INTEGER
+ && mpz_sgn (expr->value.integer) < 0)
+ gfc_warning (0, "INTEGER expression of %s clause at %L must be "
+ "non-negative", clause, &expr->where);
}
/* Emits error when symbol is pointer, cray pointer or cray pointee
@@ -3018,10 +3732,10 @@ check_symbol_not_pointer (gfc_symbol *sym, locus loc, const char *name)
gfc_error ("POINTER object %qs of derived type in %s clause at %L",
sym->name, name, &loc);
if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointer)
- gfc_error ("Cray pointer object of derived type %qs in %s clause at %L",
+ gfc_error ("Cray pointer object %qs of derived type in %s clause at %L",
sym->name, name, &loc);
if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointee)
- gfc_error ("Cray pointee object of derived type %qs in %s clause at %L",
+ gfc_error ("Cray pointee object %qs of derived type in %s clause at %L",
sym->name, name, &loc);
if ((sym->ts.type == BT_ASSUMED && sym->attr.pointer)
@@ -3032,12 +3746,12 @@ check_symbol_not_pointer (gfc_symbol *sym, locus loc, const char *name)
if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointer)
|| (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
&& CLASS_DATA (sym)->attr.cray_pointer))
- gfc_error ("Cray pointer object of polymorphic type %qs in %s clause at %L",
+ gfc_error ("Cray pointer object %qs of polymorphic type in %s clause at %L",
sym->name, name, &loc);
if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointee)
|| (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
&& CLASS_DATA (sym)->attr.cray_pointee))
- gfc_error ("Cray pointee object of polymorphic type %qs in %s clause at %L",
+ gfc_error ("Cray pointee object %qs of polymorphic type in %s clause at %L",
sym->name, name, &loc);
}
@@ -3141,7 +3855,7 @@ resolve_omp_udr_callback2 (gfc_expr **e, int *, void *)
if (!sym->attr.intrinsic
&& sym->attr.if_source == IFSRC_UNKNOWN)
gfc_error ("Implicitly declared function %s used in "
- "!$OMP DECLARE REDUCTION at %L ", sym->name, &(*e)->where);
+ "!$OMP DECLARE REDUCTION at %L", sym->name, &(*e)->where);
}
return 0;
}
@@ -3190,7 +3904,7 @@ resolve_omp_udr_clause (gfc_omp_namelist *n, gfc_namespace *ns,
&& !sym->attr.intrinsic
&& sym->attr.if_source == IFSRC_UNKNOWN)
gfc_error ("Implicitly declared subroutine %s used in "
- "!$OMP DECLARE REDUCTION at %L ", sym->name,
+ "!$OMP DECLARE REDUCTION at %L", sym->name,
&copy->loc);
}
gfc_code_walker (&copy, gfc_dummy_code_callback,
@@ -3209,15 +3923,22 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
gfc_omp_namelist *n;
gfc_expr_list *el;
int list;
+ int ifc;
+ bool if_without_mod = false;
+ gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
static const char *clause_names[]
= { "PRIVATE", "FIRSTPRIVATE", "LASTPRIVATE", "COPYPRIVATE", "SHARED",
"COPYIN", "UNIFORM", "ALIGNED", "LINEAR", "DEPEND", "MAP",
"TO", "FROM", "REDUCTION", "DEVICE_RESIDENT", "LINK", "USE_DEVICE",
- "CACHE" };
+ "CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR" };
if (omp_clauses == NULL)
return;
+ if (omp_clauses->orderedc && omp_clauses->orderedc < omp_clauses->collapse)
+ gfc_error ("ORDERED clause parameter is less than COLLAPSE at %L",
+ &code->loc);
+
if (omp_clauses->if_expr)
{
gfc_expr *expr = omp_clauses->if_expr;
@@ -3225,7 +3946,101 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
|| expr->ts.type != BT_LOGICAL || expr->rank != 0)
gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
&expr->where);
+ if_without_mod = true;
}
+ for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
+ if (omp_clauses->if_exprs[ifc])
+ {
+ gfc_expr *expr = omp_clauses->if_exprs[ifc];
+ bool ok = true;
+ if (!gfc_resolve_expr (expr)
+ || expr->ts.type != BT_LOGICAL || expr->rank != 0)
+ gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
+ &expr->where);
+ else if (if_without_mod)
+ {
+ gfc_error ("IF clause without modifier at %L used together with "
+ "IF clauses with modifiers",
+ &omp_clauses->if_expr->where);
+ if_without_mod = false;
+ }
+ else
+ switch (code->op)
+ {
+ case EXEC_OMP_PARALLEL:
+ case EXEC_OMP_PARALLEL_DO:
+ case EXEC_OMP_PARALLEL_SECTIONS:
+ case EXEC_OMP_PARALLEL_WORKSHARE:
+ case EXEC_OMP_PARALLEL_DO_SIMD:
+ case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
+ case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
+ case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
+ case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+ ok = ifc == OMP_IF_PARALLEL;
+ break;
+
+ case EXEC_OMP_TASK:
+ ok = ifc == OMP_IF_TASK;
+ break;
+
+ case EXEC_OMP_TASKLOOP:
+ case EXEC_OMP_TASKLOOP_SIMD:
+ ok = ifc == OMP_IF_TASKLOOP;
+ break;
+
+ case EXEC_OMP_TARGET:
+ case EXEC_OMP_TARGET_TEAMS:
+ case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
+ case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
+ case EXEC_OMP_TARGET_SIMD:
+ ok = ifc == OMP_IF_TARGET;
+ break;
+
+ case EXEC_OMP_TARGET_DATA:
+ ok = ifc == OMP_IF_TARGET_DATA;
+ break;
+
+ case EXEC_OMP_TARGET_UPDATE:
+ ok = ifc == OMP_IF_TARGET_UPDATE;
+ break;
+
+ case EXEC_OMP_TARGET_ENTER_DATA:
+ ok = ifc == OMP_IF_TARGET_ENTER_DATA;
+ break;
+
+ case EXEC_OMP_TARGET_EXIT_DATA:
+ ok = ifc == OMP_IF_TARGET_EXIT_DATA;
+ break;
+
+ case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
+ case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+ case EXEC_OMP_TARGET_PARALLEL:
+ case EXEC_OMP_TARGET_PARALLEL_DO:
+ case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
+ ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_PARALLEL;
+ break;
+
+ default:
+ ok = false;
+ break;
+ }
+ if (!ok)
+ {
+ static const char *ifs[] = {
+ "PARALLEL",
+ "TASK",
+ "TASKLOOP",
+ "TARGET",
+ "TARGET DATA",
+ "TARGET UPDATE",
+ "TARGET ENTER DATA",
+ "TARGET EXIT DATA"
+ };
+ gfc_error ("IF clause modifier %s at %L not appropriate for "
+ "the current OpenMP construct", ifs[ifc], &expr->where);
+ }
+ }
+
if (omp_clauses->final_expr)
{
gfc_expr *expr = omp_clauses->final_expr;
@@ -3235,13 +4050,7 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
&expr->where);
}
if (omp_clauses->num_threads)
- {
- gfc_expr *expr = omp_clauses->num_threads;
- if (!gfc_resolve_expr (expr)
- || expr->ts.type != BT_INTEGER || expr->rank != 0)
- gfc_error ("NUM_THREADS clause at %L requires a scalar "
- "INTEGER expression", &expr->where);
- }
+ resolve_positive_int_expr (omp_clauses->num_threads, "NUM_THREADS");
if (omp_clauses->chunk_size)
{
gfc_expr *expr = omp_clauses->chunk_size;
@@ -3249,6 +4058,11 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
|| expr->ts.type != BT_INTEGER || expr->rank != 0)
gfc_error ("SCHEDULE clause's chunk_size at %L requires "
"a scalar INTEGER expression", &expr->where);
+ else if (expr->expr_type == EXPR_CONSTANT
+ && expr->ts.type == BT_INTEGER
+ && mpz_sgn (expr->value.integer) <= 0)
+ gfc_warning (0, "INTEGER expression of SCHEDULE clause's chunk_size "
+ "at %L must be positive", &expr->where);
}
/* Check that no symbol appears on multiple clauses, except that
@@ -3474,6 +4288,36 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
case OMP_LIST_CACHE:
for (; n != NULL; n = n->next)
{
+ if (list == OMP_LIST_DEPEND)
+ {
+ if (n->u.depend_op == OMP_DEPEND_SINK_FIRST
+ || n->u.depend_op == OMP_DEPEND_SINK)
+ {
+ if (code->op != EXEC_OMP_ORDERED)
+ gfc_error ("SINK dependence type only allowed "
+ "on ORDERED directive at %L", &n->where);
+ else if (omp_clauses->depend_source)
+ {
+ gfc_error ("DEPEND SINK used together with "
+ "DEPEND SOURCE on the same construct "
+ "at %L", &n->where);
+ omp_clauses->depend_source = false;
+ }
+ else if (n->expr)
+ {
+ if (!gfc_resolve_expr (n->expr)
+ || n->expr->ts.type != BT_INTEGER
+ || n->expr->rank != 0)
+ gfc_error ("SINK addend not a constant integer "
+ "at %L", &n->where);
+ }
+ continue;
+ }
+ else if (code->op == EXEC_OMP_ORDERED)
+ gfc_error ("Only SOURCE or SINK dependence types "
+ "are allowed on ORDERED directive at %L",
+ &n->where);
+ }
if (n->expr)
{
if (!gfc_resolve_expr (n->expr)
@@ -3530,6 +4374,67 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
else
resolve_oacc_data_clauses (n->sym, n->where, name);
}
+ else if (list != OMP_CLAUSE_DEPEND
+ && n->sym->as
+ && n->sym->as->type == AS_ASSUMED_SIZE)
+ gfc_error ("Assumed size array %qs in %s clause at %L",
+ n->sym->name, name, &n->where);
+ if (list == OMP_LIST_MAP && !openacc)
+ switch (code->op)
+ {
+ case EXEC_OMP_TARGET:
+ case EXEC_OMP_TARGET_DATA:
+ switch (n->u.map_op)
+ {
+ case OMP_MAP_TO:
+ case OMP_MAP_ALWAYS_TO:
+ case OMP_MAP_FROM:
+ case OMP_MAP_ALWAYS_FROM:
+ case OMP_MAP_TOFROM:
+ case OMP_MAP_ALWAYS_TOFROM:
+ case OMP_MAP_ALLOC:
+ break;
+ default:
+ gfc_error ("TARGET%s with map-type other than TO, "
+ "FROM, TOFROM, or ALLOC on MAP clause "
+ "at %L",
+ code->op == EXEC_OMP_TARGET
+ ? "" : " DATA", &n->where);
+ break;
+ }
+ break;
+ case EXEC_OMP_TARGET_ENTER_DATA:
+ switch (n->u.map_op)
+ {
+ case OMP_MAP_TO:
+ case OMP_MAP_ALWAYS_TO:
+ case OMP_MAP_ALLOC:
+ break;
+ default:
+ gfc_error ("TARGET ENTER DATA with map-type other "
+ "than TO, or ALLOC on MAP clause at %L",
+ &n->where);
+ break;
+ }
+ break;
+ case EXEC_OMP_TARGET_EXIT_DATA:
+ switch (n->u.map_op)
+ {
+ case OMP_MAP_FROM:
+ case OMP_MAP_ALWAYS_FROM:
+ case OMP_MAP_RELEASE:
+ case OMP_MAP_DELETE:
+ break;
+ default:
+ gfc_error ("TARGET EXIT DATA with map-type other "
+ "than FROM, RELEASE, or DELETE on MAP "
+ "clause at %L", &n->where);
+ break;
+ }
+ break;
+ default:
+ break;
+ }
}
if (list != OMP_LIST_DEPEND)
@@ -3544,6 +4449,10 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
n->sym->name, name, &n->where);
}
break;
+ case OMP_LIST_IS_DEVICE_PTR:
+ case OMP_LIST_USE_DEVICE_PTR:
+ /* FIXME: Handle these. */
+ break;
default:
for (; n != NULL; n = n->next)
{
@@ -3701,12 +4610,30 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
}
break;
case OMP_LIST_LINEAR:
- if (n->sym->ts.type != BT_INTEGER)
+ if (code
+ && n->u.linear_op != OMP_LINEAR_DEFAULT
+ && n->u.linear_op != linear_op)
+ {
+ gfc_error ("LINEAR clause modifier used on DO or SIMD"
+ " construct at %L", &n->where);
+ linear_op = n->u.linear_op;
+ }
+ else if (omp_clauses->orderedc)
+ gfc_error ("LINEAR clause specified together with "
+ "ORDERED clause with argument at %L",
+ &n->where);
+ else if (n->u.linear_op != OMP_LINEAR_REF
+ && n->sym->ts.type != BT_INTEGER)
gfc_error ("LINEAR variable %qs must be INTEGER "
"at %L", n->sym->name, &n->where);
- else if (!code && !n->sym->attr.value)
- gfc_error ("LINEAR dummy argument %qs must have VALUE "
- "attribute at %L", n->sym->name, &n->where);
+ else if ((n->u.linear_op == OMP_LINEAR_REF
+ || n->u.linear_op == OMP_LINEAR_UVAL)
+ && n->sym->attr.value)
+ gfc_error ("LINEAR dummy argument %qs with VALUE "
+ "attribute with %s modifier at %L",
+ n->sym->name,
+ n->u.linear_op == OMP_LINEAR_REF
+ ? "REF" : "UVAL", &n->where);
else if (n->expr)
{
gfc_expr *expr = n->expr;
@@ -3717,9 +4644,25 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
"a scalar integer linear-step expression",
n->sym->name, &n->where);
else if (!code && expr->expr_type != EXPR_CONSTANT)
- gfc_error ("%qs in LINEAR clause at %L requires "
- "a constant integer linear-step expression",
- n->sym->name, &n->where);
+ {
+ if (expr->expr_type == EXPR_VARIABLE
+ && expr->symtree->n.sym->attr.dummy
+ && expr->symtree->n.sym->ns == ns)
+ {
+ gfc_omp_namelist *n2;
+ for (n2 = omp_clauses->lists[OMP_LIST_UNIFORM];
+ n2; n2 = n2->next)
+ if (n2->sym == expr->symtree->n.sym)
+ break;
+ if (n2)
+ break;
+ }
+ gfc_error ("%qs in LINEAR clause at %L requires "
+ "a constant integer linear-step "
+ "expression or dummy argument "
+ "specified in UNIFORM clause",
+ n->sym->name, &n->where);
+ }
}
break;
/* Workaround for PR middle-end/26316, nothing really needs
@@ -3733,17 +4676,24 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
&& CLASS_DATA (n->sym)->attr.allocatable))
gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
n->sym->name, name, &n->where);
- if (n->sym->attr.pointer
- || (n->sym->ts.type == BT_CLASS && CLASS_DATA (n->sym)
- && CLASS_DATA (n->sym)->attr.class_pointer))
- gfc_error ("POINTER object %qs in %s clause at %L",
- n->sym->name, name, &n->where);
+ if (n->sym->ts.type == BT_CLASS
+ && CLASS_DATA (n->sym)
+ && CLASS_DATA (n->sym)->attr.class_pointer)
+ gfc_error ("POINTER object %qs of polymorphic type in "
+ "%s clause at %L", n->sym->name, name,
+ &n->where);
if (n->sym->attr.cray_pointer)
gfc_error ("Cray pointer object %qs in %s clause at %L",
n->sym->name, name, &n->where);
- if (n->sym->attr.cray_pointee)
+ else if (n->sym->attr.cray_pointee)
gfc_error ("Cray pointee object %qs in %s clause at %L",
n->sym->name, name, &n->where);
+ else if (n->sym->attr.flavor == FL_VARIABLE
+ && !n->sym->as
+ && !n->sym->attr.pointer)
+ gfc_error ("%s clause variable %qs at %L is neither "
+ "a POINTER nor an array", name,
+ n->sym->name, &n->where);
/* FALLTHRU */
case OMP_LIST_DEVICE_RESIDENT:
check_symbol_not_pointer (n->sym, n->where, name);
@@ -3757,37 +4707,17 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
}
}
if (omp_clauses->safelen_expr)
- {
- gfc_expr *expr = omp_clauses->safelen_expr;
- if (!gfc_resolve_expr (expr)
- || expr->ts.type != BT_INTEGER || expr->rank != 0)
- gfc_error ("SAFELEN clause at %L requires a scalar "
- "INTEGER expression", &expr->where);
- }
+ resolve_positive_int_expr (omp_clauses->safelen_expr, "SAFELEN");
if (omp_clauses->simdlen_expr)
- {
- gfc_expr *expr = omp_clauses->simdlen_expr;
- if (!gfc_resolve_expr (expr)
- || expr->ts.type != BT_INTEGER || expr->rank != 0)
- gfc_error ("SIMDLEN clause at %L requires a scalar "
- "INTEGER expression", &expr->where);
- }
+ resolve_positive_int_expr (omp_clauses->simdlen_expr, "SIMDLEN");
if (omp_clauses->num_teams)
- {
- gfc_expr *expr = omp_clauses->num_teams;
- if (!gfc_resolve_expr (expr)
- || expr->ts.type != BT_INTEGER || expr->rank != 0)
- gfc_error ("NUM_TEAMS clause at %L requires a scalar "
- "INTEGER expression", &expr->where);
- }
+ resolve_positive_int_expr (omp_clauses->num_teams, "NUM_TEAMS");
if (omp_clauses->device)
- {
- gfc_expr *expr = omp_clauses->device;
- if (!gfc_resolve_expr (expr)
- || expr->ts.type != BT_INTEGER || expr->rank != 0)
- gfc_error ("DEVICE clause at %L requires a scalar "
- "INTEGER expression", &expr->where);
- }
+ resolve_nonnegative_int_expr (omp_clauses->device, "DEVICE");
+ if (omp_clauses->hint)
+ resolve_scalar_int_expr (omp_clauses->hint, "HINT");
+ if (omp_clauses->priority)
+ resolve_nonnegative_int_expr (omp_clauses->priority, "PRIORITY");
if (omp_clauses->dist_chunk_size)
{
gfc_expr *expr = omp_clauses->dist_chunk_size;
@@ -3797,36 +4727,52 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
"a scalar INTEGER expression", &expr->where);
}
if (omp_clauses->thread_limit)
- {
- gfc_expr *expr = omp_clauses->thread_limit;
- if (!gfc_resolve_expr (expr)
- || expr->ts.type != BT_INTEGER || expr->rank != 0)
- gfc_error ("THREAD_LIMIT clause at %L requires a scalar "
- "INTEGER expression", &expr->where);
- }
+ resolve_positive_int_expr (omp_clauses->thread_limit, "THREAD_LIMIT");
+ if (omp_clauses->grainsize)
+ resolve_positive_int_expr (omp_clauses->grainsize, "GRAINSIZE");
+ if (omp_clauses->num_tasks)
+ resolve_positive_int_expr (omp_clauses->num_tasks, "NUM_TASKS");
if (omp_clauses->async)
if (omp_clauses->async_expr)
- resolve_oacc_scalar_int_expr (omp_clauses->async_expr, "ASYNC");
+ resolve_scalar_int_expr (omp_clauses->async_expr, "ASYNC");
if (omp_clauses->num_gangs_expr)
- resolve_oacc_positive_int_expr (omp_clauses->num_gangs_expr, "NUM_GANGS");
+ resolve_positive_int_expr (omp_clauses->num_gangs_expr, "NUM_GANGS");
if (omp_clauses->num_workers_expr)
- resolve_oacc_positive_int_expr (omp_clauses->num_workers_expr,
- "NUM_WORKERS");
+ resolve_positive_int_expr (omp_clauses->num_workers_expr, "NUM_WORKERS");
if (omp_clauses->vector_length_expr)
- resolve_oacc_positive_int_expr (omp_clauses->vector_length_expr,
- "VECTOR_LENGTH");
+ resolve_positive_int_expr (omp_clauses->vector_length_expr,
+ "VECTOR_LENGTH");
if (omp_clauses->gang_num_expr)
- resolve_oacc_positive_int_expr (omp_clauses->gang_num_expr, "GANG");
+ resolve_positive_int_expr (omp_clauses->gang_num_expr, "GANG");
if (omp_clauses->gang_static_expr)
- resolve_oacc_positive_int_expr (omp_clauses->gang_static_expr, "GANG");
+ resolve_positive_int_expr (omp_clauses->gang_static_expr, "GANG");
if (omp_clauses->worker_expr)
- resolve_oacc_positive_int_expr (omp_clauses->worker_expr, "WORKER");
+ resolve_positive_int_expr (omp_clauses->worker_expr, "WORKER");
if (omp_clauses->vector_expr)
- resolve_oacc_positive_int_expr (omp_clauses->vector_expr, "VECTOR");
+ resolve_positive_int_expr (omp_clauses->vector_expr, "VECTOR");
if (omp_clauses->wait)
if (omp_clauses->wait_list)
for (el = omp_clauses->wait_list; el; el = el->next)
- resolve_oacc_scalar_int_expr (el->expr, "WAIT");
+ resolve_scalar_int_expr (el->expr, "WAIT");
+ if (omp_clauses->collapse && omp_clauses->tile_list)
+ gfc_error ("Incompatible use of TILE and COLLAPSE at %L", &code->loc);
+ if (omp_clauses->depend_source && code->op != EXEC_OMP_ORDERED)
+ gfc_error ("SOURCE dependence type only allowed "
+ "on ORDERED directive at %L", &code->loc);
+ if (!openacc && code && omp_clauses->lists[OMP_LIST_MAP] == NULL)
+ {
+ const char *p = NULL;
+ switch (code->op)
+ {
+ case EXEC_OMP_TARGET_DATA: p = "TARGET DATA"; break;
+ case EXEC_OMP_TARGET_ENTER_DATA: p = "TARGET ENTER DATA"; break;
+ case EXEC_OMP_TARGET_EXIT_DATA: p = "TARGET EXIT DATA"; break;
+ default: break;
+ }
+ if (p)
+ gfc_error ("%s must contain at least one MAP clause at %L",
+ p, &code->loc);
+ }
}
@@ -3914,12 +4860,33 @@ resolve_omp_atomic (gfc_code *code)
= (gfc_omp_atomic_op) (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK);
code = code->block->next;
- gcc_assert (code->op == EXEC_ASSIGN);
- gcc_assert (((aop != GFC_OMP_ATOMIC_CAPTURE) && code->next == NULL)
- || ((aop == GFC_OMP_ATOMIC_CAPTURE)
- && code->next != NULL
- && code->next->op == EXEC_ASSIGN
- && code->next->next == NULL));
+ /* resolve_blocks asserts this is initially EXEC_ASSIGN.
+ If it changed to EXEC_NOP, assume an error has been emitted already. */
+ if (code->op == EXEC_NOP)
+ return;
+ if (code->op != EXEC_ASSIGN)
+ {
+ unexpected:
+ gfc_error ("unexpected !$OMP ATOMIC expression at %L", &code->loc);
+ return;
+ }
+ if (aop != GFC_OMP_ATOMIC_CAPTURE)
+ {
+ if (code->next != NULL)
+ goto unexpected;
+ }
+ else
+ {
+ if (code->next == NULL)
+ goto unexpected;
+ if (code->next->op == EXEC_NOP)
+ return;
+ if (code->next->op != EXEC_ASSIGN || code->next->next)
+ {
+ code = code->next;
+ goto unexpected;
+ }
+ }
if (code->expr1->expr_type != EXPR_VARIABLE
|| code->expr1->symtree == NULL
@@ -4308,7 +5275,10 @@ gfc_resolve_omp_do_blocks (gfc_code *code, gfc_namespace *ns)
gfc_code *c;
omp_current_do_code = code->block->next;
- omp_current_do_collapse = code->ext.omp_clauses->collapse;
+ if (code->ext.omp_clauses->orderedc)
+ omp_current_do_collapse = code->ext.omp_clauses->orderedc;
+ else
+ omp_current_do_collapse = code->ext.omp_clauses->collapse;
for (i = 1, c = omp_current_do_code; i < omp_current_do_collapse; i++)
{
c = c->block;
@@ -4362,6 +5332,8 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
{
case EXEC_OMP_PARALLEL_DO:
case EXEC_OMP_PARALLEL_DO_SIMD:
+ case EXEC_OMP_TARGET_PARALLEL_DO:
+ case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
@@ -4487,8 +5459,17 @@ resolve_omp_do (gfc_code *code)
is_simd = true;
break;
case EXEC_OMP_SIMD: name = "!$OMP SIMD"; is_simd = true; break;
+ case EXEC_OMP_TARGET_PARALLEL_DO: name = "!$OMP TARGET PARALLEL DO"; break;
+ case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
+ name = "!$OMP TARGET PARALLEL DO SIMD";
+ is_simd = true;
+ break;
+ case EXEC_OMP_TARGET_SIMD:
+ name = "!$OMP TARGET SIMD";
+ is_simd = true;
+ break;
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
- name = "!$OMP TARGET TEAMS_DISTRIBUTE";
+ name = "!$OMP TARGET TEAMS DISTRIBUTE";
break;
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO";
@@ -4501,7 +5482,12 @@ resolve_omp_do (gfc_code *code)
name = "!$OMP TARGET TEAMS DISTRIBUTE SIMD";
is_simd = true;
break;
- case EXEC_OMP_TEAMS_DISTRIBUTE: name = "!$OMP TEAMS_DISTRIBUTE"; break;
+ case EXEC_OMP_TASKLOOP: name = "!$OMP TASKLOOP"; break;
+ case EXEC_OMP_TASKLOOP_SIMD:
+ name = "!$OMP TASKLOOP SIMD";
+ is_simd = true;
+ break;
+ case EXEC_OMP_TEAMS_DISTRIBUTE: name = "!$OMP TEAMS DISTRIBUTE"; break;
case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO";
break;
@@ -4520,9 +5506,14 @@ resolve_omp_do (gfc_code *code)
resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
do_code = code->block->next;
- collapse = code->ext.omp_clauses->collapse;
- if (collapse <= 0)
- collapse = 1;
+ if (code->ext.omp_clauses->orderedc)
+ collapse = code->ext.omp_clauses->orderedc;
+ else
+ {
+ collapse = code->ext.omp_clauses->collapse;
+ if (collapse <= 0)
+ collapse = 1;
+ }
for (i = 1; i <= collapse; i++)
{
if (do_code->op == EXEC_DO_WHILE)
@@ -4911,15 +5902,15 @@ resolve_oacc_loop_blocks (gfc_code *code)
if (el->expr == NULL)
{
/* NULL expressions are used to represent '*' arguments.
- Convert those to a -1 expressions. */
+ Convert those to a 0 expressions. */
el->expr = gfc_get_constant_expr (BT_INTEGER,
gfc_default_integer_kind,
&code->loc);
- mpz_set_si (el->expr->value.integer, -1);
+ mpz_set_si (el->expr->value.integer, 0);
}
else
{
- resolve_oacc_positive_int_expr (el->expr, "TILE");
+ resolve_positive_int_expr (el->expr, "TILE");
if (el->expr->expr_type != EXPR_CONSTANT)
gfc_error ("TILE requires constant expression at %L",
&code->loc);
@@ -4994,7 +5985,7 @@ gfc_resolve_oacc_declare (gfc_namespace *ns)
if (n->expr && n->expr->ref->type == REF_ARRAY)
{
gfc_error ("Array sections: %qs not allowed in"
- " $!ACC DECLARE at %L", n->sym->name, &oc->loc);
+ " !$ACC DECLARE at %L", n->sym->name, &oc->loc);
continue;
}
}
@@ -5081,10 +6072,15 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
case EXEC_OMP_PARALLEL_DO:
case EXEC_OMP_PARALLEL_DO_SIMD:
case EXEC_OMP_SIMD:
+ case EXEC_OMP_TARGET_PARALLEL_DO:
+ case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
+ case EXEC_OMP_TARGET_SIMD:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
+ case EXEC_OMP_TASKLOOP:
+ case EXEC_OMP_TASKLOOP_SIMD:
case EXEC_OMP_TEAMS_DISTRIBUTE:
case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
@@ -5099,6 +6095,9 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
case EXEC_OMP_SINGLE:
case EXEC_OMP_TARGET:
case EXEC_OMP_TARGET_DATA:
+ case EXEC_OMP_TARGET_ENTER_DATA:
+ case EXEC_OMP_TARGET_EXIT_DATA:
+ case EXEC_OMP_TARGET_PARALLEL:
case EXEC_OMP_TARGET_TEAMS:
case EXEC_OMP_TASK:
case EXEC_OMP_TEAMS:
@@ -5132,7 +6131,8 @@ gfc_resolve_omp_declare_simd (gfc_namespace *ns)
for (ods = ns->omp_declare_simd; ods; ods = ods->next)
{
- if (ods->proc_name != ns->proc_name)
+ if (ods->proc_name != NULL
+ && ods->proc_name != ns->proc_name)
gfc_error ("!$OMP DECLARE SIMD should refer to containing procedure "
"%qs at %L", ns->proc_name->name, &ods->where);
if (ods->clauses)