For historical reasons, incrementing a boolean was allowed (because anything
non-0 is true), while decrementing is forbidden.  This has now changed, and
since C++17 even ++ on bool is invalid.  And C++ 03/11/14 [depr.incr.bool]
says that ++ is deprecated, but we never diagnosed this.

A bunch of testcases needed updating, but nothing unexpected.

(Even though I recently changed out documentation to use "boolean" rather
than "Boolean", I'm keeping this as it is.  I can tweak that in a follow
up.)

Bootstrapped/regtested on x86_64-linux/ppc64-linux, ok for trunk?

2016-09-13  Marek Polacek  <pola...@redhat.com>

        * typeck.c (cp_build_unary_op): Diagnose incrementing boolean
        expressions.

        * c-c++-common/gomp/atomic-12.c: Use -Wno-deprecated.
        * c-c++-common/gomp/atomic-13.c: Likewise.
        * c-c++-common/gomp/atomic-14.c: Likewise.
        * g++.dg/cpp1y/lambda-init11.C: Remove invalid code.
        * g++.dg/cpp1z/bool-increment1.C: New test.
        * c-c++-common/pr60439.c: Add dg-warning.
        * g++.dg/expr/bitfield4.C: Likewise.
        * g++.dg/expr/bitfield5.C: Likewise.
        * g++.dg/expr/bitfield6.C: Likewise.
        * g++.dg/expr/bool1.C: Likewise.
        * g++.dg/expr/bool3.C: Likewise.
        * g++.dg/expr/lval3.C: Likewise.
        * g++.dg/expr/lval4.C: Likewise.
        * g++.old-deja/g++.jason/bool5.C: Likewise.

diff --git gcc/cp/typeck.c gcc/cp/typeck.c
index a591d29..341f722 100644
--- gcc/cp/typeck.c
+++ gcc/cp/typeck.c
@@ -6030,7 +6030,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int 
noconvert,
                              complain))
          return error_mark_node;
 
-       /* Forbid using -- on `bool'.  */
+       /* Forbid using -- or ++ in C++17 on `bool'.  */
        if (TREE_CODE (declared_type) == BOOLEAN_TYPE)
          {
            if (code == POSTDECREMENT_EXPR || code == PREDECREMENT_EXPR)
@@ -6040,6 +6040,20 @@ cp_build_unary_op (enum tree_code code, tree xarg, int 
noconvert,
                          "to %<operator--%>");
                return error_mark_node;
              }
+           else
+             {
+               if (cxx_dialect >= cxx1z)
+                 {
+                   if (complain & tf_error)
+                     error ("use of Boolean expression as operand "
+                            "to %<operator++%> is forbidden in C++1z");
+                   return error_mark_node;
+                 }
+               /* Otherwise, [depr.incr.bool] says this is deprecated.  */
+               else if (!in_system_header_at (input_location))
+                 warning (OPT_Wdeprecated, "use of Boolean expression as "
+                          "operand to %<operator++%> is deprecated");
+             }
            val = boolean_increment (code, arg);
          }
        else if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
diff --git gcc/testsuite/c-c++-common/gomp/atomic-12.c 
gcc/testsuite/c-c++-common/gomp/atomic-12.c
index 145e420..e9ca650 100644
--- gcc/testsuite/c-c++-common/gomp/atomic-12.c
+++ gcc/testsuite/c-c++-common/gomp/atomic-12.c
@@ -1,6 +1,6 @@
 /* PR middle-end/45423 */
 /* { dg-do compile } */
-/* { dg-options "-fopenmp -fdump-tree-gimple -g0" } */
+/* { dg-options "-fopenmp -fdump-tree-gimple -g0 -Wno-deprecated" } */
 /* atomicvar should never be referenced in between the barrier and
    following #pragma omp atomic_load.  */
 /* { dg-final { scan-tree-dump-not "barrier\[^#\]*atomicvar" "gimple" } } */
diff --git gcc/testsuite/c-c++-common/gomp/atomic-13.c 
gcc/testsuite/c-c++-common/gomp/atomic-13.c
index 2452035..7f4afcf 100644
--- gcc/testsuite/c-c++-common/gomp/atomic-13.c
+++ gcc/testsuite/c-c++-common/gomp/atomic-13.c
@@ -1,6 +1,6 @@
 /* PR middle-end/45423 */
 /* { dg-do compile } */
-/* { dg-options "-fopenmp -fdump-tree-gimple -g0 -O2" } */
+/* { dg-options "-fopenmp -fdump-tree-gimple -g0 -O2 -Wno-deprecated" } */
 /* atomicvar should never be referenced in between the barrier and
    following #pragma omp atomic_load.  */
 /* { dg-final { scan-tree-dump-not "barrier\[^#\]*atomicvar" "gimple" } } */
diff --git gcc/testsuite/c-c++-common/gomp/atomic-14.c 
gcc/testsuite/c-c++-common/gomp/atomic-14.c
index f8fc9d8..7e23453 100644
--- gcc/testsuite/c-c++-common/gomp/atomic-14.c
+++ gcc/testsuite/c-c++-common/gomp/atomic-14.c
@@ -1,6 +1,6 @@
 /* PR middle-end/45423 */
 /* { dg-do compile } */
-/* { dg-options "-fopenmp" } */
+/* { dg-options "-fopenmp -Wno-deprecated" } */
 
 #ifdef __cplusplus
 bool *baz ();
diff --git gcc/testsuite/c-c++-common/pr60439.c 
gcc/testsuite/c-c++-common/pr60439.c
index 68bd33c..71b397a 100644
--- gcc/testsuite/c-c++-common/pr60439.c
+++ gcc/testsuite/c-c++-common/pr60439.c
@@ -132,6 +132,7 @@ f6 (bool b)
       break;
     }
   switch (b++) /* { dg-warning "switch condition has" } */
+  /* { dg-warning "is deprecated" "" { target c++ } 134 } */
     {
     case 3:
       break;
diff --git gcc/testsuite/g++.dg/cpp1y/lambda-init11.C 
gcc/testsuite/g++.dg/cpp1y/lambda-init11.C
index f7525d8..4d434cd 100644
--- gcc/testsuite/g++.dg/cpp1y/lambda-init11.C
+++ gcc/testsuite/g++.dg/cpp1y/lambda-init11.C
@@ -16,5 +16,4 @@ int main(){
   foo(3.14f);
   foo(0);
   foo('a');
-  foo(false);
 }
diff --git gcc/testsuite/g++.dg/expr/bitfield4.C 
gcc/testsuite/g++.dg/expr/bitfield4.C
index d824964..7fae086 100644
--- gcc/testsuite/g++.dg/expr/bitfield4.C
+++ gcc/testsuite/g++.dg/expr/bitfield4.C
@@ -14,6 +14,6 @@ template <>
 void f(bool) {} 
 
 int main() {
-  f(s.x++);
-  f(++s.x);
+  f(s.x++); // { dg-warning "deprecated" }
+  f(++s.x); // { dg-warning "deprecated" }
 }
diff --git gcc/testsuite/g++.dg/expr/bitfield5.C 
gcc/testsuite/g++.dg/expr/bitfield5.C
index 3d18e15..0a37f9f 100644
--- gcc/testsuite/g++.dg/expr/bitfield5.C
+++ gcc/testsuite/g++.dg/expr/bitfield5.C
@@ -8,10 +8,10 @@ struct S {
 S s;
 
 int main() {
-  s.x++;
+  s.x++; // { dg-warning "deprecated" }
   if (s.x != 1)
     return 1;
-  ++s.x;
+  ++s.x; // { dg-warning "deprecated" }
   if (s.x != 1)
     return 2;
 }
diff --git gcc/testsuite/g++.dg/expr/bitfield6.C 
gcc/testsuite/g++.dg/expr/bitfield6.C
index 6f6d559..8523866 100644
--- gcc/testsuite/g++.dg/expr/bitfield6.C
+++ gcc/testsuite/g++.dg/expr/bitfield6.C
@@ -7,5 +7,5 @@ struct S {
 S s;
 
 void f() {
-  ++s.x = false;
+  ++s.x = false; // { dg-warning "deprecated" }
 }
diff --git gcc/testsuite/g++.dg/expr/bool1.C gcc/testsuite/g++.dg/expr/bool1.C
index bfb40e3..503e8b4 100644
--- gcc/testsuite/g++.dg/expr/bool1.C
+++ gcc/testsuite/g++.dg/expr/bool1.C
@@ -10,8 +10,8 @@ int main()
   my_bool b = false;
   int i;
 
-  b++;
-  b++;
+  b++; // { dg-warning "deprecated" }
+  b++; // { dg-warning "deprecated" }
   i = b;
   if (i != 1)
     abort ();
diff --git gcc/testsuite/g++.dg/expr/bool3.C gcc/testsuite/g++.dg/expr/bool3.C
index 61669e2..1866ed4 100644
--- gcc/testsuite/g++.dg/expr/bool3.C
+++ gcc/testsuite/g++.dg/expr/bool3.C
@@ -10,8 +10,8 @@ int main()
   my_bool b = false;
   int i;
 
-  b++;
-  b++;
+  b++; // { dg-warning "deprecated" }
+  b++; // { dg-warning "deprecated" }
   i = b;
   if (i != 1)
     abort ();
diff --git gcc/testsuite/g++.dg/expr/lval3.C gcc/testsuite/g++.dg/expr/lval3.C
index f106e69..8e0aead 100644
--- gcc/testsuite/g++.dg/expr/lval3.C
+++ gcc/testsuite/g++.dg/expr/lval3.C
@@ -4,6 +4,7 @@ f()
 {
   bool i = 0;
   i++ = 3; // { dg-error "" }
+  // { dg-warning "deprecated" "" { target *-*-* } 6 }
 }
 
 
diff --git gcc/testsuite/g++.dg/expr/lval4.C gcc/testsuite/g++.dg/expr/lval4.C
index c66e2f6..b903ec8 100644
--- gcc/testsuite/g++.dg/expr/lval4.C
+++ gcc/testsuite/g++.dg/expr/lval4.C
@@ -4,6 +4,7 @@ f()
 {
   bool i = 0;
   ++i = 3;
+  // { dg-warning "deprecated" "" { target *-*-* } 6 }
 }
 
 
diff --git gcc/testsuite/g++.old-deja/g++.jason/bool5.C 
gcc/testsuite/g++.old-deja/g++.jason/bool5.C
index 1d2f5b6..0a16ccb 100644
--- gcc/testsuite/g++.old-deja/g++.jason/bool5.C
+++ gcc/testsuite/g++.old-deja/g++.jason/bool5.C
@@ -2,10 +2,10 @@
 int main ()
 {
   bool b = false;
-  int i = b++;
+  int i = b++; // { dg-warning "deprecated" }
   if (i != false || b != true)
     return 1;
-  i = b++;
+  i = b++; // { dg-warning "deprecated" }
   if (i != true || b != true)
     return 1;
 }

        Marek

Reply via email to