Hi all, Hereby I am forwarding a bug I filed against Debian [1]. One of my packages there failed to build on hurd-i386 and kfreebsd-* due to unsupported ifuncs. However, I had that code guarded by __has_attribute(ifunc) which, unfortunately, evaluates to 1 on said platforms. A minimal testcase is given below. Best, Fabian 1: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=945133 ----- #include <stdio.h> int main() { return 0; } #if __has_attribute(ifunc) typedef void (fntype)(void); fntype* fn_select(void) { return NULL; } void fn(void) __attribute__((ifunc("fn_select"))); #endif
__has_attribute(ifunc) is true as the attribute is supported all the way through the compiler up to the point where it gets emitted. Really __has_attribute is a bad execuse for not doing proper feature testing in my mine.
I think the docs are clear here too: The special operator __has_attribute (operand) may be used in ‘#if’ and ‘#elif’ expressions to test whether the attribute referenced by its operand is recognized by GCC. ---- CUT --- __has_attribute just says GCC recognizes the attribute which is true, ifunc is recognized and is basically supported inside gcc until the very end of the compiler. So I want to say this is an invalid bug report ...
Hm, I feared that this would be the answer I would get. This makes GCCs __has_attribute much less useful than Clangs version where the docs state: “This function-like macro takes a single identifier argument that is the name of a GNU-style attribute. It evaluates to 1 if the attribute is supported by the current compilation target, or 0 if not.”
What does the build failure look like? Quoting from What we need in https://gcc.gnu.org/bugs: Please include all of the following items, the first three of which can be obtained from the output of gcc -v: ... the compiler output (error messages, warnings, etc.); and
Sorry for missing out the details, here goes: I work in a Debian Hurd 20290705 image using qemu. The example file is given above. Compiling with `gcc -Wall -Wextra ifunc.c` produces the following error. error: ifunc is not supported on this target int fn(void) __attribute((ifunc("fn_select"))); The output of gcc -v is (may contain typos) COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-gnu/8/lto-wrapper Target: i686-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 8.3.0-7' --with-bugurl=file:///usr/share/doc/gcc-8/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-8 --program-prefix=i686-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-include-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --disable-libitm --disable-libsanitizer --enable-plugin --enable-default-pie --with-system-zlib --disable-libphobos --enable-multiarch --disable-werror --with-arch=i586 --with-tune=generic --enable-checking=release --build=i686-gnu --host-i686-gnu --target=i686-gnu Thread model: posix gcc version 8.3.0 (Debian 8.3.0-7) So it is not 9.0 as I first thought. Hope this helps.
If the error is issued by GCC then that would make it a bug in the implementation of __has_attribute. Let me look into it.
I can reproduce the error with an rs6000-aix7.1 cross: $ cat pr93419.c && /build/rs6000-aix7.1/gcc-trunk/gcc/xgcc -B /build/rs6000-aix7.1/gcc-trunk/gcc pr93419.c #if __has_attribute (ifunc) typedef void (fntype)(void); fntype* fn_select (void) { return 0; } void fn(void) __attribute__((ifunc ("fn_select"))); #endif pr93419.c:5:6: error: 'ifunc' is not supported on this target 5 | void fn(void) __attribute__((ifunc ("fn_select"))); | ^~ It is issued in varasm.c under one of two conditions: if (TREE_CODE (decl) == FUNCTION_DECL && cgraph_node::get (decl)->ifunc_resolver) { #if defined (ASM_OUTPUT_TYPE_DIRECTIVE) if (targetm.has_ifunc_p ()) ASM_OUTPUT_TYPE_DIRECTIVE (asm_out_file, IDENTIFIER_POINTER (id), IFUNC_ASM_TYPE); else #endif error_at (DECL_SOURCE_LOCATION (decl), "%qs is not supported on this target", "ifunc"); } Neither of these seems to be considered by the operator (in fact, it looks like the only thing the handler does consider is the whether the attribute is defined for the target), so confirmed as a bug. It seems that the conditions in varasm.c (and anywhere else in the compiler) that determine whether or not an attribute is supported should be abstracted into an API and tested by the builtin handler during preprocessing as well as by later stages.
I'm not working on this anymore.