summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2005-07-16 16:01:57 +0000
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2005-07-16 16:01:57 +0000
commit2ac1e11054ba1b27fb5554489f7e24588567d4d9 (patch)
tree5f32a34bba8e5b6ed4a7e93f9ba7f8ff1df01cd4 /gcc
parentc7eca98668329969d87a2221b819d3c5028eef5b (diff)
downloadgcc-2ac1e11054ba1b27fb5554489f7e24588567d4d9.tar.gz
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/c-decl.c26
-rw-r--r--gcc/c-pretty-print.c17
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/format/bitfld-1.c46
5 files changed, 97 insertions, 4 deletions
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 <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'
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 <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
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 <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);
+}