summaryrefslogtreecommitdiff
path: root/libgomp/testsuite
diff options
context:
space:
mode:
authorSandra Loosemore <sloosemore@baylibre.com>2025-11-20 21:45:09 +0000
committerSandra Loosemore <sloosemore@baylibre.com>2025-11-22 17:05:22 +0000
commita469cf3df2ac97944a44948891e9fe22ba2f1d10 (patch)
tree735f89ddef0e2968b4f87611fc31724a68b9a210 /libgomp/testsuite
parent31107ba466715f3f662e9ddcefd5c33c483d0a31 (diff)
OpenMP: C++ front end support for "begin declare variant"
This patch implements C++ support for the "begin declare variant" construct. The OpenMP specification is hazy on interaction of this feature with C++ language features. Variant functions in classes are supported but must be defined as members in the class definition, using an unqualified name for the base function which also must be present in that class. Similarly variant functions in a namespace can only be defined in that namespace using an unqualified name for a base function already declared in that namespace. Variants for template functions or inside template classes seem to (mostly) work. gcc/c-family/ChangeLog * c-omp.cc (c_omp_directives): Uncomment "begin declare variant" and "end declare variant". gcc/cp/ChangeLog * cp-tree.h (struct cp_omp_declare_variant_attr): New. (struct saved_scope): Add omp_declare_variant_attribute field. * decl.cc (omp_declare_variant_finalize_one): Add logic to inject "this" parameter for method calls. * parser.cc (cp_parser_skip_to_pragma_omp_end_declare_variant): New. (cp_parser_translation_unit): Handle leftover "begin declare variant" functions. (omp_start_variant_function): New. (omp_finish_variant_function): New. (omp_maybe_record_variant_base): New. (cp_parser_init_declarator): Handle variant functions. (cp_parser_class_specifier): Handle deferred lookup of base functions when the entire class has been seen. (cp_parser_member_declaration): Handle variant functions. (cp_finish_omp_declare_variant): Merge context selectors if in a "begin declare variant" block. (cp_parser_omp_begin): Match "omp begin declare variant". Adjust error messages. (cp_parser_omp_end): Match "omp end declare variant". * parser.h (struct omp_begin_declare_variant_map_entry): New. (struct cp_parser): Add omp_begin_declare_variant_map field. * semantics.cc (finish_translation_unit): Detect unmatched "omp begin declare variant". gcc/testsuite/ChangeLog * g++.dg/gomp/delim-declare-variant-1.C: New. * g++.dg/gomp/delim-declare-variant-2.C: New. * g++.dg/gomp/delim-declare-variant-3.C: New. * g++.dg/gomp/delim-declare-variant-4.C: New. * g++.dg/gomp/delim-declare-variant-5.C: New. * g++.dg/gomp/delim-declare-variant-6.C: New. * g++.dg/gomp/delim-declare-variant-7.C: New. * g++.dg/gomp/delim-declare-variant-40.C: New. * g++.dg/gomp/delim-declare-variant-41.C: New. * g++.dg/gomp/delim-declare-variant-50.C: New. * g++.dg/gomp/delim-declare-variant-51.C: New. * g++.dg/gomp/delim-declare-variant-52.C: New. * g++.dg/gomp/delim-declare-variant-70.C: New. * g++.dg/gomp/delim-declare-variant-71.C: New. libgomp/ * testsuite/libgomp.c++/bdv_module1.C: New. * testsuite/libgomp.c++/bdv_module1_main.C: New. * testsuite/libgomp.c++/bdv_module2.C: New. * testsuite/libgomp.c++/bdv_module2_impl.C: New. * testsuite/libgomp.c++/bdv_module2_main.C: New. * testsuite/libgomp.c++/bdv_module3.C: New. * testsuite/libgomp.c++/bdv_module3_impl.C: New. * testsuite/libgomp.c++/bdv_module3_main.C: New. * testsuite/libgomp.c++/delim-declare-variant-1.C: New. * testsuite/libgomp.c++/delim-declare-variant-2.C: New. * testsuite/libgomp.c++/delim-declare-variant-7.C: New. Co-Authored-By: Julian Brown <julian@codesourcery.com> Co-Authored-By: waffl3x <waffl3x@baylibre.com>
Diffstat (limited to 'libgomp/testsuite')
-rw-r--r--libgomp/testsuite/libgomp.c++/bdv_module1.C23
-rw-r--r--libgomp/testsuite/libgomp.c++/bdv_module1_main.C16
-rw-r--r--libgomp/testsuite/libgomp.c++/bdv_module2.C15
-rw-r--r--libgomp/testsuite/libgomp.c++/bdv_module2_impl.C26
-rw-r--r--libgomp/testsuite/libgomp.c++/bdv_module2_main.C20
-rw-r--r--libgomp/testsuite/libgomp.c++/bdv_module3.C27
-rw-r--r--libgomp/testsuite/libgomp.c++/bdv_module3_impl.C31
-rw-r--r--libgomp/testsuite/libgomp.c++/bdv_module3_main.C25
-rw-r--r--libgomp/testsuite/libgomp.c++/delim-declare-variant-1.C29
-rw-r--r--libgomp/testsuite/libgomp.c++/delim-declare-variant-2.C37
-rw-r--r--libgomp/testsuite/libgomp.c++/delim-declare-variant-7.C39
11 files changed, 288 insertions, 0 deletions
diff --git a/libgomp/testsuite/libgomp.c++/bdv_module1.C b/libgomp/testsuite/libgomp.c++/bdv_module1.C
new file mode 100644
index 00000000000..0c8243029c0
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/bdv_module1.C
@@ -0,0 +1,23 @@
+// Test that "begin declare variant" in a module interface is
+// visible to things that import the module.
+
+// { dg-additional-sources "bdv_module1_main.C" }
+// { dg-additional-options "-fmodules" }
+
+export module bdv_module1;
+
+export int
+test ()
+{
+ return 0;
+}
+
+#if _OPENMP
+#pragma omp begin declare variant match(construct={parallel})
+export int
+test ()
+{
+ return 1;
+}
+#pragma omp end declare variant
+#endif
diff --git a/libgomp/testsuite/libgomp.c++/bdv_module1_main.C b/libgomp/testsuite/libgomp.c++/bdv_module1_main.C
new file mode 100644
index 00000000000..85f1fbf8e83
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/bdv_module1_main.C
@@ -0,0 +1,16 @@
+// { dg-skip-if "" { *-*-* } }
+// Built with bdv_module1.C
+
+import bdv_module1;
+
+int
+main ()
+{
+ if (test () != 0)
+ __builtin_abort ();
+ #pragma omp parallel if(0)
+ {
+ if (test () != 1)
+ __builtin_abort ();
+ }
+}
diff --git a/libgomp/testsuite/libgomp.c++/bdv_module2.C b/libgomp/testsuite/libgomp.c++/bdv_module2.C
new file mode 100644
index 00000000000..5152d324d3f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/bdv_module2.C
@@ -0,0 +1,15 @@
+// Test that "begin declare variant" in a module implementation unit is
+// visible only in that unit.
+
+// { dg-additional-sources "bdv_module2_impl.C bdv_module2_main.C" }
+// { dg-additional-options "-fmodules" }
+
+export module bdv_module2;
+
+export int
+test ()
+{
+ return 0;
+}
+
+export void doit ();
diff --git a/libgomp/testsuite/libgomp.c++/bdv_module2_impl.C b/libgomp/testsuite/libgomp.c++/bdv_module2_impl.C
new file mode 100644
index 00000000000..8287ae5f3b8
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/bdv_module2_impl.C
@@ -0,0 +1,26 @@
+// { dg-skip-if "" { *-*-* } }
+// Built with bdv_module2.C
+
+module bdv_module2;
+
+#if _OPENMP
+#pragma omp begin declare variant match(construct={teams})
+int
+test ()
+{
+ return -1;
+}
+#pragma omp end declare variant
+#endif
+
+void
+doit ()
+{
+ if (test () != 0)
+ __builtin_abort ();
+ #pragma omp teams
+ {
+ if (test () != -1)
+ __builtin_abort ();
+ }
+}
diff --git a/libgomp/testsuite/libgomp.c++/bdv_module2_main.C b/libgomp/testsuite/libgomp.c++/bdv_module2_main.C
new file mode 100644
index 00000000000..e3909f04e44
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/bdv_module2_main.C
@@ -0,0 +1,20 @@
+// { dg-skip-if "" { *-*-* } }
+// Built with bdv_module2.C
+
+import bdv_module2;
+
+int
+main ()
+{
+ // Calls to test from doit() should invoke the omp teams variant
+ // present in the TU where it is defined.
+ doit ();
+ // Calls to test from here shouldn't.
+ if (test () != 0)
+ __builtin_abort ();
+ #pragma omp teams
+ {
+ if (test () != 0)
+ __builtin_abort ();
+ }
+}
diff --git a/libgomp/testsuite/libgomp.c++/bdv_module3.C b/libgomp/testsuite/libgomp.c++/bdv_module3.C
new file mode 100644
index 00000000000..3afe4fba2e2
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/bdv_module3.C
@@ -0,0 +1,27 @@
+// Test that "begin declare variant" in a module interface is
+// visible to things that import the module, and that it works in
+// conjunction with additional "begin declare variant"s local
+// to a module implementation TU.
+
+// { dg-additional-sources "bdv_module3_impl.C bdv_module3_main.C" }
+// { dg-additional-options "-fmodules" }
+
+export module bdv_module3;
+
+export int
+test ()
+{
+ return 0;
+}
+
+#if _OPENMP
+#pragma omp begin declare variant match(construct={parallel})
+export int
+test ()
+{
+ return 1;
+}
+#pragma omp end declare variant
+#endif
+
+export void doit ();
diff --git a/libgomp/testsuite/libgomp.c++/bdv_module3_impl.C b/libgomp/testsuite/libgomp.c++/bdv_module3_impl.C
new file mode 100644
index 00000000000..5e798739a5c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/bdv_module3_impl.C
@@ -0,0 +1,31 @@
+// { dg-skip-if "" { *-*-* } }
+// Built with bdv_module3.C
+
+module bdv_module3;
+
+#if _OPENMP
+#pragma omp begin declare variant match(construct={teams})
+int
+test ()
+{
+ return -1;
+}
+#pragma omp end declare variant
+#endif
+
+void
+doit ()
+{
+ if (test () != 0)
+ __builtin_abort ();
+ #pragma omp teams
+ {
+ if (test () != -1)
+ __builtin_abort ();
+ }
+ #pragma omp parallel if(0)
+ {
+ if (test () != 1)
+ __builtin_abort ();
+ }
+}
diff --git a/libgomp/testsuite/libgomp.c++/bdv_module3_main.C b/libgomp/testsuite/libgomp.c++/bdv_module3_main.C
new file mode 100644
index 00000000000..08d9279471a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/bdv_module3_main.C
@@ -0,0 +1,25 @@
+// { dg-skip-if "" { *-*-* } }
+// Built with bdv_module3.C
+
+import bdv_module3;
+
+int
+main ()
+{
+ // Calls to test from doit() should invoke the omp teams variant
+ // present in the TU where it is defined.
+ doit ();
+ // Calls to test from here shouldn't.
+ if (test () != 0)
+ __builtin_abort ();
+ #pragma omp teams
+ {
+ if (test () != 0)
+ __builtin_abort ();
+ }
+ #pragma omp parallel if(0)
+ {
+ if (test () != 1)
+ __builtin_abort ();
+ }
+}
diff --git a/libgomp/testsuite/libgomp.c++/delim-declare-variant-1.C b/libgomp/testsuite/libgomp.c++/delim-declare-variant-1.C
new file mode 100644
index 00000000000..bf146dd2365
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/delim-declare-variant-1.C
@@ -0,0 +1,29 @@
+/* { dg-additional-options "-foffload=disable" } */
+
+/* Check that variants within a "begin declare variant" directive
+ are attached to the correct overloaded function. */
+
+int f (int x) { return x; }
+
+#pragma omp begin declare variant match (implementation={vendor("gnu")})
+int f (int x) { return -1; }
+#pragma omp end declare variant
+
+int f (int x, int y) { return x * y; }
+
+#pragma omp begin declare variant match (construct={target})
+int f (int x, int y) { return -2; }
+#pragma omp end declare variant
+
+int f (int x, int y, int z) { return x * y * z; }
+
+#pragma omp begin declare variant match (device={kind("host")})
+int f (int x, int y, int z) { return -3; }
+#pragma omp end declare variant
+
+int main (void)
+{
+ if (f (10) != -1) __builtin_abort ();
+ if (f (10, 20) != 200) __builtin_abort (); /* no match on this one */
+ if (f (10, 20, 30) != -3) __builtin_abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/delim-declare-variant-2.C b/libgomp/testsuite/libgomp.c++/delim-declare-variant-2.C
new file mode 100644
index 00000000000..6641768c1ef
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/delim-declare-variant-2.C
@@ -0,0 +1,37 @@
+/* Check that "omp begin declare variant" works on methods in a
+ class declaration. */
+
+class test1 {
+
+ private:
+ int n;
+ static int m;
+
+ public:
+
+ void set_n (int x) { n = x; }
+ int get_n (void) { return n; }
+
+ static void set_m (int x) { m = x; }
+ static int get_m (void) { return m; }
+
+ #pragma omp begin declare variant match (implementation={vendor("gnu")})
+ int get_n (void) { return n * 2; }
+ static int get_m (void) { return m * 2; }
+ #pragma omp end declare variant
+
+ #pragma omp begin declare variant match (construct={target})
+ int get_n (void) { return this->n * 2; }
+ #pragma omp end declare variant
+};
+
+int test1::m;
+
+int main (void)
+{
+ test1 t1;
+ t1.set_n (10);
+ if (t1.get_n () != 20) __builtin_abort ();
+ test1::set_m (1);
+ if (test1::get_m () != 2) __builtin_abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/delim-declare-variant-7.C b/libgomp/testsuite/libgomp.c++/delim-declare-variant-7.C
new file mode 100644
index 00000000000..60cc5d8a55b
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/delim-declare-variant-7.C
@@ -0,0 +1,39 @@
+/* Check that "omp begin declare variant" works on methods in a template
+ class declaration. */
+
+template <typename T>
+class test1 {
+
+ private:
+ T n;
+ static T m;
+
+ public:
+
+ void set_n (T x) { n = x; }
+ T get_n (void) { return n; }
+
+ static void set_m (T x) { m = x; }
+ static T get_m (void) { return m; }
+
+ #pragma omp begin declare variant match (implementation={vendor("gnu")})
+ T get_n (void) { return n * 2; }
+ static T get_m (void) { return m * 2; }
+ #pragma omp end declare variant
+
+ #pragma omp begin declare variant match (construct={target})
+ T get_n (void) { return this->n * 2; }
+ #pragma omp end declare variant
+};
+
+template <typename T>
+T test1<T>::m;
+
+int main (void)
+{
+ test1<int> t1;
+ t1.set_n (10);
+ if (t1.get_n () != 20) __builtin_abort ();
+ test1<int>::set_m (1);
+ if (test1<int>::get_m () != 2) __builtin_abort ();
+}