Bug 93419 - __has_attribute(ifunc) false positive on hurd and kfreebsd
Summary: __has_attribute(ifunc) false positive on hurd and kfreebsd
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: preprocessor (show other bugs)
Version: 8.3.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2020-01-24 15:41 UTC by kloetzl
Modified: 2022-01-26 17:22 UTC (History)
1 user (show)

See Also:
Host:
Target: *-aix7.1 hurd freebsd
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-01-25 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description kloetzl 2020-01-24 15:41:50 UTC
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
Comment 1 Andrew Pinski 2020-01-24 15:52:19 UTC
__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.
Comment 2 Andrew Pinski 2020-01-24 16:00:24 UTC
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 ...
Comment 3 kloetzl 2020-01-24 16:07:18 UTC
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.”
Comment 4 Martin Sebor 2020-01-24 16:25:39 UTC
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
Comment 5 kloetzl 2020-01-24 19:50:45 UTC
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.
Comment 6 Martin Sebor 2020-01-25 07:55:21 UTC
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.
Comment 7 Martin Sebor 2020-01-28 22:59:04 UTC
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.
Comment 8 Martin Sebor 2022-01-26 17:22:32 UTC
I'm not working on this anymore.