mesonbuild / meson

The Meson Build System
http://mesonbuild.com
Apache License 2.0
5.59k stars 1.63k forks source link

ifunc attribute not detected on clang++ #12413

Open bmerry opened 1 year ago

bmerry commented 1 year ago

Describe the bug compiler.has_function_attribute('ifunc') is returning false on clang++ (e.g. with clang 14).

To Reproduce

project('foo', ['c', 'cpp'])
c_compiler = meson.get_compiler('c')
cpp_compiler = meson.get_compiler('cpp')
c_compiler.has_function_attribute('ifunc')
cpp_compiler.has_function_attribute('ifunc')

Output:

The Meson build system
Version: 1.2.99
Source dir: /home/bmerry/tmp/ifunc-clang
Build dir: /home/bmerry/tmp/ifunc-clang/build
Build type: native build
Project name: foo
Project version: undefined
C compiler for the host machine: clang (clang 14.0.0-1ubuntu1 "Ubuntu clang version 14.0.0-1ubuntu1.1")
C linker for the host machine: clang ld.bfd 2.38
C++ compiler for the host machine: clang++ (clang 14.0.0-1ubuntu1 "Ubuntu clang version 14.0.0-1ubuntu1.1")
C++ linker for the host machine: clang++ ld.bfd 2.38
Host machine cpu family: x86_64
Host machine cpu: x86_64
Compiler for C supports function attribute ifunc: YES 
Compiler for C++ supports function attribute ifunc: NO 
Build targets in project: 0

Relevant part of log:

Working directory:  /home/bmerry/tmp/ifunc-clang/build/meson-private/tmptv1i4cbr
Code:
 extern "C" {int my_foo(void) { return 0; }static int (*resolve_foo(void))(void) { return my_foo; }}int foo(void) __attribute__((ifunc("resolve_foo")));
-----------
Command line: `clang++ /home/bmerry/tmp/ifunc-clang/build/meson-private/tmptv1i4cbr/testfile.cpp -o /home/bmerry/tmp/ifunc-clang/build/meson-private/tmptv1i4cbr/output.obj -c -D_FILE_OFFSET_BITS=64 -O0 -fpermissive -Werror=implicit-function-declaration -Werror=unknown-warning-option -Werror=unused-command-line-argument -Werror=ignored-optimization-argument -Werror=attributes` -> 1
stderr:
/home/bmerry/tmp/ifunc-clang/build/meson-private/tmptv1i4cbr/testfile.cpp:1:129: error: ifunc must point to a defined function
extern "C" {int my_foo(void) { return 0; }static int (*resolve_foo(void))(void) { return my_foo; }}int foo(void) __attribute__((ifunc("resolve_foo")));
                                                                                                                                ^
1 error generated.

It appears that clang++ doesn't like the resolver being declared static, even though clang (C compiler) is happy with it.

I will submit a PR to fix this.

Expected behavior The ifunc attribute should be detected as supported.

system parameters

bmerry commented 1 year ago

For interest more than anything else: clang++ not detecting the resolver when it is static appears to be a bug: https://github.com/llvm/llvm-project/issues/54549

eli-schwartz commented 1 year ago

So if I understand correctly this is specifically a workaround for old versions of clang?

bmerry commented 1 year ago

So if I understand correctly this is specifically a workaround for old versions of clang?

Based on testing with Compiler Explorer, it looks like it's still needed even for clang 17.0.1: https://gcc.godbolt.org/z/Eefn85d9b. Presumably a future release of clang will remove the need for this workaround.

bmerry commented 6 months ago

So if I understand correctly this is specifically a workaround for old versions of clang?

Based on testing with Compiler Explorer, it looks like it's still needed even for clang 17.0.1: https://gcc.godbolt.org/z/Eefn85d9b. Presumably a future release of clang will remove the need for this workaround.

I've just had another look at this. It turns out the clang bug was fixed in clang 15 BUT if the resolver is static it has to be marked with __attribute__((used)) so that it doesn't get eliminated as unused before linking. So the code in meson doesn't work even for new versions of clang.