aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Burnus <tburnus@baylibre.com>2025-01-15 10:47:29 +0100
committerTobias Burnus <tburnus@baylibre.com>2025-01-15 10:47:29 +0100
commitb67a0d6aca0c049e14e44c3f28ce3806680543ef (patch)
treececc25cf582b1e7b7de61a0f35630434d33220fa
parentdd389c2549a4891e044c96b9298efa2a363c744a (diff)
downloadgcc-b67a0d6aca0c049e14e44c3f28ce3806680543ef.zip
gcc-b67a0d6aca0c049e14e44c3f28ce3806680543ef.tar.gz
gcc-b67a0d6aca0c049e14e44c3f28ce3806680543ef.tar.bz2
OpenMP/C++: Fix 'declare variant' for struct-returning functions [PR118486]
To find the variant declaration, a call is constructed in omp_declare_variant_finalize_one, which gives here: TARGET_EXPR <D.3010, variant_fn ()> Extracting now the function declaration failed and gave the bogus error: could not find variant declaration Solution: Use the 2nd argument of the TARGET_EXPR and continue. PR c++/118486 gcc/cp/ChangeLog: * decl.cc (omp_declare_variant_finalize_one): When resolving the variant to use, handle variant calls with TARGET_EXPR. gcc/testsuite/ChangeLog: * g++.dg/gomp/declare-variant-11.C: New test.
-rw-r--r--gcc/cp/decl.cc3
-rw-r--r--gcc/testsuite/g++.dg/gomp/declare-variant-11.C38
2 files changed, 41 insertions, 0 deletions
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 90e9a7f..0532c68 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -8552,6 +8552,9 @@ omp_declare_variant_finalize_one (tree decl, tree attr)
if (variant == error_mark_node && !processing_template_decl)
return true;
+ if (TREE_CODE (variant) == TARGET_EXPR)
+ variant = TARGET_EXPR_INITIAL (variant);
+
variant = cp_get_callee_fndecl_nofold (STRIP_REFERENCE_REF (variant));
input_location = save_loc;
diff --git a/gcc/testsuite/g++.dg/gomp/declare-variant-11.C b/gcc/testsuite/g++.dg/gomp/declare-variant-11.C
new file mode 100644
index 0000000..56b2556
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/declare-variant-11.C
@@ -0,0 +1,38 @@
+/* { dg-additional-options "-fdump-tree-gimple" } */
+
+/* PR c++/118486 */
+
+struct NotAnInt {};
+
+// Wrong return type:
+NotAnInt var1();
+#pragma omp declare variant(var1) match(user={condition(true)})
+int base1();
+/* { dg-error "variant 'NotAnInt var1\\(\\)' and base 'int base1\\(\\)' have incompatible types" "" { target *-*-* } .-2 } */
+
+
+// Wrong return type:
+NotAnInt var2();
+float var2(float);
+#pragma omp declare variant(var2) match(user={condition(true)})
+int base2();
+/* { dg-error "variant 'NotAnInt var2\\(\\)' and base 'int base2\\(\\)' have incompatible types" "" { target *-*-* } .-2 } */
+
+
+// OK:
+NotAnInt var3();
+#pragma omp declare variant(var3) match(user={condition(true)})
+NotAnInt base3();
+
+void f()
+{
+ // int x;
+ NotAnInt y;
+
+ //x = base1 ();
+ //x = base2 ();
+ y = base3 ();
+}
+
+/* { dg-final { scan-tree-dump "var3 \\(\\);" "gimple" } } */
+/* { dg-final { scan-tree-dump-not "base3" "gimple" } } */