Bug #20602 cannot compile, because configure is wrong on isinf
Submitted: 21 Jun 2006 12:06 Modified: 3 Jul 2006 8:49
Reporter: Andreas Kirchwitz Email Updates:
Status: Duplicate Impact on me:
None 
Category:MySQL Server Severity:S3 (Non-critical)
Version:MySQL 5.0.22 OS:Solaris (Solaris 10 1/06 SPARC)
Assigned to: CPU Architecture:Any

[21 Jun 2006 12:06] Andreas Kirchwitz
Description:
Dear MySQL Team!

The MySQL 5.0.22 source code cannot be compiled on
Solaris 10 with GCC 4.1.1 because configure gets a wrong
result on "isinf" check.

MySQL 5.0.22 needs the "isinf()" macro/function in strings/strtod.c,
but Solaris 10 1/06 SPARC doesn't have one.

The configure scripts checks for its existence and does this with
the following test programm:

#include <math.h>
int
main ()
{
float f = 0.0; isinf(f)
  ;
  return 0;
}

If you compile this with GCC 4.1.1, it recognizes that "isinf" is in fact
never used and throws it out of the code before any further checks
are done. You see this if you compile with "-Wall" turned on.

Although isinf() doesn't exist, the test program compiles fine, and the
configure gets a wrong result. Finally, this leads to a linker problem
when compiling the MySQL server.

Well, you can argue that GCC 4.1.1 in its default configuration
does "over-optimization" here, but on the other hand, it's well-known
that compilers remove unused code. So, it's always a good idea to
actually use the result of a function you want to check for.

The following test program will give the correct result:

#include <math.h>
int
main ()
{
float f = 0.0; int r = isinf(f)
  ;
  return r;
}

On the other hand, if isinf() is not defined, MySQL defines it itself
like this in include/my_global.h:

#define isinf(X)    0

What is this good for if it never returns success?
But that's a different story ...

Greetings,
Andreas M. Kirchwitz <amk@netzwert.ag>

How to repeat:
Run the conftest program from configure script and watch how
GCC 4.1.1 optimizes it in a way that leads to wrong assumptions.

cat >>conftest.c <<_ACEOF
#include <math.h>
int
main ()
{
float f = 0.0; isinf(f)
  ;
  return 0;
}
_ACEOF

gcc -o conftest -O3 -DDBUG_OFF -DHAVE_RWLOCK_T conftest.c -lpthread -lthread -lposix4 -lcrypt -lgen -lsocket -lnsl -lm -lpthread -lthread

Same result with: gcc -o conftest -Wall conftest.c
(it compiles fine, but it shouldn't, because there is no isinf!)

Suggested fix:
Use this code to test for existence of isinf() macro/function:

#include <math.h>
int
main ()
{
float f = 0.0; int r = isinf(f)
  ;
  return r;
}

You'll see, that it cannot be compiled any longer.
(Which is the correct result of this test.)
[26 Jun 2006 19:28] Sveta Smirnova
Dear Andreas!

We don't use gcc 4.1 yet, so I'll compile gcc 4.1 by self. But may be it is unneeded? Did you compile gcc 4.1 by self or take precompiled version?

Thank you.
[30 Jun 2006 12:11] Andreas Kirchwitz
Yes, I compiled the GCC 4.1.1 myself (using the
GCC 3.4.3 that ships with Solaris 10 in /usr/sfw.)
The "newest" binares on sunfreeware.com are GCC 3.3.2,
but I haven't looked at gcc.gnu.org if they provide
newer precompiled binaries.
[3 Jul 2006 8:49] Sveta Smirnova
Bug #14862 about same problem. So I provided links between this bug and that.

Thank you for the interest in MySQL.
[17 Dec 2006 12:35] Niki W Waibel
this seems to be a real nasty one. look at this:
===
nikiwaibel@sparc-solaris1:~/fbuild $ cat conftest.c 
#include <math.h>
int
main ()
{
  float f = 0.0; int r = isinf(f);
  return r;
}
nikiwaibel@sparc-solaris1:~/fbuild $ ../opt/sparc-sun-solaris2.9/bin/gcc -Wall  conftest.c -o conftest; echo $?
conftest.c: In function 'main':
conftest.c:5: warning: implicit declaration of function 'isinf'
/var/tmp//cccmmM6f.o: In function `main':
conftest.c:(.text+0x24): undefined reference to `isinf'
collect2: ld returned 1 exit status
1
nikiwaibel@sparc-solaris1:~/fbuild $ ../opt/sparc-sun-solaris2.9/bin/gcc -O0 -Wall  conftest.c -o conftest; echo $?
conftest.c: In function 'main':
conftest.c:5: warning: implicit declaration of function 'isinf'
/var/tmp//ccQngHVy.o: In function `main':
conftest.c:(.text+0x24): undefined reference to `isinf'
collect2: ld returned 1 exit status
1
nikiwaibel@sparc-solaris1:~/fbuild $ ../opt/sparc-sun-solaris2.9/bin/gcc -O1 -Wall  conftest.c -o conftest; echo $?
conftest.c: In function 'main':
conftest.c:5: warning: implicit declaration of function 'isinf'
0
nikiwaibel@sparc-solaris1:~/fbuild $ ../opt/sparc-sun-solaris2.9/bin/gcc -O2 -Wall  conftest.c -o conftest; echo $?
conftest.c: In function 'main':
conftest.c:5: warning: implicit declaration of function 'isinf'
0
nikiwaibel@sparc-solaris1:~/fbuild $ ../opt/sparc-sun-solaris2.9/bin/gcc -O3 -Wall  conftest.c -o conftest; echo $?
conftest.c: In function 'main':
conftest.c:5: warning: implicit declaration of function 'isinf'
0
nikiwaibel@sparc-solaris1:~/fbuild $ 
===
using gcc-4.1.1, binutils-2.17.50.0.7 on solaris9.
... trying to compile mysql-5.0.27, which reports (wrongly) during configure that isinf() is available. (optimize level is set to -O2 during configure).

on linux (x86_64 and x86; same compiler and binutils), all is ok -- of course.
[17 Dec 2006 12:58] Niki W Waibel
i'd suggest that you use fpclassify() to do the check (instead of isnan()), because that macro/function is not optimized:
===
nikiwaibel@sparc-solaris1:~/fbuild $ cat conftest.c 
#include <math.h>
int
main ()
{
  float f = 0.0; int r = fpclassify(f);
  return r;
}
nikiwaibel@sparc-solaris1:~/fbuild $ ../opt/sparc-sun-solaris2.9/bin/gcc -std=c99 -O3 -Wall  conftest.c -o conftest -lm; echo $?
conftest.c: In function 'main':
conftest.c:5: warning: implicit declaration of function 'fpclassify'
/var/tmp//ccpqVfqm.o: In function `main':
conftest.c:(.text+0xc): undefined reference to `fpclassify'
collect2: ld returned 1 exit status
1
nikiwaibel@sparc-solaris1:~/fbuild $ ../opt/sparc-sun-solaris2.9/bin/gcc -O0 -Wall  conftest.c -o conftest; echo $?
conftest.c: In function 'main':
conftest.c:5: warning: implicit declaration of function 'fpclassify'
/var/tmp//ccrJeZJd.o: In function `main':
conftest.c:(.text+0x24): undefined reference to `fpclassify'
collect2: ld returned 1 exit status
1
nikiwaibel@sparc-solaris1:~/fbuild $ ../opt/sparc-sun-solaris2.9/bin/gcc -Wall  conftest.c -o conftest; echo $?
conftest.c: In function 'main':
conftest.c:5: warning: implicit declaration of function 'fpclassify'
/var/tmp//ccU1cGzB.o: In function `main':
conftest.c:(.text+0x24): undefined reference to `fpclassify'
collect2: ld returned 1 exit status
1
===
[17 Dec 2006 19:05] Niki W Waibel
i did some research, and it seems the correct way to implement this in solaris is:
===
#include <math.h>

#if __sun__
#include <ieeefp.h>
#define isinf(x) (fpclass(x) == FP_NINF || fpclass(x) == FP_PINF)
#endif

int
main ()
{
  float f = 0.0; int r = isinf(x);
  return r;
}
===

isnan() is available, anyway, it seems...
[17 Dec 2006 19:53] Niki W Waibel
ok --- it seems i am not allowed to upload a file...
anyway, here is the patch i am using for now.
===
diff -u -r mysql-5.0.27.orig/include/my_global.h mysql-5.0.27/include/my_global.h
--- mysql-5.0.27.orig/include/my_global.h       2006-10-21 02:22:53.000000000 +0200
+++ mysql-5.0.27/include/my_global.h    2006-12-17 20:12:01.000000000 +0100
@@ -275,6 +275,12 @@
 #endif
 
 #include <math.h>
+#ifdef HAVE_IEEEFP_H
+#include <ieeefp.h>
+#if __sun__
+#define isinf(x) (fpclass(x) == FP_NINF || fpclass(x) == FP_PINF)
+#endif /* __sun__ */
+#endif /* HAVE_IEEEFP_H */
 #ifdef HAVE_LIMITS_H
 #include <limits.h>
 #endif
===
with it, mysql-5.0.27 compiles fine at least on linux-x86, linux-x86_64 and solaris9-sparc (gnu gcc-4.1.1 and gnu binutils-2.17.50.0.7 on all platforms).