aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/c-common.c25
-rw-r--r--gcc/c-common.h1
-rw-r--r--gcc/c-decl.c23
-rwxr-xr-xgcc/configure4
-rw-r--r--gcc/configure.ac4
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/call.c19
-rw-r--r--gcc/cp/class.c23
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/typeck.c44
-rw-r--r--gcc/print-tree.c3
-rw-r--r--gcc/testsuite/ChangeLog14
-rw-r--r--gcc/testsuite/g++.dg/abi/bitfield1.C2
-rw-r--r--gcc/testsuite/g++.dg/abi/bitfield2.C4
-rw-r--r--gcc/testsuite/g++.dg/compat/abi/bitfield1_main.C2
-rw-r--r--gcc/testsuite/g++.dg/compat/abi/bitfield1_x.C2
-rw-r--r--gcc/testsuite/g++.dg/compat/abi/bitfield1_y.C2
-rw-r--r--gcc/testsuite/g++.dg/compat/abi/bitfield2_main.C2
-rw-r--r--gcc/testsuite/g++.dg/compat/abi/bitfield2_x.C2
-rw-r--r--gcc/testsuite/g++.dg/compat/abi/bitfield2_y.C2
-rw-r--r--gcc/testsuite/g++.dg/init/bitfield1.C6
-rw-r--r--gcc/testsuite/g++.dg/opt/bitfield1.C18
23 files changed, 178 insertions, 46 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ea6d17b..08fc7c0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2006-04-23 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/26534
+ * c-common.h (c_build_bitfield_integer_type): Declare.
+ * c-decl.c (c_build_bitfield_integer_type): Move to ...
+ * c-common.c (c_build_bitfield_integer_type): ... here.
+
2006-04-23 Roger Sayle <roger@eyesopen.com>
PR target/21283
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 1a11c3b..35982e5 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -1871,6 +1871,31 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type)
return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
}
+/* Build a bit-field integer type for the given WIDTH and UNSIGNEDP. */
+
+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);
+}
+
/* The C version of the register_builtin_type langhook. */
void
diff --git a/gcc/c-common.h b/gcc/c-common.h
index ed93f97..5636685 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -644,6 +644,7 @@ extern tree c_common_type_for_size (unsigned int, int);
extern tree c_common_unsigned_type (tree);
extern tree c_common_signed_type (tree);
extern tree c_common_signed_or_unsigned_type (int, tree);
+extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int);
extern tree c_common_truthvalue_conversion (tree);
extern void c_apply_type_quals_to_decl (int, tree);
extern tree c_sizeof_or_alignof_type (tree, bool, int);
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index db906b4..f4d3330 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -3814,29 +3814,6 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_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
diff --git a/gcc/configure b/gcc/configure
index fe6f1bd..9137c44 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -15843,6 +15843,10 @@ do
lang_specs_files="$lang_specs_files $srcdir/$subdir/lang-specs.h"
fi
;;
+ *)
+ # This language is not enabled; skip it.
+ continue
+ ;;
esac
if test -f $srcdir/$subdir/lang.opt; then
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 447f827..2fa8d99 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3325,6 +3325,10 @@ changequote(,)dnl
lang_specs_files="$lang_specs_files $srcdir/$subdir/lang-specs.h"
fi
;;
+ *)
+ # This language is not enabled; skip it.
+ continue
+ ;;
esac
changequote([,])dnl
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 711fb7c..a0a44a5 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@
+2006-04-23 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/26534
+ * cp-tree.h (is_bitfield_expr_with_lowered_type): New function.
+ * typeck.c (is_bitfield_expr_with_lowered_type): New function.
+ (decay_conversion): Convert bitfield expressions to the correct
+ type.
+ (build_modify_expr): Remove spurious conversions.
+ * class.c (layout_class_type): Modify the type of bitfields to
+ indicate a limited range.
+ * call.c (standard_conversion): Adjust the type of bitfield
+ expressions used in an rvalue context.
+ (build_conditional_expr): Likewise.
+
2006-04-22 Kazu Hirata <kazu@codesourcery.com>
* decl.c: Fix comment typos.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index c9826451..6743f92 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -623,7 +623,16 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
conv = build_conv (ck_lvalue, from, conv);
}
else if (fromref || (expr && lvalue_p (expr)))
- conv = build_conv (ck_rvalue, from, conv);
+ {
+ if (expr)
+ {
+ tree bitfield_type;
+ bitfield_type = is_bitfield_expr_with_lowered_type (expr);
+ if (bitfield_type)
+ from = bitfield_type;
+ }
+ conv = build_conv (ck_rvalue, from, conv);
+ }
/* Allow conversion between `__complex__' data types. */
if (tcode == COMPLEX_TYPE && fcode == COMPLEX_TYPE)
@@ -3196,8 +3205,12 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
array-to-pointer (_conv.array_), and function-to-pointer
(_conv.func_) standard conversions are performed on the second
and third operands. */
- arg2_type = TREE_TYPE (arg2);
- arg3_type = TREE_TYPE (arg3);
+ arg2_type = is_bitfield_expr_with_lowered_type (arg2);
+ if (!arg2_type)
+ arg2_type = TREE_TYPE (arg2);
+ arg3_type = is_bitfield_expr_with_lowered_type (arg3);
+ if (!arg3_type)
+ arg3_type = TREE_TYPE (arg3);
if (VOID_TYPE_P (arg2_type) || VOID_TYPE_P (arg3_type))
{
/* Do the conversions. We don't these for `void' type arguments
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index cc26cb8..1cf87dc 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4727,6 +4727,29 @@ layout_class_type (tree t, tree *virtuals_p)
"classes to be placed at different locations in a "
"future version of GCC", field);
+ /* The middle end uses the type of expressions to determine the
+ possible range of expression values. In order to optimize
+ "x.i > 7" to "false" for a 2-bit bitfield "i", the middle end
+ must be made aware of the width of "i", via its type.
+
+ Because C++ does not have integer types of arbitrary width,
+ we must (for the purposes of the front end) convert from the
+ type assigned here to the declared type of the bitfield
+ whenever a bitfield expression is used as an rvalue.
+ Similarly, when assigning a value to a bitfield, the value
+ must be converted to the type given the bitfield here. */
+ if (DECL_C_BIT_FIELD (field))
+ {
+ tree ftype;
+ unsigned HOST_WIDE_INT width;
+ ftype = TREE_TYPE (field);
+ width = tree_low_cst (DECL_SIZE (field), /*unsignedp=*/1);
+ if (width != TYPE_PRECISION (ftype))
+ TREE_TYPE (field)
+ = c_build_bitfield_integer_type (width,
+ TYPE_UNSIGNED (ftype));
+ }
+
/* If we needed additional padding after this field, add it
now. */
if (padding)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 0848747..34cccc0 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4351,6 +4351,7 @@ extern tree cxx_sizeof_or_alignof_expr (tree, enum tree_code);
extern tree cxx_sizeof_or_alignof_type (tree, enum tree_code, bool);
#define cxx_sizeof_nowarn(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, false)
extern tree inline_conversion (tree);
+extern tree is_bitfield_expr_with_lowered_type (tree);
extern tree decay_conversion (tree);
extern tree default_conversion (tree);
extern tree build_class_member_access_expr (tree, tree, tree, bool);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a7bdd55..7fc6cab 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1398,21 +1398,47 @@ invalid_nonstatic_memfn_p (tree expr)
return false;
}
+/* If EXP is a reference to a bitfield, and the type of EXP does not
+ match the declared type of the bitfield, return the declared type
+ of the bitfield. Otherwise, return NULL_TREE. */
+
+tree
+is_bitfield_expr_with_lowered_type (tree exp)
+{
+ tree field;
+
+ if (TREE_CODE (exp) == COND_EXPR)
+ {
+ if (!is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 1)))
+ return NULL_TREE;
+ return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 2));
+ }
+ if (TREE_CODE (exp) != COMPONENT_REF)
+ return NULL_TREE;
+ field = TREE_OPERAND (exp, 1);
+ if (TREE_CODE (field) != FIELD_DECL || !DECL_C_BIT_FIELD (field))
+ return NULL_TREE;
+ if (same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (exp), DECL_BIT_FIELD_TYPE (field)))
+ return NULL_TREE;
+ return DECL_BIT_FIELD_TYPE (field);
+}
+
/* Perform the conversions in [expr] that apply when an lvalue appears
in an rvalue context: the lvalue-to-rvalue, array-to-pointer, and
function-to-pointer conversions.
- In addition manifest constants are replaced by their values. */
+ In addition, manifest constants are replaced by their values, and
+ bitfield references are converted to their declared types. */
tree
decay_conversion (tree exp)
{
tree type;
+ tree bitfield_type;
enum tree_code code;
type = TREE_TYPE (exp);
- code = TREE_CODE (type);
-
if (type == error_mark_node)
return error_mark_node;
@@ -1422,11 +1448,15 @@ decay_conversion (tree exp)
return error_mark_node;
}
+ bitfield_type = is_bitfield_expr_with_lowered_type (exp);
+ if (bitfield_type)
+ exp = build_nop (bitfield_type, exp);
+
exp = decl_constant_value (exp);
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
Leave such NOP_EXPRs, since RHS is being used in non-lvalue context. */
-
+ code = TREE_CODE (type);
if (code == VOID_TYPE)
{
error ("void value not ignored as it ought to be");
@@ -5500,11 +5530,9 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
cond = build_conditional_expr
(TREE_OPERAND (lhs, 0),
- build_modify_expr (cp_convert (TREE_TYPE (lhs),
- TREE_OPERAND (lhs, 1)),
+ build_modify_expr (TREE_OPERAND (lhs, 1),
modifycode, rhs),
- build_modify_expr (cp_convert (TREE_TYPE (lhs),
- TREE_OPERAND (lhs, 2)),
+ build_modify_expr (TREE_OPERAND (lhs, 2),
modifycode, rhs));
if (cond == error_mark_node)
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index 02e5c7b..eed02f2 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -458,6 +458,9 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
print_node (file, "offset", DECL_FIELD_OFFSET (node), indent + 4);
print_node (file, "bit offset", DECL_FIELD_BIT_OFFSET (node),
indent + 4);
+ if (DECL_BIT_FIELD_TYPE (node))
+ print_node (file, "bit_field_type", DECL_BIT_FIELD_TYPE (node),
+ indent + 4);
}
print_node_brief (file, "context", DECL_CONTEXT (node), indent + 4);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7a3fb00..f0c3a5d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,17 @@
+2006-04-23 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/26534
+ * g++.dg/opt/bitfield1.C: New test.
+ * g++.dg/compat/abi/bitfield1_main.C: Add -w.
+ * g++.dg/compat/abi/bitfield1_x.C: Likewise.
+ * g++.dg/compat/abi/bitfield1_y.C: Likewise.
+ * g++.dg/compat/abi/bitfield2_main.C: Likewise.
+ * g++.dg/compat/abi/bitfield2_x.C: Likewise.
+ * g++.dg/compat/abi/bitfield2_y.C: Likewise.
+ * g++.dg/abi/bitfield1.C: Add dg-warning markers.
+ * g++.dg/abi/bitfield2.C: Likewise.
+ * g++.dg/init/bitfield1.C: Likewise.
+
2006-04-23 Paul Thomas <pault@gcc.gnu.org>
PR fortran/25099
diff --git a/gcc/testsuite/g++.dg/abi/bitfield1.C b/gcc/testsuite/g++.dg/abi/bitfield1.C
index c707c85..d5d04bc 100644
--- a/gcc/testsuite/g++.dg/abi/bitfield1.C
+++ b/gcc/testsuite/g++.dg/abi/bitfield1.C
@@ -19,7 +19,7 @@ int main ()
{
A a;
- a.bitS = 1;
+ a.bitS = 1; // { dg-warning "overflow" }
a.bitU = 1;
a.bit = 1;
diff --git a/gcc/testsuite/g++.dg/abi/bitfield2.C b/gcc/testsuite/g++.dg/abi/bitfield2.C
index d4d1d58..452861e 100644
--- a/gcc/testsuite/g++.dg/abi/bitfield2.C
+++ b/gcc/testsuite/g++.dg/abi/bitfield2.C
@@ -19,9 +19,9 @@ int main ()
{
A a;
- a.bitS = 1;
+ a.bitS = 1; // { dg-warning "overflow" }
a.bitU = 1;
- a.bit = 1;
+ a.bit = 1; // { dg-warning "overflow" }
if (a.bitS != -1)
return 1;
diff --git a/gcc/testsuite/g++.dg/compat/abi/bitfield1_main.C b/gcc/testsuite/g++.dg/compat/abi/bitfield1_main.C
index cdb7a45..ce9aa1f 100644
--- a/gcc/testsuite/g++.dg/compat/abi/bitfield1_main.C
+++ b/gcc/testsuite/g++.dg/compat/abi/bitfield1_main.C
@@ -1,4 +1,4 @@
-// { dg-options "-ansi -pedantic-errors -funsigned-bitfields" }
+// { dg-options "-w -ansi -pedantic-errors -funsigned-bitfields" }
// Copyright (C) 2001 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 15 Dec 2001 <nathan@codesourcery.com>
diff --git a/gcc/testsuite/g++.dg/compat/abi/bitfield1_x.C b/gcc/testsuite/g++.dg/compat/abi/bitfield1_x.C
index e081c4b..727632a 100644
--- a/gcc/testsuite/g++.dg/compat/abi/bitfield1_x.C
+++ b/gcc/testsuite/g++.dg/compat/abi/bitfield1_x.C
@@ -1,4 +1,4 @@
-// { dg-options "-ansi -pedantic-errors -funsigned-bitfields" }
+// { dg-options "-w -ansi -pedantic-errors -funsigned-bitfields" }
#include "bitfield1.h"
diff --git a/gcc/testsuite/g++.dg/compat/abi/bitfield1_y.C b/gcc/testsuite/g++.dg/compat/abi/bitfield1_y.C
index 10581da..2827767 100644
--- a/gcc/testsuite/g++.dg/compat/abi/bitfield1_y.C
+++ b/gcc/testsuite/g++.dg/compat/abi/bitfield1_y.C
@@ -1,4 +1,4 @@
-// { dg-options "-ansi -pedantic-errors -funsigned-bitfields" }
+// { dg-options "-w -ansi -pedantic-errors -funsigned-bitfields" }
extern "C" void abort (void);
diff --git a/gcc/testsuite/g++.dg/compat/abi/bitfield2_main.C b/gcc/testsuite/g++.dg/compat/abi/bitfield2_main.C
index df74037..4169843 100644
--- a/gcc/testsuite/g++.dg/compat/abi/bitfield2_main.C
+++ b/gcc/testsuite/g++.dg/compat/abi/bitfield2_main.C
@@ -1,4 +1,4 @@
-// { dg-options "-ansi -pedantic-errors -fsigned-bitfields" }
+// { dg-options "-w -ansi -pedantic-errors -fsigned-bitfields" }
// Copyright (C) 2001 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 15 Dec 2001 <nathan@codesourcery.com>
diff --git a/gcc/testsuite/g++.dg/compat/abi/bitfield2_x.C b/gcc/testsuite/g++.dg/compat/abi/bitfield2_x.C
index 47b448d..080d21b 100644
--- a/gcc/testsuite/g++.dg/compat/abi/bitfield2_x.C
+++ b/gcc/testsuite/g++.dg/compat/abi/bitfield2_x.C
@@ -1,4 +1,4 @@
-// { dg-options "-ansi -pedantic-errors -fsigned-bitfields" }
+// { dg-options "-w -ansi -pedantic-errors -fsigned-bitfields" }
#include "bitfield1.h"
diff --git a/gcc/testsuite/g++.dg/compat/abi/bitfield2_y.C b/gcc/testsuite/g++.dg/compat/abi/bitfield2_y.C
index 55edab5..d275783 100644
--- a/gcc/testsuite/g++.dg/compat/abi/bitfield2_y.C
+++ b/gcc/testsuite/g++.dg/compat/abi/bitfield2_y.C
@@ -1,4 +1,4 @@
-// { dg-options "-ansi -pedantic-errors -fsigned-bitfields" }
+// { dg-options "-w -ansi -pedantic-errors -fsigned-bitfields" }
extern "C" void abort (void);
diff --git a/gcc/testsuite/g++.dg/init/bitfield1.C b/gcc/testsuite/g++.dg/init/bitfield1.C
index 786a116..70a06d0 100644
--- a/gcc/testsuite/g++.dg/init/bitfield1.C
+++ b/gcc/testsuite/g++.dg/init/bitfield1.C
@@ -14,11 +14,11 @@ void f ();
int main ()
{
(f(), a.j) = 1;
- (f(), a).j = 2;
- (b ? a.j : a2.k) = 3;
+ (f(), a).j = 2; // { dg-warning "overflow" }
+ (b ? a.j : a2.k) = 3; // { dg-warning "overflow" }
(b ? a : a2).j = 0;
++(a.j) = 1;
- (a.j = 2) = 3;
+ (a.j = 2) = 3; // { dg-warning "overflow" }
}
diff --git a/gcc/testsuite/g++.dg/opt/bitfield1.C b/gcc/testsuite/g++.dg/opt/bitfield1.C
new file mode 100644
index 0000000..4969996
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/bitfield1.C
@@ -0,0 +1,18 @@
+// PR c++/26534
+// { dg-do run }
+// { dg-options "-w -O2" }
+
+struct X
+{
+ unsigned a:4;
+};
+
+unsigned i;
+
+int main()
+{
+ struct X x = { 63u };
+ i = x.a;
+ if (i != 15)
+ return 1;
+}