Re: Clang buildworld failure due to multiple definitions of __isnanf

From: Eric McCorkle <eric_at_shadowsun.net>
Date: Mon, 27 Jun 2011 11:59:23 -0400
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); }
Received on Mon Jun 27 2011 - 13:59:25 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:15 UTC