decl.c (omp_declare_variant_finalize_one): Call declare_simd_adjust_this not just...
authorJakub Jelinek <jakub@gcc.gnu.org>
Tue, 5 Nov 2019 07:46:03 +0000 (08:46 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 5 Nov 2019 07:46:03 +0000 (08:46 +0100)
* decl.c (omp_declare_variant_finalize_one): Call
declare_simd_adjust_this not just on the context, but also on the
variant-id expression for methods.  Don't call
cp_get_callee_fndecl_nofold, call cp_get_callee and only if it is
safe cp_get_fndecl_from_callee.  Don't try to print as %qD
NULL in diagnostics.
* pt.c (tsubst_attribute): Handle "omp declare variant base"
attribute.
(tsubst_function_decl): Call omp_declare_variant_finalize
if there are any "omp declare variant base" attributes left.

* g++.dg/gomp/declare-variant-7.C: New test.
* g++.dg/gomp/declare-variant-8.C: New test.

From-SVN: r277814

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/gomp/declare-variant-7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/gomp/declare-variant-8.C [new file with mode: 0644]

index 0f7571633a7213204ed9e84c90a8db36a621d00c..9b16121c503d3010da396948514a4897bbe78969 100644 (file)
@@ -1,7 +1,20 @@
+2019-11-05  Jakub Jelinek  <jakub@redhat.com>
+
+       * decl.c (omp_declare_variant_finalize_one): Call
+       declare_simd_adjust_this not just on the context, but also on the
+       variant-id expression for methods.  Don't call
+       cp_get_callee_fndecl_nofold, call cp_get_callee and only if it is
+       safe cp_get_fndecl_from_callee.  Don't try to print as %qD
+       NULL in diagnostics.
+       * pt.c (tsubst_attribute): Handle "omp declare variant base"
+       attribute.
+       (tsubst_function_decl): Call omp_declare_variant_finalize
+       if there are any "omp declare variant base" attributes left.
+
 2019-11-04  Kamlesh Kumar  <kamleshbhalui@gmail.com>
 
        PR c++/91979 - mangling nullptr expression
-       * cp/mangle.c (write_template_arg_literal): Handle nullptr
+       * mangle.c (write_template_arg_literal): Handle nullptr
        mangling.
 
 2019-11-04  Jason Merrill  <jason@redhat.com>
index 6057fbcd718c2e9f44f008dad61229bb423c87d4..07112aad092561f2d1c334bffefad9bf34e7203d 100644 (file)
@@ -7099,8 +7099,12 @@ static bool
 omp_declare_variant_finalize_one (tree decl, tree attr)
 {
   if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
-    walk_tree (&TREE_VALUE (TREE_VALUE (attr)), declare_simd_adjust_this,
-              DECL_ARGUMENTS (decl), NULL);
+    {
+      walk_tree (&TREE_VALUE (TREE_VALUE (attr)), declare_simd_adjust_this,
+                DECL_ARGUMENTS (decl), NULL);
+      walk_tree (&TREE_PURPOSE (TREE_VALUE (attr)), declare_simd_adjust_this,
+                DECL_ARGUMENTS (decl), NULL);
+    }
 
   tree ctx = TREE_VALUE (TREE_VALUE (attr));
   tree simd = omp_get_context_selector (ctx, "construct", "simd");
@@ -7179,7 +7183,16 @@ omp_declare_variant_finalize_one (tree decl, tree attr)
   if (variant == error_mark_node && !processing_template_decl)
     return true;
 
-  variant = cp_get_callee_fndecl_nofold (variant);
+  variant = cp_get_callee (variant);
+  if (variant)
+    {
+      if (TREE_CODE (variant) == FUNCTION_DECL)
+       ;
+      else if (TREE_TYPE (variant) && INDIRECT_TYPE_P (TREE_TYPE (variant)))
+       variant = cp_get_fndecl_from_callee (variant, false);
+      else
+       variant = NULL_TREE;
+    }
 
   input_location = save_loc;
 
@@ -7211,7 +7224,7 @@ omp_declare_variant_finalize_one (tree decl, tree attr)
     }
   else if (!processing_template_decl)
     {
-      error_at (varid_loc, "could not find variant %qD declaration", variant);
+      error_at (varid_loc, "could not find variant declaration");
       return true;
     }
 
index 419e8b8fcd76af59124a705f83db4cf4fef61235..172d3d869fbfa0c8867f5e62e09413efe5a85983 100644 (file)
@@ -11119,6 +11119,76 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
       else
        val = NULL_TREE;
     }
+  else if (flag_openmp
+          && is_attribute_p ("omp declare variant base",
+                             get_attribute_name (t)))
+    {
+      ++cp_unevaluated_operand;
+      tree varid
+       = tsubst_expr (TREE_PURPOSE (val), args, complain,
+                      in_decl, /*integral_constant_expression_p=*/false);
+      --cp_unevaluated_operand;
+      tree chain = TREE_CHAIN (val);
+      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))
+       {
+         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))
+           {
+             if (TREE_PURPOSE (t2) == simd && set[0] == 'c')
+               {
+                 tree clauses = TREE_VALUE (t2);
+                 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;
+               }
+             else
+               {
+                 TREE_VALUE (t2) = copy_list (TREE_VALUE (t2));
+                 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
+                   if (TREE_VALUE (t3))
+                     {
+                       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);
+                       v = tsubst_expr (v, args, complain, in_decl, true);
+                       v = fold_non_dependent_expr (v);
+                       if (!INTEGRAL_TYPE_P (TREE_TYPE (v))
+                           || !tree_fits_shwi_p (v))
+                         {
+                           location_t loc
+                             = cp_expr_loc_or_loc (TREE_VALUE (t3),
+                                                   match_loc);
+                           if (TREE_PURPOSE (t3) == score)
+                             error_at (loc, "score argument must be "
+                                            "constant integer expression");
+                           else if (allow_string)
+                             error_at (loc, "property must be constant "
+                                            "integer expression or string "
+                                            "literal");
+                           else
+                             error_at (loc, "property must be constant "
+                                            "integer expression");
+                           return NULL_TREE;
+                         }
+                       TREE_VALUE (t3) = v;
+                     }
+               }
+           }
+       }
+      val = tree_cons (varid, ctx, chain);
+    }
   /* If the first attribute argument is an identifier, don't
      pass it through tsubst.  Attributes like mode, format,
      cleanup and several target specific attributes expect it
@@ -13579,6 +13649,11 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
 
   apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
                                  args, complain, in_decl);
+  if (flag_openmp)
+    if (tree attr = lookup_attribute ("omp declare variant base",
+                                     DECL_ATTRIBUTES (r)))
+      omp_declare_variant_finalize (r, attr);
+
   return r;
 }
 
index cc7aaed015878a369e462aea2a0bab2ea526eca5..cdb6b31286a97a0a10b4135352d620392bb6dcd3 100644 (file)
@@ -1,3 +1,8 @@
+2019-11-05  Jakub Jelinek  <jakub@redhat.com>
+
+       * g++.dg/gomp/declare-variant-7.C: New test.
+       * g++.dg/gomp/declare-variant-8.C: New test.
+
 2019-11-04  Eric Botcazou  <ebotcazou@adacore.com>
 
        PR testsuite/92302
diff --git a/gcc/testsuite/g++.dg/gomp/declare-variant-7.C b/gcc/testsuite/g++.dg/gomp/declare-variant-7.C
new file mode 100644 (file)
index 0000000..4a3e831
--- /dev/null
@@ -0,0 +1,75 @@
+// Test parsing of #pragma omp declare variant
+// { dg-do compile }
+// { dg-additional-options "-fdump-tree-gimple" }
+
+void f01 ();
+#pragma omp declare variant (f01) match (user={condition(1)},device={arch(x86_64)})
+template <int N>
+void f02 ();
+void f03 ();
+#pragma omp declare variant (f03) match (user={condition(score(N+2):N)})
+template <int N>
+void f04 ();
+template <int N>
+void f05 ();
+#pragma omp declare variant (f05<N>) match (user={condition((T)N)},implementation={vendor(gnu)})
+template <int N, typename T>
+void f06 ();
+void f07 ();
+#pragma omp declare variant (f07) match (user={condition(score(N+2):N)})
+template <int N>
+void f08 ();
+template <int N>
+void f09 ();
+#pragma omp declare variant (f09<N>) match (user={condition((T) N)})
+template <int N, typename T>
+void f10 ();
+template <int N>
+struct S
+{
+  template <typename T>
+  void f11 (T) {}
+  #pragma omp declare variant (f11<T>) match (user={condition(score(N):N)})
+  template <typename T>
+  void f12 (T) {}
+  template <typename T>
+  void f13 (T);
+  #pragma omp declare variant (f13<T>) match (user={condition(score(N):N)})
+  template <typename T>
+  void f14 (T);
+  int s;
+};
+template <int N>
+struct T
+{
+  template <typename T>
+  void f15 (T) {}
+  #pragma omp declare variant (f15<T>) match (user={condition(score(N):N)})
+  template <typename T>
+  void f16 (T) {}
+  template <typename T>
+  void f17 (T);
+  #pragma omp declare variant (f17<T>) match (user={condition(score(N):N)})
+  template <typename T>
+  void f18 (T);
+  int t;
+};
+
+void
+test ()
+{
+  f02<1> ();   // { dg-final { scan-tree-dump-times "f01 \\\(\\\);" 1 "gimple" { target { { i?86-*-* x86_64-*-* } && lp64 } } } }
+               // { dg-final { scan-tree-dump-times "f02<1> \\\(\\\);" 1 "gimple" { target { { i?86-*-* x86_64-*-* } && { ! lp64 } } } } }
+               // { dg-final { scan-tree-dump-times "f02<1> \\\(\\\);" 1 "gimple" { target { ! { i?86-*-* x86_64-*-* } } } } }
+  f04<1> ();           // { dg-final { scan-tree-dump-times "f03 \\\(\\\);" 1 "gimple" } }
+  f06<1, long> ();     // { dg-final { scan-tree-dump-times "f05<1> \\\(\\\);" 1 "gimple" } }
+  f08<0> ();           // { dg-final { scan-tree-dump-times "f08<0> \\\(\\\);" 1 "gimple" } }
+  f10<0, short int> ();        // { dg-final { scan-tree-dump-times "f10<0, short int> \\\(\\\);" 1 "gimple" } }
+  S<1> s;
+  s.f12 (0);           // { dg-final { scan-tree-dump-times "S<1>::f11<int> \\\(&s, 0\\\);" 1 "gimple" } }
+  s.f12 (0.0);         // { dg-final { scan-tree-dump-times "S<1>::f11<double> \\\(&s, 0.0\\\);" 1 "gimple" } }
+  s.f14 (0LL);         // { dg-final { scan-tree-dump-times "S<1>::f13<long long int> \\\(&s, 0\\\);" 1 "gimple" } }
+  T<0> t;
+  t.f16 (s);           // { dg-final { scan-tree-dump-times "T<0>::f16<S<1> > \\\(&t, s\\\);" 1 "gimple" } }
+  t.f18 (s);           // { dg-final { scan-tree-dump-times "T<0>::f18<S<1> > \\\(&t, s\\\);" 1 "gimple" } }
+}
diff --git a/gcc/testsuite/g++.dg/gomp/declare-variant-8.C b/gcc/testsuite/g++.dg/gomp/declare-variant-8.C
new file mode 100644 (file)
index 0000000..f72d862
--- /dev/null
@@ -0,0 +1,18 @@
+// Test parsing of #pragma omp declare variant
+// { dg-do compile }
+
+void f01 ();
+#pragma omp declare variant (f01) match (user={condition((T) 1)})      // { dg-error "property must be constant integer expression" }
+template <typename T>
+void f02 ();
+void f03 ();
+#pragma omp declare variant (f03) match (user={condition(score((T) 1):1)})     // { dg-error "score argument must be constant integer expression" }
+template <typename T>
+void f04 ();
+
+void
+test ()
+{
+  f02 <double> ();
+  f04 <float> ();
+}