This is the mail archive of the
glibc-bugs@sources.redhat.com
mailing list for the glibc project.
[Bug libc/309] New: fwrite_unlocked bogus warning and results with gcc -O
- From: "eggert at gnu dot org" <sourceware-bugzilla at sources dot redhat dot com>
- To: glibc-bugs at sources dot redhat dot com
- Date: 7 Aug 2004 05:43:02 -0000
- Subject: [Bug libc/309] New: fwrite_unlocked bogus warning and results with gcc -O
- Reply-to: sourceware-bugzilla at sources dot redhat dot com
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.