re PR c/22421 (problems with -Wformat and bit-fields)

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.

From-SVN: r102091
This commit is contained in:
Joseph Myers 2005-07-16 17:01:57 +01:00 committed by Joseph Myers
parent 8fcef540f3
commit 0b359b0103
5 changed files with 97 additions and 4 deletions

View File

@ -1,3 +1,10 @@
2005-07-16 Joseph S. Myers <joseph@codesourcery.com>
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.
2005-07-16 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* c-typeck.c (digest_init): Call 'convert_for_assignment'

View File

@ -3774,6 +3774,30 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
warning (0, "%qs is narrower than values of its type", name);
}
}
/* Build a bit-field integer type for the given WIDTH and UNSIGNEDP. */
static tree
c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
{
/* Extended integer types of the same width as a standard type have
lesser rank, so those of the same width as int promote to int or
unsigned int and are valid for printf formats expecting int or
unsigned int. To avoid such special cases, avoid creating
extended integer types for bit-fields if a standard integer type
is available. */
if (width == TYPE_PRECISION (integer_type_node))
return unsignedp ? unsigned_type_node : integer_type_node;
if (width == TYPE_PRECISION (signed_char_type_node))
return unsignedp ? unsigned_char_type_node : signed_char_type_node;
if (width == TYPE_PRECISION (short_integer_type_node))
return unsignedp ? short_unsigned_type_node : short_integer_type_node;
if (width == TYPE_PRECISION (long_integer_type_node))
return unsignedp ? long_unsigned_type_node : long_integer_type_node;
if (width == TYPE_PRECISION (long_long_integer_type_node))
return (unsignedp ? long_long_unsigned_type_node
: long_long_integer_type_node);
return build_nonstandard_integer_type (width, unsignedp);
}
/* Given declspecs and a declarator,
determine the name and type of the object declared
@ -5376,7 +5400,7 @@ finish_struct (tree t, tree fieldlist, tree attributes)
if (width != TYPE_PRECISION (type))
{
TREE_TYPE (*fieldlistp)
= build_nonstandard_integer_type (width, TYPE_UNSIGNED (type));
= c_build_bitfield_integer_type (width, TYPE_UNSIGNED (type));
DECL_MODE (*fieldlistp) = TYPE_MODE (TREE_TYPE (*fieldlistp));
}
DECL_INITIAL (*fieldlistp) = 0;

View File

@ -315,10 +315,21 @@ pp_c_type_specifier (c_pretty_printer *pp, tree t)
case INTEGER_TYPE:
case REAL_TYPE:
if (TYPE_NAME (t))
t = TYPE_NAME (t);
{
t = TYPE_NAME (t);
pp_c_type_specifier (pp, t);
}
else
t = c_common_type_for_mode (TYPE_MODE (t), TYPE_UNSIGNED (t));
pp_c_type_specifier (pp, t);
{
int prec = TYPE_PRECISION (t);
t = c_common_type_for_mode (TYPE_MODE (t), TYPE_UNSIGNED (t));
pp_c_type_specifier (pp, t);
if (TYPE_PRECISION (t) != prec)
{
pp_string (pp, ":");
pp_decimal_int (pp, prec);
}
}
break;
case TYPE_DECL:

View File

@ -1,3 +1,8 @@
2005-07-16 Joseph S. Myers <joseph@codesourcery.com>
PR c/22421
* gcc.dg/format/bitfld-1.c: New test.
2005-07-15 Mark Mitchell <mark@codesourcery.com>
PR c++/22204

View File

@ -0,0 +1,46 @@
/* Test for printf formats and bit-fields: bug 22421. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=gnu99 -Wformat" } */
#include "format.h"
struct s {
unsigned int u1 : 1;
signed int s1 : 1;
unsigned int u15 : 15;
signed int s15 : 15;
unsigned int u16 : 16;
signed int s16 : 16;
unsigned long u31 : 31;
signed long s31 : 31;
unsigned long u32 : 32;
signed long s32 : 32;
unsigned long long u48 : 48;
} x;
void
foo (void)
{
printf ("%d%u", x.u1, x.u1);
printf ("%d%u", x.s1, x.s1);
printf ("%d%u", x.u15, x.u15);
printf ("%d%u", x.s15, x.s15);
printf ("%d%u", x.u16, x.u16);
printf ("%d%u", x.s16, x.s16);
printf ("%d%u", x.u31, x.u31);
printf ("%d%u", x.s31, x.s31);
#if __LONG_MAX__ > 2147483647 && __INT_MAX__ >= 2147483647
/* If long is wider than 32 bits, the 32-bit bit-fields are int or
unsigned int or promote to those types. Otherwise, long is 32
bits and the bit-fields are of type plain long or unsigned
long. */
printf ("%d%u", x.u32, x.u32);
printf ("%d%u", x.s32, x.s32);
#else
printf ("%ld%lu", x.u32, x.u32);
printf ("%ld%lu", x.s32, x.s32);
#endif
printf ("%llu", x.u48); /* { dg-warning "has type '.*unsigned int:48'" } */
printf ("%llu", (unsigned long long)x.u48);
}