diff mbox series

[1/3] OpenMP: Introduce accessor macros and constructors for context selectors.

Message ID 20231119092151.1690294-2-sandra@codesourcery.com
State New
Headers show
Series OpenMP: Improve data abstractions for context selectors | expand

Commit Message

Sandra Loosemore Nov. 19, 2023, 9:21 a.m. UTC
This patch hides the underlying nested TREE_LIST structure of context
selectors behind accessor macros that have more meaningful names than
the generic TREE_PURPOSE/TREE_VALUE accessors.  There is a slight
change to the representation in that the score expression in
trait-selectors has a distinguished tag and is separated from the
ordinary properties, although internally it is still represented as
the first item in the TREE_VALUE of the selector.  This patch also renames
some local variables with slightly more descriptive names so it is easier
to track whether something is a selector-set, selector, or property.

gcc/ChangeLog
	* omp-general.h (OMP_TS_SCORE_NODE): New.
	(OMP_TSS_ID, OMP_TSS_TRAIT_SELECTORS): New.
	(OMP_TS_ID, OMP_TS_SCORE, OMP_TS_PROPERTIES): New.
	(OMP_TP_NAME, OMP_TP_VALUE): New.
	(make_trait_set_selector): Declare.
	(make_trait_selector): Declare.
	(make_trait_property): Declare.
	(omp_constructor_traits_to_codes): Rename to
	omp_construct_traits_to_codes.
	* omp-general.cc (omp_constructor_traits_to_codes): Rename
	to omp_construct_traits_to_codes.  Use new accessors.
	(omp_check_context_selector): Use new accessors.
	(make_trait_set_selector): New.
	(make_trait_selector): New.
	(make_trait_property): New.
	(omp_context_name_list_prop): Use new accessors.
	(omp_context_selector_matches): Use new accessors.
	(omp_context_selector_props_compare): Use new accessors.
	(omp_context_selector_set_compare): Use new accessors.
	(omp_get_context_selector): Use new accessors.
	(omp_context_compute_score): Use new accessors.
	* gimplify.cc (omp_construct_selector_matches): Adjust for renaming
	of omp_constructor_traits_to_codes.

gcc/c/ChangeLog
	* c-parser.cc (c_parser_omp_context_selector): Use new constructors.

gcc/cp/ChangeLog
	* parser.cc (cp_parser_omp_context_selector): Use new constructors.
	* pt.cc: Include omp-general.h.
	(tsubst_attribute): Use new context selector accessors and
	 constructors.

gcc/fortran/ChangeLog
	* trans-openmp.cc (gfc_trans_omp_declare_variant): Use new
	constructors.
---
 gcc/c/c-parser.cc           |  27 ++--
 gcc/cp/parser.cc            |  30 ++--
 gcc/cp/pt.cc                |  82 ++++++----
 gcc/fortran/trans-openmp.cc |  27 ++--
 gcc/gimplify.cc             |   4 +-
 gcc/omp-general.cc          | 293 ++++++++++++++++++------------------
 gcc/omp-general.h           |  48 +++++-
 7 files changed, 297 insertions(+), 214 deletions(-)
diff mbox series

Patch

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 703f9570dbc..fcbacd461c7 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -24032,7 +24032,10 @@  static const char *const omp_user_selectors[] = {
      trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
 
    trait-score:
-     score(score-expression)  */
+     score(score-expression)
+
+   Note that this function returns a list of trait selectors for the
+   trait-selector-set SET.  */
 
 static tree
 c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
@@ -24051,6 +24054,7 @@  c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
 	}
 
       tree properties = NULL_TREE;
+      tree scoreval = NULL_TREE;
       const char *const *selectors = NULL;
       bool allow_score = true;
       bool allow_user = false;
@@ -24157,8 +24161,7 @@  c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
 		    error_at (token->location, "score argument must be "
 			      "non-negative");
 		  else
-		    properties = tree_cons (get_identifier (" score"),
-					    score, properties);
+		    scoreval = score;
 		}
 	      token = c_parser_peek_token (parser);
 	    }
@@ -24171,7 +24174,8 @@  c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
 		{
 		  t = c_parser_expr_no_commas (parser, NULL).value;
 		  if (TREE_CODE (t) == STRING_CST)
-		    properties = tree_cons (NULL_TREE, t, properties);
+		    properties = make_trait_property (NULL_TREE, t,
+						      properties);
 		  else if (t != error_mark_node)
 		    {
 		      mark_exp_read (t);
@@ -24182,7 +24186,8 @@  c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
 				  "constant integer expression or string "
 				  "literal");
 		      else
-			properties = tree_cons (NULL_TREE, t, properties);
+			properties = make_trait_property (NULL_TREE, t,
+							  properties);
 		    }
 		  else
 		    return error_mark_node;
@@ -24200,7 +24205,8 @@  c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
 		{
 		  tree prop = c_parser_peek_token (parser)->value;
 		  c_parser_consume_token (parser);
-		  properties = tree_cons (prop, NULL_TREE, properties);
+		  properties = make_trait_property (prop, NULL_TREE,
+						    properties);
 		}
 	      else
 		{
@@ -24228,7 +24234,7 @@  c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
 		      return error_mark_node;
 		    }
 
-		  properties = tree_cons (prop, value, properties);
+		  properties = make_trait_property (prop, value, properties);
 
 		  if (c_parser_next_token_is (parser, CPP_COMMA))
 		    c_parser_consume_token (parser);
@@ -24248,7 +24254,8 @@  c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
 		    error_at (token->location, "property must be "
 			      "constant integer expression");
 		  else
-		    properties = tree_cons (NULL_TREE, t, properties);
+		    properties = make_trait_property (NULL_TREE, t,
+						      properties);
 		}
 	      else
 		return error_mark_node;
@@ -24286,7 +24293,7 @@  c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
 	  return error_mark_node;
 	}
 
-      ret = tree_cons (selector, properties, ret);
+      ret = make_trait_selector (selector, scoreval, properties, ret);
 
       if (c_parser_next_token_is (parser, CPP_COMMA))
 	c_parser_consume_token (parser);
@@ -24362,7 +24369,7 @@  c_parser_omp_context_selector_specification (c_parser *parser, tree parms)
       if (selectors == error_mark_node)
 	ret = error_mark_node;
       else if (ret != error_mark_node)
-	ret = tree_cons (set, selectors, ret);
+	ret = make_trait_set_selector (set, selectors, ret);
 
       braces.skip_until_found_close (parser);
 
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index d1104336215..dd773570981 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -47271,7 +47271,10 @@  static const char *const omp_user_selectors[] = {
      trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
 
    trait-score:
-     score(score-expression)  */
+     score(score-expression)
+
+   Note that this function returns a list of trait selectors for the
+   trait-selector-set SET.  */
 
 static tree
 cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
@@ -47290,6 +47293,7 @@  cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
 	}
 
       tree properties = NULL_TREE;
+      tree scoreval = NULL_TREE;
       const char *const *selectors = NULL;
       bool allow_score = true;
       bool allow_user = false;
@@ -47396,8 +47400,7 @@  cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
 		    {
 		      score = fold_non_dependent_expr (score);
 		      if (value_dependent_expression_p (score))
-			properties = tree_cons (get_identifier (" score"),
-						score, properties);
+			scoreval = score;
 		      else if (!INTEGRAL_TYPE_P (TREE_TYPE (score))
 			       || TREE_CODE (score) != INTEGER_CST)
 			error_at (token->location, "score argument must be "
@@ -47406,8 +47409,7 @@  cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
 			error_at (token->location, "score argument must be "
 				  "non-negative");
 		      else
-			properties = tree_cons (get_identifier (" score"),
-						score, properties);
+			scoreval = score;
 		    }
 		}
 	      else
@@ -47427,7 +47429,8 @@  cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
 		    {
 		      t = fold_non_dependent_expr (t);
 		      if (TREE_CODE (t) == STRING_CST)
-			properties = tree_cons (NULL_TREE, t, properties);
+			properties = make_trait_property (NULL_TREE, t,
+							  properties);
 		      else if (!value_dependent_expression_p (t)
 			       && (!INTEGRAL_TYPE_P (TREE_TYPE (t))
 				   || !tree_fits_shwi_p (t)))
@@ -47435,7 +47438,8 @@  cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
 				  "constant integer expression or string "
 				  "literal");
 		      else
-			properties = tree_cons (NULL_TREE, t, properties);
+			properties = make_trait_property (NULL_TREE, t,
+							  properties);
 		    }
 		  else
 		    return error_mark_node;
@@ -47453,7 +47457,8 @@  cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
 		{
 		  tree prop = cp_lexer_peek_token (parser->lexer)->u.value;
 		  cp_lexer_consume_token (parser->lexer);
-		  properties = tree_cons (prop, NULL_TREE, properties);
+		  properties = make_trait_property (prop, NULL_TREE,
+						    properties);
 		}
 	      else
 		{
@@ -47482,7 +47487,7 @@  cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
 		      return error_mark_node;
 		    }
 
-		  properties = tree_cons (prop, value, properties);
+		  properties = make_trait_property (prop, value, properties);
 
 		  if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
 		    cp_lexer_consume_token (parser->lexer);
@@ -47502,7 +47507,8 @@  cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
 		    error_at (token->location, "property must be "
 			      "constant integer expression");
 		  else
-		    properties = tree_cons (NULL_TREE, t, properties);
+		    properties = make_trait_property (NULL_TREE, t,
+						      properties);
 		}
 	      else
 		return error_mark_node;
@@ -47537,7 +47543,7 @@  cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
 	  return error_mark_node;
 	}
 
-      ret = tree_cons (selector, properties, ret);
+      ret = make_trait_selector (selector, scoreval, properties, ret);
 
       if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
 	cp_lexer_consume_token (parser->lexer);
@@ -47619,7 +47625,7 @@  cp_parser_omp_context_selector_specification (cp_parser *parser,
 	  ret = error_mark_node;
 	}
       else if (ret != error_mark_node)
-	ret = tree_cons (set, selectors, ret);
+	ret = make_trait_set_selector (set, selectors, ret);
 
       braces.require_close (parser);
 
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 324f6f01555..3af793dfe20 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -47,6 +47,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "selftest.h"
 #include "target.h"
 #include "builtins.h"
+#include "omp-general.h"
 
 /* The type of functions taking a tree, and some additional data, and
    returning an int.  */
@@ -11841,50 +11842,72 @@  tsubst_attribute (tree t, tree *decl_p, tree args,
       location_t match_loc = cp_expr_loc_or_input_loc (TREE_PURPOSE (chain));
       tree ctx = copy_list (TREE_VALUE (val));
       tree simd = get_identifier ("simd");
-      tree score = get_identifier (" score");
       tree condition = get_identifier ("condition");
-      for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
+      for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
 	{
-	  const char *set = IDENTIFIER_POINTER (TREE_PURPOSE (t1));
-	  TREE_VALUE (t1) = copy_list (TREE_VALUE (t1));
-	  for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
+	  const char *set = IDENTIFIER_POINTER (OMP_TSS_ID (tss));
+	  tree selectors = NULL_TREE;
+	  for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts;
+	       ts = TREE_CHAIN (ts))
 	    {
-	      if (TREE_PURPOSE (t2) == simd && set[0] == 'c')
+	      tree properties = NULL_TREE;
+	      tree scoreval = NULL_TREE;
+	      if (OMP_TS_ID (ts) == simd && set[0] == 'c')
 		{
-		  tree clauses = TREE_VALUE (t2);
+		  tree clauses = OMP_TS_PROPERTIES (ts);
 		  clauses = tsubst_omp_clauses (clauses,
 						C_ORT_OMP_DECLARE_SIMD, args,
 						complain, in_decl);
 		  c_omp_declare_simd_clauses_to_decls (*decl_p, clauses);
 		  clauses = finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD);
-		  TREE_VALUE (t2) = clauses;
+		  properties = clauses;
 		}
 	      else
 		{
-		  TREE_VALUE (t2) = copy_list (TREE_VALUE (t2));
-		  for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
-		    if (TREE_VALUE (t3))
+		  tree v = OMP_TS_SCORE (ts);
+		  if (v)
+		    {
+		      v = tsubst_expr (v, args, complain, in_decl);
+		      v = fold_non_dependent_expr (v);
+		      if (!INTEGRAL_TYPE_P (TREE_TYPE (v))
+			  || TREE_CODE (v) != INTEGER_CST)
+			{
+			  location_t loc
+			    = cp_expr_loc_or_loc (OMP_TS_SCORE (ts),
+						  match_loc);
+			  error_at (loc, "score argument must be "
+				    "constant integer expression");
+			  return NULL_TREE;
+			}
+		      else if (tree_int_cst_sgn (v) < 0)
+			{
+			  location_t loc
+			    = cp_expr_loc_or_loc (OMP_TS_SCORE (ts),
+						  match_loc);
+			  error_at (loc, "score argument must be "
+				    "non-negative");
+			  return NULL_TREE;
+			}
+		      scoreval = v;
+		    }
+		  properties = copy_list (OMP_TS_PROPERTIES (ts));
+		  for (tree p = properties; p; p = TREE_CHAIN (p))
+		    if (OMP_TP_VALUE (p))
 		      {
 			bool allow_string
-			  = ((TREE_PURPOSE (t2) != condition || set[0] != 'u')
-			     && TREE_PURPOSE (t3) != score);
-			tree v = TREE_VALUE (t3);
+			  = (OMP_TS_ID (ts) != condition || set[0] != 'u');
+			tree v = OMP_TP_VALUE (p);
 			if (TREE_CODE (v) == STRING_CST && allow_string)
 			  continue;
 			v = tsubst_expr (v, args, complain, in_decl);
 			v = fold_non_dependent_expr (v);
 			if (!INTEGRAL_TYPE_P (TREE_TYPE (v))
-			    || (TREE_PURPOSE (t3) == score
-				? TREE_CODE (v) != INTEGER_CST
-				: !tree_fits_shwi_p (v)))
+			    || !tree_fits_shwi_p (v))
 			  {
 			    location_t loc
-			      = cp_expr_loc_or_loc (TREE_VALUE (t3),
+			      = cp_expr_loc_or_loc (OMP_TP_VALUE (p),
 						    match_loc);
-			    if (TREE_PURPOSE (t3) == score)
-			      error_at (loc, "score argument must be "
-					     "constant integer expression");
-			    else if (allow_string)
+			    if (allow_string)
 			      error_at (loc, "property must be constant "
 					     "integer expression or string "
 					     "literal");
@@ -11893,20 +11916,13 @@  tsubst_attribute (tree t, tree *decl_p, tree args,
 					     "integer expression");
 			    return NULL_TREE;
 			  }
-			else if (TREE_PURPOSE (t3) == score
-				 && tree_int_cst_sgn (v) < 0)
-			  {
-			    location_t loc
-			      = cp_expr_loc_or_loc (TREE_VALUE (t3),
-						    match_loc);
-			    error_at (loc, "score argument must be "
-					   "non-negative");
-			    return NULL_TREE;
-			  }
-			TREE_VALUE (t3) = v;
+			OMP_TP_VALUE (p) = v;
 		      }
 		}
+	      selectors = make_trait_selector (OMP_TS_ID (ts), scoreval,
+					       properties, selectors);
 	    }
+	  OMP_TSS_TRAIT_SELECTORS (tss) = nreverse (selectors);
 	}
       val = tree_cons (varid, ctx, chain);
     }
diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index 82bbc41b388..fe8044a57cd 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -8210,6 +8210,7 @@  gfc_trans_omp_declare_variant (gfc_namespace *ns)
 	  gfc_omp_selector *os;
 	  for (os = oss->trait_selectors; os; os = os->next)
 	    {
+	      tree scoreval = NULL_TREE;
 	      tree properties = NULL_TREE;
 	      gfc_omp_trait_property *otp;
 
@@ -8223,13 +8224,14 @@  gfc_trans_omp_declare_variant (gfc_namespace *ns)
 			gfc_se se;
 			gfc_init_se (&se, NULL);
 			gfc_conv_expr (&se, otp->expr);
-			properties = tree_cons (NULL_TREE, se.expr,
-						properties);
+			properties = make_trait_property (NULL_TREE, se.expr,
+							  properties);
 		      }
 		      break;
 		    case CTX_PROPERTY_ID:
-		      properties = tree_cons (get_identifier (otp->name),
-					      NULL_TREE, properties);
+		      properties
+			= make_trait_property (get_identifier (otp->name),
+					       NULL_TREE, properties);
 		      break;
 		    case CTX_PROPERTY_NAME_LIST:
 		      {
@@ -8239,7 +8241,8 @@  gfc_trans_omp_declare_variant (gfc_namespace *ns)
 			else
 			  value = gfc_conv_constant_to_tree (otp->expr);
 
-			properties = tree_cons (prop, value, properties);
+			properties = make_trait_property (prop, value,
+							  properties);
 		      }
 		      break;
 		    case CTX_PROPERTY_SIMD:
@@ -8256,17 +8259,17 @@  gfc_trans_omp_declare_variant (gfc_namespace *ns)
 		  gfc_se se;
 		  gfc_init_se (&se, NULL);
 		  gfc_conv_expr (&se, os->score);
-		  properties = tree_cons (get_identifier (" score"),
-					  se.expr, properties);
+		  scoreval = se.expr;
 		}
 
-	      selectors = tree_cons (get_identifier (os->trait_selector_name),
-				     properties, selectors);
+	      tree ts_name = get_identifier (os->trait_selector_name);
+	      selectors	= make_trait_selector (ts_name, scoreval,
+					       properties, selectors);
 	    }
 
-	  set_selectors
-	    = tree_cons (get_identifier (oss->trait_set_selector_name),
-			 selectors, set_selectors);
+	  tree tss_name = get_identifier (oss->trait_set_selector_name);
+	  set_selectors = make_trait_set_selector (tss_name, selectors,
+						   set_selectors);
 	}
 
       const char *variant_proc_name = odv->variant_proc_symtree->name;
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 77f07af6ec5..757654d5434 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -13541,8 +13541,8 @@  omp_construct_selector_matches (enum tree_code *constructs, int nconstructs,
       int variant_nconstructs = 0;
       if (!target_seen)
 	variant_nconstructs
-	  = omp_constructor_traits_to_codes (TREE_VALUE (attr),
-					     variant_constructs);
+	  = omp_construct_traits_to_codes (TREE_VALUE (attr),
+					   variant_constructs);
       for (int i = 0; i < variant_nconstructs; i++)
 	{
 	  ++cnt;
diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc
index b88d5930aab..4ea0d971273 100644
--- a/gcc/omp-general.cc
+++ b/gcc/omp-general.cc
@@ -1017,13 +1017,13 @@  omp_max_simt_vf (void)
    return their number.  */
 
 int
-omp_constructor_traits_to_codes (tree ctx, enum tree_code *constructs)
+omp_construct_traits_to_codes (tree ctx, enum tree_code *constructs)
 {
   int nconstructs = list_length (ctx);
   int i = nconstructs - 1;
-  for (tree t2 = ctx; t2; t2 = TREE_CHAIN (t2), i--)
+  for (tree ts = ctx; ts; ts = TREE_CHAIN (ts), i--)
     {
-      const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t2));
+      const char *sel = IDENTIFIER_POINTER (OMP_TS_ID (ts));
       if (!strcmp (sel, "target"))
 	constructs[i] = OMP_TARGET;
       else if (!strcmp (sel, "teams"))
@@ -1125,38 +1125,40 @@  omp_check_context_selector (location_t loc, tree ctx)
      There are just 4 set names.  */
   for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
     for (tree t2 = TREE_CHAIN (t1); t2; t2 = TREE_CHAIN (t2))
-      if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
+      if (OMP_TSS_ID (t1) == OMP_TSS_ID (t2))
 	{
 	  error_at (loc, "selector set %qs specified more than once",
-		    IDENTIFIER_POINTER (TREE_PURPOSE (t1)));
+		    IDENTIFIER_POINTER (OMP_TSS_ID (t1)));
 	  return error_mark_node;
 	}
-  for (tree t = ctx; t; t = TREE_CHAIN (t))
+  for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
     {
       /* Each trait-selector-name can only be specified once.  */
-      if (list_length (TREE_VALUE (t)) < 5)
+      if (list_length (OMP_TSS_TRAIT_SELECTORS (tss)) < 5)
 	{
-	  for (tree t1 = TREE_VALUE (t); t1; t1 = TREE_CHAIN (t1))
-	    for (tree t2 = TREE_CHAIN (t1); t2; t2 = TREE_CHAIN (t2))
-	      if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
+	  for (tree ts1 = OMP_TSS_TRAIT_SELECTORS (tss); ts1;
+	       ts1 = TREE_CHAIN (ts1))
+	    for (tree ts2 = TREE_CHAIN (ts1); ts2; ts2 = TREE_CHAIN (ts2))
+	      if (OMP_TS_ID (ts1) == OMP_TS_ID (ts2))
 		{
 		  error_at (loc,
 			    "selector %qs specified more than once in set %qs",
-			    IDENTIFIER_POINTER (TREE_PURPOSE (t1)),
-			    IDENTIFIER_POINTER (TREE_PURPOSE (t)));
+			    IDENTIFIER_POINTER (OMP_TS_ID (ts1)),
+			    IDENTIFIER_POINTER (OMP_TSS_ID (tss)));
 		  return error_mark_node;
 		}
 	}
       else
 	{
 	  hash_set<tree> pset;
-	  for (tree t1 = TREE_VALUE (t); t1; t1 = TREE_CHAIN (t1))
-	    if (pset.add (TREE_PURPOSE (t1)))
+	  for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts;
+	       ts = TREE_CHAIN (ts))
+	    if (pset.add (OMP_TS_ID (ts)))
 	      {
 		error_at (loc,
 			  "selector %qs specified more than once in set %qs",
-			  IDENTIFIER_POINTER (TREE_PURPOSE (t1)),
-			  IDENTIFIER_POINTER (TREE_PURPOSE (t)));
+			  IDENTIFIER_POINTER (OMP_TS_ID (ts)),
+			  IDENTIFIER_POINTER (OMP_TSS_ID (tss)));
 		return error_mark_node;
 	      }
 	}
@@ -1177,49 +1179,45 @@  omp_check_context_selector (location_t loc, tree ctx)
 	{ "implementation", "extension", extension },
 	{ "implementation", "atomic_default_mem_order",
 	  atomic_default_mem_order } };
-      for (tree t1 = TREE_VALUE (t); t1; t1 = TREE_CHAIN (t1))
+      for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
 	for (unsigned i = 0; i < ARRAY_SIZE (props); i++)
-	  if (!strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t1)),
+	  if (!strcmp (IDENTIFIER_POINTER (OMP_TS_ID (ts)),
 					   props[i].selector)
-	      && !strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t)),
+	      && !strcmp (IDENTIFIER_POINTER (OMP_TSS_ID (tss)),
 					      props[i].set))
-	    for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
+	    for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
 	      for (unsigned j = 0; ; j++)
 		{
 		  if (props[i].props[j] == NULL)
 		    {
-		      if (TREE_PURPOSE (t2)
-			  && !strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
-				      " score"))
-			break;
 		      if (props[i].props == atomic_default_mem_order)
 			{
 			  error_at (loc,
 				    "incorrect property %qs of %qs selector",
-				    IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
+				    IDENTIFIER_POINTER (TREE_PURPOSE (p)),
 				    "atomic_default_mem_order");
 			  return error_mark_node;
 			}
-		      else if (TREE_PURPOSE (t2))
+		      else if (OMP_TP_NAME (p))
 			warning_at (loc, 0,
 				    "unknown property %qs of %qs selector",
-				    IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
+				    IDENTIFIER_POINTER (OMP_TP_NAME (p)),
 				    props[i].selector);
 		      else
 			warning_at (loc, 0,
 				    "unknown property %qE of %qs selector",
-				    TREE_VALUE (t2), props[i].selector);
+				    OMP_TP_VALUE (p), props[i].selector);
 		      break;
 		    }
-		  else if (TREE_PURPOSE (t2) == NULL_TREE)
+		  else if (OMP_TP_NAME (p) == NULL_TREE)
 		    {
-		      const char *str = TREE_STRING_POINTER (TREE_VALUE (t2));
+		      const char *str = TREE_STRING_POINTER (OMP_TP_VALUE (p));
 		      if (!strcmp (str, props[i].props[j])
-			  && ((size_t) TREE_STRING_LENGTH (TREE_VALUE (t2))
+			  && ((size_t) TREE_STRING_LENGTH (OMP_TP_VALUE (p))
 			      == strlen (str) + (lang_GNU_Fortran () ? 0 : 1)))
 			break;
 		    }
-		  else if (!strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
+		  else if (!strcmp (IDENTIFIER_POINTER (OMP_TP_NAME (p)),
 				    props[i].props[j]))
 		    break;
 		}
@@ -1254,18 +1252,43 @@  omp_mark_declare_variant (location_t loc, tree variant, tree construct)
 }
 
 
+/* Constructors for context selectors.  */
+
+tree
+make_trait_set_selector (tree name, tree selectors, tree chain)
+{
+  return tree_cons (name, selectors, chain);
+}
+
+tree
+make_trait_selector (tree name, tree score, tree properties, tree chain)
+{
+  if (score == NULL_TREE)
+    return tree_cons (name, properties, chain);
+  else
+    return tree_cons (name,
+		      tree_cons (OMP_TS_SCORE_NODE, score, properties),
+		      chain);
+}
+
+tree
+make_trait_property (tree name, tree value, tree chain)
+{
+  return tree_cons (name, value, chain);
+}
+
 /* Return a name from PROP, a property in selectors accepting
    name lists.  */
 
 static const char *
 omp_context_name_list_prop (tree prop)
 {
-  if (TREE_PURPOSE (prop))
-    return IDENTIFIER_POINTER (TREE_PURPOSE (prop));
+  if (OMP_TP_NAME (prop))
+    return IDENTIFIER_POINTER (OMP_TP_NAME (prop));
   else
     {
-      const char *ret = TREE_STRING_POINTER (TREE_VALUE (prop));
-      if ((size_t) TREE_STRING_LENGTH (TREE_VALUE (prop))
+      const char *ret = TREE_STRING_POINTER (OMP_TP_VALUE (prop));
+      if ((size_t) TREE_STRING_LENGTH (OMP_TP_VALUE (prop))
 	  == strlen (ret) + (lang_GNU_Fortran () ? 0 : 1))
 	return ret;
       return NULL;
@@ -1282,9 +1305,9 @@  int
 omp_context_selector_matches (tree ctx)
 {
   int ret = 1;
-  for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
+  for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
     {
-      char set = IDENTIFIER_POINTER (TREE_PURPOSE (t1))[0];
+      char set = IDENTIFIER_POINTER (OMP_TSS_ID (tss))[0];
       if (set == 'c')
 	{
 	  /* For now, ignore the construct set.  While something can be
@@ -1302,7 +1325,8 @@  omp_context_selector_matches (tree ctx)
 
 	  enum tree_code constructs[5];
 	  int nconstructs
-	    = omp_constructor_traits_to_codes (TREE_VALUE (t1), constructs);
+	    = omp_construct_traits_to_codes (OMP_TSS_TRAIT_SELECTORS (tss),
+					     constructs);
 
 	  if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
 	    {
@@ -1333,20 +1357,19 @@  omp_context_selector_matches (tree ctx)
 	    ret = -1;
 	  continue;
 	}
-      for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
+      for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
 	{
-	  const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t2));
+	  const char *sel = IDENTIFIER_POINTER (OMP_TS_ID (ts));
 	  switch (*sel)
 	    {
 	    case 'v':
 	      if (set == 'i' && !strcmp (sel, "vendor"))
-		for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
+		for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
 		  {
-		    const char *prop = omp_context_name_list_prop (t3);
+		    const char *prop = omp_context_name_list_prop (p);
 		    if (prop == NULL)
 		      return 0;
-		    if ((!strcmp (prop, " score") && TREE_PURPOSE (t3))
-			|| !strcmp (prop, "gnu"))
+		    if (!strcmp (prop, "gnu"))
 		      continue;
 		    return 0;
 		  }
@@ -1377,13 +1400,8 @@  omp_context_selector_matches (tree ctx)
 		      else
 			omo = OMP_MEMORY_ORDER_RELAXED;
 		    }
-		  tree t3 = TREE_VALUE (t2);
-		  const char *prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
-		  if (!strcmp (prop, " score"))
-		    {
-		      t3 = TREE_CHAIN (t3);
-		      prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
-		    }
+		  tree p = OMP_TS_PROPERTIES (ts);
+		  const char *prop = IDENTIFIER_POINTER (OMP_TP_NAME (p));
 		  if (!strcmp (prop, "relaxed")
 		      && omo != OMP_MEMORY_ORDER_RELAXED)
 		    return 0;
@@ -1395,9 +1413,9 @@  omp_context_selector_matches (tree ctx)
 		    return 0;
 		}
 	      if (set == 'd' && !strcmp (sel, "arch"))
-		for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
+		for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
 		  {
-		    const char *arch = omp_context_name_list_prop (t3);
+		    const char *arch = omp_context_name_list_prop (p);
 		    if (arch == NULL)
 		      return 0;
 		    int r = 0;
@@ -1497,9 +1515,9 @@  omp_context_selector_matches (tree ctx)
 	      break;
 	    case 'k':
 	      if (set == 'd' && !strcmp (sel, "kind"))
-		for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
+		for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
 		  {
-		    const char *prop = omp_context_name_list_prop (t3);
+		    const char *prop = omp_context_name_list_prop (p);
 		    if (prop == NULL)
 		      return 0;
 		    if (!strcmp (prop, "any"))
@@ -1558,9 +1576,9 @@  omp_context_selector_matches (tree ctx)
 	      break;
 	    case 'i':
 	      if (set == 'd' && !strcmp (sel, "isa"))
-		for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
+		for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
 		  {
-		    const char *isa = omp_context_name_list_prop (t3);
+		    const char *isa = omp_context_name_list_prop (p);
 		    if (isa == NULL)
 		      return 0;
 		    int r = 0;
@@ -1611,12 +1629,12 @@  omp_context_selector_matches (tree ctx)
 	      break;
 	    case 'c':
 	      if (set == 'u' && !strcmp (sel, "condition"))
-		for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
-		  if (TREE_PURPOSE (t3) == NULL_TREE)
+		for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
+		  if (OMP_TP_NAME (p) == NULL_TREE)
 		    {
-		      if (integer_zerop (TREE_VALUE (t3)))
+		      if (integer_zerop (OMP_TP_VALUE (p)))
 			return 0;
-		      if (integer_nonzerop (TREE_VALUE (t3)))
+		      if (integer_nonzerop (OMP_TP_VALUE (p)))
 			break;
 		      ret = -1;
 		    }
@@ -1747,6 +1765,7 @@  omp_construct_simd_compare (tree clauses1, tree clauses2)
 }
 
 /* Compare properties of selectors SEL from SET other than construct.
+   CTX1 and CTX2 are the lists of properties to compare.
    Return 0/-1/1/2 as in omp_context_selector_set_compare.
    Unlike set names or selector names, properties can have duplicates.  */
 
@@ -1756,57 +1775,37 @@  omp_context_selector_props_compare (const char *set, const char *sel,
 {
   int ret = 0;
   for (int pass = 0; pass < 2; pass++)
-    for (tree t1 = pass ? ctx2 : ctx1; t1; t1 = TREE_CHAIN (t1))
+    for (tree p1 = pass ? ctx2 : ctx1; p1; p1 = TREE_CHAIN (p1))
       {
-	tree t2;
-	for (t2 = pass ? ctx1 : ctx2; t2; t2 = TREE_CHAIN (t2))
-	  if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
+	tree p2;
+	for (p2 = pass ? ctx1 : ctx2; p2; p2 = TREE_CHAIN (p2))
+	  if (OMP_TP_NAME (p1) == OMP_TP_NAME (p2))
 	    {
-	      if (TREE_PURPOSE (t1) == NULL_TREE)
+	      if (OMP_TP_NAME (p1) == NULL_TREE)
 		{
 		  if (set[0] == 'u' && strcmp (sel, "condition") == 0)
 		    {
-		      if (integer_zerop (TREE_VALUE (t1))
-			  != integer_zerop (TREE_VALUE (t2)))
+		      if (integer_zerop (OMP_TP_VALUE (p1))
+			  != integer_zerop (OMP_TP_VALUE (p2)))
 			return 2;
 		      break;
 		    }
-		  if (simple_cst_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
+		  if (simple_cst_equal (OMP_TP_VALUE (p1), OMP_TP_VALUE (p2)))
 		    break;
 		}
-	      else if (strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t1)),
-			       " score") == 0)
-		{
-		  if (!simple_cst_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
-		    return 2;
-		  break;
-		}
 	      else
 		break;
 	    }
-	  else if (TREE_PURPOSE (t1)
-		   && TREE_PURPOSE (t2) == NULL_TREE
-		   && TREE_CODE (TREE_VALUE (t2)) == STRING_CST)
-	    {
-	      const char *p1 = omp_context_name_list_prop (t1);
-	      const char *p2 = omp_context_name_list_prop (t2);
-	      if (p2
-		  && strcmp (p1, p2) == 0
-		  && strcmp (p1, " score"))
-		break;
-	    }
-	  else if (TREE_PURPOSE (t1) == NULL_TREE
-		   && TREE_PURPOSE (t2)
-		   && TREE_CODE (TREE_VALUE (t1)) == STRING_CST)
+	  else
 	    {
-	      const char *p1 = omp_context_name_list_prop (t1);
-	      const char *p2 = omp_context_name_list_prop (t2);
-	      if (p1
-		  && strcmp (p1, p2) == 0
-		  && strcmp (p1, " score"))
+	      /* Handle string constant vs identifier comparison for
+		 name-list properties.  */
+	      const char *n1 = omp_context_name_list_prop (p1);
+	      const char *n2 = omp_context_name_list_prop (p2);
+	      if (n1 && n2 && !strcmp (n1, n2))
 		break;
 	    }
-	if (t2 == NULL_TREE)
+	if (p2 == NULL_TREE)
 	  {
 	    int r = pass ? -1 : 1;
 	    if (ret && ret != r)
@@ -1824,6 +1823,7 @@  omp_context_selector_props_compare (const char *set, const char *sel,
 }
 
 /* Compare single context selector sets CTX1 and CTX2 with SET name.
+   CTX1 and CTX2 are lists of trait-selectors.
    Return 0 if CTX1 is equal to CTX2,
    -1 if CTX1 is a strict subset of CTX2,
    1 if CTX2 is a strict subset of CTX1, or
@@ -1845,26 +1845,26 @@  omp_context_selector_set_compare (const char *set, tree ctx1, tree ctx2)
     }
   if (set[0] == 'c')
     {
-      tree t1;
-      tree t2 = ctx2;
+      tree ts1;
+      tree ts2 = ctx2;
       tree simd = get_identifier ("simd");
       /* Handle construct set specially.  In this case the order
 	 of the selector matters too.  */
-      for (t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
-	if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
+      for (ts1 = ctx1; ts1; ts1 = TREE_CHAIN (ts1))
+	if (OMP_TS_ID (ts1) == OMP_TS_ID (ts2))
 	  {
 	    int r = 0;
-	    if (TREE_PURPOSE (t1) == simd)
-	      r = omp_construct_simd_compare (TREE_VALUE (t1),
-					      TREE_VALUE (t2));
+	    if (OMP_TS_ID (ts1) == simd)
+	      r = omp_construct_simd_compare (OMP_TS_PROPERTIES (ts1),
+					      OMP_TS_PROPERTIES (ts2));
 	    if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
 	      return 2;
 	    if (ret == 0)
 	      ret = r;
-	    t2 = TREE_CHAIN (t2);
-	    if (t2 == NULL_TREE)
+	    ts2 = TREE_CHAIN (ts2);
+	    if (ts2 == NULL_TREE)
 	      {
-		t1 = TREE_CHAIN (t1);
+		ts1 = TREE_CHAIN (ts1);
 		break;
 	      }
 	  }
@@ -1872,9 +1872,9 @@  omp_context_selector_set_compare (const char *set, tree ctx1, tree ctx2)
 	  return 2;
 	else
 	  ret = 1;
-      if (t2 != NULL_TREE)
+      if (ts2 != NULL_TREE)
 	return 2;
-      if (t1 != NULL_TREE)
+      if (ts1 != NULL_TREE)
 	{
 	  if (ret < 0)
 	    return 2;
@@ -1884,16 +1884,21 @@  omp_context_selector_set_compare (const char *set, tree ctx1, tree ctx2)
 	return 0;
       return swapped ? -ret : ret;
     }
-  for (tree t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
+  for (tree ts1 = ctx1; ts1; ts1 = TREE_CHAIN (ts1))
     {
-      tree t2;
-      for (t2 = ctx2; t2; t2 = TREE_CHAIN (t2))
-	if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
+      tree ts2;
+      for (ts2 = ctx2; ts2; ts2 = TREE_CHAIN (ts2))
+	if (OMP_TS_ID (ts1) == OMP_TS_ID (ts2))
 	  {
-	    const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t1));
+	    tree score1 = OMP_TS_SCORE (ts1);
+	    tree score2 = OMP_TS_SCORE (ts2);
+	    if (score1 && score2 && !simple_cst_equal (score1, score2))
+	      return 2;
+
+	    const char *sel = IDENTIFIER_POINTER (OMP_TS_ID (ts1));
 	    int r = omp_context_selector_props_compare (set, sel,
-							TREE_VALUE (t1),
-							TREE_VALUE (t2));
+							OMP_TS_PROPERTIES (ts1),
+							OMP_TS_PROPERTIES (ts2));
 	    if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
 	      return 2;
 	    if (ret == 0)
@@ -1901,7 +1906,7 @@  omp_context_selector_set_compare (const char *set, tree ctx1, tree ctx2)
 	    cnt++;
 	    break;
 	  }
-      if (t2 == NULL_TREE)
+      if (ts2 == NULL_TREE)
 	{
 	  if (ret == -1)
 	    return 2;
@@ -1935,15 +1940,17 @@  omp_context_selector_compare (tree ctx1, tree ctx2)
       std::swap (ctx1, ctx2);
       std::swap (len1, len2);
     }
-  for (tree t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
+  for (tree tss1 = ctx1; tss1; tss1 = TREE_CHAIN (tss1))
     {
-      tree t2;
-      for (t2 = ctx2; t2; t2 = TREE_CHAIN (t2))
-	if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
+      tree tss2;
+      for (tss2 = ctx2; tss2; tss2 = TREE_CHAIN (tss2))
+	if (OMP_TSS_ID (tss1) == OMP_TSS_ID (tss2))
 	  {
-	    const char *set = IDENTIFIER_POINTER (TREE_PURPOSE (t1));
-	    int r = omp_context_selector_set_compare (set, TREE_VALUE (t1),
-						      TREE_VALUE (t2));
+	    const char *set = IDENTIFIER_POINTER (OMP_TSS_ID (tss1));
+	    int r
+	      = omp_context_selector_set_compare
+		  (set, OMP_TSS_TRAIT_SELECTORS (tss1),
+		   OMP_TSS_TRAIT_SELECTORS (tss2));
 	    if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
 	      return 2;
 	    if (ret == 0)
@@ -1951,7 +1958,7 @@  omp_context_selector_compare (tree ctx1, tree ctx2)
 	    cnt++;
 	    break;
 	  }
-      if (t2 == NULL_TREE)
+      if (tss2 == NULL_TREE)
 	{
 	  if (ret == -1)
 	    return 2;
@@ -1974,14 +1981,14 @@  omp_get_context_selector (tree ctx, const char *set, const char *sel)
 {
   tree setid = get_identifier (set);
   tree selid = sel ? get_identifier (sel) : NULL_TREE;
-  for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
-    if (TREE_PURPOSE (t1) == setid)
+  for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
+    if (OMP_TSS_ID (tss) == setid)
       {
 	if (sel == NULL)
-	  return TREE_VALUE (t1);
-	for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
-	  if (TREE_PURPOSE (t2) == selid)
-	    return t2;
+	  return OMP_TSS_TRAIT_SELECTORS (tss);
+	for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
+	  if (OMP_TS_ID (ts) == selid)
+	    return ts;
       }
   return NULL_TREE;
 }
@@ -2004,25 +2011,23 @@  omp_context_compute_score (tree ctx, score_wide_int *score, bool declare_simd)
   bool has_isa = omp_get_context_selector (ctx, "device", "isa");
   bool ret = false;
   *score = 1;
-  for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
-    if (TREE_VALUE (t1) != construct)
-      for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
-	if (tree t3 = TREE_VALUE (t2))
-	  if (TREE_PURPOSE (t3)
-	      && strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t3)), " score") == 0
-	      && TREE_CODE (TREE_VALUE (t3)) == INTEGER_CST)
-	    {
-	      tree t4 = TREE_VALUE (t3);
-	      *score += score_wide_int::from (wi::to_wide (t4),
-					      TYPE_SIGN (TREE_TYPE (t4)));
-	    }
+  for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
+    if (OMP_TSS_TRAIT_SELECTORS (tss) != construct)
+      for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
+	{
+	  tree s = OMP_TS_SCORE (ts);
+	  if (s && TREE_CODE (s) == INTEGER_CST)
+	    *score += score_wide_int::from (wi::to_wide (s),
+					    TYPE_SIGN (TREE_TYPE (s)));
+	}
+
   if (construct || has_kind || has_arch || has_isa)
     {
       int scores[12];
       enum tree_code constructs[5];
       int nconstructs = 0;
       if (construct)
-	nconstructs = omp_constructor_traits_to_codes (construct, constructs);
+	nconstructs = omp_construct_traits_to_codes (construct, constructs);
       if (omp_construct_selector_matches (constructs, nconstructs, scores)
 	  == 2)
 	ret = true;
diff --git a/gcc/omp-general.h b/gcc/omp-general.h
index 1a52bfdb56b..28a9c0e6e17 100644
--- a/gcc/omp-general.h
+++ b/gcc/omp-general.h
@@ -92,6 +92,52 @@  struct omp_for_data
 
 #define OACC_FN_ATTRIB "oacc function"
 
+/* Accessors for OMP context selectors, used by variant directives.
+   These are represented internally by a multilevel TREE_LIST structure, but
+   these accessors should be used to avoid confusion.  The grammar is:
+
+   context-set-selector-specification:
+     trait-set-selector [, trait-set-selector [, ...]]
+   trait-set-selector:
+     trait-set-selector-name = { trait-selector [, trait-selector [, ... ]] }
+   trait-selector:
+     trait-selector-name [ ( [trait-score: ]
+			     trait-property [, trait-property  [, ...]] ) ]
+
+   trait-properties can variously be identifiers, strings, clauses, or
+   expressions.
+
+   All the lists are chained via TREE_CHAIN.  If a score is present, it is
+   internally tacked on to the properties with a TREE_PURPOSE of
+   OMP_TS_SCORE_NODE.  */
+
+#define OMP_TS_SCORE_NODE integer_minus_one_node
+
+#define OMP_TSS_ID(NODE) \
+  TREE_PURPOSE (NODE)
+#define OMP_TSS_TRAIT_SELECTORS(NODE) \
+  TREE_VALUE (NODE)
+#define OMP_TS_ID(NODE) \
+  TREE_PURPOSE (NODE)
+#define OMP_TS_SCORE(NODE) \
+  ((TREE_VALUE (NODE)					      \
+    && TREE_CODE (TREE_VALUE (NODE)) == TREE_LIST	      \
+    && TREE_PURPOSE (TREE_VALUE (NODE)) == OMP_TS_SCORE_NODE) \
+   ? TREE_VALUE (TREE_VALUE (NODE)) : NULL_TREE)
+#define OMP_TS_PROPERTIES(NODE) \
+  ((TREE_VALUE (NODE)					      \
+    && TREE_CODE (TREE_VALUE (NODE)) == TREE_LIST	      \
+    && TREE_PURPOSE (TREE_VALUE (NODE)) == OMP_TS_SCORE_NODE) \
+   ? TREE_CHAIN (TREE_VALUE (NODE)) : TREE_VALUE (NODE))
+#define OMP_TP_NAME(NODE) \
+  TREE_PURPOSE (NODE)
+#define OMP_TP_VALUE(NODE) \
+  TREE_VALUE (NODE)
+
+extern tree make_trait_set_selector (tree, tree, tree);
+extern tree make_trait_selector (tree, tree, tree, tree);
+extern tree make_trait_property (tree, tree, tree);
+
 extern tree omp_find_clause (tree clauses, enum omp_clause_code kind);
 extern bool omp_is_allocatable_or_ptr (tree decl);
 extern tree omp_check_optional_argument (tree decl, bool for_present_check);
@@ -106,7 +152,7 @@  extern gimple *omp_build_barrier (tree lhs);
 extern tree find_combined_omp_for (tree *, int *, void *);
 extern poly_uint64 omp_max_vf (void);
 extern int omp_max_simt_vf (void);
-extern int omp_constructor_traits_to_codes (tree, enum tree_code *);
+extern int omp_construct_traits_to_codes (tree, enum tree_code *);
 extern tree omp_check_context_selector (location_t loc, tree ctx);
 extern void omp_mark_declare_variant (location_t loc, tree variant,
 				      tree construct);