Implement checks for bool in increment and decrement.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61275 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index 6b11d31..b1c5cbd 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -1298,6 +1298,10 @@
      "cannot delete expression of type %0")
 DIAG(warn_delete_incomplete, WARNING,
      "deleting pointer to incomplete type %0 may cause undefined behaviour")
+DIAG(err_decrement_bool, ERROR,
+     "cannot decrement expression of type bool")
+DIAG(warn_increment_bool, WARNING,
+     "incrementing expression of type bool is deprecated")
 
 DIAG(err_invalid_use_of_function_type, ERROR,
      "a function type is not allowed here")
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 56b681c..9cab330 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1306,7 +1306,8 @@
   
   /// type checking unary operators (subroutines of ActOnUnaryOp).
   /// C99 6.5.3.1, 6.5.3.2, 6.5.3.4
-  QualType CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc);   
+  QualType CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc,
+                                          bool isInc);
   QualType CheckAddressOfOperand(Expr *op, SourceLocation OpLoc);
   QualType CheckIndirectionOperand(Expr *op, SourceLocation OpLoc);
   QualType CheckRealImagOperand(Expr *&Op, SourceLocation OpLoc);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index da03548..51e4e05 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -952,7 +952,8 @@
     // build a built-in operation.
   }
 
-  QualType result = CheckIncrementDecrementOperand(Arg, OpLoc);
+  QualType result = CheckIncrementDecrementOperand(Arg, OpLoc,
+                                                 Opc == UnaryOperator::PostInc);
   if (result.isNull())
     return true;
   return new UnaryOperator(Arg, Opc, result, OpLoc);
@@ -2762,12 +2763,20 @@
 
 /// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine
 /// doesn't need to call UsualUnaryConversions or UsualArithmeticConversions.
-QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc) {
+QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc,
+                                              bool isInc) {
   QualType ResType = Op->getType();
   assert(!ResType.isNull() && "no type for increment/decrement expression");
 
-  // C99 6.5.2.4p1: We allow complex as a GCC extension.
-  if (ResType->isRealType()) {
+  if (getLangOptions().CPlusPlus && ResType->isBooleanType()) {
+    // Decrement of bool is not allowed.
+    if (!isInc) {
+      Diag(OpLoc, diag::err_decrement_bool) << Op->getSourceRange();
+      return QualType();
+    }
+    // Increment of bool sets it to true, but is deprecated.
+    Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange();
+  } else if (ResType->isRealType()) {
     // OK!
   } else if (const PointerType *PT = ResType->getAsPointerType()) {
     // C99 6.5.2.4p2, 6.5.6p2
@@ -3350,7 +3359,8 @@
     assert(0 && "Unimplemented unary expr!");
   case UnaryOperator::PreInc:
   case UnaryOperator::PreDec:
-    resultType = CheckIncrementDecrementOperand(Input, OpLoc);
+    resultType = CheckIncrementDecrementOperand(Input, OpLoc,
+                                                Opc == UnaryOperator::PreInc);
     break;
   case UnaryOperator::AddrOf: 
     resultType = CheckAddressOfOperand(Input, OpLoc);
diff --git a/test/SemaCXX/bool.cpp b/test/SemaCXX/bool.cpp
index e35495a..e606a51 100644
--- a/test/SemaCXX/bool.cpp
+++ b/test/SemaCXX/bool.cpp
@@ -5,3 +5,12 @@
   ReadWrite = false,
   ReadOnly = true
 };
+
+// bool cannot be decremented, and gives a warning on increment
+void test(bool b)
+{
+  ++b; // expected-warning {{incrementing expression of type bool is deprecated}}
+  b++; // expected-warning {{incrementing expression of type bool is deprecated}}
+  --b; // expected-error {{cannot decrement expression of type bool}}
+  b--; // expected-error {{cannot decrement expression of type bool}}
+}
diff --git a/www/cxx_status.html b/www/cxx_status.html
index 2bb64e9..8748a0e 100644
--- a/www/cxx_status.html
+++ b/www/cxx_status.html
@@ -548,9 +548,9 @@
   <td>&nbsp;&nbsp;&nbsp;&nbsp;5.2.6 [expr.post.incr]</td>

   <td class="complete" align="center">&#x2713;</td>

   <td class="complete" align="center">&#x2713;</td>

-  <td class="advanced"></td>

+  <td class="complete" align="center">&#x2713;</td>

   <td></td>

-  <td>Decrement of bool is accepted, increment not warned about</td>

+  <td></td>

 </tr>

 <tr>

   <td>&nbsp;&nbsp;&nbsp;&nbsp;5.2.7 [expr.dynamic.cast]</td>

@@ -646,9 +646,9 @@
   <td>&nbsp;&nbsp;&nbsp;&nbsp;5.3.2 [expr.pre.incr]</td>

   <td class="complete" align="center">&#x2713;</td>

   <td class="complete" align="center">&#x2713;</td>

-  <td class="advanced"></td>

+  <td class="complete" align="center">&#x2713;</td>

   <td></td>

-  <td>Decrement of bool is accepted, increment not warned about</td>

+  <td></td>

 </tr>

 <tr>

   <td>&nbsp;&nbsp;&nbsp;&nbsp;5.3.3 [expr.sizeof]</td>