mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-21 22:51:06 +08:00
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:
parent
acb188c1ba
commit
38a4afeecd
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
23
gcc/c-decl.c
23
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
|
||||
|
4
gcc/configure
vendored
4
gcc/configure
vendored
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -19,7 +19,7 @@ int main ()
|
||||
{
|
||||
A a;
|
||||
|
||||
a.bitS = 1;
|
||||
a.bitS = 1; // { dg-warning "overflow" }
|
||||
a.bitU = 1;
|
||||
a.bit = 1;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -1,4 +1,4 @@
|
||||
// { dg-options "-ansi -pedantic-errors -funsigned-bitfields" }
|
||||
// { dg-options "-w -ansi -pedantic-errors -funsigned-bitfields" }
|
||||
|
||||
#include "bitfield1.h"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// { dg-options "-ansi -pedantic-errors -funsigned-bitfields" }
|
||||
// { dg-options "-w -ansi -pedantic-errors -funsigned-bitfields" }
|
||||
|
||||
extern "C" void abort (void);
|
||||
|
||||
|
@ -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>
|
||||
|
@ -1,4 +1,4 @@
|
||||
// { dg-options "-ansi -pedantic-errors -fsigned-bitfields" }
|
||||
// { dg-options "-w -ansi -pedantic-errors -fsigned-bitfields" }
|
||||
|
||||
#include "bitfield1.h"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// { dg-options "-ansi -pedantic-errors -fsigned-bitfields" }
|
||||
// { dg-options "-w -ansi -pedantic-errors -fsigned-bitfields" }
|
||||
|
||||
extern "C" void abort (void);
|
||||
|
||||
|
@ -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" }
|
||||
}
|
||||
|
||||
|
||||
|
18
gcc/testsuite/g++.dg/opt/bitfield1.C
Normal file
18
gcc/testsuite/g++.dg/opt/bitfield1.C
Normal 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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user