bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Unexpected frexpf implementation used by MSVC9 in C++ mode


From: Michael Goffioul
Subject: Re: Unexpected frexpf implementation used by MSVC9 in C++ mode
Date: Fri, 16 Mar 2012 09:55:01 +0000

On Sun, Mar 11, 2012 at 11:50 PM, Michael Goffioul
<address@hidden> wrote:
> On Sun, Mar 11, 2012 at 10:52 PM, Bruno Haible <address@hidden> wrote:
>> Michael Goffioul wrote:
>>> frexpf is actually defined as a macro in C,
>>> and as an inline function in C++.
>>
>> Normally gnulib avoids collisions with system functions by checking whether
>> a system function exists, via AC_CHECK_FUNCS. But AC_CHECK_FUNCS looks
>> only in the libraries and misses the inline functions...
>>
>> Would it help to set REPLACE_FREXPF to 1? To test this, simply change your
>> copy of math.in.h, replacing
>>
>>   # if @REPLACE_FREXPF@
>>
>> with a)
>>
>>   # if @REPLACE_FREXPF@ || defined _MSC_VER
>>
>> or b)
>>
>>   # if @REPLACE_FREXPF@ || (defined _MSC_VER && defined __cplusplus)
>>
>> Does one or the other produce better results?
>
> Only a) provides good results, whatever the client code (C or C++).
> The version b) does not work as you will use frexpf or rpl_frexpf,
> depending on whether you are in C or C++. So you get problems when
> mixing both. In my case, gnulib is C, while the client (octave) is
> C++: frexpf.c provides frexpf symbol, while C++ expects rpl_frexpf.
>
> I tested on my little sample and it worked fine. Now I suspect frexpf
> is not the only occurrence of the issue. AFAIK it can happen with any
> xxxf function where gnulib also provide a xxx replacement (most of the
> math xxxf functions are inlined in MSVC math.h).

I've done some more investigation, and the way MSVC math.h is built
poses various problem. The main issue is that it behaves differently
in C and C++. And that leads to multiple symbol error at link stage
when using gnulib from C++.

Take the example of ldexpf, it's defined as a macro in C, and as an
inline in C++. During the configure step, ldexpf.c module is pulled
in, because ldexpf only exists as a macro (configure tests are run in
C mode). This means that in C++ the expanded gnulib math.h will look
like:

// Original VC++ math.h
inline float ldexpf (float x, int exp) { return (float) ldexp (x, exp); }
...
// gnulib math.h
extern float ldexpf (float x, int exp);
namespace gnulib { static float (*ldexpf) (float x, int exp) = ::ldexpf; }

When using that header in C++, the compiler will insert the code of
inlined ldexpf in the object file. At link stage, there will be a
multiple symbol error, because the inlined ldexpf conflicts with the
version provided by ldexpf.c module. The solution suggested previously
for frexpf does not apply in this case, as there's no ldexpf
replacement (like rpl_ldexpf).

At the moment, the only workaround I've found is to do something
conceptually like the following:

#ifdef __cplusplus
// Prevent inlined version of ldexpf
# define ldexpf __dummy_ldexpf
#endif

#include_next <math.h>

#ifdef __cplusplus
// Undo previous definition
# undef ldexpf
#endif

extern float ldexpf (float x, int exp);
namespace gnulib { static float (*ldexpf) (float x, int exp) = ::ldexpf; }

I don't expect such hack to go into gnulib. I'm simply describing the
issue for reference.

Michael.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]