From owner-freebsd-current@FreeBSD.ORG Mon Jun 27 12:29:06 2011 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 79C66106564A for ; Mon, 27 Jun 2011 12:29:06 +0000 (UTC) (envelope-from dim@FreeBSD.org) Received: from tensor.andric.com (tensor.andric.com [87.251.56.140]) by mx1.freebsd.org (Postfix) with ESMTP id 0687F8FC18 for ; Mon, 27 Jun 2011 12:29:05 +0000 (UTC) Received: from [IPv6:2001:7b8:3a7:0:c85c:48ef:432b:843] (unknown [IPv6:2001:7b8:3a7:0:c85c:48ef:432b:843]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by tensor.andric.com (Postfix) with ESMTPSA id 3A4325C59; Mon, 27 Jun 2011 14:29:03 +0200 (CEST) Message-ID: <4E08778D.2050302@FreeBSD.org> Date: Mon, 27 Jun 2011 14:29:01 +0200 From: Dimitry Andric Organization: The FreeBSD Project User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.19pre) Gecko/20110622 Lanikai/3.1.12pre MIME-Version: 1.0 To: Eric McCorkle References: <4E07EBA2.70500@shadowsun.net> In-Reply-To: <4E07EBA2.70500@shadowsun.net> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Cc: freebsd-current@freebsd.org Subject: Re: Clang buildworld failure due to multiple definitions of __isnanf X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 27 Jun 2011 12:29:06 -0000 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) > The file tree.c in usr.bin/xlint/lint1 calls both isnan and finite from > math.h. After some investigation, I figured out what's going on. > math.h includes a macro version of isnan, which expands out to an > expression that calls isnan, __isnanl, and __isnanf. GCC seems to treat > all of these as builtin functions, and implements them with its code > generator, rather than generating calls. Clang, on the other hand, does > not, which leaves calls to __isnanf in the resulting object file, which > will result in multiple definitions at link time. 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. > There are several possible solutions. The workaround I used is to add > -Wl,--allow-multiple-definition to LDADD in the makefile for xlint. Actually, I think the problem is that there are multiple definitions of __isnanf(), one in libc and one in libm. In lib/libc/gen/isnan.c, there is this comment: /* * 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. 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. > A better solution, I think, is to modify math.h with something like this: > > #ifdef __clang__ > #define isnan(n) __builtin_isnan(n) > ... > #endif > > (It might be a good idea to add these kinds of definitions for all of > clang's builtins, actually.) I'm not sure why gcc inserts builtins for isnan() and friends, since if you wanted those, you should probably #define isnan as __builtin_isnan. Otherwise, the implementations in libc and libm would never be used. I hope those are 'better' than the ones builtin to gcc (or clang), but this is not really for me to say, better ask Bruce Evans, David Schultz or Steve Kargl. :)