diff options
author | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-03-11 03:07:59 +0000 |
---|---|---|
committer | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-03-11 03:07:59 +0000 |
commit | 154a4e700974c63cbaa7e451b839f9b704597246 (patch) | |
tree | db5f9072513ff237834cbce6b263a110d6ef3658 /gcc | |
parent | 0d9504bff42dbdd9fd8c1d5b56724cc576a5bc31 (diff) | |
download | gcc-154a4e700974c63cbaa7e451b839f9b704597246.tar.gz |
PR c++/30274
* cp-tree.h (unlowered_expr_type): New function.
* typeck.c (is_bitfield_expr_with_lowered_type): Handle
COMPOUND_EXPR, MODIFY_EXPR, and SAVE_EXPR.
(unlowered_expr_type): New function.
(build_unary_op): Disallow predecrements of bool bitfields.
* call.c (build_conditional_expr): Use unlowered_expr_type.
* pt.c (type_unification_real): Likewise.
PR c++/30274
* g++.dg/expr/bitfield3.C: New test.
* g++.dg/expr/bitfield4.C: Likewise.
* g++.dg/expr/bitfield5.C: Likewise.
* g++.dg/expr/bitfield6.C: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122813 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/call.c | 8 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/pt.c | 2 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 58 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/expr/bitfield3.C | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/expr/bitfield4.C | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/expr/bitfield5.C | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/expr/bitfield6.C | 11 |
10 files changed, 125 insertions, 20 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 886b305c4a8..2f9b251c562 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2007-03-10 Mark Mitchell <mark@codesourcery.com> + + PR c++/30274 + * cp-tree.h (unlowered_expr_type): New function. + * typeck.c (is_bitfield_expr_with_lowered_type): Handle + COMPOUND_EXPR, MODIFY_EXPR, and SAVE_EXPR. + (unlowered_expr_type): New function. + (build_unary_op): Disallow predecrements of bool bitfields. + * call.c (build_conditional_expr): Use unlowered_expr_type. + * pt.c (type_unification_real): Likewise. + 2007-03-09 Douglas Gregor <doug.gregor@gmail.com> PR c++/20599 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index fb4609edf7b..637671bc1bc 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3250,12 +3250,8 @@ 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 = 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); + arg2_type = unlowered_expr_type (arg2); + arg3_type = unlowered_expr_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/cp-tree.h b/gcc/cp/cp-tree.h index c90d5290eb3..2632137eb26 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4645,6 +4645,7 @@ 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 unlowered_expr_type (tree); extern tree decay_conversion (tree); extern tree build_class_member_access_expr (tree, tree, tree, bool); extern tree finish_class_member_access_expr (tree, tree, bool); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index bf82f8c5330..f947da2b0fa 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -11260,7 +11260,7 @@ type_unification_real (tree tparms, return 1; continue; } - arg = TREE_TYPE (arg); + arg = unlowered_expr_type (arg); if (arg == error_mark_node) return 1; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index c774671ef0d..e8f1a183fc9 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1418,23 +1418,52 @@ invalid_nonstatic_memfn_p (tree expr) tree is_bitfield_expr_with_lowered_type (tree exp) { - tree field; - - if (TREE_CODE (exp) == COND_EXPR) + switch (TREE_CODE (exp)) { + case 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)); + + case COMPOUND_EXPR: + return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 1)); + + case MODIFY_EXPR: + case SAVE_EXPR: + return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0)); + + case COMPONENT_REF: + { + tree field; + + 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); + } + + default: + return NULL_TREE; } - 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); +} + +/* Like is_bitfield_with_lowered_type, except that if EXP is not a + bitfield with a lowered type, the type of EXP is returned, rather + than NULL_TREE. */ + +tree +unlowered_expr_type (tree exp) +{ + tree type; + + type = is_bitfield_expr_with_lowered_type (exp); + if (!type) + type = TREE_TYPE (exp); + + return type; } /* Perform the conversions in [expr] that apply when an lvalue appears @@ -4217,8 +4246,11 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) { tree inc; + tree declared_type; tree result_type = TREE_TYPE (arg); + declared_type = unlowered_expr_type (arg); + arg = get_unwidened (arg, 0); argtype = TREE_TYPE (arg); @@ -4296,7 +4328,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) return error_mark_node; /* Forbid using -- on `bool'. */ - if (same_type_p (TREE_TYPE (arg), boolean_type_node)) + if (same_type_p (declared_type, boolean_type_node)) { if (code == POSTDECREMENT_EXPR || code == PREDECREMENT_EXPR) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4447fd8e5a6..edc908c5b9f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,11 @@ 2007-03-10 Mark Mitchell <mark@codesourcery.com> + PR c++/30274 + * g++.dg/expr/bitfield3.C: New test. + * g++.dg/expr/bitfield4.C: Likewise. + * g++.dg/expr/bitfield5.C: Likewise. + * g++.dg/expr/bitfield6.C: Likewise. + PR c++/30924 * g++.dg/template/array18.C: New test. diff --git a/gcc/testsuite/g++.dg/expr/bitfield3.C b/gcc/testsuite/g++.dg/expr/bitfield3.C new file mode 100644 index 00000000000..7b856e9e8b8 --- /dev/null +++ b/gcc/testsuite/g++.dg/expr/bitfield3.C @@ -0,0 +1,12 @@ +// PR c++/30274 + +struct S { + bool x : 4; +}; + +S s; + +void f() { + s.x--; // { dg-error "bool" } + --s.x; // { dg-error "bool" } +} diff --git a/gcc/testsuite/g++.dg/expr/bitfield4.C b/gcc/testsuite/g++.dg/expr/bitfield4.C new file mode 100644 index 00000000000..d824964e187 --- /dev/null +++ b/gcc/testsuite/g++.dg/expr/bitfield4.C @@ -0,0 +1,19 @@ +// PR c++/30274 +// { dg-do link } + +struct S { + bool x : 4; +}; + +S s; + +template <typename T> +void f(T); + +template <> +void f(bool) {} + +int main() { + f(s.x++); + f(++s.x); +} diff --git a/gcc/testsuite/g++.dg/expr/bitfield5.C b/gcc/testsuite/g++.dg/expr/bitfield5.C new file mode 100644 index 00000000000..3d18e159cc0 --- /dev/null +++ b/gcc/testsuite/g++.dg/expr/bitfield5.C @@ -0,0 +1,17 @@ +// PR c++/30274 +// { dg-do run } + +struct S { + bool x : 4; +}; + +S s; + +int main() { + s.x++; + if (s.x != 1) + return 1; + ++s.x; + if (s.x != 1) + return 2; +} diff --git a/gcc/testsuite/g++.dg/expr/bitfield6.C b/gcc/testsuite/g++.dg/expr/bitfield6.C new file mode 100644 index 00000000000..6f6d559a38e --- /dev/null +++ b/gcc/testsuite/g++.dg/expr/bitfield6.C @@ -0,0 +1,11 @@ +// PR c++/30274 + +struct S { + bool x : 4; +}; + +S s; + +void f() { + ++s.x = false; +} |