aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2007-03-11 03:07:59 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2007-03-11 03:07:59 +0000
commitf9aa54d3c5c8b4993678c52b2c4d2ee2f7bdabaf (patch)
treedb5f9072513ff237834cbce6b263a110d6ef3658 /gcc
parenteae920410eba880ef056809d8dea2393233b4d58 (diff)
downloadgcc-f9aa54d3c5c8b4993678c52b2c4d2ee2f7bdabaf.zip
gcc-f9aa54d3c5c8b4993678c52b2c4d2ee2f7bdabaf.tar.gz
gcc-f9aa54d3c5c8b4993678c52b2c4d2ee2f7bdabaf.tar.bz2
re PR c++/30274 (bool bit-field: wrong increment and decremenet)
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. From-SVN: r122813
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/call.c8
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/pt.c2
-rw-r--r--gcc/cp/typeck.c58
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/expr/bitfield3.C12
-rw-r--r--gcc/testsuite/g++.dg/expr/bitfield4.C19
-rw-r--r--gcc/testsuite/g++.dg/expr/bitfield5.C17
-rw-r--r--gcc/testsuite/g++.dg/expr/bitfield6.C11
10 files changed, 125 insertions, 20 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 886b305..2f9b251 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 fb4609e..637671b 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 c90d529..2632137 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 bf82f8c..f947da2 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 c774671..e8f1a18 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 4447fd8..edc908c 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 0000000..7b856e9
--- /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 0000000..d824964
--- /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 0000000..3d18e15
--- /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 0000000..6f6d559
--- /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;
+}