diff options
author | Mark Mitchell <mark@codesourcery.com> | 2006-04-23 18:04:33 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2006-04-23 18:04:33 +0000 |
commit | 38a4afeecdf392267ff73a27a69f458b5d8b424c (patch) | |
tree | 795f298e0af32f79064b451399d8021ab268f911 /gcc/cp | |
parent | acb188c1ba3c0a94da659f679d4227f955488037 (diff) | |
download | gcc-38a4afeecdf392267ff73a27a69f458b5d8b424c.zip gcc-38a4afeecdf392267ff73a27a69f458b5d8b424c.tar.gz gcc-38a4afeecdf392267ff73a27a69f458b5d8b424c.tar.bz2 |
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
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/cp/call.c | 19 | ||||
-rw-r--r-- | gcc/cp/class.c | 23 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 44 |
5 files changed, 90 insertions, 11 deletions
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) |