diff options
-rw-r--r-- | include/clang/Basic/DiagnosticKinds.def | 4 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 3 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 20 | ||||
-rw-r--r-- | test/SemaCXX/bool.cpp | 9 | ||||
-rw-r--r-- | www/cxx_status.html | 8 |
5 files changed, 34 insertions, 10 deletions
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 6b11d31701..b1c5cbdaa8 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -1298,6 +1298,10 @@ DIAG(err_delete_operand, ERROR, "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 56b681c070..9cab3308c5 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1306,7 +1306,8 @@ public: /// 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 da0354886c..51e4e05eec 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -952,7 +952,8 @@ Action::ExprResult Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, // 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 @@ QualType Sema::CheckCommaOperands(Expr *LHS, Expr *&RHS, SourceLocation Loc) { /// 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 @@ Action::ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc, 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 e35495abab..e606a518d7 100644 --- a/test/SemaCXX/bool.cpp +++ b/test/SemaCXX/bool.cpp @@ -5,3 +5,12 @@ enum { 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 2bb64e9a71..8748a0e605 100644 --- a/www/cxx_status.html +++ b/www/cxx_status.html @@ -548,9 +548,9 @@ welcome!</p> <td> 5.2.6 [expr.post.incr]</td>
<td class="complete" align="center">✓</td>
<td class="complete" align="center">✓</td>
- <td class="advanced"></td>
+ <td class="complete" align="center">✓</td>
+ <td></td>
<td></td>
- <td>Decrement of bool is accepted, increment not warned about</td>
</tr>
<tr>
<td> 5.2.7 [expr.dynamic.cast]</td>
@@ -646,9 +646,9 @@ welcome!</p> <td> 5.3.2 [expr.pre.incr]</td>
<td class="complete" align="center">✓</td>
<td class="complete" align="center">✓</td>
- <td class="advanced"></td>
+ <td class="complete" align="center">✓</td>
+ <td></td>
<td></td>
- <td>Decrement of bool is accepted, increment not warned about</td>
</tr>
<tr>
<td> 5.3.3 [expr.sizeof]</td>
|