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. --- 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 +++++++++ .../g++.target/aarch64/mvc-warning1.C | 12 +++++++++-- 15 files changed, 171 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.target/aarch64/mv-and-mvc-error1.C create mode 100644 gcc/testsuite/g++.target/aarch64/mv-and-mvc-error2.C create mode 100644 gcc/testsuite/g++.target/aarch64/mv-and-mvc-error3.C create mode 100644 gcc/testsuite/g++.target/aarch64/mv-error1.C create mode 100644 gcc/testsuite/g++.target/aarch64/mv-error2.C create mode 100644 gcc/testsuite/g++.target/aarch64/mv-error3.C create mode 100644 gcc/testsuite/g++.target/aarch64/mv-error4.C create mode 100644 gcc/testsuite/g++.target/aarch64/mv-error5.C create mode 100644 gcc/testsuite/g++.target/aarch64/mv-error6.C create mode 100644 gcc/testsuite/g++.target/aarch64/mv-error7.C create mode 100644 gcc/testsuite/g++.target/aarch64/mv-error8.C create mode 100644 gcc/testsuite/g++.target/aarch64/mvc-error1.C create mode 100644 gcc/testsuite/g++.target/aarch64/mvc-error2.C
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 83f24b1ddb2..10e5ce82313 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 00000000000..00d3826f757 --- /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 00000000000..bf8a4112a21 --- /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 00000000000..3233a98d1ad --- /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 00000000000..0b9642c9ab6 --- /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 00000000000..167af4ad380 --- /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 00000000000..cc641488263 --- /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 00000000000..a6b57a73c3e --- /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 00000000000..3d2c73446be --- /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 00000000000..8ea26750480 --- /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 00000000000..c1b58edca11 --- /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 00000000000..0b6b38ce100 --- /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 00000000000..db6f5a40b39 --- /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 00000000000..157086d439d --- /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 59acec3fad2..b6fb2840ab6 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; +}