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/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);