re PR c++/26534 ([4.1] bitfield wrong optimize)

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  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.

From-SVN: r113199
This commit is contained in:
Mark Mitchell 2006-04-23 18:04:33 +00:00 committed by Mark Mitchell
parent acb188c1ba
commit 38a4afeecd
23 changed files with 178 additions and 46 deletions

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

4
gcc/configure vendored
View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -19,7 +19,7 @@ int main ()
{
A a;
a.bitS = 1;
a.bitS = 1; // { dg-warning "overflow" }
a.bitU = 1;
a.bit = 1;

View File

@ -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;

View File

@ -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>

View File

@ -1,4 +1,4 @@
// { dg-options "-ansi -pedantic-errors -funsigned-bitfields" }
// { dg-options "-w -ansi -pedantic-errors -funsigned-bitfields" }
#include "bitfield1.h"

View File

@ -1,4 +1,4 @@
// { dg-options "-ansi -pedantic-errors -funsigned-bitfields" }
// { dg-options "-w -ansi -pedantic-errors -funsigned-bitfields" }
extern "C" void abort (void);

View File

@ -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>

View File

@ -1,4 +1,4 @@
// { dg-options "-ansi -pedantic-errors -fsigned-bitfields" }
// { dg-options "-w -ansi -pedantic-errors -fsigned-bitfields" }
#include "bitfield1.h"

View File

@ -1,4 +1,4 @@
// { dg-options "-ansi -pedantic-errors -fsigned-bitfields" }
// { dg-options "-w -ansi -pedantic-errors -fsigned-bitfields" }
extern "C" void abort (void);

View File

@ -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" }
}

View File

@ -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;
}