Currently target_clones attribute results in a linker error when there are no multi-versioned function declarations in the calling TU.
foo.cpp int foo1(); __attribute__((target_clones("default", "arch=core2"))) int foo1() { return 0; } main.cpp int foo1(); int main() { return foo1(); } $ clang++ main.cpp foo.cpp /usr/bin/ld: /tmp/main-981c32.o: in function `main': main.cpp:(.text+0x10): undefined reference to `foo1()' clang++: error: linker command failed with exit code 1 (use -v to see invocation)
In the calling TU, the call is generated with ‘normal’ assembly name. This does not match any of the versions since their mangling includes a .versionstring. The linker error is not seen with GCC since the mangling for the ifunc symbol in GCC is the ‘normal’ assembly name for function.
Clang – $nm foo.o U __cpu_indicator_init U __cpu_model T _Z4foo1v.arch_core2.0 T _Z4foo1v.default.1 i _Z4foo1v.ifunc <---------- W _Z4foo1v.resolver $ nm main.o T main U _Z4foo1v GCC $ nm foo.o U __cpu_indicator_init U __cpu_model i _Z4foo1v <--------------- t _Z4foo1v.arch_core2.0 t _Z4foo1v.default.1 W _Z4foo1v.resolver $ nm main.o T main U _Z4foo1v
I was initially inclined to match GCC behavior here and remove the ifunc suffix but I decided against it because I am not sure why ifunc mangling was used in the first place. Maybe to maintain consistency between various multiversion attributes? I see target attribute also uses ifunc mangling (while GCC has some other mangling scheme for this attribute). As a less disruptive solution I just added an alias to the ifunc function, similar to what was done for CPU dispatch here - https://reviews.llvm.org/D67058. If the correct solution here is to remove the ifunc suffix, I can make that change instead.