From 2ac1e11054ba1b27fb5554489f7e24588567d4d9 Mon Sep 17 00:00:00 2001 From: jsm28 Date: Sat, 16 Jul 2005 16:01:57 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@102091 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 7 ++++++ gcc/c-decl.c | 26 ++++++++++++++++++- gcc/c-pretty-print.c | 17 ++++++++++--- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.dg/format/bitfld-1.c | 46 ++++++++++++++++++++++++++++++++++ 5 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/format/bitfld-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8b57b807621..a9faa79a611 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2005-07-16 Joseph S. Myers + + 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 * c-typeck.c (digest_init): Call 'convert_for_assignment' diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 67c72a58d8c..aff59bc170f 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -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; diff --git a/gcc/c-pretty-print.c b/gcc/c-pretty-print.c index ebd917ef20a..6276923e794 100644 --- a/gcc/c-pretty-print.c +++ b/gcc/c-pretty-print.c @@ -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: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 30bde128ae4..6590ad75820 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-07-16 Joseph S. Myers + + PR c/22421 + * gcc.dg/format/bitfld-1.c: New test. + 2005-07-15 Mark Mitchell PR c++/22204 diff --git a/gcc/testsuite/gcc.dg/format/bitfld-1.c b/gcc/testsuite/gcc.dg/format/bitfld-1.c new file mode 100644 index 00000000000..2cea5d220e5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/format/bitfld-1.c @@ -0,0 +1,46 @@ +/* Test for printf formats and bit-fields: bug 22421. */ +/* Origin: Joseph Myers */ +/* { 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); +} -- 2.11.0