- To: libc-gnats at gnu dot org, gnats-admin at gnu dot org
- Subject: libc/2245: <tgmath.h> wrong for fn (float, int)
- From: mitr at volny dot cz
- Date: Tue, 08 May 2001 16:15:02 -0400
- Reply-To: mitr at volny dot cz
- Xref: gee.suse.de mail.gnats-libc-bugs:5969
>Number: 2245
>Category: libc
>Synopsis: <tgmath.h> wrong for fn (float, int)
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: libc-gnats
>State: open
>Quarter:
>Keywords:
>Class: sw-bug
>Submitter-Id: unknown
>Arrival-Date: Tue May 08 16:15:01 -0400 2001
>Cases:
>Originator: Miloslav Trmac
>Release: libc-2.2.3
>Organization:
None
>Environment:
Host type: i386-redhat-linux-gnu
System: Linux linux.localdomain 2.4.2-2 #1 Sun Apr 8 19:37:14 EDT 2001 i586 unknown
Architecture: i586
Addons: c_stubs glibc-compat linuxthreads
Build CFLAGS: -march=i386 -D__USE_STRING_INLINES -fstrict-aliasing -freorder-blocks -DNDEBUG=1 -g -O3
Build CC: gcc
Compiler version: 2.96 20000731 (Red Hat Linux 7.1 2.96-79)
Kernel headers: 2.4.2-2
Symbol versioning: yes
Build static: yes
Build shared: yes
Build pic-default: no
Build profile: yes
Build omitfp: no
Build bounded: no
Build static-nss: no
Stdio: libio
>Description:
Hi,
the <tgmath.h> macros call the foo##f () [the float one] function when
invoked as foo (float, int). According to the standards I have access to
(C9X draft and SUSv3 draft) foo () [the double one] should be called.
>How-To-Repeat:
-------------------------
#include <tgmath.h>
int i;
float f;
void
fn (void)
{
atan2 (i, f);
remquo (i, f, &i);
fma (i, f, i);
pow (i, f);
}
--------------
Compile with -S: the float functions are called instead of double ones.
>Fix:
The following patch fixes the above testcase. It should be correct, but don't
take my word for it :-). The patch also seems to increase the compile-time
resource consumption quite a bit, so I couldn't compile test-tgmath.c with
the patched version on my 24M machine.
[The glibcbug script is from my system libc, while the patch is against 2.2.3.
Sorry for any inconvenience.]
Thanks for all the good work on glibc.
Mirek
BTW, please forward my sincere admiration to the original author of
__tgmath_real_type. I spent an hour just understanding how it works.
-------------------------------------------------------------------------------
--- glibc-2.2.3/math/tgmath.h Fri Feb 9 19:04:15 2001
+++ tgmath.h Tue May 8 21:52:18 2001
@@ -59,6 +59,14 @@
# define __tgmath_real_type(expr) \
__tgmath_real_type_sub(__typeof__(expr), __floating_type(__typeof__(expr)))
+/* The tgmath real type of EXPR1, EXPR2 */
+# define __tgmath_real_type_2(expr1, expr2) \
+ __typeof__ ((__tgmath_real_type (expr1))0 + (__tgmath_real_type (expr2))0)
+
+/* The tgmath real type of EXPR1, EXPR2, EXPR3 */
+# define __tgmath_real_type_3(expr1, expr2, expr3) \
+ __typeof__ ((__tgmath_real_type (expr1))0 + (__tgmath_real_type (expr2))0 \
+ + (__tgmath_real_type (expr3))0)
/* We have two kinds of generic macros: to support functions which are
only defined on real valued parameters and those which are defined
@@ -85,53 +93,55 @@
__tgmres = __tgml(Fct) (Val1, Val2); \
__tgmres; }))
+# define __TGMATH_BINARY_REAL_ONLY_SUB(Val1, Val2, Fct, Type) \
+ (__extension__ ({ Type __tgmres; \
+ if (sizeof (Type) > sizeof (double) \
+ && __builtin_classify_type ((Type)0) == 8) \
+ __tgmres = __tgml(Fct) (Val1, Val2); \
+ else if (sizeof (Type) == sizeof (double) \
+ || __builtin_classify_type ((Type)0) != 8) \
+ __tgmres = Fct (Val1, Val2); \
+ else \
+ __tgmres = Fct##f (Val1, Val2); \
+ __tgmres; }))
+
# define __TGMATH_BINARY_REAL_ONLY(Val1, Val2, Fct) \
- (__extension__ ({ __tgmath_real_type ((Val1) + (Val2)) __tgmres; \
- if ((sizeof (Val1) > sizeof (double) \
- || sizeof (Val2) > sizeof (double)) \
- && __builtin_classify_type ((Val1) + (Val2)) == 8) \
- __tgmres = __tgml(Fct) (Val1, Val2); \
- else if (sizeof (Val1) == sizeof (double) \
- || sizeof (Val2) == sizeof (double) \
- || __builtin_classify_type ((Val1) \
- + (Val2)) != 8) \
- __tgmres = Fct (Val1, Val2); \
- else \
- __tgmres = Fct##f (Val1, Val2); \
+ __TGMATH_BINARY_REAL_ONLY_SUB (Val1, Val2, Fct, \
+ __tgmath_real_type_2 (Val1, Val2))
+
+# define __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY_SUB(Val1, Val2, Val3, Fct, \
+ Type) \
+ (__extension__ ({ Type __tgmres; \
+ if (sizeof (Type) > sizeof (double) \
+ && __builtin_classify_type ((Type)0) == 8) \
+ __tgmres = __tgml(Fct) (Val1, Val2, Val3); \
+ else if (sizeof (Type) == sizeof (double) \
+ || __builtin_classify_type ((Type)0) != 8) \
+ __tgmres = Fct (Val1, Val2, Val3); \
+ else \
+ __tgmres = Fct##f (Val1, Val2, Val3); \
__tgmres; }))
# define __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY(Val1, Val2, Val3, Fct) \
- (__extension__ ({ __tgmath_real_type ((Val1) + (Val2)) __tgmres; \
- if ((sizeof (Val1) > sizeof (double) \
- || sizeof (Val2) > sizeof (double)) \
- && __builtin_classify_type ((Val1) + (Val2)) == 8) \
- __tgmres = __tgml(Fct) (Val1, Val2, Val3); \
- else if (sizeof (Val1) == sizeof (double) \
- || sizeof (Val2) == sizeof (double) \
- || __builtin_classify_type ((Val1) \
- + (Val2)) != 8) \
- __tgmres = Fct (Val1, Val2, Val3); \
- else \
- __tgmres = Fct##f (Val1, Val2, Val3); \
+ __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY_SUB (Val1, Val2, Val3, Fct, \
+ __tgmath_real_type_2 (Val1, \
+ Val2))
+
+# define __TGMATH_TERNARY_REAL_ONLY_SUB(Val1, Val2, Val3, Fct, Type) \
+ (__extension__ ({ Type __tgmres; \
+ if (sizeof (Type) > sizeof (double) \
+ && __builtin_classify_type ((Type)0) == 8) \
+ __tgmres = __tgml(Fct) (Val1, Val2, Val3); \
+ else if (sizeof (Type) == sizeof (double) \
+ || __builtin_classify_type ((Type)0) != 8) \
+ __tgmres = Fct (Val1, Val2, Val3); \
+ else \
+ __tgmres = Fct##f (Val1, Val2, Val3); \
__tgmres; }))
# define __TGMATH_TERNARY_REAL_ONLY(Val1, Val2, Val3, Fct) \
- (__extension__ ({ __tgmath_real_type ((Val1) + (Val2) + (Val3)) __tgmres;\
- if ((sizeof (Val1) > sizeof (double) \
- || sizeof (Val2) > sizeof (double) \
- || sizeof (Val3) > sizeof (double)) \
- && __builtin_classify_type ((Val1) + (Val2) \
- + (Val3)) == 8) \
- __tgmres = __tgml(Fct) (Val1, Val2, Val3); \
- else if (sizeof (Val1) == sizeof (double) \
- || sizeof (Val2) == sizeof (double) \
- || sizeof (Val3) == sizeof (double) \
- || __builtin_classify_type ((Val1) + (Val2) \
- + (Val3)) != 8) \
- __tgmres = Fct (Val1, Val2, Val3); \
- else \
- __tgmres = Fct##f (Val1, Val2, Val3); \
- __tgmres; }))
+ __TGMATH_TERNARY_REAL_ONLY_SUB (Val1, Val2, Val3, Fct, \
+ __tgmath_real_type_3 (Val1, Val2, Val3))
/* XXX This definition has to be changed as soon as the compiler understands
the imaginary keyword. */
@@ -178,41 +188,39 @@
/* XXX This definition has to be changed as soon as the compiler understands
the imaginary keyword. */
-# define __TGMATH_BINARY_REAL_IMAG(Val1, Val2, Fct, Cfct) \
- (__extension__ ({ __tgmath_real_type ((Val1) + (Val2)) __tgmres; \
- if ((sizeof (__real__ (Val1)) > sizeof (double) \
- || sizeof (__real__ (Val2)) > sizeof (double)) \
- && __builtin_classify_type (__real__ (Val1) \
- + __real__ (Val2)) \
- == 8) \
- { \
- if (sizeof (__real__ (Val1)) == sizeof (Val1) \
- && sizeof (__real__ (Val2)) == sizeof (Val2)) \
- __tgmres = __tgml(Fct) (Val1, Val2); \
- else \
- __tgmres = __tgml(Cfct) (Val1, Val2); \
- } \
- else if (sizeof (__real__ (Val1)) == sizeof (double) \
- || sizeof (__real__ (Val2)) == sizeof(double) \
- || __builtin_classify_type (__real__ (Val1) \
- + __real__ (Val2))\
- != 8) \
- { \
- if (sizeof (__real__ (Val1)) == sizeof (Val1) \
- && sizeof (__real__ (Val2)) == sizeof (Val2)) \
- __tgmres = Fct (Val1, Val2); \
- else \
- __tgmres = Cfct (Val1, Val2); \
- } \
- else \
- { \
- if (sizeof (__real__ (Val1)) == sizeof (Val1) \
- && sizeof (__real__ (Val2)) == sizeof (Val2)) \
- __tgmres = Fct##f (Val1, Val2); \
- else \
- __tgmres = Cfct##f (Val1, Val2); \
- } \
+# define __TGMATH_BINARY_REAL_IMAG_SUB(Val1, Val2, Fct, Cfct, Type, RType) \
+ (__extension__ ({ Type __tgmres; \
+ if (sizeof (RType) > sizeof (double) \
+ && __builtin_classify_type ((RType)0) == 8) \
+ { \
+ if (sizeof (RType) == sizeof (Type)) \
+ __tgmres = __tgml(Fct) (Val1, Val2); \
+ else \
+ __tgmres = __tgml(Cfct) (Val1, Val2); \
+ } \
+ else if (sizeof (RType) == sizeof (double) \
+ || __builtin_classify_type ((RType)0) != 8) \
+ { \
+ if (sizeof (RType) == sizeof (Type)) \
+ __tgmres = Fct (Val1, Val2); \
+ else \
+ __tgmres = Cfct (Val1, Val2); \
+ } \
+ else \
+ { \
+ if (sizeof (RType) == sizeof (Type)) \
+ __tgmres = Fct##f (Val1, Val2); \
+ else \
+ __tgmres = Cfct##f (Val1, Val2); \
+ } \
__tgmres; }))
+
+# define __TGMATH_BINARY_REAL_IMAG(Val1, Val2, Fct, Cfct) \
+ __TGMATH_BINARY_REAL_IMAG_SUB (Val1, Val2, Fct, Cfct, \
+ __tgmath_real_type_2 (Val1, Val2), \
+ __tgmath_real_type_2 (__real__ (Val1), \
+ __real__ (Val2)))
+
#else
# error "Unsupported compiler; you cannot use <tgmath.h>"
#endif