c-common.h (c_omp_mark_declare_variant, [...]): Declare.
authorJakub Jelinek <jakub@redhat.com>
Sat, 12 Oct 2019 08:27:36 +0000 (10:27 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sat, 12 Oct 2019 08:27:36 +0000 (10:27 +0200)
c-family/
* c-common.h (c_omp_mark_declare_variant,
c_omp_context_selector_matches): Declare.
* c-omp.c: Include attribs.h, gimplify.h, cgraph.h, symbol-summary.h
and hsa-common.h.
(c_omp_get_context_selector): Support second argument NULL.
(c_omp_mark_declare_variant, c_omp_context_selector_matches): New
functions.
* c-attribs.c (c_common_attribute_table): Remove "omp declare variant"
attribute, add "omp declare variant base" and
"omp declare variant variant" attributes.
c/
* c-parser.c (c_parser_omp_context_selector): Improve error recovery.
For simd properties, put them directly into TREE_VALUE.
(c_finish_omp_declare_variant): Call c_omp_mark_declare_variant.
If c_omp_context_selector_matches is 0, don't add attribute, otherwise
add "omp declare variant base" attribute rather than
"omp declare variant".
cp/
* parser.c (cp_parser_omp_context_selector): Improve error recovery.
For simd properties, put them directly into TREE_VALUE.
(cp_finish_omp_declare_variant): Add "omp declare variant base"
attribute rather than "omp declare variant".
testsuite/
* c-c++-common/gomp/declare-variant-2.c: Adjust for error recovery
improvements.  Add new tests.
* c-c++-common/gomp/declare-variant-4.c: New test.
* c-c++-common/gomp/declare-variant-5.c: New test.
* c-c++-common/gomp/declare-variant-6.c: New test.
* c-c++-common/gomp/declare-variant-7.c: New test.

From-SVN: r276914

14 files changed:
gcc/c-family/ChangeLog
gcc/c-family/c-attribs.c
gcc/c-family/c-common.h
gcc/c-family/c-omp.c
gcc/c/ChangeLog
gcc/c/c-parser.c
gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/gomp/declare-variant-2.c
gcc/testsuite/c-c++-common/gomp/declare-variant-4.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/gomp/declare-variant-5.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/gomp/declare-variant-6.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/gomp/declare-variant-7.c [new file with mode: 0644]

index fea97bb434f969f58b6e63dae764cc0308d71fa3..2b63689bc7a778e3a96d5ab823af4e6f0db08bef 100644 (file)
@@ -1,3 +1,16 @@
+2019-10-12  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-common.h (c_omp_mark_declare_variant,
+       c_omp_context_selector_matches): Declare.
+       * c-omp.c: Include attribs.h, gimplify.h, cgraph.h, symbol-summary.h
+       and hsa-common.h.
+       (c_omp_get_context_selector): Support second argument NULL.
+       (c_omp_mark_declare_variant, c_omp_context_selector_matches): New
+       functions.
+       * c-attribs.c (c_common_attribute_table): Remove "omp declare variant"
+       attribute, add "omp declare variant base" and
+       "omp declare variant variant" attributes.
+
 2019-10-11  Joseph Myers  <joseph@codesourcery.com>
 
        * c.opt (Wc11-c2x-compat): Add CPP(cpp_warn_c11_c2x_compat)
index 917d483bcbfd872a19f53d4b014708985211d4bd..ea273f89a8ef1f13a47e666f69ecc7bfd6f55d8a 100644 (file)
@@ -444,7 +444,9 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_returns_nonnull_attribute, NULL },
   { "omp declare simd",       0, -1, true,  false, false, false,
                              handle_omp_declare_simd_attribute, NULL },
-  { "omp declare variant",    0, -1, true,  false, false, false,
+  { "omp declare variant base", 0, -1, true,  false, false, false,
+                             handle_omp_declare_variant_attribute, NULL },
+  { "omp declare variant variant", 0, -1, true,  false, false, false,
                              handle_omp_declare_variant_attribute, NULL },
   { "simd",                  0, 1, true,  false, false, false,
                              handle_simd_attribute, NULL },
@@ -3068,7 +3070,7 @@ handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *)
   return NULL_TREE;
 }
 
-/* Handle an "omp declare variant" attribute; arguments as in
+/* Handle an "omp declare variant {base,variant}" attribute; arguments as in
    struct attribute_spec.handler.  */
 
 static tree
index eabe689120fed38b7b49bb48a3e19cd92eac2e14..db7f26eec5350590d13b5c5c7f8f72345141c28c 100644 (file)
@@ -1191,6 +1191,8 @@ extern bool c_omp_predefined_variable (tree);
 extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
 extern tree c_omp_check_context_selector (location_t, tree);
 extern tree c_omp_get_context_selector (tree, const char *, const char *);
+extern void c_omp_mark_declare_variant (location_t, tree, tree);
+extern int c_omp_context_selector_matches (tree);
 
 /* Return next tree in the chain for chain_next walking of tree nodes.  */
 static inline tree
index 542625604ad336b8bb74d56651a90ba11548064f..339818817e2805d9bf09a7e8a2bcc1e516f09ed4 100644 (file)
@@ -32,6 +32,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "omp-general.h"
 #include "gomp-constants.h"
 #include "memmodel.h"
+#include "attribs.h"
+#include "gimplify.h"
+#include "cgraph.h"
+#include "symbol-summary.h"
+#include "hsa-common.h"
 
 
 /* Complete a #pragma oacc wait construct.  LOC is the location of
@@ -2236,17 +2241,335 @@ c_omp_check_context_selector (location_t loc, tree ctx)
 }
 
 /* From context selector CTX, return trait-selector with name SEL in
-   trait-selector-set with name SET if any, or NULL_TREE if not found.  */
+   trait-selector-set with name SET if any, or NULL_TREE if not found.
+   If SEL is NULL, return the list of trait-selectors in SET.  */
 
 tree
 c_omp_get_context_selector (tree ctx, const char *set, const char *sel)
 {
   tree setid = get_identifier (set);
-  tree selid = get_identifier (sel);
+  tree selid = sel ? get_identifier (sel) : NULL_TREE;
   for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
     if (TREE_PURPOSE (t1) == setid)
-      for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
-       if (TREE_PURPOSE (t2) == selid)
-         return t2;
+      {
+       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 NULL_TREE;
 }
+
+/* Register VARIANT as variant of some base function marked with
+   #pragma omp declare variant.  CONSTRUCT is corresponding construct
+   selector set.  */
+
+void
+c_omp_mark_declare_variant (location_t loc, tree variant, tree construct)
+{
+  tree attr = lookup_attribute ("omp declare variant variant",
+                               DECL_ATTRIBUTES (variant));
+  if (attr == NULL_TREE)
+    {
+      attr = tree_cons (get_identifier ("omp declare variant variant"),
+                       unshare_expr (construct),
+                       DECL_ATTRIBUTES (variant));
+      DECL_ATTRIBUTES (variant) = attr;
+      return;
+    }
+  tree t1 = TREE_VALUE (attr);
+  tree t2 = construct;
+  tree simd = get_identifier ("simd");
+  while (t1 && t2)
+    {
+      if (TREE_PURPOSE (t1) != TREE_PURPOSE (t2))
+       break;
+      if (TREE_PURPOSE (t1) == simd)
+       {
+         if ((TREE_VALUE (t1) == NULL_TREE)
+             != (TREE_VALUE (t2) == NULL_TREE))
+           break;
+         if (TREE_VALUE (t1))
+           {
+             struct declare_variant_simd_data {
+               bool inbranch, notinbranch;
+               tree simdlen;
+               auto_vec<tree,16> data_sharing;
+               auto_vec<tree,16> aligned;
+               declare_variant_simd_data ()
+                 : inbranch(false), notinbranch(false), simdlen(NULL_TREE) {}
+             } data[2];
+             unsigned int i;
+             for (i = 0; i < 2; i++)
+               for (tree c = TREE_VALUE (i ? t2 : t1);
+                    c; c = OMP_CLAUSE_CHAIN (c))
+                 {
+                   vec<tree> *v;
+                   switch (OMP_CLAUSE_CODE (c))
+                     {
+                     case OMP_CLAUSE_INBRANCH:
+                       data[i].inbranch = true;
+                       continue;
+                     case OMP_CLAUSE_NOTINBRANCH:
+                       data[i].notinbranch = true;
+                       continue;
+                     case OMP_CLAUSE_SIMDLEN:
+                       data[i].simdlen = OMP_CLAUSE_SIMDLEN_EXPR (c);
+                       continue;
+                     case OMP_CLAUSE_UNIFORM:
+                     case OMP_CLAUSE_LINEAR:
+                       v = &data[i].data_sharing;
+                       break;
+                     case OMP_CLAUSE_ALIGNED:
+                       v = &data[i].aligned;
+                       break;
+                     default:
+                       gcc_unreachable ();
+                     }
+                   unsigned HOST_WIDE_INT argno
+                     = tree_to_uhwi (OMP_CLAUSE_DECL (c));
+                   if (argno >= v->length ())
+                     v->safe_grow_cleared (argno + 1);
+                   (*v)[argno] = c;
+                 }
+             if (data[0].inbranch != data[1].inbranch
+                 || data[0].notinbranch != data[1].notinbranch
+                 || !simple_cst_equal (data[0].simdlen,
+                                       data[1].simdlen)
+                 || (data[0].data_sharing.length ()
+                     != data[1].data_sharing.length ())
+                 || (data[0].aligned.length ()
+                     != data[1].aligned.length ()))
+               break;
+             tree c1, c2;
+             FOR_EACH_VEC_ELT (data[0].data_sharing, i, c1)
+               {
+                 c2 = data[1].data_sharing[i];
+                 if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
+                   break;
+                 if (c1 == NULL_TREE)
+                   continue;
+                 if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_CODE (c2))
+                   break;
+                 if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_LINEAR)
+                   continue;
+                 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c1)
+                     != OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c2))
+                   break;
+                 if (OMP_CLAUSE_LINEAR_KIND (c1)
+                     != OMP_CLAUSE_LINEAR_KIND (c2))
+                   break;
+                 if (!simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (c1),
+                                        OMP_CLAUSE_LINEAR_STEP (c2)))
+                   break;
+               }
+             if (i < data[0].data_sharing.length ())
+               break;
+             FOR_EACH_VEC_ELT (data[0].aligned, i, c1)
+               {
+                 c2 = data[1].aligned[i];
+                 if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
+                   break;
+                 if (c1 == NULL_TREE)
+                   continue;
+                 if (!simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (c1),
+                                        OMP_CLAUSE_ALIGNED_ALIGNMENT (c2)))
+                   break;
+               }
+             if (i < data[0].aligned.length ())
+               break;
+           }
+       }
+      t1 = TREE_CHAIN (t1);
+      t2 = TREE_CHAIN (t2);
+    }
+  if (t1 || t2)
+    error_at (loc, "%qD used as a variant with incompatible %<constructor%> "
+                  "selector sets", variant);
+}
+
+/* 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),
+   others need to wait until the whole TU is parsed, others need to wait until
+   IPA, others until vectorization.  */
+
+int
+c_omp_context_selector_matches (tree ctx)
+{
+  int ret = 1;
+  for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
+    {
+      char set = IDENTIFIER_POINTER (TREE_PURPOSE (t1))[0];
+      if (set == 'c')
+       {
+         /* For now, ignore the construct set.  While something can be
+            determined already during parsing, we don't know until end of TU
+            whether additional constructs aren't added through declare variant
+            unless "omp declare variant variant" attribute exists already
+            (so in most of the cases), and we'd need to maintain set of
+            surrounding OpenMP constructs, which is better handled during
+            gimplification.  */
+         ret = -1;
+         continue;
+       }
+      for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
+       {
+         const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t2));
+         switch (*sel)
+           {
+           case 'v':
+             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"))
+                     continue;
+                   return 0;
+                 }
+             break;
+           case 'e':
+             if (set == 'i' && !strcmp (sel, "extension"))
+               /* We don't support any extensions right now.  */
+               return 0;
+             break;
+           case 'a':
+             if (set == 'i' && !strcmp (sel, "atomic_default_mem_order"))
+               {
+                 enum omp_memory_order omo
+                   = ((enum omp_memory_order)
+                      (omp_requires_mask
+                       & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER));
+                 if (omo == OMP_MEMORY_ORDER_UNSPECIFIED)
+                   {
+                     /* We don't know yet, until end of TU.  */
+                     ret = -1;
+                     break;
+                   }
+                 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));
+                   }
+                 if (!strcmp (prop, "relaxed")
+                     && omo != OMP_MEMORY_ORDER_RELAXED)
+                   return 0;
+                 else if (!strcmp (prop, "seq_cst")
+                          && omo != OMP_MEMORY_ORDER_SEQ_CST)
+                   return 0;
+                 else if (!strcmp (prop, "acq_rel")
+                          && omo != OMP_MEMORY_ORDER_ACQ_REL)
+                   return 0;
+               }
+             if (set == 'd' && !strcmp (sel, "arch"))
+               /* For now, need a target hook.  */
+               ret = -1;
+             break;
+           case 'u':
+             if (set == 'i' && !strcmp (sel, "unified_address"))
+               {
+                 if ((omp_requires_mask & OMP_REQUIRES_UNIFIED_ADDRESS) == 0)
+                   ret = -1;
+                 break;
+               }
+             if (set == 'i' && !strcmp (sel, "unified_shared_memory"))
+               {
+                 if ((omp_requires_mask
+                      & OMP_REQUIRES_UNIFIED_SHARED_MEMORY) == 0)
+                   ret = -1;
+                 break;
+               }
+             break;
+           case 'd':
+             if (set == 'i' && !strcmp (sel, "dynamic_allocators"))
+               {
+                 if ((omp_requires_mask
+                      & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0)
+                   ret = -1;
+                 break;
+               }
+             break;
+           case 'r':
+             if (set == 'i' && !strcmp (sel, "reverse_offload"))
+               {
+                 if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
+                   ret = -1;
+                 break;
+               }
+             break;
+           case 'k':
+             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));
+                   if (!strcmp (prop, "any"))
+                     continue;
+                   if (!strcmp (prop, "fpga"))
+                     return 0; /* Right now GCC doesn't support any fpgas.  */
+                   if (!strcmp (prop, "host"))
+                     {
+                       if (ENABLE_OFFLOADING || hsa_gen_requested_p ())
+                         ret = -1;
+                       continue;
+                     }
+                   if (!strcmp (prop, "nohost"))
+                     {
+                       if (ENABLE_OFFLOADING || hsa_gen_requested_p ())
+                         ret = -1;
+                       else
+                         return 0;
+                       continue;
+                     }
+                   if (!strcmp (prop, "cpu") || !strcmp (prop, "gpu"))
+                     {
+                       bool maybe_gpu = false;
+                       if (hsa_gen_requested_p ())
+                         maybe_gpu = true;
+                       else if (ENABLE_OFFLOADING)
+                         for (const char *c = getenv ("OFFLOAD_TARGET_NAMES");
+                              c; )
+                           {
+                             if (!strncmp (c, "nvptx", strlen ("nvptx"))
+                                 || !strncmp (c, "amdgcn", strlen ("amdgcn")))
+                               {
+                                 maybe_gpu = true;
+                                 break;
+                               }
+                             else if ((c = strchr (c, ',')))
+                               c++;
+                           }
+                       if (!maybe_gpu)
+                         {
+                           if (prop[0] == 'g')
+                             return 0;
+                         }
+                       else
+                         ret = -1;
+                       continue;
+                     }
+                   /* Any other kind doesn't match.  */
+                   return 0;
+                 }
+             break;
+           case 'i':
+             if (set == 'd' && !strcmp (sel, "isa"))
+               /* For now, need a target hook.  */
+               ret = -1;
+             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
+                     && integer_zerop (TREE_VALUE (t3)))
+                   return 0;
+             break;
+           default:
+             break;
+           }
+       }
+    }
+  return ret;
+}
index 894f5e752e3a8024c6a206bd69829b8bad2df469..5fb386c4b9e18d137295501529a31e64e0a8c1ab 100644 (file)
@@ -1,3 +1,12 @@
+2019-10-12  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-parser.c (c_parser_omp_context_selector): Improve error recovery.
+       For simd properties, put them directly into TREE_VALUE.
+       (c_finish_omp_declare_variant): Call c_omp_mark_declare_variant.
+       If c_omp_context_selector_matches is 0, don't add attribute, otherwise
+       add "omp declare variant base" attribute rather than
+       "omp declare variant".
+
 2019-10-11  Joseph Myers  <joseph@codesourcery.com>
 
        * c-decl.c (declspecs_add_type): Use pedwarn_c11 for DFP types.
index 2daaee80d85b31a17f7bf94b4bc70d4e6c6fc409..9d0b2b671f84b9efc5645c2fe0096e73ebbd49b6 100644 (file)
@@ -19219,6 +19219,8 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
                      else
                        properties = tree_cons (NULL_TREE, t, properties);
                    }
+                 else
+                   return error_mark_node;
 
                  if (c_parser_next_token_is (parser, CPP_COMMA))
                    c_parser_consume_token (parser);
@@ -19263,6 +19265,8 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
                  else
                    properties = tree_cons (NULL_TREE, t, properties);
                }
+             else
+               return error_mark_node;
              break;
            case CTX_PROPERTY_SIMD:
              if (parms == NULL_TREE)
@@ -19280,7 +19284,7 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
                                                         == error_mark_node
                                                         ? NULL_TREE : parms,
                                                         c);
-             properties = tree_cons (NULL_TREE, c, properties);
+             properties = c;
              break;
            default:
              gcc_unreachable ();
@@ -19389,7 +19393,7 @@ c_parser_omp_context_selector_specification (c_parser *parser, tree parms)
 }
 
 /* Finalize #pragma omp declare variant after FNDECL has been parsed, and put
-   that into "omp declare variant" attribute.  */
+   that into "omp declare variant base" attribute.  */
 
 static void
 c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
@@ -19473,10 +19477,16 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
       if (variant != error_mark_node)
        {
          C_DECL_USED (variant) = 1;
-         tree attr = tree_cons (get_identifier ("omp declare variant"),
-                                build_tree_list (variant, ctx),
-                                DECL_ATTRIBUTES (fndecl));
-         DECL_ATTRIBUTES (fndecl) = attr;
+         tree construct = c_omp_get_context_selector (ctx, "construct", NULL);
+         c_omp_mark_declare_variant (match_loc, variant, construct);
+         if (c_omp_context_selector_matches (ctx))
+           {
+             tree attr
+               = tree_cons (get_identifier ("omp declare variant base"),
+                            build_tree_list (variant, ctx),
+                            DECL_ATTRIBUTES (fndecl));
+             DECL_ATTRIBUTES (fndecl) = attr;
+           }
        }
     }
 
@@ -19486,7 +19496,7 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
 
 /* Finalize #pragma omp declare simd or #pragma omp declare variant
    clauses after FNDECL has been parsed, and put that into "omp declare simd"
-   or "omp declare variant" attribute.  */
+   or "omp declare variant base" attribute.  */
 
 static void
 c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
index 02a330d772e95667ee26efc38d7c2aea49f5f255..dcae4909d5e10a4e7ffd0a3eab797baa0f09c80c 100644 (file)
@@ -1,3 +1,10 @@
+2019-10-12  Jakub Jelinek  <jakub@redhat.com>
+
+       * parser.c (cp_parser_omp_context_selector): Improve error recovery.
+       For simd properties, put them directly into TREE_VALUE.
+       (cp_finish_omp_declare_variant): Add "omp declare variant base"
+       attribute rather than "omp declare variant".
+
 2019-10-11  Marek Polacek  <polacek@redhat.com>
 
        PR c++/92049 - extra error with -fchecking=2.
index 3ee8da7db949aff0e9a8bc33868e0c41b0e4aa65..9bf690a0efbd5e0632d0f39989087d2a6e8d5d0a 100644 (file)
@@ -40488,6 +40488,8 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
                      else
                        properties = tree_cons (NULL_TREE, t, properties);
                    }
+                 else
+                   return error_mark_node;
 
                  if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
                    cp_lexer_consume_token (parser->lexer);
@@ -40532,6 +40534,8 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
                  else
                    properties = tree_cons (NULL_TREE, t, properties);
                }
+             else
+               return error_mark_node;
              break;
            case CTX_PROPERTY_SIMD:
              if (!has_parms_p)
@@ -40541,11 +40545,10 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
                            "%<metadirective%>");
                  return error_mark_node;
                }
-             tree c;
-             c = cp_parser_omp_all_clauses (parser,
+             properties
+               = cp_parser_omp_all_clauses (parser,
                                             OMP_DECLARE_SIMD_CLAUSE_MASK,
                                             "simd", NULL, true, true);
-             properties = tree_cons (NULL_TREE, c, properties);
              break;
            default:
              gcc_unreachable ();
@@ -40662,7 +40665,7 @@ cp_parser_omp_context_selector_specification (cp_parser *parser,
 }
 
 /* Finalize #pragma omp declare variant after a fndecl has been parsed, and put
-   that into "omp declare variant" attribute.  */
+   that into "omp declare variant base" attribute.  */
 
 static tree
 cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok,
@@ -40717,7 +40720,7 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok,
   ctx = c_omp_check_context_selector (match_loc, ctx);
   if (ctx != error_mark_node && variant != error_mark_node)
     {
-      attrs = tree_cons (get_identifier ("omp declare variant"),
+      attrs = tree_cons (get_identifier ("omp declare variant base"),
                         build_tree_list (variant, ctx), attrs);
       if (processing_template_decl)
        ATTR_IS_DEPENDENT (attrs) = 1;
index 9b31f3536423869ba2b318f5210410aae77c35d0..14b5da645ec25063fbb240da095688252d885363 100644 (file)
@@ -1,3 +1,12 @@
+2019-10-12  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-c++-common/gomp/declare-variant-2.c: Adjust for error recovery
+       improvements.  Add new tests.
+       * c-c++-common/gomp/declare-variant-4.c: New test.
+       * c-c++-common/gomp/declare-variant-5.c: New test.
+       * c-c++-common/gomp/declare-variant-6.c: New test.
+       * c-c++-common/gomp/declare-variant-7.c: New test.
+
 2019-10-11  Joseph Myers  <joseph@codesourcery.com>
 
        * gcc.dg/dfp/c11-constants-1.c, gcc.dg/dfp/c11-constants-2.c,
index bc12398911cd42e706b76956d71c116036b1e422..f058f57e68726f2178b38893a2a011563a0543a3 100644 (file)
@@ -1,3 +1,4 @@
+void f0 (void);
 void f1 (void);
 #pragma omp declare variant    /* { dg-error "expected '\\(' before end of line" } */
 void f2 (void);
@@ -34,7 +35,7 @@ void f17 (void);
 #pragma omp declare variant (f1) match(user={condition})       /* { dg-error "expected '\\(' before '\\\}' token" } */
 void f18 (void);
 #pragma omp declare variant (f1) match(user={condition(})      /* { dg-error "expected \[^\n\r]*expression before '\\\}' token" } */
-void f19 (void);                                               /* { dg-error "expected '\\)' before '\\\}' token" "" { target c++ } .-1 } */
+void f19 (void);
 #pragma omp declare variant (f1) match(user={condition()})     /* { dg-error "expected \[^\n\r]*expression before '\\)' token" } */
 void f20 (void);
 #pragma omp declare variant (f1) match(user={condition(f1)})   /* { dg-error "property must be constant integer expression" "" { target { c || c++11 } } } */
@@ -50,7 +51,7 @@ void f25 (void);                                              /* { dg-error "expected '\\\}' before end of line" "" { ta
                                                                /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-2 } */
 #pragma omp declare variant (f1) match(construct={parallel(1)})        /* { dg-error "selector 'parallel' does not accept any properties" } */
 void f26 (void);                                                       /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-1 } */
-#pragma omp declare variant (f1) match(construct={simd(12)})   /* { dg-error "expected \[^\n\r]* clause before" } */
+#pragma omp declare variant (f0) match(construct={simd(12)})   /* { dg-error "expected \[^\n\r]* clause before" } */
 void f27 (void);                                               /* { dg-error "'\\)' before numeric constant" "" { target c++ } .-1 } */
 #pragma omp declare variant (f1) match(construct={parallel},construct={for})   /* { dg-error "selector set 'construct' specified more than once" } */
 void f28 (void);
@@ -120,3 +121,31 @@ void f58 (void);                                           /* { dg-error "expected '\\\}' before '\\(' token" "" { ta
 void f59 (void);                                               /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-1 } */
 #pragma omp declare variant (f1) match(construct={parallel},foobar={bar})      /* { dg-error "expected 'construct', 'device', 'implementation' or 'user' before 'foobar'" } */
 void f60 (void);
+#pragma omp declare variant (f1) match(construct={parallel,parallel})  /* { dg-error "selector 'parallel' specified more than once in set 'construct'" } */
+void f61 (void);
+#pragma omp declare variant (f1) match(construct={target,parallel,for,simd,parallel})  /* { dg-error "selector 'parallel' specified more than once in set 'construct'" } */
+void f62 (void);
+#pragma omp declare variant (f1) match(construct={target,teams,teams}) /* { dg-error "selector 'teams' specified more than once in set 'construct'" } */
+void f63 (void);
+#pragma omp declare variant (f1) match(construct={single})     /* { dg-error "selector 'single' not allowed for context selector set 'construct'" } */
+void f64 (void);
+#pragma omp declare variant (f1) match(construct={taskgroup})  /* { dg-error "selector 'taskgroup' not allowed for context selector set 'construct'" } */
+void f65 (void);
+#pragma omp declare variant (f1) match(construct={do}) /* { dg-error "selector 'do' not allowed for context selector set 'construct'" } */
+void f66 (void);
+#pragma omp declare variant (f1) match(construct={threadprivate})      /* { dg-error "selector 'threadprivate' not allowed for context selector set 'construct'" } */
+void f67 (void);
+#pragma omp declare variant (f1) match(construct={critical})   /* { dg-error "selector 'critical' not allowed for context selector set 'construct'" } */
+void f68 (void);
+#pragma omp declare variant (f1) match(construct={task})       /* { dg-error "selector 'task' not allowed for context selector set 'construct'" } */
+void f69 (void);
+#pragma omp declare variant (f1) match(construct={taskloop})   /* { dg-error "selector 'taskloop' not allowed for context selector set 'construct'" } */
+void f70 (void);
+#pragma omp declare variant (f1) match(construct={sections})   /* { dg-error "selector 'sections' not allowed for context selector set 'construct'" } */
+void f71 (void);
+#pragma omp declare variant (f1) match(construct={section})    /* { dg-error "selector 'section' not allowed for context selector set 'construct'" } */
+void f72 (void);
+#pragma omp declare variant (f1) match(construct={workshare})  /* { dg-error "selector 'workshare' not allowed for context selector set 'construct'" } */
+void f73 (void);
+#pragma omp declare variant (f1) match(construct={requires})   /* { dg-error "selector 'requires' not allowed for context selector set 'construct'" } */
+void f74 (void);
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-4.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-4.c
new file mode 100644 (file)
index 0000000..add3730
--- /dev/null
@@ -0,0 +1,22 @@
+double f1 (int, long, float);
+double f2 (int, long, float);
+double f3 (int, long, float);
+double f4 (int, long, float);
+double f5 (int, long, float);
+
+#pragma omp declare variant (f1) match (user={condition(1)})
+#pragma omp declare variant (f2) match (user={condition(score(1):1)})
+#pragma omp declare variant (f3) match (user={condition(score(3):1)})
+#pragma omp declare variant (f4) match (user={condition(score(2):1)})
+#pragma omp declare variant (f5) match (implementation={vendor(gnu)})
+double
+f6 (int x, long y, float z)
+{
+  return z + x + y;
+}
+
+double
+test (int x)
+{
+  return f6 (x, x, 3.5f);
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-5.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-5.c
new file mode 100644 (file)
index 0000000..6ebf094
--- /dev/null
@@ -0,0 +1,36 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-additional-options "-mavx2" } */
+
+typedef float __v4sf __attribute__((vector_size (16)));
+typedef int __v4si __attribute__((vector_size (16)));
+typedef float __v8sf __attribute__((vector_size (32)));
+typedef int __v8si __attribute__((vector_size (32)));
+__v4si f1 (__v4sf, __v4sf, float *);
+__v8si f2 (__v8sf, __v8sf, float *);
+__v4si f3 (__v4si, int, __v4si);
+
+#pragma omp declare variant (f1) match (construct={parallel,for,simd(simdlen(4),notinbranch,uniform(z),aligned(z:4 * sizeof (*z)))})
+#pragma omp declare variant (f2) match (construct={for,simd(uniform(z),simdlen(8),notinbranch)})
+int f4 (float x, float y, float *z);
+
+#pragma omp declare variant (f3) match (construct={simd(simdlen(4),inbranch,linear(y:1))})
+int f5 (int x, int y);
+
+void
+test (int *x, float *y, float *z, float *w)
+{
+  #pragma omp parallel
+  #pragma omp for simd aligned (w:4 * sizeof (float))
+  for (int i = 0; i < 1024; i++)
+    x[i] = f4 (y[i], z[i], w);
+  #pragma omp parallel for simd aligned (w:4 * sizeof (float)) simdlen(4)
+  for (int i = 1024; i < 2048; i++)
+    x[i] = f4 (y[i], z[i], w);
+  #pragma omp simd aligned (w:4 * sizeof (float))
+  for (int i = 2048; i < 4096; i++)
+    x[i] = f4 (y[i], z[i], w);
+  #pragma omp simd
+  for (int i = 4096; i < 8192; i++)
+    if (x[i] > 10)
+      x[i] = f5 (x[i], i);
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-6.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-6.c
new file mode 100644 (file)
index 0000000..67c5a00
--- /dev/null
@@ -0,0 +1,35 @@
+double f1 (int, long, float);
+double f2 (int, long, float);
+#pragma omp declare variant (f1) match (user={condition(0)},construct={parallel})
+double f3 (int, long, float);
+#pragma omp declare variant (f1) match (construct={parallel},user={condition(score(1):1)})
+double f4 (int, long, float);
+double f5 (int, long, float);
+#pragma omp declare variant (f5) match (user={condition(0)})
+double f6 (int, long, float);
+#pragma omp declare variant (f5) match (construct={parallel},user={condition(score(1):1)})     /* { dg-error "'f5' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+double f7 (int, long, float);
+double f8 (int, long, float);
+#pragma omp declare variant (f8) match (user={condition(0)},construct={for})
+double f9 (int, long, float);
+#pragma omp declare variant (f8) match (user={condition(1)})                                   /* { dg-error "'f8' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+double f10 (int, long, float);
+double f11 (int, long, float);
+#pragma omp declare variant (f11) match (construct={target,teams,parallel,for})
+double f12 (int, long, float);
+#pragma omp declare variant (f11) match (user={condition(score(1):1)},construct={target,teams,parallel,for})
+double f13 (int, long, float);
+#pragma omp declare variant (f11) match (implementation={vendor(gnu)},construct={target,teams,parallel})       /* { dg-error "'f11' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+double f14 (int, long, float);
+#pragma omp declare variant (f11) match (device={kind(any)},construct={teams,parallel})                /* { dg-error "'f11' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+double f15 (int, long, float);
+double f16 (int, long, float);
+#pragma omp declare variant (f16) match (construct={teams,parallel})
+double f17 (int, long, float);
+#pragma omp declare variant (f16) match(construct={teams,parallel,for})                                /* { dg-error "'f16' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+double f18 (int, long, float);
+double f19 (int, long, float);
+#pragma omp declare variant (f19) match (construct={parallel})
+double f20 (int, long, float);
+#pragma omp declare variant (f19) match (construct={for},implementation={vendor(gnu,llvm)})    /* { dg-error "'f19' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+double f21 (int, long, float);
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-7.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-7.c
new file mode 100644 (file)
index 0000000..f818cd5
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-additional-options "-mavx2" } */
+
+typedef float __v4sf __attribute__((vector_size (16)));
+typedef int __v4si __attribute__((vector_size (16)));
+typedef float __v8sf __attribute__((vector_size (32)));
+typedef int __v8si __attribute__((vector_size (32)));
+__v4si f1 (__v4sf, __v4sf, float *);
+__v8si f2 (__v8sf, __v8sf, float *);
+__v4si f3 (__v4si, int, __v4si);
+
+#pragma omp declare variant (f1) match (construct={parallel,for,simd(simdlen(4),notinbranch,uniform(z),aligned(z:4 * sizeof (*z)))})
+int f4 (float x, float y, float *z);
+#pragma omp declare variant (f1) match (construct={parallel,for,simd(uniform(w),simdlen(8*2-12),aligned(w:4*sizeof (float)),notinbranch)})
+int f5 (float u, float v, float *w);
+#pragma omp declare variant (f1) match (construct={parallel,for,simd(linear(w),notinbranch,simdlen(4),aligned(w:4*sizeof (float)))})   /* { dg-error "'f1' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+int f6 (float u, float v, float *w);
+#pragma omp declare variant (f1) match (construct={parallel,for,simd(uniform(w),notinbranch,simdlen(4),aligned(w:2*sizeof (float)))})  /* { dg-error "'f1' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+int f7 (float u, float v, float *w);
+#pragma omp declare variant (f1) match (construct={parallel,for,simd(uniform(w),notinbranch,simdlen(4),aligned(w))})                   /* { dg-error "'f1' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+int f8 (float u, float v, float *w);
+#pragma omp declare variant (f2) match (construct={for,simd(uniform(z),simdlen(8),notinbranch)})
+int f9 (float x, float y, float *z);
+#pragma omp declare variant (f2) match (construct={for,simd(notinbranch,simdlen(2+2+4),uniform (q))})
+int f10 (float x, float y, float *q);
+#pragma omp declare variant (f2) match (construct={for,simd(linear(z:2),simdlen(8),notinbranch)})      /* { dg-error "'f2' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+int f11 (float x, float y, float *z);
+#pragma omp declare variant (f3) match (construct={simd(simdlen(4),inbranch,linear(y:1))})
+int f12 (int x, int y);
+#pragma omp declare variant (f3) match (construct={simd(inbranch,simdlen(5-1),linear(q:4-3))})
+int f13 (int x, int q);
+#pragma omp declare variant (f3) match (construct={simd(inbranch,simdlen(4),linear(q:2))})             /* { dg-error "'f3' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+int f14 (int x, int q);