Summary: | problems with -Wformat and bit-fields | ||
---|---|---|---|
Product: | gcc | Reporter: | Jim Wilson <wilson> |
Component: | c | Assignee: | Joseph S. Myers <jsm28> |
Status: | RESOLVED FIXED | ||
Severity: | minor | CC: | gcc-bugs, pawel_sikora |
Priority: | P2 | Keywords: | diagnostic |
Version: | 4.0.1 | ||
Target Milestone: | 4.0.2 | ||
Host: | ia64-linux | Target: | |
Build: | Known to work: | ||
Known to fail: | Last reconfirmed: | 2005-07-15 22:05:00 | |
Attachments: | 31/32/33 bit-fields vs %u/%lu/%ld/%d printf formats |
Description
Jim Wilson
2005-07-12 01:49:14 UTC
Created attachment 9247 [details]
31/32/33 bit-fields vs %u/%lu/%ld/%d printf formats
Compile on an LP64 machine (e.g. ia64-linux, x86_64-linux, etc) with -Wformat,
and look at the warnings. gcc-3.3.x generates 12 warnings. gcc-4.0 and up
generate 18 warnings, 6 of which appear to be wrong.
Subject: Re: New: problems with -Wformat and bit-fields On Tue, 12 Jul 2005, wilson at gcc dot gnu dot org wrote: > This problem showed up compiling the IA-64 linux kernel with gcc-4.0.1. There > was an unexpected printf format warnings for a 32-bit bit-field. The same > problem can be reproduced on any LP64 machine, such as x86_64-linux. The format issues are bug 21962, but this bug is more detailed. > 1) What printf formats should be allowed to match for a bit-field? Or do we > want to force use of a cast? I think the gcc-3.3.x behaviour is correct and > desirable. If the bit-field has rank above that of int, then we must require a cast. > 2) The type checking code in check_format_types needs to be extended to handle > bit-field types properly. I don't think any format checking code should need changing for this if the code handling creating bit-field types, promotions and diagnostics is made correct. > 3) The behaviour of c_common_signed_or_unsigned_type should be checked. Is it > OK to return a standard integral type when the input is a non-standard integral > type? If this is OK, then shouldn't we also do this when the signedness is the > same? It seems odd that this routine can return either a standard integral type > or a non-standard integral type, depending on signedness. > 4) We should check if we still want the special bit-field check in > perform_integral_promotions. This one I think we can defer indefinitely. If 32-bit bit-field types are to be nonstandard types (i.e. extended integer types) then they have rank less than that of 32-bit int so should promote to int and be accepted for int formats. Either there should be a special check to make nonstandard types the same width as int promote to int, or possibly simpler the standard type should be used for bit-fields in that case. More generally it may make sense to use standard types for bit-fields which have the same width as a standard type. *** Bug 21962 has been marked as a duplicate of this bug. *** As mentioned, just the text in the diagnostic is wong, not the diagnostic is wrong. I don't know if I should mark this as a regression as this is really a progression as mentioned in comment #2. Subject: Re: problems with -Wformat and bit-fields
On Tue, 12 Jul 2005, pinskia at gcc dot gnu dot org wrote:
> I don't know if I should mark this as a regression as this is really a progression as mentioned in
> comment #2.
The special case of 32-bit bit-fields is a regression, as they should be
accepted where int is (most simply done by making bit-fields of the same
width as int have type int / unsigned int; likewise for other standard
types but with int / unsigned int taking precedence in the choice of types
where multiple standard types have the same width).
Testing a patch. Subject: Bug 22421 CVSROOT: /cvs/gcc Module name: gcc Changes by: jsm28@gcc.gnu.org 2005-07-16 16:01:58 Modified files: gcc : ChangeLog c-decl.c c-pretty-print.c gcc/testsuite : ChangeLog Added files: gcc/testsuite/gcc.dg/format: bitfld-1.c Log message: PR c/22421 * c-decl.c (c_build_bitfield_integer_type): New function. (finish_struct): Call it. * c-pretty-print.c (pp_c_type_specifier): Handle bit-field types. testsuite: * gcc.dg/format/bitfld-1.c: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.9457&r2=2.9458 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/c-decl.c.diff?cvsroot=gcc&r1=1.675&r2=1.676 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/c-pretty-print.c.diff?cvsroot=gcc&r1=1.64&r2=1.65 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.5774&r2=1.5775 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/format/bitfld-1.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 Subject: Bug 22421 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-4_0-branch Changes by: jsm28@gcc.gnu.org 2005-07-16 16:04:38 Modified files: gcc : ChangeLog c-decl.c c-pretty-print.c gcc/testsuite : ChangeLog Added files: gcc/testsuite/gcc.dg/format: bitfld-1.c Log message: PR c/22421 * c-decl.c (c_build_bitfield_integer_type): New function. (finish_struct): Call it. * c-pretty-print.c (pp_c_type_specifier): Handle bit-field types. testsuite: * gcc.dg/format/bitfld-1.c: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=2.7592.2.316&r2=2.7592.2.317 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/c-decl.c.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=1.630.6.14&r2=1.630.6.15 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/c-pretty-print.c.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=1.59&r2=1.59.2.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=1.5084.2.281&r2=1.5084.2.282 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/format/bitfld-1.c.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=NONE&r2=1.1.2.1 Fixed in 4.0.2. Broken (again?) in 4.1 $ cat u.c typedef unsigned long u64; struct pal_freq_ratio { u64 den : 32, num : 32; /* numerator & denominator */ } x; main() { printf("den=%lx num=%lx\n", x.den, x.num); } $ cc -Wformat u.c u.c:9: warning: format ‘%lx’ expects type ‘long unsigned int’, but argument 2 has type ‘unsigned int’ u.c:9: warning: format ‘%lx’ expects type ‘long unsigned int’, but argument 3 has type ‘unsigned int’ $ cc --version cc (GCC) 4.1.0 20060109 (prerelease) (SUSE Linux) Copyright (C) 2005 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Should this be re-opened, or is it logged elsewhere? Subject: Re: problems with -Wformat and bit-fields On Mon, 2006-01-23 at 16:06, tony dot luck at intel dot com wrote: > u64 den : 32, num : 32; /* numerator & denominator */ > printf("den=%lx num=%lx\n", x.den, x.num); > u.c:9: warning: format %lx expects type long unsigned int, but argument 2 > has type unsigned int This is deliberate, as per our interpretation of the ISO C99 rules for integer conversions. If a bit-field has 32-bits, int is a 32-bit type, and long is a 64-bit type, then the bit-field promotes to int/unsigned int, even if declared with a long or unsigned long type. If long is a 32-bit type, then the bit-field promotes to long if declared with long type. This is mentioned in Joseph's response in comment #2. See also the testcase that was added for this PR. You can click on the testsuite link in comment #8 to see it. |