public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Patch] Fortran: cleanup OpenMP's OMP_LIST_* handling
@ 2020-11-16 14:08 Tobias Burnus
  2020-11-18 11:14 ` Jakub Jelinek
  0 siblings, 1 reply; 2+ messages in thread
From: Tobias Burnus @ 2020-11-16 14:08 UTC (permalink / raw)
  To: gcc-patches, fortran, Jakub Jelinek

[-- Attachment #1: Type: text/plain, Size: 831 bytes --]

Hi all,

as discussed the other day (I think via IRC or in a patch review),
   omp_list_clauses
did grow quite a bit: it has 26 entries and I am about to add two
more.

This variable is used as:
  typedef struct gfc_omp_clauses
  {
    ...
    gfc_omp_namelist *lists[OMP_LIST_NUM];

with sizeof(gfc_omp_namelist) = 5*sizeof(void*) + sizeof(locus);

This patch replaces it with a linked list.


I am not really sure the new version is that readable and whether
we move into the right direction or not.

Comments?

Tobias

PS: If the direction is sensible, a very careful reading of the
patch is probably useful.

-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander Walter

[-- Attachment #2: omp-list-cleanup.diff --]
[-- Type: text/x-patch, Size: 105685 bytes --]

Fortran: cleanup OpenMP's OMP_LIST_* handling

gcc/fortran/ChangeLog:

	* dump-parse-tree.c (show_omp_namelist, show_omp_node): Update for
	new internal representation of gfc_omp_namelist.
	(show_omp_clauses): Likewise; replace own list by call to
	gfc_omp_get_clause_name.
	* frontend-passes.c (gfc_code_walker): Update gfc_omp_namelist handling.
	* gfortran.h (gfc_omp_namelist_item): Renamed from gfc_omp_namelist.
	(gfc_get_omp_namelist_item): Renamed from gfc_get_omp_namelist.
	(enum omp_list_clauses): Add name to enum, remove OMP_LIST_FIRST and
	OMP_LIST_NUM, add OMP_LIST_UNSET.
	(gfc_get_omp_namelist, gfc_omp_namelist): New.
	(gfc_omp_clauses): Use new gfc_get_omp_namelist.
	(gfc_code): Update for renaming.
	(gfc_free_omp_namelist_item): Renamed from gfc_free_omp_namelist and
	updated.
	(gfc_omp_get_clause_name, gfc_omp_get_nm_ref, gfc_omp_get_nm_list): New.
	* match.c (gfc_free_omp_namelist_item): Renamed from
	gfc_free_omp_namelist.
	* module.c (mio_omp_declare_simd): Update for gfc_omp_namelist changes.
	* openmp.c (gfc_free_omp_clauses, gfc_match_omp_variable_list,
	gfc_match_omp_to_link, gfc_match_omp_depend_sink,
	gfc_match_oacc_clause_link, gfc_match_omp_map_clause): Likewise.
	(gfc_omp_get_clause_name, gfc_omp_get_nm_ref, gfc_omp_get_nm_list): New.
	(gfc_match_omp_clause_reduction, gfc_match_omp_clauses,
	gfc_match_oacc_declare, gfc_match_oacc_update, gfc_match_oacc_cache,
	gfc_match_omp_flush, gfc_match_omp_declare_target,
	resolve_omp_udr_clause, resolve_omp_clauses,
	gfc_resolve_omp_parallel_blocks, gfc_resolve_do_iterator,
	resolve_omp_do, gfc_resolve_oacc_blocks, gfc_resolve_oacc_declare,
	gfc_resolve_omp_directive): Use new functions; update for
	gfc_omp_namelist changes.
	* parse.c (parse_omp_structured_block): Likewise
	* st.c (gfc_free_statement): Likewise
	* trans-decl.c (add_clause, finish_oacc_declare): Likewise.
	* trans-openmp.c (gfc_copy_list_clauses,
	gfc_trans_omp_free_clausea): New.
	(gfc_trans_omp_variable_list, gfc_trans_omp_array_reduction_or_udr,
	gfc_trans_omp_reduction_list, gfc_trans_omp_array_section,
	gfc_trans_omp_clauses, gfc_trans_omp_do,
	gfc_trans_oacc_combined_directive, gfc_split_omp_clauses,
	gfc_trans_omp_do_simd, gfc_trans_omp_parallel_do,
	gfc_trans_omp_parallel_do_simd, gfc_trans_omp_sections,
	gfc_trans_omp_distribute, gfc_trans_omp_teams, gfc_trans_omp_target,
	gfc_trans_omp_taskloop): Use them; update for gfc_omp_namelist changes.

gcc/testsuite/ChangeLog:

	* gfortran.dg/goacc/combined-directives.f90: Update scan-tree pattern.
	* gfortran.dg/goacc/reduction-2.f95: Likewise.
	* gfortran.dg/gomp/openmp-simd-6.f90: Likewise.
	* gfortran.dg/gomp/reduction4.f90: Likewise.

 gcc/fortran/dump-parse-tree.c                      |  57 +-
 gcc/fortran/frontend-passes.c                      |  14 +-
 gcc/fortran/gfortran.h                             |  40 +-
 gcc/fortran/match.c                                |   4 +-
 gcc/fortran/module.c                               |  31 +-
 gcc/fortran/openmp.c                               | 723 ++++++++++++---------
 gcc/fortran/parse.c                                |  10 +-
 gcc/fortran/st.c                                   |   2 +-
 gcc/fortran/trans-decl.c                           |  35 +-
 gcc/fortran/trans-openmp.c                         | 237 ++++---
 .../gfortran.dg/goacc/combined-directives.f90      |   5 +-
 gcc/testsuite/gfortran.dg/goacc/reduction-2.f95    |   4 +-
 gcc/testsuite/gfortran.dg/gomp/openmp-simd-6.f90   |   4 +-
 gcc/testsuite/gfortran.dg/gomp/reduction4.f90      |   6 +-
 14 files changed, 666 insertions(+), 506 deletions(-)

diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index cab0fb2979f..7ddf4216361 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -1273,7 +1273,7 @@ show_code (int level, gfc_code *c)
 }
 
 static void
-show_omp_namelist (int list_type, gfc_omp_namelist *n)
+show_omp_namelist (enum omp_list_clauses list_type, gfc_omp_namelist_item *n)
 {
   for (; n; n = n->next)
     {
@@ -1366,7 +1366,7 @@ show_omp_namelist (int list_type, gfc_omp_namelist *n)
 static void
 show_omp_clauses (gfc_omp_clauses *omp_clauses)
 {
-  int list_type, i;
+  int i;
 
   switch (omp_clauses->cancel)
     {
@@ -1567,48 +1567,16 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
     fputs (" MERGEABLE", dumpfile);
   if (omp_clauses->collapse)
     fprintf (dumpfile, " COLLAPSE(%d)", omp_clauses->collapse);
-  for (list_type = 0; list_type < OMP_LIST_NUM; list_type++)
-    if (omp_clauses->lists[list_type] != NULL
-	&& list_type != OMP_LIST_COPYPRIVATE)
+  for (gfc_omp_namelist *list = omp_clauses->lists; list; list = list->next)
+    if (list->clause != OMP_LIST_COPYPRIVATE)
       {
-	const char *type = NULL;
-	switch (list_type)
-	  {
-	  case OMP_LIST_PRIVATE: type = "PRIVATE"; break;
-	  case OMP_LIST_FIRSTPRIVATE: type = "FIRSTPRIVATE"; break;
-	  case OMP_LIST_LASTPRIVATE: type = "LASTPRIVATE"; break;
-	  case OMP_LIST_COPYPRIVATE: type = "COPYPRIVATE"; break;
-	  case OMP_LIST_SHARED: type = "SHARED"; break;
-	  case OMP_LIST_COPYIN: type = "COPYIN"; break;
-	  case OMP_LIST_UNIFORM: type = "UNIFORM"; break;
-	  case OMP_LIST_ALIGNED: type = "ALIGNED"; break;
-	  case OMP_LIST_LINEAR: type = "LINEAR"; break;
-	  case OMP_LIST_DEPEND: type = "DEPEND"; break;
-	  case OMP_LIST_MAP: type = "MAP"; break;
-	  case OMP_LIST_TO: type = "TO"; break;
-	  case OMP_LIST_FROM: type = "FROM"; break;
-	  case OMP_LIST_REDUCTION:
-	  case OMP_LIST_REDUCTION_INSCAN:
-	  case OMP_LIST_REDUCTION_TASK: type = "REDUCTION"; break;
-	  case OMP_LIST_IN_REDUCTION: type = "IN_REDUCTION"; break;
-	  case OMP_LIST_TASK_REDUCTION: type = "TASK_REDUCTION"; break;
-	  case OMP_LIST_DEVICE_RESIDENT: type = "DEVICE_RESIDENT"; break;
-	  case OMP_LIST_LINK: type = "LINK"; break;
-	  case OMP_LIST_USE_DEVICE: type = "USE_DEVICE"; break;
-	  case OMP_LIST_CACHE: type = "CACHE"; break;
-	  case OMP_LIST_IS_DEVICE_PTR: type = "IS_DEVICE_PTR"; break;
-	  case OMP_LIST_USE_DEVICE_PTR: type = "USE_DEVICE_PTR"; break;
-	  case OMP_LIST_USE_DEVICE_ADDR: type = "USE_DEVICE_ADDR"; break;
-	  case OMP_LIST_NONTEMPORAL: type = "NONTEMPORAL"; break;
-	  default:
-	    gcc_unreachable ();
-	  }
+	const char *type = gfc_omp_get_clause_name (list->clause);
 	fprintf (dumpfile, " %s(", type);
-	if (list_type == OMP_LIST_REDUCTION_INSCAN)
+	if (list->clause == OMP_LIST_REDUCTION_INSCAN)
 	  fputs ("inscan, ", dumpfile);
-	if (list_type == OMP_LIST_REDUCTION_TASK)
+	if (list->clause == OMP_LIST_REDUCTION_TASK)
 	  fputs ("task, ", dumpfile);
-	show_omp_namelist (list_type, omp_clauses->lists[list_type]);
+	show_omp_namelist (list->clause, list->item);
 	fputc (')', dumpfile);
       }
   if (omp_clauses->safelen_expr)
@@ -1910,7 +1878,7 @@ show_omp_node (int level, gfc_code *c)
       if (c->ext.omp_namelist)
 	{
 	  fputs (" (", dumpfile);
-	  show_omp_namelist (OMP_LIST_NUM, c->ext.omp_namelist);
+	  show_omp_namelist (OMP_LIST_UNSET, c->ext.omp_namelist);
 	  fputc (')', dumpfile);
 	}
       return;
@@ -1958,11 +1926,12 @@ show_omp_node (int level, gfc_code *c)
   fprintf (dumpfile, "!$%s END %s", is_oacc ? "ACC" : "OMP", name);
   if (omp_clauses != NULL)
     {
-      if (omp_clauses->lists[OMP_LIST_COPYPRIVATE])
+      gfc_omp_namelist_item *list = gfc_omp_get_nm_list (omp_clauses,
+							 OMP_LIST_COPYPRIVATE);
+      if (list)
 	{
 	  fputs (" COPYPRIVATE(", dumpfile);
-	  show_omp_namelist (OMP_LIST_COPYPRIVATE,
-			     omp_clauses->lists[OMP_LIST_COPYPRIVATE]);
+	  show_omp_namelist (OMP_LIST_COPYPRIVATE, list);
 	  fputc (')', dumpfile);
 	}
       else if (omp_clauses->nowait)
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c
index 83f6fd804b1..8629259d675 100644
--- a/gcc/fortran/frontend-passes.c
+++ b/gcc/fortran/frontend-passes.c
@@ -5578,10 +5578,8 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
 
 	      if (co->ext.omp_clauses)
 		{
-		  gfc_omp_namelist *n;
-		  static int list_types[]
-		    = { OMP_LIST_ALIGNED, OMP_LIST_LINEAR, OMP_LIST_DEPEND,
-			OMP_LIST_MAP, OMP_LIST_TO, OMP_LIST_FROM };
+		  gfc_omp_namelist *list;
+		  gfc_omp_namelist_item *n;
 		  size_t idx;
 		  WALK_SUBEXPR (co->ext.omp_clauses->if_expr);
 		  WALK_SUBEXPR (co->ext.omp_clauses->final_expr);
@@ -5599,11 +5597,9 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
 		  WALK_SUBEXPR (co->ext.omp_clauses->priority);
 		  for (idx = 0; idx < OMP_IF_LAST; idx++)
 		    WALK_SUBEXPR (co->ext.omp_clauses->if_exprs[idx]);
-		  for (idx = 0;
-		       idx < sizeof (list_types) / sizeof (list_types[0]);
-		       idx++)
-		    for (n = co->ext.omp_clauses->lists[list_types[idx]];
-			 n; n = n->next)
+		  for (list = co->ext.omp_clauses->lists;
+		       list; list = list->next)
+		    for (n = list->item; n; n = n->next)
 		      WALK_SUBEXPR (n->expr);
 		}
 	      break;
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 6467985ea7f..69f231f688d 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1240,7 +1240,7 @@ enum gfc_omp_linear_op
 /* For use in OpenMP clauses in case we need extra information
    (aligned clause alignment, linear clause step, etc.).  */
 
-typedef struct gfc_omp_namelist
+typedef struct gfc_omp_namelist_item
 {
   struct gfc_symbol *sym;
   struct gfc_expr *expr;
@@ -1254,17 +1254,16 @@ typedef struct gfc_omp_namelist
       bool lastprivate_conditional;
     } u;
   struct gfc_omp_namelist_udr *udr;
-  struct gfc_omp_namelist *next;
+  struct gfc_omp_namelist_item *next;
   locus where;
 }
-gfc_omp_namelist;
+gfc_omp_namelist_item;
+#define gfc_get_omp_namelist_item() XCNEW (gfc_omp_namelist_item)
 
-#define gfc_get_omp_namelist() XCNEW (gfc_omp_namelist)
-
-enum
+enum omp_list_clauses
 {
-  OMP_LIST_FIRST,
-  OMP_LIST_PRIVATE = OMP_LIST_FIRST,
+  OMP_LIST_UNSET,
+  OMP_LIST_PRIVATE,
   OMP_LIST_FIRSTPRIVATE,
   OMP_LIST_LASTPRIVATE,
   OMP_LIST_COPYPRIVATE,
@@ -1289,8 +1288,7 @@ enum
   OMP_LIST_IS_DEVICE_PTR,
   OMP_LIST_USE_DEVICE_PTR,
   OMP_LIST_USE_DEVICE_ADDR,
-  OMP_LIST_NONTEMPORAL,
-  OMP_LIST_NUM
+  OMP_LIST_NONTEMPORAL
 };
 
 /* Because a symbol can belong to multiple namelists, they must be
@@ -1386,12 +1384,22 @@ enum gfc_omp_memorder
   OMP_MEMORDER_RELAXED
 };
 
+typedef struct gfc_omp_namelist
+{
+  enum omp_list_clauses clause;
+  gfc_omp_namelist_item *item;
+  struct gfc_omp_namelist *next;
+}
+gfc_omp_namelist;
+
+#define gfc_get_omp_namelist() XCNEW (gfc_omp_namelist)
+
 typedef struct gfc_omp_clauses
 {
   struct gfc_expr *if_expr;
   struct gfc_expr *final_expr;
   struct gfc_expr *num_threads;
-  gfc_omp_namelist *lists[OMP_LIST_NUM];
+  gfc_omp_namelist *lists;
   enum gfc_omp_sched_kind sched_kind;
   enum gfc_omp_device_type device_type;
   struct gfc_expr *chunk_size;
@@ -1434,7 +1442,6 @@ typedef struct gfc_omp_clauses
   unsigned par_auto:1, gang_static:1;
   unsigned if_present:1, finalize:1;
   locus loc;
-
 }
 gfc_omp_clauses;
 
@@ -2752,7 +2759,7 @@ typedef struct gfc_code
     gfc_oacc_declare *oacc_declare;
     gfc_omp_clauses *omp_clauses;
     const char *omp_name;
-    gfc_omp_namelist *omp_namelist;
+    gfc_omp_namelist_item *omp_namelist;
     bool omp_bool;
   }
   ext;		/* Points to additional structures required by statement */
@@ -3311,7 +3318,7 @@ void gfc_free_iterator (gfc_iterator *, int);
 void gfc_free_forall_iterator (gfc_forall_iterator *);
 void gfc_free_alloc_list (gfc_alloc *);
 void gfc_free_namelist (gfc_namelist *);
-void gfc_free_omp_namelist (gfc_omp_namelist *);
+void gfc_free_omp_namelist_item (gfc_omp_namelist_item *);
 void gfc_free_equiv (gfc_equiv *);
 void gfc_free_equiv_until (gfc_equiv *, gfc_equiv *);
 void gfc_free_data (gfc_data *);
@@ -3325,6 +3332,7 @@ gfc_expr *gfc_get_parentheses (gfc_expr *);
 struct gfc_omp_saved_state { void *ptrs[2]; int ints[1]; };
 bool gfc_omp_requires_add_clause (gfc_omp_requires_kind, const char *,
 				  locus *, const char *);
+const char* gfc_omp_get_clause_name (enum omp_list_clauses clause);
 void gfc_check_omp_requires (gfc_namespace *, int);
 void gfc_free_omp_clauses (gfc_omp_clauses *);
 void gfc_free_oacc_declare_clauses (struct gfc_oacc_declare *);
@@ -3332,6 +3340,10 @@ void gfc_free_omp_declare_simd (gfc_omp_declare_simd *);
 void gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *);
 void gfc_free_omp_udr (gfc_omp_udr *);
 gfc_omp_udr *gfc_omp_udr_find (gfc_symtree *, gfc_typespec *);
+gfc_omp_namelist_item** gfc_omp_get_nm_ref (gfc_omp_clauses *,
+					    enum omp_list_clauses);
+gfc_omp_namelist_item* gfc_omp_get_nm_list (gfc_omp_clauses *,
+					    enum omp_list_clauses);
 void gfc_resolve_omp_directive (gfc_code *, gfc_namespace *);
 void gfc_resolve_do_iterator (gfc_code *, gfc_symbol *, bool);
 void gfc_resolve_omp_local_vars (gfc_namespace *);
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index bee73e7b008..baacf28cb95 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -5467,9 +5467,9 @@ gfc_free_namelist (gfc_namelist *name)
 /* Free an OpenMP namelist structure.  */
 
 void
-gfc_free_omp_namelist (gfc_omp_namelist *name)
+gfc_free_omp_namelist_item (gfc_omp_namelist_item *name)
 {
-  gfc_omp_namelist *n;
+  gfc_omp_namelist_item *n;
 
   for (; name; name = n)
     {
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 4c6ff22d5c1..1091228d3e5 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -4357,7 +4357,7 @@ mio_omp_declare_simd (gfc_namespace *ns, gfc_omp_declare_simd **odsp)
       write_atom (ATOM_NAME, "OMP_DECLARE_SIMD");
       if (ods->clauses)
 	{
-	  gfc_omp_namelist *n;
+	  gfc_omp_namelist_item *n;
 
 	  if (ods->clauses->inbranch)
 	    mio_name (0, omp_declare_simd_clauses);
@@ -4368,12 +4368,14 @@ mio_omp_declare_simd (gfc_namespace *ns, gfc_omp_declare_simd **odsp)
 	      mio_name (2, omp_declare_simd_clauses);
 	      mio_expr (&ods->clauses->simdlen_expr);
 	    }
-	  for (n = ods->clauses->lists[OMP_LIST_UNIFORM]; n; n = n->next)
+	  n = gfc_omp_get_nm_list (ods->clauses, OMP_LIST_UNIFORM);
+	  for (; n; n = n->next)
 	    {
 	      mio_name (3, omp_declare_simd_clauses);
 	      mio_symbol_ref (&n->sym);
 	    }
-	  for (n = ods->clauses->lists[OMP_LIST_LINEAR]; n; n = n->next)
+	  n = gfc_omp_get_nm_list (ods->clauses, OMP_LIST_LINEAR);
+	  for (; n; n = n->next)
 	    {
 	      if (n->u.linear_op == OMP_LINEAR_DEFAULT)
 		mio_name (4, omp_declare_simd_clauses);
@@ -4382,7 +4384,8 @@ mio_omp_declare_simd (gfc_namespace *ns, gfc_omp_declare_simd **odsp)
 	      mio_symbol_ref (&n->sym);
 	      mio_expr (&n->expr);
 	    }
-	  for (n = ods->clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
+	  n = gfc_omp_get_nm_list (ods->clauses, OMP_LIST_ALIGNED);
+	  for (; n; n = n->next)
 	    {
 	      mio_name (5, omp_declare_simd_clauses);
 	      mio_symbol_ref (&n->sym);
@@ -4392,7 +4395,7 @@ mio_omp_declare_simd (gfc_namespace *ns, gfc_omp_declare_simd **odsp)
     }
   else
     {
-      gfc_omp_namelist **ptrs[3] = { NULL, NULL, NULL };
+      gfc_omp_namelist_item **ptrs[3] = { NULL, NULL, NULL };
 
       require_atom (ATOM_NAME);
       *odsp = ods = gfc_get_omp_declare_simd ();
@@ -4401,13 +4404,19 @@ mio_omp_declare_simd (gfc_namespace *ns, gfc_omp_declare_simd **odsp)
       if (peek_atom () == ATOM_NAME)
 	{
 	  ods->clauses = gfc_get_omp_clauses ();
-	  ptrs[0] = &ods->clauses->lists[OMP_LIST_UNIFORM];
-	  ptrs[1] = &ods->clauses->lists[OMP_LIST_LINEAR];
-	  ptrs[2] = &ods->clauses->lists[OMP_LIST_ALIGNED];
+	  ods->clauses->lists = gfc_get_omp_namelist ();
+	  ods->clauses->lists->next = gfc_get_omp_namelist ();
+	  ods->clauses->lists->next->next = gfc_get_omp_namelist ();
+	  ods->clauses->lists->clause = OMP_LIST_UNIFORM;
+	  ods->clauses->lists->next->clause = OMP_LIST_UNIFORM;
+	  ods->clauses->lists->next->next->clause = OMP_LIST_UNIFORM;
+	  ptrs[0] = &ods->clauses->lists->item;
+	  ptrs[1] = &ods->clauses->lists->next->item;
+	  ptrs[2] = &ods->clauses->lists->next->next->item;
 	}
       while (peek_atom () == ATOM_NAME)
 	{
-	  gfc_omp_namelist *n;
+	  gfc_omp_namelist_item *n;
 	  int t = mio_name (0, omp_declare_simd_clauses);
 
 	  switch (t)
@@ -4418,7 +4427,7 @@ mio_omp_declare_simd (gfc_namespace *ns, gfc_omp_declare_simd **odsp)
 	    case 3:
 	    case 4:
 	    case 5:
-	      *ptrs[t - 3] = n = gfc_get_omp_namelist ();
+	      *ptrs[t - 3] = n = gfc_get_omp_namelist_item ();
 	    finish_namelist:
 	      n->where = gfc_current_locus;
 	      ptrs[t - 3] = &n->next;
@@ -4429,7 +4438,7 @@ mio_omp_declare_simd (gfc_namespace *ns, gfc_omp_declare_simd **odsp)
 	    case 33:
 	    case 34:
 	    case 35:
-	      *ptrs[1] = n = gfc_get_omp_namelist ();
+	      *ptrs[1] = n = gfc_get_omp_namelist_item ();
 	      n->u.linear_op = (enum gfc_omp_linear_op) (t - 32);
 	      t = 4;
 	      goto finish_namelist;
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 68d0b65ff87..19ccdd52ce9 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -101,8 +101,13 @@ gfc_free_omp_clauses (gfc_omp_clauses *c)
   gfc_free_expr (c->num_gangs_expr);
   gfc_free_expr (c->num_workers_expr);
   gfc_free_expr (c->vector_length_expr);
-  for (i = 0; i < OMP_LIST_NUM; i++)
-    gfc_free_omp_namelist (c->lists[i]);
+  for (gfc_omp_namelist *list = c->lists; list; )
+    {
+      gfc_omp_namelist *next = list->next;
+      gfc_free_omp_namelist_item (list->item);
+      free (list);
+      list = next;
+    }
   gfc_free_expr_list (c->wait_list);
   gfc_free_expr_list (c->tile_list);
   free (CONST_CAST (char *, c->critical_name));
@@ -230,13 +235,13 @@ gfc_find_omp_udr (gfc_namespace *ns, const char *name, gfc_typespec *ts)
 /* Match a variable/common block list and construct a namelist from it.  */
 
 static match
-gfc_match_omp_variable_list (const char *str, gfc_omp_namelist **list,
+gfc_match_omp_variable_list (const char *str, gfc_omp_namelist_item **list,
 			     bool allow_common, bool *end_colon = NULL,
-			     gfc_omp_namelist ***headp = NULL,
+			     gfc_omp_namelist_item ***headp = NULL,
 			     bool allow_sections = false,
 			     bool allow_derived = false)
 {
-  gfc_omp_namelist *head, *tail, *p;
+  gfc_omp_namelist_item *head, *tail, *p;
   locus old_loc, cur_loc;
   char n[GFC_MAX_SYMBOL_LEN+1];
   gfc_symbol *sym;
@@ -281,7 +286,7 @@ gfc_match_omp_variable_list (const char *str, gfc_omp_namelist **list,
 		}
 	    }
 	  gfc_set_sym_referenced (sym);
-	  p = gfc_get_omp_namelist ();
+	  p = gfc_get_omp_namelist_item ();
 	  if (head == NULL)
 	    head = tail = p;
 	  else
@@ -317,7 +322,7 @@ gfc_match_omp_variable_list (const char *str, gfc_omp_namelist **list,
       for (sym = st->n.common->head; sym; sym = sym->common_next)
 	{
 	  gfc_set_sym_referenced (sym);
-	  p = gfc_get_omp_namelist ();
+	  p = gfc_get_omp_namelist_item ();
 	  if (head == NULL)
 	    head = tail = p;
 	  else
@@ -353,7 +358,7 @@ syntax:
   gfc_error ("Syntax error in OpenMP variable list at %C");
 
 cleanup:
-  gfc_free_omp_namelist (head);
+  gfc_free_omp_namelist_item (head);
   gfc_current_locus = old_loc;
   return MATCH_ERROR;
 }
@@ -362,9 +367,9 @@ cleanup:
    from it.  */
 
 static match
-gfc_match_omp_to_link (const char *str, gfc_omp_namelist **list)
+gfc_match_omp_to_link (const char *str, gfc_omp_namelist_item **list)
 {
-  gfc_omp_namelist *head, *tail, *p;
+  gfc_omp_namelist_item *head, *tail, *p;
   locus old_loc, cur_loc;
   char n[GFC_MAX_SYMBOL_LEN+1];
   gfc_symbol *sym;
@@ -386,7 +391,7 @@ gfc_match_omp_to_link (const char *str, gfc_omp_namelist **list)
       switch (m)
 	{
 	case MATCH_YES:
-	  p = gfc_get_omp_namelist ();
+	  p = gfc_get_omp_namelist_item ();
 	  if (head == NULL)
 	    head = tail = p;
 	  else
@@ -415,7 +420,7 @@ gfc_match_omp_to_link (const char *str, gfc_omp_namelist **list)
 	  gfc_error ("COMMON block /%s/ not found at %C", n);
 	  goto cleanup;
 	}
-      p = gfc_get_omp_namelist ();
+      p = gfc_get_omp_namelist_item ();
       if (head == NULL)
 	head = tail = p;
       else
@@ -443,7 +448,7 @@ syntax:
   gfc_error ("Syntax error in OpenMP variable list at %C");
 
 cleanup:
-  gfc_free_omp_namelist (head);
+  gfc_free_omp_namelist_item (head);
   gfc_current_locus = old_loc;
   return MATCH_ERROR;
 }
@@ -451,9 +456,9 @@ cleanup:
 /* Match depend(sink : ...) construct a namelist from it.  */
 
 static match
-gfc_match_omp_depend_sink (gfc_omp_namelist **list)
+gfc_match_omp_depend_sink (gfc_omp_namelist_item **list)
 {
-  gfc_omp_namelist *head, *tail, *p;
+  gfc_omp_namelist_item *head, *tail, *p;
   locus old_loc, cur_loc;
   gfc_symbol *sym;
 
@@ -468,7 +473,7 @@ gfc_match_omp_depend_sink (gfc_omp_namelist **list)
 	{
 	case MATCH_YES:
 	  gfc_set_sym_referenced (sym);
-	  p = gfc_get_omp_namelist ();
+	  p = gfc_get_omp_namelist_item ();
 	  if (head == NULL)
 	    {
 	      head = tail = p;
@@ -517,7 +522,7 @@ syntax:
   gfc_error ("Syntax error in OpenMP DEPEND SINK list at %C");
 
 cleanup:
-  gfc_free_omp_namelist (head);
+  gfc_free_omp_namelist_item (head);
   gfc_current_locus = old_loc;
   return MATCH_ERROR;
 }
@@ -649,10 +654,10 @@ match_oacc_clause_gwv (gfc_omp_clauses *cp, unsigned gwv)
 }
 
 static match
-gfc_match_oacc_clause_link (const char *str, gfc_omp_namelist **list)
+gfc_match_oacc_clause_link (const char *str, gfc_omp_namelist_item **list)
 {
-  gfc_omp_namelist *head = NULL;
-  gfc_omp_namelist *tail, *p;
+  gfc_omp_namelist_item *head = NULL;
+  gfc_omp_namelist_item *tail, *p;
   locus old_loc;
   char n[GFC_MAX_SYMBOL_LEN+1];
   gfc_symbol *sym;
@@ -679,7 +684,7 @@ gfc_match_oacc_clause_link (const char *str, gfc_omp_namelist **list)
 	      goto cleanup;
 	    }
 	  gfc_set_sym_referenced (sym);
-	  p = gfc_get_omp_namelist ();
+	  p = gfc_get_omp_namelist_item ();
 	  if (head == NULL)
 	    head = tail = p;
 	  else
@@ -714,7 +719,7 @@ gfc_match_oacc_clause_link (const char *str, gfc_omp_namelist **list)
       for (sym = st->n.common->head; sym; sym = sym->common_next)
 	{
 	  gfc_set_sym_referenced (sym);
-	  p = gfc_get_omp_namelist ();
+	  p = gfc_get_omp_namelist_item ();
 	  if (head == NULL)
 	    head = tail = p;
 	  else
@@ -944,15 +949,15 @@ omp_inv_mask::omp_inv_mask (const omp_mask &m) : omp_mask (m)
    mapping.  */
 
 static bool
-gfc_match_omp_map_clause (gfc_omp_namelist **list, gfc_omp_map_op map_op,
+gfc_match_omp_map_clause (gfc_omp_namelist_item **list, gfc_omp_map_op map_op,
 			  bool allow_common, bool allow_derived)
 {
-  gfc_omp_namelist **head = NULL;
+  gfc_omp_namelist_item **head = NULL;
   if (gfc_match_omp_variable_list ("", list, allow_common, NULL, &head, true,
 				   allow_derived)
       == MATCH_YES)
     {
-      gfc_omp_namelist *n;
+      gfc_omp_namelist_item *n;
       for (n = *head; n; n = n->next)
 	n->u.map_op = map_op;
       return true;
@@ -961,6 +966,79 @@ gfc_match_omp_map_clause (gfc_omp_namelist **list, gfc_omp_map_op map_op,
   return false;
 }
 
+
+const char*
+gfc_omp_get_clause_name (enum omp_list_clauses clause)
+{
+  switch (clause)
+    {
+    case OMP_LIST_PRIVATE: return "PRIVATE";
+    case OMP_LIST_FIRSTPRIVATE: return "FIRSTPRIVATE";
+    case OMP_LIST_LASTPRIVATE: return "LASTPRIVATE";
+    case OMP_LIST_COPYPRIVATE: return "COPYPRIVATE";
+    case OMP_LIST_SHARED: return "SHARED";
+    case OMP_LIST_COPYIN: return "COPYIN";
+    case OMP_LIST_UNIFORM: return "UNIFORM";
+    case OMP_LIST_ALIGNED: return "ALIGNED";
+    case OMP_LIST_LINEAR: return "LINEAR";
+    case OMP_LIST_DEPEND: return "DEPEND";
+    case OMP_LIST_MAP: return "MAP";
+    case OMP_LIST_TO: return "TO";
+    case OMP_LIST_FROM: return "FROM";
+    case OMP_LIST_REDUCTION:
+    case OMP_LIST_REDUCTION_INSCAN:
+    case OMP_LIST_REDUCTION_TASK: return "REDUCTION";
+    case OMP_LIST_IN_REDUCTION: return "IN_REDUCTION";
+    case OMP_LIST_TASK_REDUCTION: return "TASK_REDUCTION";
+    case OMP_LIST_DEVICE_RESIDENT: return "DEVICE_RESIDENT";
+    case OMP_LIST_LINK: return "LINK";
+    case OMP_LIST_USE_DEVICE: return "USE_DEVICE";
+    case OMP_LIST_CACHE: return "CACHE";
+    case OMP_LIST_IS_DEVICE_PTR: return "IS_DEVICE_PTR";
+    case OMP_LIST_USE_DEVICE_PTR: return "USE_DEVICE_PTR";
+    case OMP_LIST_USE_DEVICE_ADDR: return "USE_DEVICE_ADDR";
+    case OMP_LIST_NONTEMPORAL: return "NONTEMPORAL";
+    case OMP_LIST_UNSET: break;
+    }
+  gcc_unreachable ();
+  return "";
+}
+
+
+gfc_omp_namelist_item **
+gfc_omp_get_nm_ref (gfc_omp_clauses *clauses, enum omp_list_clauses clause)
+{
+  gfc_omp_namelist *found, *last = NULL;
+  for (found = clauses->lists; found; found = found->next)
+    {
+      if (found->clause == clause)
+	break;
+      last = found;
+    }
+  if (!found)
+    {
+      found = gfc_get_omp_namelist ();
+      found->clause = clause;
+      if (last)
+	last->next = found;
+      else
+        clauses->lists = found;
+    }
+  return &found->item;
+}
+
+
+gfc_omp_namelist_item *
+gfc_omp_get_nm_list (gfc_omp_clauses *clauses, enum omp_list_clauses clause)
+{
+  gfc_omp_namelist *found;
+  for (found = clauses->lists; found; found = found->next)
+    if (found->clause == clause)
+      break;
+  return found ? found->item : NULL;
+}
+
+
 /* reduction ( reduction-modifier, reduction-operator : variable-list )
    in_reduction ( reduction-operator : variable-list )
    task_reduction ( reduction-operator : variable-list )  */
@@ -977,31 +1055,31 @@ gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc,
     return MATCH_NO;
 
   locus old_loc = gfc_current_locus;
-  int list_idx = 0;
+  enum omp_list_clauses subclause = OMP_LIST_UNSET;
 
   if (pc == 'r' && !openacc)
     {
       if (gfc_match ("inscan") == MATCH_YES)
-	list_idx = OMP_LIST_REDUCTION_INSCAN;
+	subclause = OMP_LIST_REDUCTION_INSCAN;
       else if (gfc_match ("task") == MATCH_YES)
-	list_idx = OMP_LIST_REDUCTION_TASK;
+	subclause = OMP_LIST_REDUCTION_TASK;
       else if (gfc_match ("default") == MATCH_YES)
-	list_idx = OMP_LIST_REDUCTION;
-      if (list_idx != 0 && gfc_match (", ") != MATCH_YES)
+	subclause = OMP_LIST_REDUCTION;
+      if (subclause != OMP_LIST_UNSET && gfc_match (", ") != MATCH_YES)
 	{
 	  gfc_error ("Comma expected at %C");
 	  gfc_current_locus = old_loc;
 	  return MATCH_NO;
 	}
-      if (list_idx == 0)
-	list_idx = OMP_LIST_REDUCTION;
+      if (subclause == OMP_LIST_UNSET)
+	subclause = OMP_LIST_REDUCTION;
     }
   else if (pc == 'i')
-    list_idx = OMP_LIST_IN_REDUCTION;
+    subclause = OMP_LIST_IN_REDUCTION;
   else if (pc == 't')
-    list_idx = OMP_LIST_TASK_REDUCTION;
+    subclause = OMP_LIST_TASK_REDUCTION;
   else
-    list_idx = OMP_LIST_REDUCTION;
+    subclause = OMP_LIST_REDUCTION;
 
   gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
   char buffer[GFC_MAX_SYMBOL_LEN + 3];
@@ -1086,24 +1164,25 @@ gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc,
     buffer[0] = '\0';
   gfc_omp_udr *udr = (buffer[0] ? gfc_find_omp_udr (gfc_current_ns, buffer, NULL)
 				: NULL);
-  gfc_omp_namelist **head = NULL;
+  gfc_omp_namelist_item **head = NULL;
   if (rop == OMP_REDUCTION_NONE && udr)
     rop = OMP_REDUCTION_USER;
 
-  if (gfc_match_omp_variable_list (" :", &c->lists[list_idx], false, NULL,
-				   &head, openacc, allow_derived) != MATCH_YES)
+  gfc_omp_namelist_item **list = gfc_omp_get_nm_ref (c, subclause);
+  if (gfc_match_omp_variable_list (" :", list, false, NULL, &head, openacc,
+				   allow_derived) != MATCH_YES)
     {
       gfc_current_locus = old_loc;
       return MATCH_NO;
     }
-  gfc_omp_namelist *n;
+  gfc_omp_namelist_item *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);
+      gfc_free_omp_namelist_item (n);
     }
   else
     for (n = *head; n; n = n->next)
@@ -1148,7 +1227,7 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
       first = false;
       gfc_gobble_whitespace ();
       bool end_colon;
-      gfc_omp_namelist **head;
+      gfc_omp_namelist_item **head;
       old_loc = gfc_current_locus;
       char pc = gfc_peek_ascii_char ();
       switch (pc)
@@ -1157,17 +1236,16 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	  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_match_omp_variable_list (
+		   "aligned (", gfc_omp_get_nm_ref (c, OMP_LIST_ALIGNED),
+		   false, &end_colon, &head) == MATCH_YES)
 	    {
 	      gfc_expr *alignment = NULL;
-	      gfc_omp_namelist *n;
+	      gfc_omp_namelist_item *n;
 
 	      if (end_colon && gfc_match (" %e )", &alignment) != MATCH_YES)
 		{
-		  gfc_free_omp_namelist (*head);
+		  gfc_free_omp_namelist_item (*head);
 		  gfc_current_locus = old_loc;
 		  *head = NULL;
 		  break;
@@ -1227,9 +1305,9 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	    }
 	  if ((mask & OMP_CLAUSE_ATTACH)
 	      && gfc_match ("attach ( ") == MATCH_YES
-	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
-					   OMP_MAP_ATTACH, false,
-					   allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_ATTACH, false, allow_derived))
 	    continue;
 	  break;
 	case 'c':
@@ -1265,39 +1343,43 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	    }
 	  if ((mask & OMP_CLAUSE_COPY)
 	      && gfc_match ("copy ( ") == MATCH_YES
-	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
-					   OMP_MAP_TOFROM, true,
-					   allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_TOFROM, true, allow_derived))
 	    continue;
 	  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_TO, true,
-						   allow_derived))
+		      && gfc_match_omp_map_clause (
+			   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+			   OMP_MAP_TO, true, allow_derived))
 		    continue;
 		}
-	      else if (gfc_match_omp_variable_list ("copyin (",
-						    &c->lists[OMP_LIST_COPYIN],
-						    true) == MATCH_YES)
+	      else if (gfc_match_omp_variable_list (
+			 "copyin (",
+			 gfc_omp_get_nm_ref (c, 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_FROM, true, allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_FROM, true, allow_derived))
 	    continue;
 	  if ((mask & OMP_CLAUSE_COPYPRIVATE)
-	      && gfc_match_omp_variable_list ("copyprivate (",
-					      &c->lists[OMP_LIST_COPYPRIVATE],
-					      true) == MATCH_YES)
+	      && gfc_match_omp_variable_list (
+		   "copyprivate (",
+		   gfc_omp_get_nm_ref (c, 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_ALLOC, true, allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_ALLOC, true, allow_derived))
 	    continue;
 	  break;
 	case 'd':
@@ -1332,9 +1414,9 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	    }
 	  if ((mask & OMP_CLAUSE_DELETE)
 	      && gfc_match ("delete ( ") == MATCH_YES
-	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
-					   OMP_MAP_RELEASE, true,
-					   allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_RELEASE, true, allow_derived))
 	    continue;
 	  if ((mask & OMP_CLAUSE_DEPEND)
 	      && gfc_match ("depend ( ") == MATCH_YES)
@@ -1355,8 +1437,8 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 		}
 	      else if (gfc_match ("sink : ") == MATCH_YES)
 		{
-		  if (gfc_match_omp_depend_sink (&c->lists[OMP_LIST_DEPEND])
-		      == MATCH_YES)
+		  if (gfc_match_omp_depend_sink (
+			gfc_omp_get_nm_ref (c, OMP_LIST_DEPEND)) == MATCH_YES)
 		    continue;
 		  m = MATCH_NO;
 		}
@@ -1364,12 +1446,11 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 		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_match_omp_variable_list (
+			" : ", gfc_omp_get_nm_ref (c, OMP_LIST_DEPEND),
+			false, NULL, &head, true) == MATCH_YES)
 		{
-		  gfc_omp_namelist *n;
+		  gfc_omp_namelist_item *n;
 		  for (n = *head; n; n = n->next)
 		    n->u.depend_op = depend_op;
 		  continue;
@@ -1379,9 +1460,9 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	    }
 	  if ((mask & OMP_CLAUSE_DETACH)
 	      && gfc_match ("detach ( ") == MATCH_YES
-	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
-					   OMP_MAP_DETACH, false,
-					   allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_DETACH, false, allow_derived))
 	    continue;
 	  if ((mask & OMP_CLAUSE_DEVICE)
 	      && !openacc
@@ -1391,15 +1472,15 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	  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, true,
-					   allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_FORCE_TO, true, allow_derived))
 	    continue;
 	  if ((mask & OMP_CLAUSE_DEVICEPTR)
 	      && gfc_match ("deviceptr ( ") == MATCH_YES
-	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
-					   OMP_MAP_FORCE_DEVICEPTR, false,
-					   allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_FORCE_DEVICEPTR, false, allow_derived))
 	    continue;
 	  if ((mask & OMP_CLAUSE_DEVICE_TYPE)
 	      && gfc_match ("device_type ( ") == MATCH_YES)
@@ -1422,7 +1503,8 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	  if ((mask & OMP_CLAUSE_DEVICE_RESIDENT)
 	      && gfc_match_omp_variable_list
 		   ("device_resident (",
-		    &c->lists[OMP_LIST_DEVICE_RESIDENT], true) == MATCH_YES)
+		    gfc_omp_get_nm_ref (c, OMP_LIST_DEVICE_RESIDENT), true)
+		 == MATCH_YES)
 	    continue;
 	  if ((mask & OMP_CLAUSE_DIST_SCHEDULE)
 	      && c->dist_sched_kind == OMP_SCHED_NONE
@@ -1456,14 +1538,15 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	      continue;
 	    }
 	  if ((mask & OMP_CLAUSE_FIRSTPRIVATE)
-	      && gfc_match_omp_variable_list ("firstprivate (",
-					      &c->lists[OMP_LIST_FIRSTPRIVATE],
-					      true) == MATCH_YES)
+	      && gfc_match_omp_variable_list (
+		    "firstprivate (",
+		    gfc_omp_get_nm_ref (c, 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)
+	      && gfc_match_omp_variable_list (
+		    "from (", gfc_omp_get_nm_ref (c, OMP_LIST_FROM),
+		    false, NULL, &head, true) == MATCH_YES)
 	    continue;
 	  break;
 	case 'g':
@@ -1494,9 +1577,9 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	    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, true,
-					   allow_derived))
+	      && gfc_match_omp_map_clause (
+		    gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		    OMP_MAP_FORCE_FROM, true, allow_derived))
 	    continue;
 	  break;
 	case 'i':
@@ -1561,7 +1644,8 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	  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)
+		    gfc_omp_get_nm_ref (c, OMP_LIST_IS_DEVICE_PTR), false)
+		 == MATCH_YES)
 	    continue;
 	  break;
 	case 'l':
@@ -1570,11 +1654,11 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	    {
 	      bool conditional = gfc_match ("conditional : ") == MATCH_YES;
 	      head = NULL;
-	      if (gfc_match_omp_variable_list ("",
-					       &c->lists[OMP_LIST_LASTPRIVATE],
-					       false, NULL, &head) == MATCH_YES)
+	      if (gfc_match_omp_variable_list (
+		    "", gfc_omp_get_nm_ref (c, OMP_LIST_LASTPRIVATE),
+		    false, NULL, &head) == MATCH_YES)
 		{
-		  gfc_omp_namelist *n;
+		  gfc_omp_namelist_item *n;
 		  for (n = *head; n; n = n->next)
 		    n->u.lastprivate_conditional = conditional;
 		  continue;
@@ -1590,25 +1674,21 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	      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)
+	      if (gfc_match_omp_variable_list (
+		    " ref (", gfc_omp_get_nm_ref (c, 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)
+	      else if (gfc_match_omp_variable_list (
+		       " val (", gfc_omp_get_nm_ref (c, 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)
+	      else if (gfc_match_omp_variable_list (
+		       " uval (", gfc_omp_get_nm_ref (c, 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)
+	      else if (gfc_match_omp_variable_list (
+		       "", gfc_omp_get_nm_ref (c, OMP_LIST_LINEAR),
+		       false, &end_colon, &head) == MATCH_YES)
 		linear_op = OMP_LINEAR_DEFAULT;
 	      else
 		{
@@ -1621,7 +1701,7 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 		    end_colon = true;
 		  else if (gfc_match (" )") != MATCH_YES)
 		    {
-		      gfc_free_omp_namelist (*head);
+		      gfc_free_omp_namelist_item (*head);
 		      gfc_current_locus = old_loc;
 		      *head = NULL;
 		      break;
@@ -1629,7 +1709,7 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 		}
 	      if (end_colon && gfc_match (" %e )", &step) != MATCH_YES)
 		{
-		  gfc_free_omp_namelist (*head);
+		  gfc_free_omp_namelist_item (*head);
 		  gfc_current_locus = old_loc;
 		  *head = NULL;
 		  break;
@@ -1643,20 +1723,20 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 		}
 	      (*head)->expr = step;
 	      if (linear_op != OMP_LINEAR_DEFAULT)
-		for (gfc_omp_namelist *n = *head; n; n = n->next)
+		for (gfc_omp_namelist_item *n = *head; n; n = n->next)
 		  n->u.linear_op = linear_op;
 	      continue;
 	    }
 	  if ((mask & OMP_CLAUSE_LINK)
 	      && openacc
-	      && (gfc_match_oacc_clause_link ("link (",
-					      &c->lists[OMP_LIST_LINK])
+	      && (gfc_match_oacc_clause_link (
+		    "link (", gfc_omp_get_nm_ref (c, OMP_LIST_LINK))
 		  == MATCH_YES))
 	    continue;
 	  else if ((mask & OMP_CLAUSE_LINK)
 		   && !openacc
-		   && (gfc_match_omp_to_link ("link (",
-					      &c->lists[OMP_LIST_LINK])
+		   && (gfc_match_omp_to_link (
+		         "link (", gfc_omp_get_nm_ref (c, OMP_LIST_LINK))
 		       == MATCH_YES))
 	    continue;
 	  break;
@@ -1687,11 +1767,11 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 		  always = false;
 		}
 	      head = NULL;
-	      if (gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_MAP],
-					       false, NULL, &head,
-					       true, true) == MATCH_YES)
+	      if (gfc_match_omp_variable_list (
+		    "", gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		    false, NULL, &head, true, true) == MATCH_YES)
 		{
-		  gfc_omp_namelist *n;
+		  gfc_omp_namelist_item *n;
 		  for (n = *head; n; n = n->next)
 		    n->u.map_op = map_op;
 		  continue;
@@ -1709,9 +1789,9 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	case 'n':
 	  if ((mask & OMP_CLAUSE_NO_CREATE)
 	      && gfc_match ("no_create ( ") == MATCH_YES
-	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
-					   OMP_MAP_IF_PRESENT, true,
-					   allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_IF_PRESENT, true, allow_derived))
 	    continue;
 	  if ((mask & OMP_CLAUSE_NOGROUP)
 	      && !c->nogroup
@@ -1721,9 +1801,10 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	      continue;
 	    }
 	  if ((mask & OMP_CLAUSE_NOTEMPORAL)
-	      && gfc_match_omp_variable_list ("nontemporal (",
-					      &c->lists[OMP_LIST_NONTEMPORAL],
-					      true) == MATCH_YES)
+	      && gfc_match_omp_variable_list (
+		   "nontemporal (",
+		   gfc_omp_get_nm_ref (c, OMP_LIST_NONTEMPORAL), true)
+		 == MATCH_YES)
 	    continue;
 	  if ((mask & OMP_CLAUSE_NOTINBRANCH)
 	      && !c->notinbranch
@@ -1803,59 +1884,66 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	case 'p':
 	  if ((mask & OMP_CLAUSE_COPY)
 	      && gfc_match ("pcopy ( ") == MATCH_YES
-	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
-					   OMP_MAP_TOFROM, true, allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_TOFROM, true, allow_derived))
 	    continue;
 	  if ((mask & OMP_CLAUSE_COPYIN)
 	      && gfc_match ("pcopyin ( ") == MATCH_YES
-	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
-					   OMP_MAP_TO, true, allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_TO, true, allow_derived))
 	    continue;
 	  if ((mask & OMP_CLAUSE_COPYOUT)
 	      && gfc_match ("pcopyout ( ") == MATCH_YES
-	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
-					   OMP_MAP_FROM, true, allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_FROM, true, allow_derived))
 	    continue;
 	  if ((mask & OMP_CLAUSE_CREATE)
 	      && gfc_match ("pcreate ( ") == MATCH_YES
-	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
-					   OMP_MAP_ALLOC, true, allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_ALLOC, true, allow_derived))
 	    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, false,
-					   allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_FORCE_PRESENT, false, allow_derived))
 	    continue;
 	  if ((mask & OMP_CLAUSE_COPY)
 	      && gfc_match ("present_or_copy ( ") == MATCH_YES
-	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
-					   OMP_MAP_TOFROM, true,
-					   allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_TOFROM, true, allow_derived))
 	    continue;
 	  if ((mask & OMP_CLAUSE_COPYIN)
 	      && gfc_match ("present_or_copyin ( ") == MATCH_YES
-	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
-					   OMP_MAP_TO, true, allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_TO, true, allow_derived))
 	    continue;
 	  if ((mask & OMP_CLAUSE_COPYOUT)
 	      && gfc_match ("present_or_copyout ( ") == MATCH_YES
-	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
-					   OMP_MAP_FROM, true, allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_FROM, true, allow_derived))
 	    continue;
 	  if ((mask & OMP_CLAUSE_CREATE)
 	      && gfc_match ("present_or_create ( ") == MATCH_YES
-	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
-					   OMP_MAP_ALLOC, true, allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_ALLOC, true, allow_derived))
 	    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)
+	      && gfc_match_omp_variable_list (
+		   "private (", gfc_omp_get_nm_ref (c, OMP_LIST_PRIVATE),
+		   true) == MATCH_YES)
 	    continue;
 	  if ((mask & OMP_CLAUSE_PROC_BIND)
 	      && c->proc_bind == OMP_PROC_BIND_UNKNOWN)
@@ -1987,9 +2075,9 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	    }
 	  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, true,
-					   allow_derived))
+	      && gfc_match_omp_map_clause (
+		   gfc_omp_get_nm_ref (c, OMP_LIST_MAP),
+		   OMP_MAP_FORCE_FROM, true, allow_derived))
 	    continue;
 	  if ((mask & OMP_CLAUSE_SEQ)
 	      && !c->seq
@@ -2008,9 +2096,9 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	      continue;
 	    }
 	  if ((mask & OMP_CLAUSE_SHARED)
-	      && gfc_match_omp_variable_list ("shared (",
-					      &c->lists[OMP_LIST_SHARED],
-					      true) == MATCH_YES)
+	      && gfc_match_omp_variable_list (
+		   "shared (", gfc_omp_get_nm_ref (c, OMP_LIST_SHARED), true)
+		 == MATCH_YES)
 	    continue;
 	  if ((mask & OMP_CLAUSE_SIMDLEN)
 	      && c->simdlen_expr == NULL
@@ -2048,21 +2136,22 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	    continue;
 	  if ((mask & OMP_CLAUSE_TO) && (mask & OMP_CLAUSE_LINK))
 	    {
-	      if (gfc_match_omp_to_link ("to (", &c->lists[OMP_LIST_TO])
+	      if (gfc_match_omp_to_link (
+		    "to (", gfc_omp_get_nm_ref (c, OMP_LIST_TO))
 		  == MATCH_YES)
 		continue;
 	    }
 	  else if ((mask & OMP_CLAUSE_TO)
-	      && gfc_match_omp_variable_list ("to (",
-					      &c->lists[OMP_LIST_TO], false,
-					      NULL, &head, true) == MATCH_YES)
+		   && gfc_match_omp_variable_list (
+			"to (", gfc_omp_get_nm_ref (c, 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)
+	      && gfc_match_omp_variable_list (
+		   "uniform (", gfc_omp_get_nm_ref (c, OMP_LIST_UNIFORM), false)
+		 == MATCH_YES)
 	    continue;
 	  if ((mask & OMP_CLAUSE_UNTIED)
 	      && !c->untied
@@ -2080,19 +2169,22 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	      continue;
 	    }
 	  if ((mask & OMP_CLAUSE_USE_DEVICE)
-	      && gfc_match_omp_variable_list ("use_device (",
-					      &c->lists[OMP_LIST_USE_DEVICE],
-					      true) == MATCH_YES)
+	      && gfc_match_omp_variable_list (
+		   "use_device (",
+		   gfc_omp_get_nm_ref (c, 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)
+		    gfc_omp_get_nm_ref (c, OMP_LIST_USE_DEVICE_PTR),
+		    false) == MATCH_YES)
 	    continue;
 	  if ((mask & OMP_CLAUSE_USE_DEVICE_ADDR)
 	      && gfc_match_omp_variable_list
 		   ("use_device_addr (",
-		    &c->lists[OMP_LIST_USE_DEVICE_ADDR], false) == MATCH_YES)
+		    gfc_omp_get_nm_ref (c, OMP_LIST_USE_DEVICE_ADDR),
+		    false) == MATCH_YES)
 	    continue;
 	  break;
 	case 'v':
@@ -2324,7 +2416,7 @@ match
 gfc_match_oacc_declare (void)
 {
   gfc_omp_clauses *c;
-  gfc_omp_namelist *n;
+  gfc_omp_namelist_item *n;
   gfc_namespace *ns = gfc_current_ns;
   gfc_oacc_declare *new_oc;
   bool module_var = false;
@@ -2334,13 +2426,16 @@ gfc_match_oacc_declare (void)
       != MATCH_YES)
     return MATCH_ERROR;
 
-  for (n = c->lists[OMP_LIST_DEVICE_RESIDENT]; n != NULL; n = n->next)
+  n = gfc_omp_get_nm_list (c, OMP_LIST_DEVICE_RESIDENT);
+  for (; n != NULL; n = n->next)
     n->sym->attr.oacc_declare_device_resident = 1;
 
-  for (n = c->lists[OMP_LIST_LINK]; n != NULL; n = n->next)
+  n = gfc_omp_get_nm_list (c, OMP_LIST_LINK);
+  for (; n != NULL; n = n->next)
     n->sym->attr.oacc_declare_link = 1;
 
-  for (n = c->lists[OMP_LIST_MAP]; n != NULL; n = n->next)
+  n = gfc_omp_get_nm_list (c, OMP_LIST_MAP);
+  for (; n != NULL; n = n->next)
     {
       gfc_symbol *s = n->sym;
 
@@ -2423,7 +2518,7 @@ gfc_match_oacc_update (void)
       != MATCH_YES)
     return MATCH_ERROR;
 
-  if (!c->lists[OMP_LIST_MAP])
+  if (!gfc_omp_get_nm_list (c, OMP_LIST_MAP))
     {
       gfc_error ("%<acc update%> must contain at least one "
 		 "%<device%> or %<host%> or %<self%> clause at %L", &here);
@@ -2501,9 +2596,9 @@ gfc_match_oacc_cache (void)
      subarrays", which we're currently not checking here.  Either check this
      after the call of gfc_match_omp_variable_list, or add something like a
      only_sections variant next to its allow_sections parameter.  */
-  match m = gfc_match_omp_variable_list (" (",
-					 &c->lists[OMP_LIST_CACHE], true,
-					 NULL, NULL, true);
+  match m = gfc_match_omp_variable_list (
+	      " (", gfc_omp_get_nm_ref (c, OMP_LIST_CACHE),
+	      true, NULL, NULL, true);
   if (m != MATCH_YES)
     {
       gfc_free_omp_clauses(c);
@@ -2911,7 +3006,7 @@ gfc_match_omp_do_simd (void)
 match
 gfc_match_omp_flush (void)
 {
-  gfc_omp_namelist *list = NULL;
+  gfc_omp_namelist_item *list = NULL;
   gfc_omp_clauses *c = NULL;
   gfc_gobble_whitespace ();
   enum gfc_omp_memorder mo = OMP_MEMORDER_UNSET;
@@ -2936,14 +3031,14 @@ gfc_match_omp_flush (void)
     {
       gfc_error ("List specified together with memory order clause in FLUSH "
 		 "directive at %C");
-      gfc_free_omp_namelist (list);
-      gfc_free_omp_clauses (c);
+      gfc_free_omp_namelist_item (list);
       return MATCH_ERROR;
     }
   if (gfc_match_omp_eos () != MATCH_YES)
     {
       gfc_error ("Unexpected junk after $OMP FLUSH statement at %C");
-      gfc_free_omp_namelist (list);
+      gfc_free_omp_namelist_item (list);
+      free (list);
       gfc_free_omp_clauses (c);
       return MATCH_ERROR;
     }
@@ -3387,8 +3482,7 @@ gfc_match_omp_declare_target (void)
   locus old_loc;
   match m;
   gfc_omp_clauses *c = NULL;
-  int list;
-  gfc_omp_namelist *n;
+  gfc_omp_namelist_item *n;
   gfc_symbol *s;
 
   old_loc = gfc_current_locus;
@@ -3416,7 +3510,7 @@ gfc_match_omp_declare_target (void)
     {
       c = gfc_get_omp_clauses ();
       gfc_current_locus = old_loc;
-      m = gfc_match_omp_to_link (" (", &c->lists[OMP_LIST_TO]);
+      m = gfc_match_omp_to_link (" (", gfc_omp_get_nm_ref (c, OMP_LIST_TO));
       if (m != MATCH_YES)
 	goto syntax;
       if (gfc_match_omp_eos () != MATCH_YES)
@@ -3430,17 +3524,19 @@ gfc_match_omp_declare_target (void)
 
   gfc_buffer_error (false);
 
-  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)
+  for (gfc_omp_namelist *list = c->lists; list; list = list->next)
+    for (n = (list->clause == OMP_LIST_TO || list->clause == OMP_LIST_LINK)
+	     ? list->item : NULL;
+	 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)
+  for (gfc_omp_namelist *list = c->lists; list; list = list->next)
+    for (n = (list->clause == OMP_LIST_TO || list->clause == OMP_LIST_LINK)
+	     ? list->item : NULL;
+	 n; n = n->next)
       if (n->sym)
 	{
 	  if (n->sym->attr.in_common)
@@ -3448,13 +3544,13 @@ gfc_match_omp_declare_target (void)
 			   "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)
+		   && list->clause != 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)
+		   && list->clause == OMP_LIST_LINK)
 	    gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
 			   "mentioned in TO clause and later in LINK clause",
 			   &n->where);
@@ -3465,7 +3561,7 @@ gfc_match_omp_declare_target (void)
 	  else if (gfc_add_omp_declare_target (&n->sym->attr, n->sym->name,
 					       &n->sym->declared_at))
 	    {
-	      if (list == OMP_LIST_LINK)
+	      if (list->clause == OMP_LIST_LINK)
 		gfc_add_omp_declare_target_link (&n->sym->attr, n->sym->name,
 						 &n->sym->declared_at);
 	    }
@@ -3482,13 +3578,13 @@ gfc_match_omp_declare_target (void)
 	}
       else if (n->u.common->omp_declare_target
 	       && n->u.common->omp_declare_target_link
-	       && list != OMP_LIST_LINK)
+	       && list->clause != 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)
+	       && list->clause == OMP_LIST_LINK)
 	gfc_error_now ("OMP DECLARE TARGET COMMON at %L previously "
 		       "mentioned in TO clause and later in LINK clause",
 		       &n->where);
@@ -3499,7 +3595,8 @@ gfc_match_omp_declare_target (void)
       else
 	{
 	  n->u.common->omp_declare_target = 1;
-	  n->u.common->omp_declare_target_link = (list == OMP_LIST_LINK);
+	  n->u.common->omp_declare_target_link
+	    = (list->clause == OMP_LIST_LINK);
 	  if (n->u.common->omp_device_type != OMP_DEVICE_TYPE_UNSET
 	      && n->u.common->omp_device_type != c->device_type)
 	    gfc_error_now ("COMMON at %L set in previous OMP DECLARE "
@@ -3513,7 +3610,7 @@ gfc_match_omp_declare_target (void)
 	      if (gfc_add_omp_declare_target (&s->attr, s->name,
 					      &s->declared_at))
 		{
-		  if (list == OMP_LIST_LINK)
+		  if (list->clause == OMP_LIST_LINK)
 		    gfc_add_omp_declare_target_link (&s->attr, s->name,
 						     &s->declared_at);
 		}
@@ -3525,7 +3622,9 @@ gfc_match_omp_declare_target (void)
 	      s->attr.omp_device_type = c->device_type;
 	    }
 	}
-  if (c->device_type && !c->lists[OMP_LIST_TO] && !c->lists[OMP_LIST_LINK])
+  if (c->device_type
+      && !gfc_omp_get_nm_list (c, OMP_LIST_TO)
+      && !gfc_omp_get_nm_list (c, OMP_LIST_LINK))
     gfc_warning_now (0, "OMP DECLARE TARGET directive at %L with only "
 			"DEVICE_TYPE clause is ignored", &old_loc);
 
@@ -4561,7 +4660,7 @@ resolve_omp_udr_callback2 (gfc_expr **e, int *, void *)
 
 
 static gfc_code *
-resolve_omp_udr_clause (gfc_omp_namelist *n, gfc_namespace *ns,
+resolve_omp_udr_clause (gfc_omp_namelist_item *n, gfc_namespace *ns,
 			gfc_symbol *sym1, gfc_symbol *sym2)
 {
   gfc_code *copy;
@@ -4619,21 +4718,11 @@ static void
 resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 		     gfc_namespace *ns, bool openacc = false)
 {
-  gfc_omp_namelist *n;
+  gfc_omp_namelist_item *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", "REDUCTION" /*inscan*/, "REDUCTION" /*task*/,
-	"IN_REDUCTION", "TASK_REDUCTION",
-	"DEVICE_RESIDENT", "LINK", "USE_DEVICE",
-	"CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR", "USE_DEVICE_ADDR",
-	"NONTEMPORAL" };
-  STATIC_ASSERT (ARRAY_SIZE (clause_names) == OMP_LIST_NUM);
 
   if (omp_clauses == NULL)
     return;
@@ -4807,8 +4896,8 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 
   /* Check that no symbol appears on multiple clauses, except that
      a symbol can appear on both firstprivate and lastprivate.  */
-  for (list = 0; list < OMP_LIST_NUM; list++)
-    for (n = omp_clauses->lists[list]; n; n = n->next)
+  for (gfc_omp_namelist *list = omp_clauses->lists; list; list = list->next)
+    for (n = list->item; n; n = n->next)
       {
 	n->sym->mark = 0;
 	n->sym->comp_mark = 0;
@@ -4849,7 +4938,7 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 		  continue;
 	      }
 	  }
-	if (list == OMP_LIST_MAP
+	if (list->clause == OMP_LIST_MAP
 	    && n->sym->attr.flavor == FL_PARAMETER)
 	  {
 	    if (openacc)
@@ -4866,20 +4955,20 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 		     &n->where);
       }
 
-  for (list = 0; list < OMP_LIST_NUM; list++)
-    if (list != OMP_LIST_FIRSTPRIVATE
-	&& list != OMP_LIST_LASTPRIVATE
-	&& list != OMP_LIST_ALIGNED
-	&& list != OMP_LIST_DEPEND
-	&& (list != OMP_LIST_MAP || openacc)
-	&& list != OMP_LIST_FROM
-	&& list != OMP_LIST_TO
-	&& (list != OMP_LIST_REDUCTION || !openacc)
-	&& list != OMP_LIST_REDUCTION_INSCAN
-	&& list != OMP_LIST_REDUCTION_TASK
-	&& list != OMP_LIST_IN_REDUCTION
-	&& list != OMP_LIST_TASK_REDUCTION)
-      for (n = omp_clauses->lists[list]; n; n = n->next)
+  for (gfc_omp_namelist *list = omp_clauses->lists; list; list = list->next)
+    if (list->clause != OMP_LIST_FIRSTPRIVATE
+	&& list->clause != OMP_LIST_LASTPRIVATE
+	&& list->clause != OMP_LIST_ALIGNED
+	&& list->clause != OMP_LIST_DEPEND
+	&& (list->clause != OMP_LIST_MAP || openacc)
+	&& list->clause != OMP_LIST_FROM
+	&& list->clause != OMP_LIST_TO
+	&& (list->clause != OMP_LIST_REDUCTION || !openacc)
+	&& list->clause != OMP_LIST_REDUCTION_INSCAN
+	&& list->clause != OMP_LIST_REDUCTION_TASK
+	&& list->clause != OMP_LIST_IN_REDUCTION
+	&& list->clause != OMP_LIST_TASK_REDUCTION)
+      for (n = list->item; n; n = n->next)
 	{
 	  bool component_ref_p = false;
 
@@ -4904,18 +4993,19 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 		n->sym->mark = 1;
 	    }
 	}
+  for (gfc_omp_namelist *list = omp_clauses->lists; list; list = list->next)
+    if (list->clause == OMP_LIST_FIRSTPRIVATE
+	|| list->clause == OMP_LIST_LASTPRIVATE)
+      for (n = list->item; n; n = n->next)
+	if (n->sym->mark)
+	  {
+	    gfc_error ("Symbol %qs present on multiple clauses at %L",
+		       n->sym->name, &n->where);
+	    n->sym->mark = 0;
+	  }
 
-  gcc_assert (OMP_LIST_LASTPRIVATE == OMP_LIST_FIRSTPRIVATE + 1);
-  for (list = OMP_LIST_FIRSTPRIVATE; list <= OMP_LIST_LASTPRIVATE; list++)
-    for (n = omp_clauses->lists[list]; n; n = n->next)
-      if (n->sym->mark)
-	{
-	  gfc_error ("Symbol %qs present on multiple clauses at %L",
-		     n->sym->name, &n->where);
-	  n->sym->mark = 0;
-	}
-
-  for (n = omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; n; n = n->next)
+  for (n = gfc_omp_get_nm_list (omp_clauses, OMP_LIST_FIRSTPRIVATE);
+       n; n = n->next)
     {
       if (n->sym->mark)
 	gfc_error ("Symbol %qs present on multiple clauses at %L",
@@ -4923,10 +5013,12 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
       else
 	n->sym->mark = 1;
     }
-  for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
+  for (n = gfc_omp_get_nm_list (omp_clauses, OMP_LIST_LASTPRIVATE);
+       n; n = n->next)
     n->sym->mark = 0;
 
-  for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
+  for (n = gfc_omp_get_nm_list (omp_clauses, OMP_LIST_LASTPRIVATE);
+       n; n = n->next)
     {
       if (n->sym->mark)
 	gfc_error ("Symbol %qs present on multiple clauses at %L",
@@ -4935,10 +5027,10 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 	n->sym->mark = 1;
     }
 
-  for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
+  for (n = gfc_omp_get_nm_list (omp_clauses, OMP_LIST_ALIGNED); n; n = n->next)
     n->sym->mark = 0;
 
-  for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
+  for (n = gfc_omp_get_nm_list (omp_clauses, OMP_LIST_ALIGNED); n; n = n->next)
     {
       if (n->sym->mark)
 	gfc_error ("Symbol %qs present on multiple clauses at %L",
@@ -4950,10 +5042,12 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
   /* OpenACC reductions.  */
   if (openacc)
     {
-      for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
+      for (n = gfc_omp_get_nm_list (omp_clauses, OMP_LIST_REDUCTION);
+	   n; n = n->next)
 	n->sym->mark = 0;
 
-      for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
+      for (n = gfc_omp_get_nm_list (omp_clauses, OMP_LIST_REDUCTION);
+	   n; n = n->next)
 	{
 	  if (n->sym->mark)
 	    gfc_error ("Symbol %qs present on multiple clauses at %L",
@@ -4968,12 +5062,12 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 	}
     }
   
-  for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
+  for (n = gfc_omp_get_nm_list (omp_clauses, OMP_LIST_TO); n; n = n->next)
     n->sym->mark = 0;
-  for (n = omp_clauses->lists[OMP_LIST_FROM]; n; n = n->next)
+  for (n = gfc_omp_get_nm_list (omp_clauses, OMP_LIST_FROM); n; n = n->next)
     if (n->expr == NULL)
       n->sym->mark = 1;
-  for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
+  for (n = gfc_omp_get_nm_list (omp_clauses, OMP_LIST_TO); n; n = n->next)
     {
       if (n->expr == NULL && n->sym->mark)
 	gfc_error ("Symbol %qs present on both FROM and TO clauses at %L",
@@ -4982,12 +5076,12 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 	n->sym->mark = 1;
     }
 
-  for (list = 0; list < OMP_LIST_NUM; list++)
-    if ((n = omp_clauses->lists[list]) != NULL)
+  for (gfc_omp_namelist *list = omp_clauses->lists; list; list = list->next)
       {
-	const char *name = clause_names[list];
+	const char *name = gfc_omp_get_clause_name (list->clause);
+	n = list->item;
 
-	switch (list)
+	switch (list->clause)
 	  {
 	  case OMP_LIST_COPYIN:
 	    for (; n != NULL; n = n->next)
@@ -5058,7 +5152,7 @@ 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 (list->clause == OMP_LIST_DEPEND)
 		  {
 		    if (n->u.depend_op == OMP_DEPEND_SINK_FIRST
 			|| n->u.depend_op == OMP_DEPEND_SINK)
@@ -5106,8 +5200,8 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 			   array isn't contiguous.  An expression such as
 			   arr(-n:n,-n:n) could be contiguous even if it looks
 			   like it may not be.  */
-			if (list != OMP_LIST_CACHE
-			    && list != OMP_LIST_DEPEND
+			if (list->clause != OMP_LIST_CACHE
+			    && list->clause != OMP_LIST_DEPEND
 			    && !gfc_is_simply_contiguous (n->expr, false, true)
 			    && gfc_is_not_contiguous (n->expr))
 			  gfc_error ("Array is not contiguous at %L",
@@ -5153,7 +5247,7 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 					 n->sym->name, name, &n->where);
 			      break;
 			    }
-			  else if (list == OMP_LIST_DEPEND
+			  else if (list->clause == OMP_LIST_DEPEND
 				   && ar->start[i]
 				   && ar->start[i]->expr_type == EXPR_CONSTANT
 				   && ar->end[i]
@@ -5170,25 +5264,25 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 		  }
 		else if (openacc)
 		  {
-		    if (list == OMP_LIST_MAP
+		    if (list->clause == OMP_LIST_MAP
 			&& n->u.map_op == OMP_MAP_FORCE_DEVICEPTR)
 		      resolve_oacc_deviceptr_clause (n->sym, n->where, name);
 		    else
 		      resolve_oacc_data_clauses (n->sym, n->where, name);
 		  }
-		else if (list != OMP_LIST_DEPEND
+		else if (list->clause != OMP_LIST_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 (!openacc
-		    && list == OMP_LIST_MAP
+		    && list->clause == OMP_LIST_MAP
 		    && n->sym->ts.type == BT_DERIVED
 		    && n->sym->ts.u.derived->attr.alloc_comp)
 		  gfc_error ("List item %qs with allocatable components is not "
 			     "permitted in map clause at %L", n->sym->name,
 			     &n->where);
-		if (list == OMP_LIST_MAP && !openacc)
+		if (list->clause == OMP_LIST_MAP && !openacc)
 		  switch (code->op)
 		    {
 		    case EXEC_OMP_TARGET:
@@ -5246,8 +5340,8 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 		    }
 	      }
 
-	    if (list != OMP_LIST_DEPEND)
-	      for (n = omp_clauses->lists[list]; n != NULL; n = n->next)
+	    if (list->clause != OMP_LIST_DEPEND)
+	      for (n = list->item; n != NULL; n = n->next)
 		{
 		  n->sym->attr.referenced = 1;
 		  if (n->sym->attr.threadprivate)
@@ -5284,11 +5378,12 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 	    for (; n != NULL; n = n->next)
 	      {
 		bool bad = false;
-		bool is_reduction = (list == OMP_LIST_REDUCTION
-				     || list == OMP_LIST_REDUCTION_INSCAN
-				     || list == OMP_LIST_REDUCTION_TASK
-				     || list == OMP_LIST_IN_REDUCTION
-				     || list == OMP_LIST_TASK_REDUCTION);
+		bool is_reduction
+		  = (list->clause == OMP_LIST_REDUCTION
+		     || list->clause == OMP_LIST_REDUCTION_INSCAN
+		     || list->clause == OMP_LIST_REDUCTION_TASK
+		     || list->clause == OMP_LIST_IN_REDUCTION
+		     || list->clause == OMP_LIST_TASK_REDUCTION);
 		if (n->sym->attr.threadprivate)
 		  gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
 			     n->sym->name, name, &n->where);
@@ -5298,7 +5393,7 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 		if (n->sym->attr.associate_var)
 		  gfc_error ("ASSOCIATE name %qs in %s clause at %L",
 			     n->sym->name, name, &n->where);
-		if (list != OMP_LIST_PRIVATE && is_reduction)
+		if (list->clause != OMP_LIST_PRIVATE && is_reduction)
 		  {
 		    if (n->sym->attr.proc_pointer)
 		      gfc_error ("Procedure pointer %qs in %s clause at %L",
@@ -5323,7 +5418,7 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 			     "NAMELIST statement at %L",
 			     n->sym->name, name, &n->where);
 		if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
-		  switch (list)
+		  switch (list->clause)
 		    {
 		    case OMP_LIST_PRIVATE:
 		    case OMP_LIST_LASTPRIVATE:
@@ -5336,7 +5431,7 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 		      break;
 		    }
 
-		switch (list)
+		switch (list->clause)
 		  {
 		  case OMP_LIST_REDUCTION_INSCAN:
 		  case OMP_LIST_REDUCTION_TASK:
@@ -5497,9 +5592,10 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 				&& 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)
+				gfc_omp_namelist_item *n2;
+				n2 = gfc_omp_get_nm_list (omp_clauses,
+							  OMP_LIST_UNIFORM);
+				for (; n2; n2 = n2->next)
 				  if (n2->sym == expr->symtree->n.sym)
 				    break;
 				if (n2)
@@ -5614,9 +5710,9 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 	       "on ORDERED directive at %L", &code->loc);
   if (!openacc
       && code
-      && omp_clauses->lists[OMP_LIST_MAP] == NULL
-      && omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR] == NULL
-      && omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] == NULL)
+      && !gfc_omp_get_nm_list (omp_clauses, OMP_LIST_MAP)
+      && !gfc_omp_get_nm_list (omp_clauses, OMP_LIST_USE_DEVICE_PTR)
+      && !gfc_omp_get_nm_list (omp_clauses, OMP_LIST_USE_DEVICE_ADDR))
     {
       const char *p = NULL;
       switch (code->op)
@@ -6163,8 +6259,7 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
 {
   struct fortran_omp_context ctx;
   gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
-  gfc_omp_namelist *n;
-  int list;
+  gfc_omp_namelist_item *n;
 
   ctx.code = code;
   ctx.sharing_clauses = new hash_set<gfc_symbol *>;
@@ -6173,8 +6268,8 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
   ctx.is_openmp = true;
   omp_current_ctx = &ctx;
 
-  for (list = 0; list < OMP_LIST_NUM; list++)
-    switch (list)
+  for (gfc_omp_namelist *list = omp_clauses->lists; list; list = list->next)
+    switch (list->clause)
       {
       case OMP_LIST_SHARED:
       case OMP_LIST_PRIVATE:
@@ -6186,7 +6281,7 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
       case OMP_LIST_IN_REDUCTION:
       case OMP_LIST_TASK_REDUCTION:
       case OMP_LIST_LINEAR:
-	for (n = omp_clauses->lists[list]; n; n = n->next)
+	for (n = list->item; n; n = n->next)
 	  ctx.sharing_clauses->add (n->sym);
 	break;
       default:
@@ -6284,13 +6379,13 @@ gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym, bool add_clause)
 
   if (! omp_current_ctx->private_iterators->add (sym) && add_clause)
     {
+      gfc_omp_namelist_item **list;
       gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
-      gfc_omp_namelist *p;
-
-      p = gfc_get_omp_namelist ();
+      list = gfc_omp_get_nm_ref (omp_clauses, OMP_LIST_PRIVATE);
+      gfc_omp_namelist_item *p = gfc_get_omp_namelist_item ();
       p->sym = sym;
-      p->next = omp_clauses->lists[OMP_LIST_PRIVATE];
-      omp_clauses->lists[OMP_LIST_PRIVATE] = p;
+      p->next = *list;
+      *list = p;
     }
 }
 
@@ -6315,8 +6410,8 @@ static void
 resolve_omp_do (gfc_code *code)
 {
   gfc_code *do_code, *c;
-  int list, i, collapse;
-  gfc_omp_namelist *n;
+  int i, collapse;
+  gfc_omp_namelist_item *n;
   gfc_symbol *dovar;
   const char *name;
   bool is_simd = false;
@@ -6421,12 +6516,15 @@ resolve_omp_do (gfc_code *code)
 	gfc_error ("%s iteration variable must not be THREADPRIVATE "
 		   "at %L", name, &do_code->loc);
       if (code->ext.omp_clauses)
-	for (list = 0; list < OMP_LIST_NUM; list++)
+	for (gfc_omp_namelist *list = code->ext.omp_clauses->lists;
+	     list; list = list->next)
 	  if (!is_simd || code->ext.omp_clauses->collapse > 1
-	      ? (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE)
-	      : (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE
-		 && list != OMP_LIST_LINEAR))
-	    for (n = code->ext.omp_clauses->lists[list]; n; n = n->next)
+	      ? (list->clause != OMP_LIST_PRIVATE
+		 && list->clause != OMP_LIST_LASTPRIVATE)
+	      : (list->clause != OMP_LIST_PRIVATE
+		 && list->clause != OMP_LIST_LASTPRIVATE
+		 && list->clause != OMP_LIST_LINEAR))
+	    for (n = list->item; n; n = n->next)
 	      if (dovar == n->sym)
 		{
 		  if (!is_simd || code->ext.omp_clauses->collapse > 1)
@@ -6786,8 +6884,7 @@ gfc_resolve_oacc_blocks (gfc_code *code, gfc_namespace *ns)
 {
   fortran_omp_context ctx;
   gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
-  gfc_omp_namelist *n;
-  int list;
+  gfc_omp_namelist_item *n;
 
   resolve_oacc_loop_blocks (code);
 
@@ -6798,11 +6895,11 @@ gfc_resolve_oacc_blocks (gfc_code *code, gfc_namespace *ns)
   ctx.is_openmp = false;
   omp_current_ctx = &ctx;
 
-  for (list = 0; list < OMP_LIST_NUM; list++)
-    switch (list)
+  for (gfc_omp_namelist *list = omp_clauses->lists; list; list = list->next)
+    switch (list->clause)
       {
       case OMP_LIST_PRIVATE:
-	for (n = omp_clauses->lists[list]; n; n = n->next)
+	for (n = list->item; n; n = n->next)
 	  ctx.sharing_clauses->add (n->sym);
 	break;
       default:
@@ -6849,8 +6946,7 @@ resolve_oacc_loop (gfc_code *code)
 void
 gfc_resolve_oacc_declare (gfc_namespace *ns)
 {
-  int list;
-  gfc_omp_namelist *n;
+  gfc_omp_namelist_item *n;
   gfc_oacc_declare *oc;
 
   if (ns->oacc_declare == NULL)
@@ -6858,8 +6954,8 @@ gfc_resolve_oacc_declare (gfc_namespace *ns)
 
   for (oc = ns->oacc_declare; oc; oc = oc->next)
     {
-      for (list = 0; list < OMP_LIST_NUM; list++)
-	for (n = oc->clauses->lists[list]; n; n = n->next)
+      for (gfc_omp_namelist *list = oc->clauses->lists; list; list = list->next)
+	for (n = list->item; n; n = n->next)
 	  {
 	    n->sym->mark = 0;
 	    if (n->sym->attr.flavor != FL_VARIABLE
@@ -6879,14 +6975,15 @@ gfc_resolve_oacc_declare (gfc_namespace *ns)
 	      }
 	  }
 
-      for (n = oc->clauses->lists[OMP_LIST_DEVICE_RESIDENT]; n; n = n->next)
+      n = gfc_omp_get_nm_list (oc->clauses, OMP_LIST_DEVICE_RESIDENT);
+      for (; n; n = n->next)
 	check_array_not_assumed (n->sym, oc->loc, "DEVICE_RESIDENT");
     }
 
   for (oc = ns->oacc_declare; oc; oc = oc->next)
     {
-      for (list = 0; list < OMP_LIST_NUM; list++)
-	for (n = oc->clauses->lists[list]; n; n = n->next)
+      for (gfc_omp_namelist *list = oc->clauses->lists; list; list = list->next)
+	for (n = list->item; n; n = n->next)
 	  {
 	    if (n->sym->mark)
 	      {
@@ -6901,8 +6998,8 @@ gfc_resolve_oacc_declare (gfc_namespace *ns)
 
   for (oc = ns->oacc_declare; oc; oc = oc->next)
     {
-      for (list = 0; list < OMP_LIST_NUM; list++)
-	for (n = oc->clauses->lists[list]; n; n = n->next)
+      for (gfc_omp_namelist *list = oc->clauses->lists; list; list = list->next)
+	for (n = list->item; n; n = n->next)
 	  n->sym->mark = 0;
     }
 }
@@ -7027,8 +7124,8 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
       if (code->ext.omp_clauses)
 	resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
       if (code->ext.omp_clauses == NULL
-	  || (code->ext.omp_clauses->lists[OMP_LIST_TO] == NULL
-	      && code->ext.omp_clauses->lists[OMP_LIST_FROM] == NULL))
+	  || (!gfc_omp_get_nm_list (code->ext.omp_clauses, OMP_LIST_TO)
+	      && !gfc_omp_get_nm_list (code->ext.omp_clauses, OMP_LIST_FROM)))
 	gfc_error ("OMP TARGET UPDATE at %L requires at least one TO or "
 		   "FROM clause", &code->loc);
       break;
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index ec7abc240d6..3f4358ca348 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -5434,9 +5434,13 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
       new_st.ext.omp_name = NULL;
       break;
     case EXEC_OMP_END_SINGLE:
-      cp->ext.omp_clauses->lists[OMP_LIST_COPYPRIVATE]
-	= new_st.ext.omp_clauses->lists[OMP_LIST_COPYPRIVATE];
-      new_st.ext.omp_clauses->lists[OMP_LIST_COPYPRIVATE] = NULL;
+      if (cp->ext.omp_clauses->lists && new_st.ext.omp_clauses->lists)
+	{
+	  gcc_assert (!new_st.ext.omp_clauses->lists->next);
+	  new_st.ext.omp_clauses->lists->next = cp->ext.omp_clauses->lists;
+	}
+      cp->ext.omp_clauses->lists = new_st.ext.omp_clauses->lists;
+      new_st.ext.omp_clauses->lists = NULL;
       gfc_free_omp_clauses (new_st.ext.omp_clauses);
       break;
     case EXEC_NOP:
diff --git a/gcc/fortran/st.c b/gcc/fortran/st.c
index a3b0f12b171..6e4b0ada171 100644
--- a/gcc/fortran/st.c
+++ b/gcc/fortran/st.c
@@ -265,7 +265,7 @@ gfc_free_statement (gfc_code *p)
       break;
 
     case EXEC_OMP_FLUSH:
-      gfc_free_omp_namelist (p->ext.omp_namelist);
+      gfc_free_omp_namelist_item (p->ext.omp_namelist);
       break;
 
     case EXEC_OMP_BARRIER:
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 71d5c670e55..e0bdbc0e5b4 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -6603,19 +6603,27 @@ static gfc_omp_clauses *module_oacc_clauses;
 static void
 add_clause (gfc_symbol *sym, gfc_omp_map_op map_op)
 {
-  gfc_omp_namelist *n;
+  gfc_omp_namelist *list;
+  gfc_omp_namelist_item *n;
 
-  n = gfc_get_omp_namelist ();
+  n = gfc_get_omp_namelist_item ();
   n->sym = sym;
   n->u.map_op = map_op;
 
   if (!module_oacc_clauses)
     module_oacc_clauses = gfc_get_omp_clauses ();
 
-  if (module_oacc_clauses->lists[OMP_LIST_MAP])
-    n->next = module_oacc_clauses->lists[OMP_LIST_MAP];
-
-  module_oacc_clauses->lists[OMP_LIST_MAP] = n;
+  for (list = module_oacc_clauses->lists; list; list = list->next)
+    if (list->clause == OMP_LIST_MAP)
+      break;
+  if (list)
+    n->next = list->item;
+  else
+    {
+      module_oacc_clauses->lists = list = gfc_get_omp_namelist ();
+      list->clause = OMP_LIST_MAP;
+    }
+  list->item = n;
 }
 
 
@@ -6657,7 +6665,7 @@ finish_oacc_declare (gfc_namespace *ns, gfc_symbol *sym, bool block)
   gfc_oacc_declare *oc;
   locus where = gfc_current_locus;
   gfc_omp_clauses *omp_clauses = NULL;
-  gfc_omp_namelist *n, *p;
+  gfc_omp_namelist_item *n, *p;
 
   module_oacc_clauses = NULL;
   gfc_traverse_ns (ns, find_module_oacc_declare_clauses);
@@ -6685,8 +6693,10 @@ finish_oacc_declare (gfc_namespace *ns, gfc_symbol *sym, bool block)
 	gfc_error ("Sorry, !$ACC DECLARE at %L is not allowed "
 		   "in BLOCK construct", &oc->loc);
 
-
-      if (oc->clauses && oc->clauses->lists[OMP_LIST_MAP])
+      gfc_omp_namelist_item *oc_list;
+      oc_list = (oc->clauses ? gfc_omp_get_nm_list (oc->clauses, OMP_LIST_MAP)
+			     : NULL);
+      if (oc_list)
 	{
 	  if (omp_clauses == NULL)
 	    {
@@ -6694,12 +6704,12 @@ finish_oacc_declare (gfc_namespace *ns, gfc_symbol *sym, bool block)
 	      continue;
 	    }
 
-	  for (n = oc->clauses->lists[OMP_LIST_MAP]; n; p = n, n = n->next)
+	  for (n = oc_list; n; p = n, n = n->next)
 	    ;
 
 	  gcc_assert (p->next == NULL);
 
-	  p->next = omp_clauses->lists[OMP_LIST_MAP];
+	  p->next = gfc_omp_get_nm_list (omp_clauses, OMP_LIST_MAP);
 	  omp_clauses = oc->clauses;
 	}
     }
@@ -6707,7 +6717,8 @@ finish_oacc_declare (gfc_namespace *ns, gfc_symbol *sym, bool block)
   if (!omp_clauses)
     return;
 
-  for (n = omp_clauses->lists[OMP_LIST_MAP]; n; n = n->next)
+  n = gfc_omp_get_nm_list (omp_clauses, OMP_LIST_MAP);
+  for (; n; n = n->next)
     {
       switch (n->u.map_op)
 	{
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 6b4ad6a7050..c067d808f8d 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -1694,7 +1694,7 @@ gfc_trans_omp_variable (gfc_symbol *sym, bool declare_simd)
 
 static tree
 gfc_trans_omp_variable_list (enum omp_clause_code code,
-			     gfc_omp_namelist *namelist, tree list,
+			     gfc_omp_namelist_item *namelist, tree list,
 			     bool declare_simd)
 {
   for (; namelist != NULL; namelist = namelist->next)
@@ -1734,7 +1734,7 @@ omp_udr_find_orig (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
 }
 
 static void
-gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where)
+gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist_item *n, locus where)
 {
   gfc_symbol *sym = n->sym;
   gfc_symtree *root1 = NULL, *root2 = NULL, *root3 = NULL, *root4 = NULL;
@@ -2033,7 +2033,8 @@ gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where)
 }
 
 static tree
-gfc_trans_omp_reduction_list (int kind, gfc_omp_namelist *namelist, tree list,
+gfc_trans_omp_reduction_list (enum omp_list_clauses kind,
+			      gfc_omp_namelist_item *namelist, tree list,
 			      locus where, bool mark_addressable)
 {
   omp_clause_code clause = OMP_CLAUSE_REDUCTION;
@@ -2142,7 +2143,7 @@ static vec<tree, va_heap, vl_embed> *doacross_steps;
 /* Translate an array section or array element.  */
 
 static void
-gfc_trans_omp_array_section (stmtblock_t *block, gfc_omp_namelist *n,
+gfc_trans_omp_array_section (stmtblock_t *block, gfc_omp_namelist_item *n,
 			     tree decl, bool element, gomp_map_kind ptr_kind,
 			     tree &node, tree &node2, tree &node3, tree &node4)
 {
@@ -2275,20 +2276,20 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
 		       bool openacc = false)
 {
   tree omp_clauses = NULL_TREE, chunk_size, c;
-  int list, ifc;
+  int ifc;
   enum omp_clause_code clause_code;
   gfc_se se;
 
   if (clauses == NULL)
     return NULL_TREE;
 
-  for (list = 0; list < OMP_LIST_NUM; list++)
+  for (gfc_omp_namelist *list = clauses->lists; list; list = list->next)
     {
-      gfc_omp_namelist *n = clauses->lists[list];
+      gfc_omp_namelist_item *n = list->item;
 
       if (n == NULL)
 	continue;
-      switch (list)
+      switch (list->clause)
 	{
 	case OMP_LIST_REDUCTION:
 	case OMP_LIST_REDUCTION_INSCAN:
@@ -2297,8 +2298,9 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
 	case OMP_LIST_TASK_REDUCTION:
 	  /* An OpenACC async clause indicates the need to set reduction
 	     arguments addressable, to allow asynchronous copy-out.  */
-	  omp_clauses = gfc_trans_omp_reduction_list (list, n, omp_clauses,
-						      where, clauses->async);
+	  omp_clauses = gfc_trans_omp_reduction_list (list->clause, n,
+						      omp_clauses, where,
+						      clauses->async);
 	  break;
 	case OMP_LIST_PRIVATE:
 	  clause_code = OMP_CLAUSE_PRIVATE;
@@ -3162,7 +3164,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
 	      if (!n->sym->attr.referenced)
 		continue;
 
-	      switch (list)
+	      switch (list->clause)
 		{
 		case OMP_LIST_TO:
 		  clause_code = OMP_CLAUSE_TO;
@@ -4445,9 +4447,9 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
 
       if (clauses)
 	{
-	  gfc_omp_namelist *n = NULL;
+	  gfc_omp_namelist_item *n = NULL;
 	  if (op == EXEC_OMP_SIMD && collapse == 1)
-	    for (n = clauses->lists[OMP_LIST_LINEAR];
+	    for (n = gfc_omp_get_nm_list (clauses, OMP_LIST_LINEAR);
 		 n != NULL; n = n->next)
 	      if (code->ext.iterator->var->symtree->n.sym == n->sym)
 		{
@@ -4455,7 +4457,7 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
 		  break;
 		}
 	  if (n == NULL && op != EXEC_OMP_DISTRIBUTE)
-	    for (n = clauses->lists[OMP_LIST_LASTPRIVATE];
+	    for (n = gfc_omp_get_nm_list (clauses, OMP_LIST_LASTPRIVATE);
 		 n != NULL; n = n->next)
 	      if (code->ext.iterator->var->symtree->n.sym == n->sym)
 		{
@@ -4463,7 +4465,8 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
 		  break;
 		}
 	  if (n == NULL)
-	    for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
+	    for (n = gfc_omp_get_nm_list (clauses, OMP_LIST_PRIVATE);
+		 n != NULL; n = n->next)
 	      if (code->ext.iterator->var->symtree->n.sym == n->sym)
 		{
 		  dovar_found = 1;
@@ -4791,10 +4794,22 @@ gfc_trans_oacc_combined_directive (gfc_code *code)
       loop_clauses.par_auto = construct_clauses.par_auto;
       loop_clauses.independent = construct_clauses.independent;
       loop_clauses.tile_list = construct_clauses.tile_list;
-      loop_clauses.lists[OMP_LIST_PRIVATE]
-	= construct_clauses.lists[OMP_LIST_PRIVATE];
-      loop_clauses.lists[OMP_LIST_REDUCTION]
-	= construct_clauses.lists[OMP_LIST_REDUCTION];
+      for (gfc_omp_namelist *list = construct_clauses.lists;
+	   list; list = list->next)
+	{
+	  if (list->clause == OMP_LIST_PRIVATE)
+	    {
+	      *gfc_omp_get_nm_ref (&loop_clauses, OMP_LIST_PRIVATE) = list->item;
+	      list->item = NULL;
+	    }
+	  else if (list->clause == OMP_LIST_REDUCTION)
+	    {
+	      *gfc_omp_get_nm_ref (&loop_clauses, OMP_LIST_REDUCTION)
+		= list->item;
+	      if (construct_code == OACC_KERNELS)
+		list->item = NULL;
+	    }
+	}
       construct_clauses.gang = false;
       construct_clauses.gang_static = false;
       construct_clauses.gang_num_expr = NULL;
@@ -4808,9 +4823,6 @@ gfc_trans_oacc_combined_directive (gfc_code *code)
       construct_clauses.independent = false;
       construct_clauses.independent = false;
       construct_clauses.tile_list = NULL;
-      construct_clauses.lists[OMP_LIST_PRIVATE] = NULL;
-      if (construct_code == OACC_KERNELS)
-	construct_clauses.lists[OMP_LIST_REDUCTION] = NULL;
       oacc_clauses = gfc_trans_omp_clauses (&block, &construct_clauses,
 					    code->loc, false, true);
     }
@@ -4923,6 +4935,17 @@ enum
 };
 
 static void
+gfc_copy_list_clauses (gfc_omp_clauses *to, gfc_omp_clauses *from,
+		       enum omp_list_clauses clause)
+{
+  gfc_omp_namelist_item *list = gfc_omp_get_nm_list (from, clause);
+  if (list)
+    *gfc_omp_get_nm_ref (to, clause) = list;
+}
+
+/* Return true if actual splitting was done.  */
+
+bool
 gfc_split_omp_clauses (gfc_code *code,
 		       gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])
 {
@@ -5045,17 +5068,17 @@ gfc_split_omp_clauses (gfc_code *code,
   if (mask == 0)
     {
       clausesa[innermost] = *code->ext.omp_clauses;
-      return;
+      return false;
     }
   if (code->ext.omp_clauses != NULL)
     {
       if (mask & GFC_OMP_MASK_TARGET)
 	{
 	  /* First the clauses that are unique to some constructs.  */
-	  clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_MAP]
-	    = code->ext.omp_clauses->lists[OMP_LIST_MAP];
-	  clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IS_DEVICE_PTR]
-	    = code->ext.omp_clauses->lists[OMP_LIST_IS_DEVICE_PTR];
+	  gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_TARGET],
+				 code->ext.omp_clauses, OMP_LIST_MAP);
+	  gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_TARGET],
+				 code->ext.omp_clauses, OMP_LIST_IS_DEVICE_PTR);
 	  clausesa[GFC_OMP_SPLIT_TARGET].device
 	    = code->ext.omp_clauses->device;
 	  clausesa[GFC_OMP_SPLIT_TARGET].defaultmap
@@ -5075,8 +5098,8 @@ gfc_split_omp_clauses (gfc_code *code,
 	    = code->ext.omp_clauses->thread_limit;
 	  /* Shared and default clauses are allowed on parallel, teams
 	     and taskloop.  */
-	  clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_SHARED]
-	    = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
+	  gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_TEAMS],
+				 code->ext.omp_clauses, OMP_LIST_SHARED);
 	  clausesa[GFC_OMP_SPLIT_TEAMS].default_sharing
 	    = code->ext.omp_clauses->default_sharing;
 	}
@@ -5096,16 +5119,16 @@ gfc_split_omp_clauses (gfc_code *code,
       if (mask & GFC_OMP_MASK_PARALLEL)
 	{
 	  /* First the clauses that are unique to some constructs.  */
-	  clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_COPYIN]
-	    = code->ext.omp_clauses->lists[OMP_LIST_COPYIN];
+	  gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_PARALLEL],
+				 code->ext.omp_clauses, OMP_LIST_COPYIN);
 	  clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads
 	    = code->ext.omp_clauses->num_threads;
 	  clausesa[GFC_OMP_SPLIT_PARALLEL].proc_bind
 	    = code->ext.omp_clauses->proc_bind;
 	  /* Shared and default clauses are allowed on parallel, teams
 	     and taskloop.  */
-	  clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_SHARED]
-	    = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
+	  gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_PARALLEL],
+				 code->ext.omp_clauses, OMP_LIST_SHARED);
 	  clausesa[GFC_OMP_SPLIT_PARALLEL].default_sharing
 	    = code->ext.omp_clauses->default_sharing;
 	  clausesa[GFC_OMP_SPLIT_PARALLEL].if_exprs[OMP_IF_PARALLEL]
@@ -5146,8 +5169,8 @@ gfc_split_omp_clauses (gfc_code *code,
 	    = code->ext.omp_clauses->safelen_expr;
 	  clausesa[GFC_OMP_SPLIT_SIMD].simdlen_expr
 	    = code->ext.omp_clauses->simdlen_expr;
-	  clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_ALIGNED]
-	    = code->ext.omp_clauses->lists[OMP_LIST_ALIGNED];
+	  gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_SIMD],
+				 code->ext.omp_clauses, OMP_LIST_ALIGNED);
 	  /* Duplicate collapse.  */
 	  clausesa[GFC_OMP_SPLIT_SIMD].collapse
 	    = code->ext.omp_clauses->collapse;
@@ -5183,8 +5206,8 @@ gfc_split_omp_clauses (gfc_code *code,
 	    = code->ext.omp_clauses->if_expr;
 	  /* Shared and default clauses are allowed on parallel, teams
 	     and taskloop.  */
-	  clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_SHARED]
-	    = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
+	  gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_TASKLOOP],
+				 code->ext.omp_clauses, OMP_LIST_SHARED);
 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].default_sharing
 	    = code->ext.omp_clauses->default_sharing;
 	  /* Duplicate collapse.  */
@@ -5195,75 +5218,92 @@ gfc_split_omp_clauses (gfc_code *code,
 	 it is enough to put it on the innermost one.  For
 	 !$ omp parallel do put it on parallel though,
 	 as that's what we did for OpenMP 3.1.  */
-      clausesa[innermost == GFC_OMP_SPLIT_DO
-	       ? (int) GFC_OMP_SPLIT_PARALLEL
-	       : innermost].lists[OMP_LIST_PRIVATE]
-	= code->ext.omp_clauses->lists[OMP_LIST_PRIVATE];
+      gfc_copy_list_clauses (&clausesa[innermost == GFC_OMP_SPLIT_DO
+				       ? (int) GFC_OMP_SPLIT_PARALLEL
+				       : innermost],
+			     code->ext.omp_clauses, OMP_LIST_PRIVATE);
       /* Firstprivate clause is supported on all constructs but
 	 simd.  Put it on the outermost of those and duplicate
 	 on parallel and teams.  */
       if (mask & GFC_OMP_MASK_TARGET)
-	clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_FIRSTPRIVATE]
-	  = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
+	gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_TARGET],
+			       code->ext.omp_clauses, OMP_LIST_FIRSTPRIVATE);
       if (mask & GFC_OMP_MASK_TEAMS)
-	clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_FIRSTPRIVATE]
-	  = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
+	gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_TEAMS],
+			       code->ext.omp_clauses, OMP_LIST_FIRSTPRIVATE);
       else if (mask & GFC_OMP_MASK_DISTRIBUTE)
-	clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_FIRSTPRIVATE]
-	  = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
+	gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
+			       code->ext.omp_clauses, OMP_LIST_FIRSTPRIVATE);
       if (mask & GFC_OMP_MASK_PARALLEL)
-	clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_FIRSTPRIVATE]
-	  = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
+	gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_PARALLEL],
+			       code->ext.omp_clauses, OMP_LIST_FIRSTPRIVATE);
       else if (mask & GFC_OMP_MASK_DO)
-	clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_FIRSTPRIVATE]
-	  = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
+	gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_DO],
+			       code->ext.omp_clauses, OMP_LIST_FIRSTPRIVATE);
       /* Lastprivate is allowed on distribute, do and simd.
          In parallel do{, simd} we actually want to put it on
 	 parallel rather than do.  */
       if (mask & GFC_OMP_MASK_DISTRIBUTE)
-	clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_LASTPRIVATE]
-	  = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
+	gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
+			       code->ext.omp_clauses, OMP_LIST_LASTPRIVATE);
       if (mask & GFC_OMP_MASK_PARALLEL)
-	clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_LASTPRIVATE]
-	  = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
+	gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_PARALLEL],
+			       code->ext.omp_clauses, OMP_LIST_LASTPRIVATE);
       else if (mask & GFC_OMP_MASK_DO)
-	clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_LASTPRIVATE]
-	  = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
+	gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_DO],
+			       code->ext.omp_clauses, OMP_LIST_LASTPRIVATE);
       if (mask & GFC_OMP_MASK_SIMD)
-	clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LASTPRIVATE]
-	  = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
+	gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_SIMD],
+			       code->ext.omp_clauses, OMP_LIST_LASTPRIVATE);
       /* Reduction is allowed on simd, do, parallel and teams.
 	 Duplicate it on all of them, but omit on do if
 	 parallel is present.  */
-      for (int i = OMP_LIST_REDUCTION; i <= OMP_LIST_REDUCTION_TASK; i++)
-	{
-	  if (mask & GFC_OMP_MASK_TEAMS)
-	    clausesa[GFC_OMP_SPLIT_TEAMS].lists[i]
-	      = code->ext.omp_clauses->lists[i];
-	  if (mask & GFC_OMP_MASK_PARALLEL)
-	    clausesa[GFC_OMP_SPLIT_PARALLEL].lists[i]
-	      = code->ext.omp_clauses->lists[i];
-	  else if (mask & GFC_OMP_MASK_DO)
-	    clausesa[GFC_OMP_SPLIT_DO].lists[i]
-	      = code->ext.omp_clauses->lists[i];
-	  if (mask & GFC_OMP_MASK_SIMD)
-	    clausesa[GFC_OMP_SPLIT_SIMD].lists[i]
-	      = code->ext.omp_clauses->lists[i];
-	}
+      for (gfc_omp_namelist *list = code->ext.omp_clauses->lists;
+	   list; list = list->next)
+	if (list->clause == OMP_LIST_REDUCTION
+	    || list->clause == OMP_LIST_REDUCTION_INSCAN
+	    || list->clause == OMP_LIST_REDUCTION_TASK)
+	  {
+	    if (mask & GFC_OMP_MASK_TEAMS)
+	      *gfc_omp_get_nm_ref (&clausesa[GFC_OMP_SPLIT_TEAMS], list->clause)
+		= list->item;
+	    if (mask & GFC_OMP_MASK_PARALLEL)
+	      *gfc_omp_get_nm_ref (&clausesa[GFC_OMP_SPLIT_PARALLEL],
+				   list->clause) = list->item;
+	    else if (mask & GFC_OMP_MASK_DO)
+	      *gfc_omp_get_nm_ref (&clausesa[GFC_OMP_SPLIT_DO], list->clause)
+		= list->item;
+	    if (mask & GFC_OMP_MASK_SIMD)
+	      *gfc_omp_get_nm_ref (&clausesa[GFC_OMP_SPLIT_SIMD], list->clause)
+		= list->item;
+	  }
       if (mask & GFC_OMP_MASK_TARGET)
-	clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IN_REDUCTION]
-	  = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION];
+	gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_TARGET],
+			       code->ext.omp_clauses, OMP_LIST_IN_REDUCTION);
       if (mask & GFC_OMP_MASK_TASKLOOP)
-	clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_IN_REDUCTION]
-	  = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION];
+	gfc_copy_list_clauses (&clausesa[GFC_OMP_SPLIT_TASKLOOP],
+				 code->ext.omp_clauses, OMP_LIST_IN_REDUCTION);
       /* Linear clause is supported on do and simd,
 	 put it on the innermost one.  */
-      clausesa[innermost].lists[OMP_LIST_LINEAR]
-	= code->ext.omp_clauses->lists[OMP_LIST_LINEAR];
+      gfc_copy_list_clauses (&clausesa[innermost],
+			     code->ext.omp_clauses, OMP_LIST_LINEAR);
     }
   if ((mask & (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
       == (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
     clausesa[GFC_OMP_SPLIT_DO].nowait = true;
+  return true;
+}
+
+static void
+gfc_trans_omp_free_clausea (gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])
+{
+  gfc_omp_namelist *next, *list;
+  for (int i = 0; i < GFC_OMP_SPLIT_NUM; ++i)
+    for (list = clausesa[i].lists; list; list = next)
+      {
+	next = list->next;
+	free (list);
+      }
 }
 
 static tree
@@ -5273,6 +5313,7 @@ gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock,
   stmtblock_t block;
   gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
   tree stmt, body, omp_do_clauses = NULL_TREE;
+  bool do_free = false;
 
   if (pblock == NULL)
     gfc_start_block (&block);
@@ -5282,7 +5323,7 @@ gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock,
   if (clausesa == NULL)
     {
       clausesa = clausesa_buf;
-      gfc_split_omp_clauses (code, clausesa);
+      do_free = gfc_split_omp_clauses (code, clausesa);
     }
   if (flag_openmp)
     omp_do_clauses
@@ -5308,6 +5349,8 @@ gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock,
   else
     stmt = body;
   gfc_add_expr_to_block (&block, stmt);
+  if (clausesa == clausesa_buf && do_free)
+    gfc_trans_omp_free_clausea (clausesa_buf);
   return gfc_finish_block (&block);
 }
 
@@ -5318,6 +5361,7 @@ gfc_trans_omp_parallel_do (gfc_code *code, stmtblock_t *pblock,
   stmtblock_t block, *new_pblock = pblock;
   gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
   tree stmt, omp_clauses = NULL_TREE;
+  bool do_free = false;
 
   if (pblock == NULL)
     gfc_start_block (&block);
@@ -5327,7 +5371,7 @@ gfc_trans_omp_parallel_do (gfc_code *code, stmtblock_t *pblock,
   if (clausesa == NULL)
     {
       clausesa = clausesa_buf;
-      gfc_split_omp_clauses (code, clausesa);
+      do_free = gfc_split_omp_clauses (code, clausesa);
     }
   omp_clauses
     = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
@@ -5355,6 +5399,8 @@ gfc_trans_omp_parallel_do (gfc_code *code, stmtblock_t *pblock,
 		     void_type_node, stmt, omp_clauses);
   OMP_PARALLEL_COMBINED (stmt) = 1;
   gfc_add_expr_to_block (&block, stmt);
+  if (clausesa == clausesa_buf && do_free)
+    gfc_trans_omp_free_clausea (clausesa_buf);
   return gfc_finish_block (&block);
 }
 
@@ -5365,6 +5411,7 @@ gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock,
   stmtblock_t block;
   gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
   tree stmt, omp_clauses = NULL_TREE;
+  bool do_free = false;
 
   if (pblock == NULL)
     gfc_start_block (&block);
@@ -5374,7 +5421,7 @@ gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock,
   if (clausesa == NULL)
     {
       clausesa = clausesa_buf;
-      gfc_split_omp_clauses (code, clausesa);
+      do_free = gfc_split_omp_clauses (code, clausesa);
     }
   if (flag_openmp)
     omp_clauses
@@ -5399,6 +5446,8 @@ gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock,
       OMP_PARALLEL_COMBINED (stmt) = 1;
     }
   gfc_add_expr_to_block (&block, stmt);
+  if (clausesa == clausesa_buf && do_free)
+    gfc_trans_omp_free_clausea (clausesa_buf);
   return gfc_finish_block (&block);
 }
 
@@ -5456,7 +5505,7 @@ gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
 {
   stmtblock_t block, body;
   tree omp_clauses, stmt;
-  bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL;
+  bool has_lastprivate = !!gfc_omp_get_nm_list (clauses, OMP_LIST_LASTPRIVATE);
   location_t loc = gfc_get_location (&code->loc);
 
   gfc_start_block (&block);
@@ -5543,12 +5592,13 @@ gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa)
   stmtblock_t block;
   gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
   tree stmt, omp_clauses = NULL_TREE;
+  bool do_free = false;
 
   gfc_start_block (&block);
   if (clausesa == NULL)
     {
       clausesa = clausesa_buf;
-      gfc_split_omp_clauses (code, clausesa);
+      do_free = gfc_split_omp_clauses (code, clausesa);
     }
   if (flag_openmp)
     omp_clauses
@@ -5602,6 +5652,8 @@ gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa)
       stmt = distribute;
     }
   gfc_add_expr_to_block (&block, stmt);
+  if (clausesa == clausesa_buf && do_free)
+    gfc_trans_omp_free_clausea (clausesa_buf);
   return gfc_finish_block (&block);
 }
 
@@ -5613,12 +5665,13 @@ gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa,
   gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
   tree stmt;
   bool combined = true;
+  bool do_free = false;
 
   gfc_start_block (&block);
   if (clausesa == NULL)
     {
       clausesa = clausesa_buf;
-      gfc_split_omp_clauses (code, clausesa);
+      do_free = gfc_split_omp_clauses (code, clausesa);
     }
   if (flag_openmp)
     {
@@ -5655,6 +5708,8 @@ gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa,
 	OMP_TEAMS_COMBINED (stmt) = 1;
     }
   gfc_add_expr_to_block (&block, stmt);
+  if (clausesa == clausesa_buf && do_free)
+    gfc_trans_omp_free_clausea (clausesa_buf);
   return gfc_finish_block (&block);
 }
 
@@ -5664,9 +5719,10 @@ gfc_trans_omp_target (gfc_code *code)
   stmtblock_t block;
   gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
   tree stmt, omp_clauses = NULL_TREE;
+  bool do_free = false;
 
   gfc_start_block (&block);
-  gfc_split_omp_clauses (code, clausesa);
+  do_free = gfc_split_omp_clauses (code, clausesa);
   if (flag_openmp)
     omp_clauses
       = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET],
@@ -5760,6 +5816,8 @@ gfc_trans_omp_target (gfc_code *code)
       cfun->has_omp_target = true;
     }
   gfc_add_expr_to_block (&block, stmt);
+  if (do_free)
+    gfc_trans_omp_free_clausea (clausesa);
   return gfc_finish_block (&block);
 }
 
@@ -5769,9 +5827,10 @@ gfc_trans_omp_taskloop (gfc_code *code)
   stmtblock_t block;
   gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
   tree stmt, omp_clauses = NULL_TREE;
+  bool do_free = false;
 
   gfc_start_block (&block);
-  gfc_split_omp_clauses (code, clausesa);
+  do_free = gfc_split_omp_clauses (code, clausesa);
   if (flag_openmp)
     omp_clauses
       = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TASKLOOP],
@@ -5802,6 +5861,8 @@ gfc_trans_omp_taskloop (gfc_code *code)
       stmt = taskloop;
     }
   gfc_add_expr_to_block (&block, stmt);
+  if (do_free)
+    gfc_trans_omp_free_clausea (clausesa);
   return gfc_finish_block (&block);
 }
 
diff --git a/gcc/testsuite/gfortran.dg/goacc/combined-directives.f90 b/gcc/testsuite/gfortran.dg/goacc/combined-directives.f90
index 956349204f4..72acb982a68 100644
--- a/gcc/testsuite/gfortran.dg/goacc/combined-directives.f90
+++ b/gcc/testsuite/gfortran.dg/goacc/combined-directives.f90
@@ -146,5 +146,6 @@ end subroutine test
 ! { dg-final { scan-tree-dump-times "acc loop private.i. private.j. tile.2, 3" 2 "gimple" } }
 ! { dg-final { scan-tree-dump-times "acc loop private.i. independent" 2 "gimple" } }
 ! { dg-final { scan-tree-dump-times "private.z" 2 "gimple" } }
-! { dg-final { scan-tree-dump-times "omp target oacc_\[^ \]+ map.tofrom:y" 2 "gimple" } }
-! { dg-final { scan-tree-dump-times "acc loop private.i. reduction..:y." 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "omp target oacc_parallel reduction..:y. map.tofrom:y" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "omp target oacc_kernels map.tofrom:y" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "acc loop reduction..:y. private.i." 2 "gimple" } }
diff --git a/gcc/testsuite/gfortran.dg/goacc/reduction-2.f95 b/gcc/testsuite/gfortran.dg/goacc/reduction-2.f95
index 4d40998958c..d083c7b6762 100644
--- a/gcc/testsuite/gfortran.dg/goacc/reduction-2.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/reduction-2.f95
@@ -16,7 +16,7 @@ subroutine foo ()
 end subroutine
 
 ! { dg-final { scan-tree-dump-times "target oacc_parallel reduction..:a. map.tofrom.a." 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "acc loop private.p. reduction..:a." 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "acc loop reduction..:a. private.p." 1 "gimple" } }
 ! { dg-final { scan-tree-dump-times "target oacc_kernels map.force_tofrom:a .len: 4.." 1 "gimple" } }
-! { dg-final { scan-tree-dump-times "acc loop private.k. reduction..:a." 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "acc loop reduction..:a. private.k." 1 "gimple" } }
 
diff --git a/gcc/testsuite/gfortran.dg/gomp/openmp-simd-6.f90 b/gcc/testsuite/gfortran.dg/gomp/openmp-simd-6.f90
index 361e0dad343..0f2425ae98a 100644
--- a/gcc/testsuite/gfortran.dg/gomp/openmp-simd-6.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/openmp-simd-6.f90
@@ -49,9 +49,9 @@ subroutine bar(n, m, u)
 end
 
 
-! { dg-final { scan-tree-dump-times "#pragma omp teams firstprivate\\(a1\\) firstprivate\\(b1\\) shared\\(u\\) default\\(none\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams shared\\(u\\) firstprivate\\(a1\\) firstprivate\\(b1\\) default\\(none\\)" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp distribute lastprivate\\(d1\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp parallel firstprivate\\(a1\\) firstprivate\\(b1\\) lastprivate\\(d1\\) shared\\(u\\) default\\(none\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel shared\\(u\\) firstprivate\\(a1\\) firstprivate\\(b1\\) lastprivate\\(d1\\) default\\(none\\)" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp for nowait" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp simd lastprivate\\(d1\\)" 1 "original" } }
 
diff --git a/gcc/testsuite/gfortran.dg/gomp/reduction4.f90 b/gcc/testsuite/gfortran.dg/gomp/reduction4.f90
index af8c91b2a87..0a10ecf4d80 100644
--- a/gcc/testsuite/gfortran.dg/gomp/reduction4.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/reduction4.f90
@@ -155,9 +155,9 @@ end
 ! { dg-final { scan-tree-dump-times "#pragma omp for reduction\\(inscan,\\\+:a\\)" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp for reduction\\(task,\\\+:a\\)" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp parallel\[\n\r\]" 8 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp parallel private\\(i\\) reduction\\(\\\+:a\\)" 2 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp parallel private\\(i\\) reduction\\(inscan,\\\+:a\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp parallel private\\(i\\) reduction\\(task,\\\+:a\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel reduction\\(\\\+:a\\) private\\(i\\)" 2 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel reduction\\(inscan,\\\+:a\\) private\\(i\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel reduction\\(task,\\\+:a\\) private\\(i\\)" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp section\[\n\r\]" 4 "original" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp sections reduction\\(\\\+:a\\)" 2 "original" } }
 ! { dg-final { scan-tree-dump-times "#pragma omp sections reduction\\(inscan,\\\+:a\\)" 1 "original" } }

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [Patch] Fortran: cleanup OpenMP's OMP_LIST_* handling
  2020-11-16 14:08 [Patch] Fortran: cleanup OpenMP's OMP_LIST_* handling Tobias Burnus
@ 2020-11-18 11:14 ` Jakub Jelinek
  0 siblings, 0 replies; 2+ messages in thread
From: Jakub Jelinek @ 2020-11-18 11:14 UTC (permalink / raw)
  To: Tobias Burnus; +Cc: gcc-patches, fortran

On Mon, Nov 16, 2020 at 03:08:36PM +0100, Tobias Burnus wrote:
> as discussed the other day (I think via IRC or in a patch review),
>   omp_list_clauses
> did grow quite a bit: it has 26 entries and I am about to add two
> more.
> 
> This variable is used as:
>  typedef struct gfc_omp_clauses
>  {
>    ...
>    gfc_omp_namelist *lists[OMP_LIST_NUM];
> 
> with sizeof(gfc_omp_namelist) = 5*sizeof(void*) + sizeof(locus);
> 
> This patch replaces it with a linked list.
> 
> 
> I am not really sure the new version is that readable and whether
> we move into the right direction or not.

> --- a/gcc/fortran/gfortran.h
> +++ b/gcc/fortran/gfortran.h
> @@ -1240,7 +1240,7 @@ enum gfc_omp_linear_op
>  /* For use in OpenMP clauses in case we need extra information
>     (aligned clause alignment, linear clause step, etc.).  */
>  
> -typedef struct gfc_omp_namelist
> +typedef struct gfc_omp_namelist_item
>  {
>    struct gfc_symbol *sym;
>    struct gfc_expr *expr;
> @@ -1254,17 +1254,16 @@ typedef struct gfc_omp_namelist
>        bool lastprivate_conditional;
>      } u;
>    struct gfc_omp_namelist_udr *udr;
> -  struct gfc_omp_namelist *next;
> +  struct gfc_omp_namelist_item *next;
>    locus where;
>  }
> -gfc_omp_namelist;
> +gfc_omp_namelist_item;
> +#define gfc_get_omp_namelist_item() XCNEW (gfc_omp_namelist_item)
>  
> -#define gfc_get_omp_namelist() XCNEW (gfc_omp_namelist)
> -
> -enum
> +enum omp_list_clauses
>  {
> -  OMP_LIST_FIRST,
> -  OMP_LIST_PRIVATE = OMP_LIST_FIRST,
> +  OMP_LIST_UNSET,
> +  OMP_LIST_PRIVATE,
>    OMP_LIST_FIRSTPRIVATE,
>    OMP_LIST_LASTPRIVATE,
>    OMP_LIST_COPYPRIVATE,
> @@ -1289,8 +1288,7 @@ enum
>    OMP_LIST_IS_DEVICE_PTR,
>    OMP_LIST_USE_DEVICE_PTR,
>    OMP_LIST_USE_DEVICE_ADDR,
> -  OMP_LIST_NONTEMPORAL,
> -  OMP_LIST_NUM
> +  OMP_LIST_NONTEMPORAL
>  };
>  
>  /* Because a symbol can belong to multiple namelists, they must be
> @@ -1386,12 +1384,22 @@ enum gfc_omp_memorder
>    OMP_MEMORDER_RELAXED
>  };
>  
> +typedef struct gfc_omp_namelist
> +{
> +  enum omp_list_clauses clause;
> +  gfc_omp_namelist_item *item;
> +  struct gfc_omp_namelist *next;
> +}
> +gfc_omp_namelist;

I meant something slightly different, in particular not
this gfc_omp_namelist vs. gfc_omp_namelist_item (i.e. linked list of linked
lists), but just a linked list, i.e. just add
  ENUM_BITFIELD (enum omp_list_clauses) clause : 16;
  int flags : 16;
into gfc_omp_namelist where the flags could hold various flags for certain
clauses, e.g. for OMP_LIST_LASTPRIVATE it could hold the conditional
modifier, for OMP_LIST_REDUCTION the inscan and task modifiers, etc.
Or do you see any advantages in having the same clauses for different
symbols adjacent in the FE?

	Jakub


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-11-18 11:14 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-16 14:08 [Patch] Fortran: cleanup OpenMP's OMP_LIST_* handling Tobias Burnus
2020-11-18 11:14 ` Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).