diff options
| -rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 11 | ||||
| -rw-r--r-- | clang/test/Sema/compare.c | 5 |
2 files changed, 16 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index f2520fc5eb7..5091daf3235 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1885,6 +1885,17 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { // Left shift gets black-listed based on a judgement call. case BinaryOperator::Shl: + // ...except that we want to treat '1 << (blah)' as logically + // positive. It's an important idiom. + if (IntegerLiteral *I + = dyn_cast<IntegerLiteral>(BO->getLHS()->IgnoreParenCasts())) { + if (I->getValue() == 1) { + IntRange R = IntRange::forType(C, E->getType()); + return IntRange(R.Width, /*NonNegative*/ true); + } + } + // fallthrough + case BinaryOperator::ShlAssign: return IntRange::forType(C, E->getType()); diff --git a/clang/test/Sema/compare.c b/clang/test/Sema/compare.c index 7c8c36f0c14..631b6942029 100644 --- a/clang/test/Sema/compare.c +++ b/clang/test/Sema/compare.c @@ -282,3 +282,8 @@ int test5(unsigned int x) { && (x >= 0) // expected-warning {{comparison of unsigned expression >= 0 is always true}} && (0 <= x); // expected-warning {{comparison of 0 <= unsigned expression is always true}} } + +int test6(unsigned i, unsigned power) { + unsigned x = (i < (1 << power) ? i : 0); + return x != 3 ? 1 << power : i; +} |

