OSDN Git Service

PR c++/30274
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 11 Mar 2007 03:07:59 +0000 (03:07 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 11 Mar 2007 03:07:59 +0000 (03:07 +0000)
* 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

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/expr/bitfield3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/expr/bitfield4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/expr/bitfield5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/expr/bitfield6.C [new file with mode: 0644]

index 886b305..2f9b251 100644 (file)
@@ -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
index fb4609e..637671b 100644 (file)
@@ -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
index c90d529..2632137 100644 (file)
@@ -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);
index bf82f8c..f947da2 100644 (file)
@@ -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;
        }
index c774671..e8f1a18 100644 (file)
@@ -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)
              {
index 4447fd8..edc908c 100644 (file)
@@ -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 (file)
index 0000000..7b856e9
--- /dev/null
@@ -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 (file)
index 0000000..d824964
--- /dev/null
@@ -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 (file)
index 0000000..3d18e15
--- /dev/null
@@ -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 (file)
index 0000000..6f6d559
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/30274
+
+struct S {
+  bool x : 4;
+};
+
+S s;
+
+void f() {
+  ++s.x = false;
+}