Clang buildworld failure due to multiple definitions of __isnanf

Eric McCorkle eric at
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.


.if !defined(CC) || ${CC} == "cc"
.if !defined(CXX) || ${CXX} == "c++"

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