This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[mitr@volny.cz] libc/2245: <tgmath.h> wrong for fn (float, int)



Hi glibc developers,

I agree with Miloslav's analysis.  Could somebody please double check
that the fix is correct?  I'd also appreciate a test for the
testsuite.

Thanks,
Andreas



>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






-- 
 Andreas Jaeger
  SuSE Labs aj@suse.de
   private aj@arthur.inka.de
    http://www.suse.de/~aj

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]