Hi! The following patch handles declare variant in templates, including instantiating the "omp declare variant base" attribute value.
Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk. 2019-11-05 Jakub Jelinek <ja...@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. * g++.dg/gomp/declare-variant-7.C: New test. * g++.dg/gomp/declare-variant-8.C: New test. --- gcc/cp/decl.c.jj 2019-11-02 10:00:59.646252496 +0100 +++ gcc/cp/decl.c 2019-11-04 19:05:24.292235486 +0100 @@ -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 d 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 d } 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; } --- gcc/cp/pt.c.jj 2019-10-31 08:08:42.883786288 +0100 +++ gcc/cp/pt.c 2019-11-04 19:29:54.115165644 +0100 @@ -11119,6 +11119,76 @@ tsubst_attribute (tree t, tree *decl_p, 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, 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; } --- gcc/testsuite/g++.dg/gomp/declare-variant-7.C.jj 2019-11-04 19:35:26.351176805 +0100 +++ gcc/testsuite/g++.dg/gomp/declare-variant-7.C 2019-11-04 19:35:18.165299723 +0100 @@ -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" } } +} --- gcc/testsuite/g++.dg/gomp/declare-variant-8.C.jj 2019-11-04 19:46:20.060360684 +0100 +++ gcc/testsuite/g++.dg/gomp/declare-variant-8.C 2019-11-04 19:48:27.344449360 +0100 @@ -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> (); +} Jakub