This is the mail archive of the glibc-bugs@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]
Other format: [Raw text]

[Bug libc/309] New: fwrite_unlocked bogus warning and results with gcc -O


The impetus for this bug report is that I've lately been getting these
annoying warnings for a while, when compiling with gcc -O:

foobar.c:108: warning: signed and unsigned type in conditional expression

Here's the relevant source line:

	fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);

The warning goes away if I don't use -O.  I tracked it down to the
fact that fread_unlocked and fwrite_unlocked don't properly evaluate
their arguments and assume their arguments are of the correct type.
In my case the type was ptrdiff_t rather than size_t.

Here's an amusing sample program illustrating the problem:

   #include <stdio.h>

   int main (void)
   {
     int buf[10];
     double d = fwrite_unlocked (buf, 0, -0.0, stdout);
     if (1 / d < 0)
       fprintf (stderr, "returned %.17g! should have returned zero\n", d);
     buf[0] = 123456;
     fread_unlocked (buf, sizeof *buf, 0.5, stdin);
     if (buf[0] != 123456)
       fprintf (stderr, "modified the buffer; should have left it alone!\n");
     return 0;
   }

Here's what happens when I compile it with "gcc -O" and run it:

  $ echo sdafasdfsadfasdfsadfdsa | ./a.out
  returned -0! should have returned zero
  modified the buffer; should have left it alone!

The output should be empty.

Here's a patch to libio/bits/stdio.h:

2004-08-06  Paul Eggert  <eggert@cs.ucla.edu>

	* libio/bits/stdio.h (fread_unlocked, fwrite_unlocked)
	[defined __USE_MISC && defined __GNUC__ && defined __OPTIMIZE__]:
	Don't assume that arguments are already of the proper type.

--- libio/bits/stdio.h.~1.9.~	2003-05-10 01:25:21 -0700
+++ libio/bits/stdio.h	2004-08-06 22:12:08 -0700
@@ -128,41 +128,45 @@ ferror_unlocked (FILE *__stream) __THROW
 #if defined __USE_MISC && defined __GNUC__ && defined __OPTIMIZE__
 /* Perform some simple optimizations.  */
 # define fread_unlocked(ptr, size, n, stream) \
-  (__extension__ ((__builtin_constant_p (size) && __builtin_constant_p (n)    \
-		   && (size_t) ((size) * (n)) <= 8 && (size) != 0)	      \
-		  ? ({ char *__ptr = (char *) (ptr);			      \
-		       FILE *__stream = (stream);			      \
-		       size_t __cnt;					      \
-		       for (__cnt = (size) * (n); __cnt > 0; --__cnt)	      \
-			 {						      \
-			   int __c = _IO_getc_unlocked (__stream);	      \
-			   if (__c == EOF)				      \
-			     break;					      \
-			   *__ptr++ = __c;				      \
-			 }						      \
-		       ((size_t) ((size) * (n)) - __cnt) / (size); })	      \
-		  : (((__builtin_constant_p (size) && (size) == 0)	      \
-		      || (__builtin_constant_p (n) && (n) == 0))	      \
-			/* Evaluate all parameters once.  */		      \
-		     ? ((void) (ptr), (void) (stream), (void) (size),	      \
-			(void) (n), 0)					      \
-		     : fread_unlocked (ptr, size, n, stream))))
+  (__extension__ ({ void *__ptr = (ptr);				      \
+		    size_t __size = (size);				      \
+		    size_t __n = (n);					      \
+		    FILE *__stream = (stream);				      \
+		    ((__builtin_constant_p (size) && __builtin_constant_p (n) \
+		      && __size * __n <= 8 && __size != 0)		      \
+		     ? ({ size_t __cnt;					      \
+			  char *__cptr = __ptr;				      \
+			  for (__cnt = __size * __n; __cnt > 0; --__cnt)      \
+			    {						      \
+			      int __c = _IO_getc_unlocked (__stream);	      \
+			      if (__c == EOF)				      \
+				break;					      \
+			      *__cptr++ = __c;				      \
+			    }						      \
+			  (__size * __n - __cnt) / __size; })		      \
+		     : ((__builtin_constant_p (size) && __size == 0)	      \
+			|| (__builtin_constant_p (n) && __n == 0))	      \
+		     ? __n						      \
+		     : fread_unlocked (__ptr, __size, __n, __stream)); }))
 
 # define fwrite_unlocked(ptr, size, n, stream) \
-  (__extension__ ((__builtin_constant_p (size) && __builtin_constant_p (n)    \
-		   && (size_t) ((size) * (n)) <= 8 && (size) != 0)	      \
-		  ? ({ const char *__ptr = (const char *) (ptr);	      \
-		       FILE *__stream = (stream);			      \
-		       size_t __cnt;					      \
-		       for (__cnt = (size) * (n); __cnt > 0; --__cnt)	      \
-			 if (_IO_putc_unlocked (*__ptr++, __stream) == EOF)   \
-			   break;					      \
-		       ((size_t) ((size) * (n)) - __cnt) / (size); })	      \
-		  : (((__builtin_constant_p (size) && (size) == 0)	      \
-		      || (__builtin_constant_p (n) && (n) == 0))	      \
-			/* Evaluate all parameters once.  */		      \
-		     ? ((void) (ptr), (void) (stream), (void) (size), n)      \
-		     : fwrite_unlocked (ptr, size, n, stream))))
+  (__extension__ ({ const void *__ptr = (ptr);				      \
+		    size_t __size = (size);				      \
+		    size_t __n = (n);					      \
+		    FILE *__stream = (stream);				      \
+		    ((__builtin_constant_p (size) && __builtin_constant_p (n) \
+		      && __size * __n <= 8 && __size != 0)		      \
+		     ? ({ size_t __cnt;					      \
+			  const char *__cptr = __ptr;			      \
+			  for (__cnt = __size * __n; __cnt > 0; --__cnt)      \
+			    if (_IO_putc_unlocked (*__cptr++, __stream)	      \
+			        == EOF)					      \
+			      break;					      \
+			  (__size * __n - __cnt) / __size; })		      \
+		     : ((__builtin_constant_p (size) && __size == 0)	      \
+			|| (__builtin_constant_p (n) && __n == 0))	      \
+		     ? __n						      \
+		     : fwrite_unlocked (__ptr, __size, __n, __stream)); }))
 #endif
 
 /* Define helper macro.  */

-- 
           Summary: fwrite_unlocked bogus warning and results with gcc -O
           Product: glibc
           Version: 2.3.3
            Status: NEW
          Severity: normal
          Priority: P2
         Component: libc
        AssignedTo: gotom at debian dot or dot jp
        ReportedBy: eggert at gnu dot org
                CC: glibc-bugs at sources dot redhat dot com
 GCC build triplet: i686-pc-linux-gnu
  GCC host triplet: i686-pc-linux-gnu
GCC target triplet: i686-pc-linux-gnu


http://sources.redhat.com/bugzilla/show_bug.cgi?id=309

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


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