Hello. The refactoring in r251316 changed the logic when cgraph_node::record_function_versions function is called. Suggested patch reverts the logic prior to the revision.
Patch can bootstrap on ppc64le-redhat-linux and survives regression tests. And make check RUNTESTFLAGS="i386.exp" on x86_64 works. Ready to be installed? Martin gcc/cp/ChangeLog: 2018-01-26 Martin Liska <mli...@suse.cz> PR c++/84059. * class.c (add_method): Append argument value. * cp-tree.h (maybe_version_functions): Add new argument. * decl.c (decls_match): Call it if a declaration does not have DECL_FUNCTION_VERSIONED. (maybe_version_functions): record argument is added. gcc/testsuite/ChangeLog: 2018-01-26 Martin Liska <mli...@suse.cz> PR c++/84059. * g++.dg/ext/mv26.C: New test. --- gcc/cp/class.c | 2 +- gcc/cp/cp-tree.h | 2 +- gcc/cp/decl.c | 14 ++++++-------- gcc/testsuite/g++.dg/ext/mv26.C | 15 +++++++++++++++ 4 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/mv26.C
diff --git a/gcc/cp/class.c b/gcc/cp/class.c index a4098ac872e..57a2e69ada6 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1099,7 +1099,7 @@ add_method (tree type, tree method, bool via_using) /* If these are versions of the same function, process and move on. */ if (TREE_CODE (fn) == FUNCTION_DECL - && maybe_version_functions (method, fn)) + && maybe_version_functions (method, fn, true)) continue; if (DECL_INHERITED_CTOR (method)) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a53f4fd9c03..b636333b93f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6136,7 +6136,7 @@ extern bool note_iteration_stmt_body_start (void); extern void note_iteration_stmt_body_end (bool); extern tree make_lambda_name (void); extern int decls_match (tree, tree, bool = true); -extern bool maybe_version_functions (tree, tree); +extern bool maybe_version_functions (tree, tree, bool); extern tree duplicate_decls (tree, tree, bool); extern tree declare_local_label (tree); extern tree define_label (location_t, tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 01ce9fb6d69..3ccea9e6a45 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1087,7 +1087,9 @@ decls_match (tree newdecl, tree olddecl, bool record_versions /* = true */) && !DECL_EXTERN_C_P (newdecl) && !DECL_EXTERN_C_P (olddecl) && record_versions - && maybe_version_functions (newdecl, olddecl)) + && maybe_version_functions (newdecl, olddecl, + (!DECL_FUNCTION_VERSIONED (newdecl) + || !DECL_FUNCTION_VERSIONED (olddecl)))) return 0; } else if (TREE_CODE (newdecl) == TEMPLATE_DECL) @@ -1145,19 +1147,17 @@ decls_match (tree newdecl, tree olddecl, bool record_versions /* = true */) } /* NEWDECL and OLDDECL have identical signatures. If they are - different versions adjust them and return true. */ + different versions adjust them and return true. + If RECORD is set to true, record function versions. */ bool -maybe_version_functions (tree newdecl, tree olddecl) +maybe_version_functions (tree newdecl, tree olddecl, bool record) { if (!targetm.target_option.function_versions (newdecl, olddecl)) return false; - bool record = false; - if (!DECL_FUNCTION_VERSIONED (olddecl)) { - record = true; DECL_FUNCTION_VERSIONED (olddecl) = 1; if (DECL_ASSEMBLER_NAME_SET_P (olddecl)) mangle_decl (olddecl); @@ -1165,13 +1165,11 @@ maybe_version_functions (tree newdecl, tree olddecl) if (!DECL_FUNCTION_VERSIONED (newdecl)) { - record = true; DECL_FUNCTION_VERSIONED (newdecl) = 1; if (DECL_ASSEMBLER_NAME_SET_P (newdecl)) mangle_decl (newdecl); } - /* Only record if at least one was not already versions. */ if (record) cgraph_node::record_function_versions (olddecl, newdecl); diff --git a/gcc/testsuite/g++.dg/ext/mv26.C b/gcc/testsuite/g++.dg/ext/mv26.C new file mode 100644 index 00000000000..1b455130e46 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/mv26.C @@ -0,0 +1,15 @@ +// PR c++/84059 +// { dg-do compile { target i?86-*-* x86_64-*-* } } +// { dg-require-ifunc "" } + +template <typename> struct a +{ + int __attribute__ ((target ("arch=ivybridge"))) c (int) {return 1;} + int __attribute__ ((target ("default"))) c (int) { return 2; } +}; +void +d () +{ + a<double> b; + b.c (2); +}