From: Alfie Richards <[email protected]>

This patch adds exclusions and diagnostics to prevent function multi-versioning
being used with omp simd pragmas and renaming extensions.

This behaviour is forbidden by the ACLE as the expected behaviour is not clear.

gcc/c-family/ChangeLog:

        * c-attribs.cc: Add exclusions.

gcc/c/ChangeLog:

        * c-decl.cc (maybe_mark_function_versioned): Add diagnostic.
        * c-parser.cc (c_finish_omp_declare_simd): Add diagnostic.

gcc/testsuite/ChangeLog:

        * gcc.target/aarch64/mv-error11.c: New test.
        * gcc.target/aarch64/mv-error12.c: New test.
---
 gcc/c-family/c-attribs.cc                     | 30 +++++++++++++++++--
 gcc/c/c-decl.cc                               |  6 ++++
 gcc/c/c-parser.cc                             |  7 +++++
 gcc/testsuite/gcc.target/aarch64/mv-error11.c |  9 ++++++
 gcc/testsuite/gcc.target/aarch64/mv-error12.c | 13 ++++++++
 5 files changed, 62 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/mv-error11.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/mv-error12.c

diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index df9ff9947a8..5bc5183f421 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -249,6 +249,29 @@ static const struct attribute_spec::exclusions 
attr_target_clones_exclusions[] =
   ATTR_EXCL ("always_inline", true, true, true),
   ATTR_EXCL ("target", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
             TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE),
+  ATTR_EXCL ("omp declare simd", true, true, true),
+  ATTR_EXCL ("simd", true, true, true),
+  ATTR_EXCL (NULL, false, false, false),
+};
+
+static const struct attribute_spec::exclusions 
attr_target_version_exclusions[] =
+{
+  ATTR_EXCL ("omp declare simd", true, true, true),
+  ATTR_EXCL ("simd", true, true, true),
+  ATTR_EXCL (NULL, false, false, false),
+};
+
+static const struct attribute_spec::exclusions 
attr_omp_declare_simd_exclusions[] =
+{
+  ATTR_EXCL ("target_version", true, true, true),
+  ATTR_EXCL ("target_clones", true, true, true),
+  ATTR_EXCL (NULL, false, false, false),
+};
+
+static const struct attribute_spec::exclusions attr_simd_exclusions[] =
+{
+  ATTR_EXCL ("target_version", true, true, true),
+  ATTR_EXCL ("target_clones", true, true, true),
   ATTR_EXCL (NULL, false, false, false),
 };
 
@@ -536,7 +559,7 @@ const struct attribute_spec c_common_gnu_attributes[] =
                              attr_target_exclusions },
   { "target_version",         1, 1, true, false, false, false,
                              handle_target_version_attribute,
-                             NULL },
+                             attr_target_version_exclusions},
   { "target_clones",          1, -1, true, false, false, false,
                              handle_target_clones_attribute,
                              attr_target_clones_exclusions },
@@ -563,7 +586,8 @@ const struct attribute_spec c_common_gnu_attributes[] =
   { "returns_nonnull",        0, 0, false, true, true, false,
                              handle_returns_nonnull_attribute, NULL },
   { "omp declare simd",       0, -1, true,  false, false, false,
-                             handle_omp_declare_simd_attribute, NULL },
+                             handle_omp_declare_simd_attribute,
+                             attr_omp_declare_simd_exclusions },
   { "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,
@@ -572,7 +596,7 @@ const struct attribute_spec c_common_gnu_attributes[] =
                              false, false,
                              handle_omp_declare_variant_attribute, NULL },
   { "simd",                  0, 1, true,  false, false, false,
-                             handle_simd_attribute, NULL },
+                             handle_simd_attribute, attr_simd_exclusions },
   { "omp declare target",     0, -1, true, false, false, false,
                              handle_omp_declare_target_attribute, NULL },
   { "omp declare target link", 0, 0, true, false, false, false,
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 825487529d0..eed87258d40 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -2094,6 +2094,12 @@ maybe_mark_function_versioned (tree decl)
 {
   if (!DECL_FUNCTION_VERSIONED (decl))
     {
+      /* Check if the name of the function has been overridden.  */
+      if (DECL_ASSEMBLER_NAME_SET_P (decl)
+         && IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))[0] == '*')
+       error_at (DECL_SOURCE_LOCATION (decl),
+                 "Cannot use function multiversioning on a renamed function");
+
       /* We need to insert function version now to make sure the correct
         pre-mangled assembler name is recorded.  */
       cgraph_node *node = cgraph_node::get_create (decl);
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index df44a915ed4..7c2452644bd 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -27776,6 +27776,13 @@ c_finish_omp_declare_simd (c_parser *parser, tree 
fndecl, tree parms,
       clauses[0].type = CPP_EOF;
       return;
     }
+  if (DECL_FUNCTION_VERSIONED (fndecl))
+    {
+      error_at (DECL_SOURCE_LOCATION (fndecl),
+               "%<#pragma omp declare %s%> cannot be used with function "
+               "multi-versioning", kind);
+      return;
+    }
 
   if (parms == NULL_TREE)
     parms = DECL_ARGUMENTS (fndecl);
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error11.c 
b/gcc/testsuite/gcc.target/aarch64/mv-error11.c
new file mode 100644
index 00000000000..58c9b3fbfa6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-error11.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+int fn () asm("name");
+int fn () { return 1; } /* { dg-error "Cannot use function multiversioning on 
a renamed function" } */
+int fn [[gnu::target_version("sve")]] () { return 1; }
+
+int fn2 [[gnu::target_version("sve")]] () asm("name"); /* { dg-warning ".asm. 
declaration ignored due to conflict with previous rename" } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error12.c 
b/gcc/testsuite/gcc.target/aarch64/mv-error12.c
new file mode 100644
index 00000000000..45da85a67b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-error12.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+/* { dg-require-ifunc "" } */
+
+#pragma omp declare simd
+int fn [[gnu::target_version("sve")]] () { return 1; } /* { dg-error ".#pragma 
omp declare simd. cannot be used with function multi-versioning" } */
+
+#pragma omp declare simd
+int fn2 () { return 1; }
+
+int fn2 [[gnu::target_version("sve")]] (); /* { dg-warning "ignoring attribute 
.target_version. because it conflicts with attribute .omp declare simd." } */
+
+int fn3 [[gnu::target_version("sve")]] [[gnu::simd]] () { return 1; } /* { 
dg-warning "ignoring attribute .simd. because it conflicts with attribute 
.target_version." } */
-- 
2.34.1

Reply via email to