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 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-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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@113199
138bc75d-0d04-0410-961f-
82ee72b054a4
+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
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
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);
}
}
-/* 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);
-}
\f
/* Given declspecs and a declarator,
determine the name and type of the object declared
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
lang_specs_files="$lang_specs_files $srcdir/$subdir/lang-specs.h"
fi
;;
+ *)
+ # This language is not enabled; skip it.
+ continue
+ ;;
esac
changequote([,])dnl
+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.
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)
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
"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)
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);
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;
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");
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)
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);
+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
{
A a;
- a.bitS = 1;
+ a.bitS = 1; // { dg-warning "overflow" }
a.bitU = 1;
a.bit = 1;
{
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;
-// { 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>
-// { dg-options "-ansi -pedantic-errors -funsigned-bitfields" }
+// { dg-options "-w -ansi -pedantic-errors -funsigned-bitfields" }
#include "bitfield1.h"
-// { dg-options "-ansi -pedantic-errors -funsigned-bitfields" }
+// { dg-options "-w -ansi -pedantic-errors -funsigned-bitfields" }
extern "C" void abort (void);
-// { 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>
-// { dg-options "-ansi -pedantic-errors -fsigned-bitfields" }
+// { dg-options "-w -ansi -pedantic-errors -fsigned-bitfields" }
#include "bitfield1.h"
-// { dg-options "-ansi -pedantic-errors -fsigned-bitfields" }
+// { dg-options "-w -ansi -pedantic-errors -fsigned-bitfields" }
extern "C" void abort (void);
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" }
}
--- /dev/null
+// 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;
+}