Clang buildworld failure due to multiple definitions of __isnanf
Eric McCorkle
eric at shadowsun.net
Mon Jun 27 15:59:25 UTC 2011
On 6/27/11 8:29 AM, Dimitry Andric wrote:
> On 2011-06-27 04:32, Eric McCorkle wrote:
>> I've both seen reports and experienced make buildworld with clang
>> failing in usr.bin/xlint/lint1 (really, make kernel-toolchain is what
>> fails), because lint1 is statically linked, and there is a definition of
>> __isnanf in both libc and libm. GCC, on the other hand, builds just fine.
> ...
>
> I have never seen this failure, and neither does the clang buildbot, so
> maybe there is something in your build environment causing this problem?
> Can you please post:
>
> - Your build architecture (e.g. i386 or amd64)
> - Your /etc/make.conf and /etc/src.conf, if applicable
> - Any build-related environment variables (WITH_FOO, WITHOUT_FOO,
> CFLAGS, etc)
>
Sorry. It's an amd64 system, 9-CURRENT, last updated on friday.
src.conf:
LOADER_ZFS_SUPPORT="YES"
make.conf:
CPUTYPE?=core2
.if !defined(CC) || ${CC} == "cc"
CC=clang
CFLAGS=-Qunused-arguments
.endif
.if !defined(CXX) || ${CXX} == "c++"
CXX=clang++
.endif
NO_WERROR=
WERROR=
NO_FSCHG=
PERL_VERSION=5.12.3
Just noticed, the CFLAGS would disable optimization, which would explain
why no one else seems to see this. Still, I think the underlying issue
warrants investigation.
> I don't see this at all here. Clang simply expands the macro:
>
> #define isnan(x) \
> ((sizeof (x) == sizeof (float)) ? __isnanf(x) \
> : (sizeof (x) == sizeof (double)) ? isnan(x) \
> : __isnanl(x))
>
> then sees x is a double, so eliminates the unneeded parts of the ?:
> operators, and simply calls the isnan() function. There is no trace of
> __isnanf() anywhere in the resulting .s or .o file.
>
> Maybe you compiled with non-default optimization flags? If so, please
> supply them.
Hmm. I somehow got clang to generate calls to isnan, __isnanf, and
__isnanl, (ie expanding the macro but not simplifying it) last night,
but I can't seem to reproduce it now...
However, compiling:
#include <math.h>
double d;
int main() { return isnan(d); }
with gcc -S -O0 produces a .s file with no calls to isnan, so it's
definitely replacing calls to isnan.
> /*
> * XXX These routines belong in libm, but they must remain in libc for
> * binary compat until we can bump libm's major version number.
> */
>
> after which both __isnan() and __isnanf() are defined, and weakly bound
> to isnan() and isnanf(). Then, in lib/msun/src/s_isnan.c, the isnan()
> definition is commented out, but not the __isnanf() definition.
>
> I think this never caused a problem with gcc, since, as you said, it
> usually expands it using builtins.
I saw that. Perhaps removing the duplicate __isnanf could be rolled
into 9-RELEASE?
>
> Weirdly enough, a small test program that directly calls __isnanf(), and
> is linked with -lm doesn't cause any problems here, neither with gcc,
> nor with clang.
>
You need to call __isnanf and something that's in libm, otherwise the
linker appears to stop at libc and doesn't link with libm at all. Try this:
double d;
int main() { return __isnanf(d) && __isnanl(d); }
More information about the freebsd-current
mailing list