| Index: cp/call.c |
| =================================================================== |
| --- cp/call.c (revision 184569) |
| +++ cp/call.c (working copy) |
| @@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see |
| #include "c-family/c-objc.h" |
| #include "timevar.h" |
| #include "tree-threadsafe-analyze.h" |
| +#include "multiversion.h" |
| /* The various kinds of conversion. */ |
| @@ -6752,9 +6753,21 @@ build_over_call (struct z_candidate *cand, int fla |
| return fold_convert (void_type_node, argarray[0]); |
| /* FIXME handle trivial default constructor, too. */ |
| + /* For a call to a multi-versioned function, the call should actually be to |
| + the dispatcher. */ |
| + if (DECL_FUNCTION_VERSIONED (fn)) |
| + { |
| + tree ifunc_decl; |
| + ifunc_decl = get_ifunc_for_version (fn); |
| + gcc_assert (ifunc_decl != NULL); |
| + return build_call_expr_loc_array (UNKNOWN_LOCATION, ifunc_decl, |
| + nargs, argarray); |
| + } |
| + |
| if (!already_used) |
| mark_used (fn); |
| + /* XXX: Handle dispatching of virtual multiversioned functions. */ |
| if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0) |
| { |
| tree t; |
| @@ -8064,6 +8077,24 @@ joust (struct z_candidate *cand1, struct z_candida |
| size_t i; |
| size_t len; |
| + /* For Candidates of a multi-versioned function, the one marked default |
| + wins. This is because the default decl is used as key to aggregate |
| + all the other versions provided for it in multiversion.c. When |
| + generating the actual call, the appropriate dispatcher is created |
| + to call the right function version at run-time. */ |
| + |
| + if ((TREE_CODE (cand1->fn) == FUNCTION_DECL |
| + && DECL_FUNCTION_VERSIONED (cand1->fn)) |
| + ||(TREE_CODE (cand2->fn) == FUNCTION_DECL |
| + && DECL_FUNCTION_VERSIONED (cand2->fn))) |
| + { |
| + if (is_default_function (cand1->fn)) |
| + return 1; |
| + if (is_default_function (cand2->fn)) |
| + return -1; |
| + return 0; |
| + } |
| + |
| /* Candidates that involve bad conversions are always worse than those |
| that don't. */ |
| if (cand1->viable > cand2->viable) |