https://gcc.gnu.org/g:f54b7da000f2d3fe1211957fb2e33a87882461cc

commit f54b7da000f2d3fe1211957fb2e33a87882461cc
Author: Alfie Richards <alfie.richa...@arm.com>
Date:   Thu Feb 13 15:59:43 2025 +0000

    Add error cases and tests for Aarch64 FMV.
    
    This changes the ambiguation error for C++ to cover cases of differently
    annotated FMV function sets whose signatures only differ by their return
    type.
    
    It also adds tests covering many FMV errors for Aarch64, including
    redeclaration, and mixing target_clones and target_versions.
    
    gcc/cp/ChangeLog:
            PR c++/119498
            * decl.cc (duplicate_decls): Change logic to not always exclude FMV
            annotated functions in cases of return type non-ambiguation.
    
    gcc/testsuite/ChangeLog:
    
            * g++.target/aarch64/mv-and-mvc-error1.C: New test.
            * g++.target/aarch64/mv-and-mvc-error2.C: New test.
            * g++.target/aarch64/mv-and-mvc-error3.C: New test.
            * g++.target/aarch64/mv-error1.C: New test.
            * g++.target/aarch64/mv-error2.C: New test.
            * g++.target/aarch64/mv-error3.C: New test.
            * g++.target/aarch64/mv-error4.C: New test.
            * g++.target/aarch64/mv-error5.C: New test.
            * g++.target/aarch64/mv-error6.C: New test.
            * g++.target/aarch64/mv-error7.C: New test.
            * g++.target/aarch64/mv-error8.C: New test.
            * g++.target/aarch64/mvc-error1.C: New test.
            * g++.target/aarch64/mvc-error2.C: New test.
            * g++.target/aarch64/mvc-warning1.C: Modified test.

Diff:
---
 gcc/cp/decl.cc                                      |  7 +++++--
 .../g++.target/aarch64/mv-and-mvc-error1.C          | 10 ++++++++++
 .../g++.target/aarch64/mv-and-mvc-error2.C          | 10 ++++++++++
 .../g++.target/aarch64/mv-and-mvc-error3.C          |  9 +++++++++
 gcc/testsuite/g++.target/aarch64/mv-error1.C        | 19 +++++++++++++++++++
 gcc/testsuite/g++.target/aarch64/mv-error2.C        | 10 ++++++++++
 gcc/testsuite/g++.target/aarch64/mv-error3.C        | 13 +++++++++++++
 gcc/testsuite/g++.target/aarch64/mv-error4.C        | 10 ++++++++++
 gcc/testsuite/g++.target/aarch64/mv-error5.C        |  9 +++++++++
 gcc/testsuite/g++.target/aarch64/mv-error6.C        | 21 +++++++++++++++++++++
 gcc/testsuite/g++.target/aarch64/mv-error7.C        | 12 ++++++++++++
 gcc/testsuite/g++.target/aarch64/mv-error8.C        | 13 +++++++++++++
 gcc/testsuite/g++.target/aarch64/mvc-error1.C       | 10 ++++++++++
 gcc/testsuite/g++.target/aarch64/mvc-error2.C       | 10 ++++++++++
 gcc/testsuite/g++.target/aarch64/mvc-warning1.C     | 12 ++++++++++--
 15 files changed, 171 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index c53a8ac4567a..c20af9bc322a 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -2022,8 +2022,11 @@ duplicate_decls (tree newdecl, tree olddecl, bool 
hiding, bool was_hidden)
            }
          /* For function versions, params and types match, but they
             are not ambiguous.  */
-         else if ((!DECL_FUNCTION_VERSIONED (newdecl)
-                   && !DECL_FUNCTION_VERSIONED (olddecl))
+         else if (((!DECL_FUNCTION_VERSIONED (newdecl)
+                    && !DECL_FUNCTION_VERSIONED (olddecl))
+                   || !comptypes (TREE_TYPE (TREE_TYPE (newdecl)),
+                                  TREE_TYPE (TREE_TYPE (olddecl)),
+                                  COMPARE_STRICT))
                   /* Let constrained hidden friends coexist for now, we'll
                      check satisfaction later.  */
                   && !member_like_constrained_friend_p (newdecl)
diff --git a/gcc/testsuite/g++.target/aarch64/mv-and-mvc-error1.C 
b/gcc/testsuite/g++.target/aarch64/mv-and-mvc-error1.C
new file mode 100644
index 000000000000..00d3826f757f
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/mv-and-mvc-error1.C
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-Wno-experimental-fmv-target" } */
+
+__attribute__ ((target_version ("dotprod"))) int
+foo () { return 3; } /* { dg-message "previous definition" } */
+
+__attribute__ ((target_clones ("dotprod", "sve"))) int
+foo () { return 1; } /* { dg-error "conflicting .dotprod. versions" } */
diff --git a/gcc/testsuite/g++.target/aarch64/mv-and-mvc-error2.C 
b/gcc/testsuite/g++.target/aarch64/mv-and-mvc-error2.C
new file mode 100644
index 000000000000..bf8a4112a216
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/mv-and-mvc-error2.C
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-Wno-experimental-fmv-target" } */
+
+__attribute__ ((target_version ("default"))) int
+foo () { return 1; } /* { dg-message "old declaration" } */
+
+__attribute__ ((target_clones ("dotprod", "sve"))) float
+foo () { return 3; } /* { dg-error "ambiguating new declaration of" } */
diff --git a/gcc/testsuite/g++.target/aarch64/mv-and-mvc-error3.C 
b/gcc/testsuite/g++.target/aarch64/mv-and-mvc-error3.C
new file mode 100644
index 000000000000..3233a98d1ad9
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/mv-and-mvc-error3.C
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-Wno-experimental-fmv-target" } */
+
+float foo () { return 1; } /* { dg-message "previous definition" } */
+
+__attribute__ ((target_clones ("default", "dotprod", "sve"))) float
+foo () { return 3; } /* { dg-error "conflicting .default. versions" } */
diff --git a/gcc/testsuite/g++.target/aarch64/mv-error1.C 
b/gcc/testsuite/g++.target/aarch64/mv-error1.C
new file mode 100644
index 000000000000..0b9642c9ab64
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/mv-error1.C
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-Wno-experimental-fmv-target" } */
+
+__attribute__ ((target_version ("default"))) int
+foo ();
+
+__attribute__ ((target_version ("default"))) int
+foo () { return 1; } /* { dg-message "old declaration" } */
+
+__attribute__ ((target_version ("dotprod"))) float
+foo () { return 3; } /* { dg-error "ambiguating new declaration of" } */
+
+__attribute__ ((target_version ("sve"))) int
+foo2 () { return 1; } /* { dg-message "old declaration" } */
+
+__attribute__ ((target_version ("dotprod"))) float
+foo2 () { return 3; } /* { dg-error "ambiguating new declaration of" } */
diff --git a/gcc/testsuite/g++.target/aarch64/mv-error2.C 
b/gcc/testsuite/g++.target/aarch64/mv-error2.C
new file mode 100644
index 000000000000..167af4ad380d
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/mv-error2.C
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-Wno-experimental-fmv-target" } */
+
+__attribute__ ((target_version ("dotprod"))) float
+foo () { return 3; } /* { dg-message "previously defined here" } */
+
+__attribute__ ((target_version ("dotprod"))) float
+foo () { return 3; } /* { dg-error "redefinition of" } */
diff --git a/gcc/testsuite/g++.target/aarch64/mv-error3.C 
b/gcc/testsuite/g++.target/aarch64/mv-error3.C
new file mode 100644
index 000000000000..cc6414882639
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/mv-error3.C
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-Wno-experimental-fmv-target" } */
+
+__attribute__ ((target_version ("dotprod"))) float
+foo () { return 3; }
+
+__attribute__ ((target_version ("default"))) float
+foo () { return 3; } /* { dg-message "previously defined here" } */
+
+__attribute__ ((target_version ("default"))) float
+foo () { return 3; } /* { dg-error "redefinition of" } */
diff --git a/gcc/testsuite/g++.target/aarch64/mv-error4.C 
b/gcc/testsuite/g++.target/aarch64/mv-error4.C
new file mode 100644
index 000000000000..a6b57a73c3ed
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/mv-error4.C
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-Wno-experimental-fmv-target" } */
+
+__attribute__ ((target_version ("test"))) float
+foo () { return 3; } /* { dg-error "invalid feature modifier .test. of value 
.test. in .target_version. attribute" } */
+
+__attribute__ ((target_version ("sve+test"))) float
+foo2 () { return 3; } /* { dg-error "invalid feature modifier .test. of value 
.sve.test. in .target_version. attribute" } */
diff --git a/gcc/testsuite/g++.target/aarch64/mv-error5.C 
b/gcc/testsuite/g++.target/aarch64/mv-error5.C
new file mode 100644
index 000000000000..3d2c73446beb
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/mv-error5.C
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-Wno-experimental-fmv-target" } */
+
+__attribute__ ((target_version ("sve+sve2"))) int
+foo();
+
+int bar () { return foo (); } /* { dg-error "no default version in scope" } */
diff --git a/gcc/testsuite/g++.target/aarch64/mv-error6.C 
b/gcc/testsuite/g++.target/aarch64/mv-error6.C
new file mode 100644
index 000000000000..8ea267504802
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/mv-error6.C
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-Wno-experimental-fmv-target" } */
+
+__attribute__ ((target_version ("sve+sve2"))) int
+foo () {
+       return 1;
+}
+
+__attribute__ ((target_version ("sve"))) int
+foo () {
+       return 1;
+}
+
+int bar () { return foo (); } /* { dg-error "no matching function for call to" 
} */
+
+__attribute__ ((target_version ("sve+sve2"))) int
+foo2();
+
+int bar2 () { return foo2 (); } /* { dg-error "no default version in scope" } 
*/
diff --git a/gcc/testsuite/g++.target/aarch64/mv-error7.C 
b/gcc/testsuite/g++.target/aarch64/mv-error7.C
new file mode 100644
index 000000000000..c1b58edca11d
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/mv-error7.C
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-Wno-experimental-fmv-target" } */
+
+__attribute__ ((target_version ("dotprod"))) int
+foo ();
+
+__attribute__ ((target_version ("sve+sve2"))) int
+foo ();
+
+int bar () { return foo (); } /* { dg-error "no matching function for call to" 
} */
diff --git a/gcc/testsuite/g++.target/aarch64/mv-error8.C 
b/gcc/testsuite/g++.target/aarch64/mv-error8.C
new file mode 100644
index 000000000000..0b6b38ce1000
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/mv-error8.C
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-Wno-experimental-fmv-target" } */
+
+__attribute__ ((target_version ("dotprod"))) int
+foo ();
+
+int
+bar ()
+{
+  return foo (); /* { dg-error "no default version in scope" } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/mvc-error1.C 
b/gcc/testsuite/g++.target/aarch64/mvc-error1.C
new file mode 100644
index 000000000000..db6f5a40b391
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/mvc-error1.C
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-Wno-experimental-fmv-target" } */
+
+__attribute__ ((target_clones ("default, dotprod"))) float
+foo (); /* { dg-message "previous definition" } */
+
+__attribute__ ((target_clones ("dotprod", "sve"))) float
+foo () { return 3; } /* { dg-error "conflicting .dotprod. versions" } */
diff --git a/gcc/testsuite/g++.target/aarch64/mvc-error2.C 
b/gcc/testsuite/g++.target/aarch64/mvc-error2.C
new file mode 100644
index 000000000000..157086d439d3
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/mvc-error2.C
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-Wno-experimental-fmv-target" } */
+
+__attribute__ ((target_clones ("default, dotprod"))) float
+foo () { return 3; } /* { dg-message "previous definition" } */
+
+__attribute__ ((target_clones ("dotprod", "sve"))) float
+foo () { return 3; } /* { dg-error "conflicting .dotprod. versions" } */
diff --git a/gcc/testsuite/g++.target/aarch64/mvc-warning1.C 
b/gcc/testsuite/g++.target/aarch64/mvc-warning1.C
index 59acec3fad2f..b6fb2840ab63 100644
--- a/gcc/testsuite/g++.target/aarch64/mvc-warning1.C
+++ b/gcc/testsuite/g++.target/aarch64/mvc-warning1.C
@@ -1,6 +1,14 @@
 /* { dg-do compile } */
 /* { dg-require-ifunc "" } */
 /* { dg-options "-O0" } */
+/* { dg-additional-options "-Wno-experimental-fmv-target" } */
 
-__attribute__((target_clones("default", "sve")))
-int foo () { return 1; }/* { dg-warning "Function Multi Versioning support is 
experimental, and the behavior is likely to change" } */
+__attribute__((target_clones("default", "dotprod", "sve+sve2")))
+int foo () {
+  return 1;
+}
+
+__attribute__((target_clones("invalid1")))
+int foo () { /* { dg-warning "invalid .target_clones. version .invalid1. 
ignored" } */
+  return 2;
+}

Reply via email to