aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2012-08-24 07:42:09 +0000
committerTed Kremenek <kremenek@apple.com>2012-08-24 07:42:09 +0000
commit3d1125b27e8006385a830f5b3748b7b44d227b4c (patch)
tree6606420ad0ddbd9cea40556bc359104311a4e6c6
parent8268fe7c4bdfa341975a687a8a5e236c2c5b88a4 (diff)
Teach CFG that 'if (x & 0)' and 'if (x * 0)' is an unfeasible branch.
Fixes <rdar://problem/11005770>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162545 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Analysis/CFG.cpp24
-rw-r--r--test/Sema/warn-unreachable.c9
2 files changed, 33 insertions, 0 deletions
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 70ea990f55..f811fa3f0f 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -467,6 +467,30 @@ private:
CachedBoolEvals[S] = Result; // update or insert
return Result;
}
+ else {
+ switch (Bop->getOpcode()) {
+ default: break;
+ // For 'x & 0' and 'x * 0', we can determine that
+ // the value is always false.
+ case BO_Mul:
+ case BO_And: {
+ // If either operand is zero, we know the value
+ // must be false.
+ llvm::APSInt IntVal;
+ if (Bop->getLHS()->EvaluateAsInt(IntVal, *Context)) {
+ if (IntVal.getBoolValue() == false) {
+ return TryResult(false);
+ }
+ }
+ if (Bop->getRHS()->EvaluateAsInt(IntVal, *Context)) {
+ if (IntVal.getBoolValue() == false) {
+ return TryResult(false);
+ }
+ }
+ }
+ break;
+ }
+ }
}
return evaluateAsBooleanConditionNoCache(S);
diff --git a/test/Sema/warn-unreachable.c b/test/Sema/warn-unreachable.c
index 636513f62c..2fbe1c78eb 100644
--- a/test/Sema/warn-unreachable.c
+++ b/test/Sema/warn-unreachable.c
@@ -132,3 +132,12 @@ void PR9774(int *s) {
s[i] = 0;
}
+// Test case for <rdar://problem/11005770>. We should treat code guarded
+// by 'x & 0' and 'x * 0' as unreachable.
+void calledFun();
+void test_mul_and_zero(int x) {
+ if (x & 0) calledFun(); // expected-warning {{will never be executed}}
+ if (0 & x) calledFun(); // expected-warning {{will never be executed}}
+ if (x * 0) calledFun(); // expected-warning {{will never be executed}}
+ if (0 * x) calledFun(); // expected-warning {{will never be executed}}
+}