2017-08-23 Nathan Sidwell * cp-tree.h (maybe_version_functions): Declare. * decl.c (decls_match): Break function versioning check to separate function. Call it. (maybe_version_functions): Broken out of decls_match. * class.c (add_method): Use maybe_version_functions. Index: class.c =================================================================== --- class.c (revision 251313) +++ class.c (working copy) @@ -1154,33 +1154,11 @@ add_method (tree type, tree method, bool TREE_TYPE (method_type))) && equivalently_constrained (fn, method)) { - /* For function versions, their parms and types match - but they are not duplicates. Record function versions - as and when they are found. extern "C" functions are - not treated as versions. */ + /* If these are versions of the same function, process and + move on. */ if (TREE_CODE (fn) == FUNCTION_DECL - && TREE_CODE (method) == FUNCTION_DECL - && !DECL_EXTERN_C_P (fn) - && !DECL_EXTERN_C_P (method) - && targetm.target_option.function_versions (fn, method)) - { - /* Mark functions as versions if necessary. Modify the mangled - decl name if necessary. */ - if (!DECL_FUNCTION_VERSIONED (fn)) - { - DECL_FUNCTION_VERSIONED (fn) = 1; - if (DECL_ASSEMBLER_NAME_SET_P (fn)) - mangle_decl (fn); - } - if (!DECL_FUNCTION_VERSIONED (method)) - { - DECL_FUNCTION_VERSIONED (method) = 1; - if (DECL_ASSEMBLER_NAME_SET_P (method)) - mangle_decl (method); - } - cgraph_node::record_function_versions (fn, method); - continue; - } + && maybe_version_functions (method, fn)) + continue; if (DECL_INHERITED_CTOR (method)) { Index: cp-tree.h =================================================================== --- cp-tree.h (revision 251313) +++ cp-tree.h (working copy) @@ -6071,6 +6071,7 @@ extern void push_switch (tree); extern void pop_switch (void); extern tree make_lambda_name (void); extern int decls_match (tree, tree); +extern bool maybe_version_functions (tree, tree); extern tree duplicate_decls (tree, tree, bool); extern tree declare_local_label (tree); extern tree define_label (location_t, tree); Index: decl.c =================================================================== --- decl.c (revision 251313) +++ decl.c (working copy) @@ -1088,28 +1088,8 @@ decls_match (tree newdecl, tree olddecl) if (types_match && !DECL_EXTERN_C_P (newdecl) && !DECL_EXTERN_C_P (olddecl) - && targetm.target_option.function_versions (newdecl, olddecl)) - { - /* Mark functions as versions if necessary. Modify the mangled decl - name if necessary. */ - if (DECL_FUNCTION_VERSIONED (newdecl) - && DECL_FUNCTION_VERSIONED (olddecl)) - return 0; - if (!DECL_FUNCTION_VERSIONED (newdecl)) - { - DECL_FUNCTION_VERSIONED (newdecl) = 1; - if (DECL_ASSEMBLER_NAME_SET_P (newdecl)) - mangle_decl (newdecl); - } - if (!DECL_FUNCTION_VERSIONED (olddecl)) - { - DECL_FUNCTION_VERSIONED (olddecl) = 1; - if (DECL_ASSEMBLER_NAME_SET_P (olddecl)) - mangle_decl (olddecl); - } - cgraph_node::record_function_versions (olddecl, newdecl); - return 0; - } + && maybe_version_functions (newdecl, olddecl)) + return 0; } else if (TREE_CODE (newdecl) == TEMPLATE_DECL) { @@ -1165,6 +1145,40 @@ decls_match (tree newdecl, tree olddecl) return types_match; } +/* NEWDECL and OLDDECL have identical signatures. If they are + different versions adjust them and return true. */ + +bool +maybe_version_functions (tree newdecl, tree olddecl) +{ + 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); + } + + 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); + + return true; +} + /* If NEWDECL is `static' and an `extern' was seen previously, warn about it. OLDDECL is the previous declaration.