[committed] Support both identifiers and string literals as properties of declare variant *-name-list selectors

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[committed] Support both identifiers and string literals as properties of declare variant *-name-list selectors

Jakub Jelinek
Hi!

OpenMP 5.0 is not clear enough here, but on Tuesday language committee
it was agreed that the selectors like arch/isa/kind/vendor/extension
should accept both identifiers and string literals.
kind(host) and kind("host") are then the same thing, but there can be
properties that are not valid identifiers and those can be only expressed
as string literals, like isa("sse4.2").
atomic_default_mem_order, being a clause on the requires directive, must
still use only identifier.

The following patch implements it.  Bootstrapped/regtested on x86_64-linux
and i686-linux, committed to trunk.

2019-11-14  Jakub Jelinek  <[hidden email]>

        * omp-general.c (omp_context_name_list_prop): New function.
        (omp_context_selector_matches): Use it.  Return 0 if it returns
        NULL.
        (omp_context_selector_props_compare): Allow equivalency of an
        identifier and a string literal containing no embedded zeros.
c-family/
        * c-omp.c (c_omp_check_context_selector): Handle name lists
        containing string literals.  Don't diagnose atomic_default_mem_order
        with multiple props.
c/
        * c-parser.c (c_parser_omp_context_selector): Rename
        CTX_PROPERTY_IDLIST to CTX_PROPERTY_NAME_LIST, add CTX_PROPERTY_ID.
        Use CTX_PROPERTY_ID for atomic_default_mem_order, only allow a single
        identifier in that.  For CTX_PROPERTY_NAME_LIST, allow identifiers
        and string literals.
cp/
        * parser.c (cp_parser_omp_context_selector): Rename
        CTX_PROPERTY_IDLIST to CTX_PROPERTY_NAME_LIST, add CTX_PROPERTY_ID.
        Use CTX_PROPERTY_ID for atomic_default_mem_order, only allow a single
        identifier in that.  For CTX_PROPERTY_NAME_LIST, allow identifiers
        and string literals.
        * pt.c (tsubst_attribute): Fix up STRING_CST handling if allow_string.
testsuite/
        * c-c++-common/gomp/declare-variant-2.c: Adjust expected diagnostics,
        add a test for atomic_default_mem_order with a string literal.
        * c-c++-common/gomp/declare-variant-3.c: Use string literal props
        in a few random places, add a few string literal prop related tests.
        * c-c++-common/gomp/declare-variant-8.c: Likewise.
        * c-c++-common/gomp/declare-variant-9.c: Use string literal props
        in a few random places.
        * c-c++-common/gomp/declare-variant-10.c: Likewise.
        * c-c++-common/gomp/declare-variant-11.c: Likewise.
        * c-c++-common/gomp/declare-variant-12.c: Likewise.
        * g++.dg/gomp/declare-variant-7.C: Likewise.

--- gcc/omp-general.c.jj 2019-11-11 21:04:06.675237225 +0100
+++ gcc/omp-general.c 2019-11-13 12:29:34.686583916 +0100
@@ -652,6 +652,23 @@ omp_maybe_offloaded (void)
   return false;
 }
 
+/* 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));
+  else
+    {
+      const char *ret = TREE_STRING_POINTER (TREE_VALUE (prop));
+      if ((size_t) TREE_STRING_LENGTH (TREE_VALUE (prop)) == strlen (ret) + 1)
+ return ret;
+      return NULL;
+    }
+}
+
 /* Return 1 if context selector matches the current OpenMP context, 0
    if it does not and -1 if it is unknown and need to be determined later.
    Some properties can be checked right away during parsing (this routine),
@@ -701,8 +718,11 @@ omp_context_selector_matches (tree ctx)
       if (set == 'i' && !strcmp (sel, "vendor"))
  for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
   {
-    const char *prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
-    if (!strcmp (prop, " score") || !strcmp (prop, "gnu"))
+    const char *prop = omp_context_name_list_prop (t3);
+    if (prop == NULL)
+      return 0;
+    if ((!strcmp (prop, " score") && TREE_PURPOSE (t3))
+ || !strcmp (prop, "gnu"))
       continue;
     return 0;
   }
@@ -750,7 +770,9 @@ omp_context_selector_matches (tree ctx)
       if (set == 'd' && !strcmp (sel, "arch"))
  for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
   {
-    const char *arch = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
+    const char *arch = omp_context_name_list_prop (t3);
+    if (arch == NULL)
+      return 0;
     int r = 0;
     if (targetm.omp.device_kind_arch_isa != NULL)
       r = targetm.omp.device_kind_arch_isa (omp_device_arch,
@@ -844,7 +866,9 @@ omp_context_selector_matches (tree ctx)
       if (set == 'd' && !strcmp (sel, "kind"))
  for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
   {
-    const char *prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
+    const char *prop = omp_context_name_list_prop (t3);
+    if (prop == NULL)
+      return 0;
     if (!strcmp (prop, "any"))
       continue;
     if (!strcmp (prop, "host"))
@@ -903,7 +927,9 @@ omp_context_selector_matches (tree ctx)
       if (set == 'd' && !strcmp (sel, "isa"))
  for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
   {
-    const char *isa = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
+    const char *isa = omp_context_name_list_prop (t3);
+    if (isa == NULL)
+      return 0;
     int r = 0;
     if (targetm.omp.device_kind_arch_isa != NULL)
       r = targetm.omp.device_kind_arch_isa (omp_device_isa,
@@ -1109,6 +1135,28 @@ omp_context_selector_props_compare (cons
       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)
+    {
+      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"))
+ break;
+    }
  if (t2 == NULL_TREE)
   {
     int r = pass ? -1 : 1;
--- gcc/c-family/c-omp.c.jj 2019-11-02 10:00:59.597253244 +0100
+++ gcc/c-family/c-omp.c 2019-11-13 12:36:30.453265616 +0100
@@ -2196,8 +2196,9 @@ c_omp_check_context_selector (location_t
  {
   if (props[i].props[j] == NULL)
     {
-      if (!strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
-   " score"))
+      if (TREE_PURPOSE (t2)
+  && !strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
+      " score"))
  break;
       if (props[i].props == atomic_default_mem_order)
  {
@@ -2207,31 +2208,28 @@ c_omp_check_context_selector (location_t
     "atomic_default_mem_order");
   return error_mark_node;
  }
-      else
+      else if (TREE_PURPOSE (t2))
  warning_at (loc, 0,
     "unknown property %qs of %qs selector",
     IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
     props[i].selector);
+      else
+ warning_at (loc, 0,
+    "unknown property %qE of %qs selector",
+    TREE_VALUE (t2), props[i].selector);
       break;
     }
-  else if (!strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
-    props[i].props[j]))
+  else if (TREE_PURPOSE (t2) == NULL_TREE)
     {
-      if (props[i].props == atomic_default_mem_order
-  && t2 != TREE_VALUE (t1))
- {
-  tree t3 = TREE_VALUE (t1);
-  if (!strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t3)),
-       " score")
-      && t2 == TREE_CHAIN (TREE_VALUE (t1)))
-    break;
-  error_at (loc,
-    "%qs selector must have a single property",
-    "atomic_default_mem_order");
-  return error_mark_node;
- }
-      break;
+      const char *str = TREE_STRING_POINTER (TREE_VALUE (t2));
+      if (!strcmp (str, props[i].props[j])
+  && ((size_t) TREE_STRING_LENGTH (TREE_VALUE (t2))
+      == strlen (str) + 1))
+ break;
     }
+  else if (!strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
+    props[i].props[j]))
+    break;
  }
     }
   return ctx;
--- gcc/c/c-parser.c.jj 2019-11-13 10:54:42.137095971 +0100
+++ gcc/c/c-parser.c 2019-11-13 12:41:14.625947998 +0100
@@ -19499,9 +19499,9 @@ c_parser_omp_context_selector (c_parser
       bool allow_score = true;
       bool allow_user = false;
       int property_limit = 0;
-      enum { CTX_PROPERTY_NONE, CTX_PROPERTY_USER, CTX_PROPERTY_IDLIST,
-     CTX_PROPERTY_EXPR, CTX_PROPERTY_SIMD } property_kind
- = CTX_PROPERTY_NONE;
+      enum { CTX_PROPERTY_NONE, CTX_PROPERTY_USER, CTX_PROPERTY_NAME_LIST,
+     CTX_PROPERTY_ID, CTX_PROPERTY_EXPR,
+     CTX_PROPERTY_SIMD } property_kind = CTX_PROPERTY_NONE;
       switch (IDENTIFIER_POINTER (set)[0])
  {
  case 'c': /* construct */
@@ -19515,13 +19515,13 @@ c_parser_omp_context_selector (c_parser
   allow_score = false;
   allow_user = true;
   property_limit = 3;
-  property_kind = CTX_PROPERTY_IDLIST;
+  property_kind = CTX_PROPERTY_NAME_LIST;
   break;
  case 'i': /* implementation */
   selectors = omp_implementation_selectors;
   allow_user = true;
   property_limit = 3;
-  property_kind = CTX_PROPERTY_IDLIST;
+  property_kind = CTX_PROPERTY_NAME_LIST;
   break;
  case 'u': /* user */
   selectors = omp_user_selectors;
@@ -19555,6 +19555,11 @@ c_parser_omp_context_selector (c_parser
   if (strcmp (selectors[i], IDENTIFIER_POINTER (selector)) == 0)
     break;
  }
+      if (property_kind == CTX_PROPERTY_NAME_LIST
+  && IDENTIFIER_POINTER (set)[0] == 'i'
+  && strcmp (IDENTIFIER_POINTER (selector),
+     "atomic_default_mem_order") == 0)
+ property_kind = CTX_PROPERTY_ID;
 
       c_parser_consume_token (parser);
 
@@ -19630,21 +19635,41 @@ c_parser_omp_context_selector (c_parser
  }
       while (1);
       break;
-    case CTX_PROPERTY_IDLIST:
+    case CTX_PROPERTY_ID:
+      if (c_parser_next_token_is (parser, CPP_KEYWORD)
+  || c_parser_next_token_is (parser, CPP_NAME))
+ {
+  tree prop = c_parser_peek_token (parser)->value;
+  c_parser_consume_token (parser);
+  properties = tree_cons (prop, NULL_TREE, properties);
+ }
+      else
+ {
+  c_parser_error (parser, "expected identifier");
+  return error_mark_node;
+ }
+      break;
+    case CTX_PROPERTY_NAME_LIST:
       do
  {
-  tree prop;
+  tree prop = NULL_TREE, value = NULL_TREE;
   if (c_parser_next_token_is (parser, CPP_KEYWORD)
       || c_parser_next_token_is (parser, CPP_NAME))
-    prop = c_parser_peek_token (parser)->value;
+    {
+      prop = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
+    }
+  else if (c_parser_next_token_is (parser, CPP_STRING))
+    value = c_parser_string_literal (parser, false,
+     false).value;
   else
     {
-      c_parser_error (parser, "expected identifier");
+      c_parser_error (parser, "expected identifier or "
+      "string literal");
       return error_mark_node;
     }
-  c_parser_consume_token (parser);
 
-  properties = tree_cons (prop, NULL_TREE, properties);
+  properties = tree_cons (prop, value, properties);
 
   if (c_parser_next_token_is (parser, CPP_COMMA))
     c_parser_consume_token (parser);
@@ -19694,7 +19719,8 @@ c_parser_omp_context_selector (c_parser
   parens.skip_until_found_close (parser);
   properties = nreverse (properties);
  }
-      else if (property_kind == CTX_PROPERTY_IDLIST
+      else if (property_kind == CTX_PROPERTY_NAME_LIST
+       || property_kind == CTX_PROPERTY_ID
        || property_kind == CTX_PROPERTY_EXPR)
  {
   c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>");
--- gcc/cp/parser.c.jj 2019-11-13 10:54:45.483045094 +0100
+++ gcc/cp/parser.c 2019-11-13 13:35:50.337188794 +0100
@@ -40464,9 +40464,9 @@ cp_parser_omp_context_selector (cp_parse
       bool allow_score = true;
       bool allow_user = false;
       int property_limit = 0;
-      enum { CTX_PROPERTY_NONE, CTX_PROPERTY_USER, CTX_PROPERTY_IDLIST,
-     CTX_PROPERTY_EXPR, CTX_PROPERTY_SIMD } property_kind
- = CTX_PROPERTY_NONE;
+      enum { CTX_PROPERTY_NONE, CTX_PROPERTY_USER, CTX_PROPERTY_NAME_LIST,
+     CTX_PROPERTY_ID, CTX_PROPERTY_EXPR,
+     CTX_PROPERTY_SIMD } property_kind = CTX_PROPERTY_NONE;
       switch (IDENTIFIER_POINTER (set)[0])
  {
  case 'c': /* construct */
@@ -40480,13 +40480,13 @@ cp_parser_omp_context_selector (cp_parse
   allow_score = false;
   allow_user = true;
   property_limit = 3;
-  property_kind = CTX_PROPERTY_IDLIST;
+  property_kind = CTX_PROPERTY_NAME_LIST;
   break;
  case 'i': /* implementation */
   selectors = omp_implementation_selectors;
   allow_user = true;
   property_limit = 3;
-  property_kind = CTX_PROPERTY_IDLIST;
+  property_kind = CTX_PROPERTY_NAME_LIST;
   break;
  case 'u': /* user */
   selectors = omp_user_selectors;
@@ -40519,6 +40519,11 @@ cp_parser_omp_context_selector (cp_parse
   if (strcmp (selectors[i], IDENTIFIER_POINTER (selector)) == 0)
     break;
  }
+      if (property_kind == CTX_PROPERTY_NAME_LIST
+  && IDENTIFIER_POINTER (set)[0] == 'i'
+  && strcmp (IDENTIFIER_POINTER (selector),
+     "atomic_default_mem_order") == 0)
+ property_kind = CTX_PROPERTY_ID;
 
       cp_lexer_consume_token (parser->lexer);
 
@@ -40607,21 +40612,40 @@ cp_parser_omp_context_selector (cp_parse
  }
       while (1);
       break;
-    case CTX_PROPERTY_IDLIST:
+    case CTX_PROPERTY_ID:
+      if (cp_lexer_next_token_is (parser->lexer, CPP_KEYWORD)
+  || cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+  tree prop = cp_lexer_peek_token (parser->lexer)->u.value;
+  cp_lexer_consume_token (parser->lexer);
+  properties = tree_cons (prop, NULL_TREE, properties);
+ }
+      else
+ {
+  cp_parser_error (parser, "expected identifier");
+  return error_mark_node;
+ }
+      break;
+    case CTX_PROPERTY_NAME_LIST:
       do
  {
-  tree prop;
+  tree prop = NULL_TREE, value = NULL_TREE;
   if (cp_lexer_next_token_is (parser->lexer, CPP_KEYWORD)
       || cp_lexer_next_token_is (parser->lexer, CPP_NAME))
-    prop = cp_lexer_peek_token (parser->lexer)->u.value;
+    {
+      prop = cp_lexer_peek_token (parser->lexer)->u.value;
+      cp_lexer_consume_token (parser->lexer);
+    }
+  else if (cp_lexer_next_token_is (parser->lexer, CPP_STRING))
+    value = cp_parser_string_literal (parser, false, false);
   else
     {
-      cp_parser_error (parser, "expected identifier");
+      cp_parser_error (parser, "expected identifier or "
+       "string literal");
       return error_mark_node;
     }
-  cp_lexer_consume_token (parser->lexer);
 
-  properties = tree_cons (prop, NULL_TREE, properties);
+  properties = tree_cons (prop, value, properties);
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
     cp_lexer_consume_token (parser->lexer);
@@ -40668,7 +40692,8 @@ cp_parser_omp_context_selector (cp_parse
 
   properties = nreverse (properties);
  }
-      else if (property_kind == CTX_PROPERTY_IDLIST
+      else if (property_kind == CTX_PROPERTY_NAME_LIST
+       || property_kind == CTX_PROPERTY_ID
        || property_kind == CTX_PROPERTY_EXPR)
  {
   cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
--- gcc/cp/pt.c.jj 2019-11-13 10:54:45.452045564 +0100
+++ gcc/cp/pt.c 2019-11-13 13:47:08.181894187 +0100
@@ -11166,9 +11166,9 @@ tsubst_attribute (tree t, tree *decl_p,
  bool allow_string
   = ((TREE_PURPOSE (t2) != condition || set[0] != 'u')
      && TREE_PURPOSE (t3) != score);
- if (TREE_CODE (t3) == STRING_CST && allow_string)
-  continue;
  tree v = TREE_VALUE (t3);
+ if (TREE_CODE (v) == STRING_CST && allow_string)
+  continue;
  v = tsubst_expr (v, args, complain, in_decl, true);
  v = fold_non_dependent_expr (v);
  if (!INTEGRAL_TYPE_P (TREE_TYPE (v))
--- gcc/testsuite/c-c++-common/gomp/declare-variant-2.c.jj 2019-10-30 12:38:38.179142956 +0100
+++ gcc/testsuite/c-c++-common/gomp/declare-variant-2.c 2019-11-13 13:03:38.390533852 +0100
@@ -69,15 +69,15 @@ void f33 (void);
 void f34 (void);
 #pragma omp declare variant (f1) match(device={kind,isa,arch}) /* { dg-error "expected '\\(' before ',' token" } */
 void f35 (void);
-#pragma omp declare variant (f1) match(device={kind(}) /* { dg-error "expected identifier before '\\\}' token" } */
+#pragma omp declare variant (f1) match(device={kind(}) /* { dg-error "expected identifier or string literal before '\\\}' token" } */
 void f36 (void);
 #pragma omp declare variant (f1) match(device={kind(unknown)}) /* { dg-warning "unknown property 'unknown' of 'kind' selector" } */
 void f37 (void);
 #pragma omp declare variant (f1) match(device={kind(unknown,foobar)}) /* { dg-warning "unknown property 'unknown' of 'kind' selector" } */
 void f38 (void); /* { dg-warning "unknown property 'foobar' of 'kind' selector" "" { target *-*-* } .-1 } */
-#pragma omp declare variant (f1) match(device={isa(1)}) /* { dg-error "expected identifier before numeric constant" } */
+#pragma omp declare variant (f1) match(device={isa(1)}) /* { dg-error "expected identifier or string literal before numeric constant" } */
 void f39 (void);
-#pragma omp declare variant (f1) match(device={arch(17)}) /* { dg-error "expected identifier before numeric constant" } */
+#pragma omp declare variant (f1) match(device={arch(17)}) /* { dg-error "expected identifier or string literal before numeric constant" } */
 void f40 (void);
 #pragma omp declare variant (f1) match(device={foobar(3)})
 void f41 (void);
@@ -89,11 +89,11 @@ void f43 (void);
 void f44 (void);
 #pragma omp declare variant (f1) match(implementation={extension}) /* { dg-error "expected '\\(' before '\\\}' token" } */
 void f45 (void);
-#pragma omp declare variant (f1) match(implementation={vendor()}) /* { dg-error "expected identifier before '\\)' token" } */
+#pragma omp declare variant (f1) match(implementation={vendor()}) /* { dg-error "expected identifier or string literal before '\\)' token" } */
 void f45 (void);
-#pragma omp declare variant (f1) match(implementation={vendor(123-234)}) /* { dg-error "expected identifier before numeric constant" } */
+#pragma omp declare variant (f1) match(implementation={vendor(123-234)}) /* { dg-error "expected identifier or string literal before numeric constant" } */
 void f46 (void);
-#pragma omp declare variant (f1) match(implementation={vendor("x86_64")}) /* { dg-error "expected identifier before string constant" } */
+#pragma omp declare variant (f1) match(implementation={vendor("foobar")}) /* { dg-warning "unknown property '.foobar.' of 'vendor' selector" } */
 void f47 (void);
 #pragma omp declare variant (f1) match(implementation={unified_address(yes)}) /* { dg-error "selector 'unified_address' does not accept any properties" } */
 void f48 (void); /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-1 } */
@@ -111,7 +111,7 @@ void f53 (void);
 void f54 (void);
 #pragma omp declare variant (f1) match(implementation={atomic_default_mem_order(foobar)}) /* { dg-error "incorrect property 'foobar' of 'atomic_default_mem_order' selector" } */
 void f55 (void);
-#pragma omp declare variant (f1) match(implementation={atomic_default_mem_order(relaxed,seq_cst)}) /* { dg-error "'atomic_default_mem_order' selector must have a single property" } */
+#pragma omp declare variant (f1) match(implementation={atomic_default_mem_order(relaxed,seq_cst)}) /* { dg-error "expected '\\)' before ',' token" } */
 void f56 (void);
 #pragma omp declare variant (f1) match(implementation={atomic_default_mem_order(relaxed)},implementation={atomic_default_mem_order(relaxed)}) /* { dg-error "selector set 'implementation' specified more than once" } */
 void f57 (void);
@@ -151,3 +151,5 @@ void f73 (void);
 void f74 (void);
 #pragma omp declare variant (f1),match(construct={parallel}) /* { dg-error "expected 'match' before ','" } */
 void f75 (void);
+#pragma omp declare variant (f1) match(implementation={atomic_default_mem_order("relaxed")}) /* { dg-error "expected identifier before string constant" } */
+void f76 (void);
--- gcc/testsuite/c-c++-common/gomp/declare-variant-3.c.jj 2019-10-10 09:05:44.037888779 +0200
+++ gcc/testsuite/c-c++-common/gomp/declare-variant-3.c 2019-11-13 12:48:57.234919664 +0100
@@ -19,13 +19,13 @@ void f12 (void);
 void f13 (void);
 #pragma omp declare variant (f13) match (device={kind(any)})
 void f14 (void);
-#pragma omp declare variant (f13) match (device={kind(host)})
+#pragma omp declare variant (f13) match (device={kind("host")})
 void f15 (void);
 #pragma omp declare variant (f13) match (device={kind(nohost)})
 void f16 (void);
 #pragma omp declare variant (f13) match (device={kind(cpu)})
 void f17 (void);
-#pragma omp declare variant (f13) match (device={kind(gpu)})
+#pragma omp declare variant (f13) match (device={kind("gpu")})
 void f18 (void);
 #pragma omp declare variant (f13) match (device={kind(fpga)})
 void f19 (void);
@@ -33,27 +33,27 @@ void f19 (void);
 void f20 (void);
 #pragma omp declare variant (f13) match (device={kind(host,nohost)})
 void f21 (void);
-#pragma omp declare variant (f13) match (device={kind(cpu,gpu,fpga)})
+#pragma omp declare variant (f13) match (device={kind("cpu","gpu","fpga")})
 void f22 (void);
 #pragma omp declare variant (f13) match (device={kind(any,cpu,nohost)})
 void f23 (void);
 #pragma omp declare variant (f13) match (device={isa(avx)})
 void f24 (void);
-#pragma omp declare variant (f13) match (device={isa(sse4,avx512f,avx512vl,avx512bw)})
+#pragma omp declare variant (f13) match (device={isa(sse4,"avx512f",avx512vl,avx512bw)})
 void f25 (void);
-#pragma omp declare variant (f13) match (device={arch(x86_64)})
+#pragma omp declare variant (f13) match (device={arch("x86_64")})
 void f26 (void);
 #pragma omp declare variant (f13) match (device={arch(riscv64)})
 void f27 (void);
 #pragma omp declare variant (f13) match (device={arch(nvptx)})
 void f28 (void);
-#pragma omp declare variant (f13) match (device={arch(x86_64),isa(avx512f,avx512vl),kind(cpu)})
+#pragma omp declare variant (f13) match (device={arch(x86_64),isa("avx512f","avx512vl"),kind(cpu)})
 void f29 (void);
 #pragma omp declare variant (f13) match (implementation={vendor(amd)})
 void f30 (void);
 #pragma omp declare variant (f13) match (implementation={vendor(arm)})
 void f31 (void);
-#pragma omp declare variant (f13) match (implementation={vendor(bsc)})
+#pragma omp declare variant (f13) match (implementation={vendor("bsc")})
 void f32 (void);
 #pragma omp declare variant (f13) match (implementation={vendor(cray)})
 void f33 (void);
@@ -63,7 +63,7 @@ void f34 (void);
 void f35 (void);
 #pragma omp declare variant (f13) match (implementation={vendor(ibm)})
 void f36 (void);
-#pragma omp declare variant (f13) match (implementation={vendor(intel)})
+#pragma omp declare variant (f13) match (implementation={vendor("intel")})
 void f37 (void);
 #pragma omp declare variant (f13) match (implementation={vendor(llvm)})
 void f38 (void);
@@ -97,7 +97,7 @@ void f51 (void);
 void f52 (void);
 #pragma omp declare variant (f13) match (implementation={vendor(score(3):amd)})
 void f53 (void);
-#pragma omp declare variant (f13) match (implementation={vendor(score(4):arm)})
+#pragma omp declare variant (f13) match (implementation={vendor(score(4):"arm")})
 void f54 (void);
 #pragma omp declare variant (f13) match (implementation={vendor(score(5):bsc)})
 void f55 (void);
@@ -115,7 +115,7 @@ void f60 (void);
 void f61 (void);
 #pragma omp declare variant (f13) match (implementation={vendor(score(12):pgi)})
 void f62 (void);
-#pragma omp declare variant (f13) match (implementation={vendor(score(13):ti)})
+#pragma omp declare variant (f13) match (implementation={vendor(score(13):"ti")})
 void f63 (void);
 #pragma omp declare variant (f13) match (implementation={vendor(score(14):unknown)})
 void f64 (void);
@@ -139,3 +139,9 @@ void f72 (void);
 void f73 (void);
 #pragma omp declare variant (f13) match (user={condition(score(25):1)})
 void f74 (void);
+#pragma omp declare variant (f13) match (device={kind(any,"any")})
+void f75 (void);
+#pragma omp declare variant (f13) match (device={kind("any","any")})
+void f76 (void);
+#pragma omp declare variant (f13) match (device={kind("any",any)})
+void f77 (void);
--- gcc/testsuite/c-c++-common/gomp/declare-variant-8.c.jj 2019-10-25 00:27:43.649318215 +0200
+++ gcc/testsuite/c-c++-common/gomp/declare-variant-8.c 2019-11-13 13:10:34.337215559 +0100
@@ -12,10 +12,10 @@ void f05 (void);
 void f06 (void);
 #pragma omp requires atomic_default_mem_order(seq_cst)
 void f07 (void);
-#pragma omp declare variant (f07) match (construct={parallel,for},device={kind(any)})
+#pragma omp declare variant (f07) match (construct={parallel,for},device={kind("any")})
 void f08 (void);
 void f09 (void);
-#pragma omp declare variant (f09) match (construct={parallel,for},implementation={vendor(gnu)})
+#pragma omp declare variant (f09) match (construct={parallel,for},implementation={vendor("gnu")})
 void f10 (void);
 void f11 (void);
 #pragma omp declare variant (f11) match (construct={parallel,for})
@@ -51,6 +51,12 @@ void f30 (void);
 void f31 (void);
 #pragma omp declare variant (f31) match (construct={teams,parallel,for})
 void f32 (void);
+void f33 (void);
+#pragma omp declare variant (f33) match (device={kind("any\0any")}) /* { dg-warning "unknown property '.any.000any.' of 'kind' selector" } */
+void f34 (void);
+void f35 (void);
+#pragma omp declare variant (f35) match (implementation={vendor("gnu\0")}) /* { dg-warning "unknown property '.gnu.000.' of 'vendor' selector" } */
+void f36 (void);
 
 void
 test1 (void)
@@ -76,6 +82,8 @@ test1 (void)
   for (i = 0; i < 1; i++)
     f14 (); /* { dg-final { scan-tree-dump-times "f14 \\\(\\\);" 1 "gimple" } } */
   f16 (); /* { dg-final { scan-tree-dump-times "f16 \\\(\\\);" 1 "gimple" } } */
+  f34 (); /* { dg-final { scan-tree-dump-times "f34 \\\(\\\);" 1 "gimple" } } */
+  f36 (); /* { dg-final { scan-tree-dump-times "f36 \\\(\\\);" 1 "gimple" } } */
 }
 
 #pragma omp declare target
--- gcc/testsuite/c-c++-common/gomp/declare-variant-9.c.jj 2019-10-31 11:06:07.393874793 +0100
+++ gcc/testsuite/c-c++-common/gomp/declare-variant-9.c 2019-11-13 12:54:33.736807256 +0100
@@ -4,16 +4,16 @@
 
 #undef i386
 void f01 (void);
-#pragma omp declare variant (f01) match (device={isa(avx512f,avx512bw)})
+#pragma omp declare variant (f01) match (device={isa("avx512f",avx512bw)})
 void f02 (void);
 void f03 (void);
-#pragma omp declare variant (f03) match (device={kind(any),arch(x86_64),isa(avx512f,avx512bw)})
+#pragma omp declare variant (f03) match (device={kind(any),arch(x86_64),isa("avx512f","avx512bw")})
 void f04 (void);
 void f05 (void);
 #pragma omp declare variant (f05) match (device={kind(gpu)})
 void f06 (void);
 void f07 (void);
-#pragma omp declare variant (f07) match (device={kind(cpu)})
+#pragma omp declare variant (f07) match (device={kind("cpu")})
 void f08 (void);
 void f09 (void);
 #pragma omp declare variant (f09) match (device={isa(sm_35)})
@@ -22,13 +22,13 @@ void f11 (void);
 #pragma omp declare variant (f11) match (device={arch(nvptx)})
 void f12 (void);
 void f13 (void);
-#pragma omp declare variant (f13) match (device={arch(i386),isa(sse4)})
+#pragma omp declare variant (f13) match (device={arch("i386"),isa(sse4)})
 void f14 (void);
 void f15 (void);
 #pragma omp declare variant (f15) match (device={isa(sse4,ssse3),arch(i386)})
 void f16 (void);
 void f17 (void);
-#pragma omp declare variant (f17) match (device={kind(any,fpga)})
+#pragma omp declare variant (f17) match (device={kind("any","fpga")})
 void f18 (void);
 
 void
--- gcc/testsuite/c-c++-common/gomp/declare-variant-10.c.jj 2019-10-31 11:06:13.891774165 +0100
+++ gcc/testsuite/c-c++-common/gomp/declare-variant-10.c 2019-11-13 12:55:07.685291533 +0100
@@ -7,7 +7,7 @@ void f01 (void);
 #pragma omp declare variant (f01) match (device={isa(avx512f,avx512bw)})
 void f02 (void);
 void f03 (void);
-#pragma omp declare variant (f03) match (device={kind(any),arch(x86_64),isa(avx512f,avx512bw)})
+#pragma omp declare variant (f03) match (device={kind("any"),arch(x86_64),isa(avx512f,avx512bw)})
 void f04 (void);
 void f05 (void);
 #pragma omp declare variant (f05) match (device={kind(gpu)})
@@ -19,10 +19,10 @@ void f09 (void);
 #pragma omp declare variant (f09) match (device={isa(sm_35)})
 void f10 (void);
 void f11 (void);
-#pragma omp declare variant (f11) match (device={arch(nvptx)})
+#pragma omp declare variant (f11) match (device={arch("nvptx")})
 void f12 (void);
 void f13 (void);
-#pragma omp declare variant (f13) match (device={arch(i386),isa(sse4)})
+#pragma omp declare variant (f13) match (device={arch(i386),isa("sse4")})
 void f14 (void);
 void f15 (void);
 #pragma omp declare variant (f15) match (device={isa(sse4,ssse3),arch(i386)})
--- gcc/testsuite/c-c++-common/gomp/declare-variant-11.c.jj 2019-11-02 00:29:23.115514759 +0100
+++ gcc/testsuite/c-c++-common/gomp/declare-variant-11.c 2019-11-13 12:56:27.328081745 +0100
@@ -4,8 +4,8 @@
 
 void f01 (void);
 void f02 (void);
-#pragma omp declare variant (f01) match (device={isa(avx512f,avx512vl)})
-#pragma omp declare variant (f02) match (device={isa(avx512bw,avx512vl,avx512f)})
+#pragma omp declare variant (f01) match (device={isa(avx512f,"avx512vl")})
+#pragma omp declare variant (f02) match (device={isa(avx512bw,avx512vl,"avx512f")})
 void f03 (void);
 void f04 (void);
 void f05 (void);
@@ -14,13 +14,13 @@ void f05 (void);
 void f06 (void);
 void f07 (void);
 void f08 (void);
-#pragma omp declare variant (f07) match (device={isa(sse4,sse3,avx)})
-#pragma omp declare variant (f08) match (device={isa(avx,sse3)})
+#pragma omp declare variant (f07) match (device={isa(sse4,sse3,"avx")})
+#pragma omp declare variant (f08) match (device={isa("avx",sse3)})
 void f09 (void);
 void f10 (void);
 void f11 (void);
 void f12 (void);
-#pragma omp declare variant (f10) match (device={isa(avx512f)})
+#pragma omp declare variant (f10) match (device={isa("avx512f")})
 #pragma omp declare variant (f11) match (user={condition(1)},device={isa(avx512f)},implementation={vendor(gnu)})
 #pragma omp declare variant (f12) match (user={condition(2 + 1)},device={isa(avx512f)})
 void f13 (void);
--- gcc/testsuite/c-c++-common/gomp/declare-variant-12.c.jj 2019-11-02 10:00:59.647252481 +0100
+++ gcc/testsuite/c-c++-common/gomp/declare-variant-12.c 2019-11-13 12:57:02.870541850 +0100
@@ -6,7 +6,7 @@
 void f01 (void);
 void f02 (void);
 void f03 (void);
-#pragma omp declare variant (f01) match (device={isa(avx512f,avx512vl)}) /* 16 */
+#pragma omp declare variant (f01) match (device={isa("avx512f","avx512vl")}) /* 16 */
 #pragma omp declare variant (f02) match (implementation={vendor(score(15):gnu)})
 #pragma omp declare variant (f03) match (user={condition(score(11):1)})
 void f04 (void);
@@ -22,7 +22,7 @@ void f10 (void);
 void f11 (void);
 void f12 (void);
 #pragma omp declare variant (f09) match (device={arch(x86_64)},user={condition(score(65):1)}) /* 64+65 */
-#pragma omp declare variant (f10) match (implementation={vendor(score(127):gnu)})
+#pragma omp declare variant (f10) match (implementation={vendor(score(127):"gnu")})
 #pragma omp declare variant (f11) match (device={isa(ssse3)}) /* 128 */
 #pragma omp declare variant (f12) match (implementation={atomic_default_mem_order(score(126):seq_cst)})
 void f13 (void);
--- gcc/testsuite/g++.dg/gomp/declare-variant-7.C.jj 2019-11-05 08:40:54.489135162 +0100
+++ gcc/testsuite/g++.dg/gomp/declare-variant-7.C 2019-11-13 13:38:51.680434638 +0100
@@ -12,7 +12,7 @@ template <int N>
 void f04 ();
 template <int N>
 void f05 ();
-#pragma omp declare variant (f05<N>) match (user={condition((T)N)},implementation={vendor(gnu)})
+#pragma omp declare variant (f05<N>) match (user={condition((T)N)},implementation={vendor("gnu")})
 template <int N, typename T>
 void f06 ();
 void f07 ();

        Jakub