aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Analysis/SimpleSValuator.cpp21
-rw-r--r--test/Analysis/misc-ps-basic-store.m14
-rw-r--r--test/Analysis/misc-ps-region-store.m15
-rw-r--r--test/Analysis/misc-ps.m17
4 files changed, 66 insertions, 1 deletions
diff --git a/lib/Analysis/SimpleSValuator.cpp b/lib/Analysis/SimpleSValuator.cpp
index 76a8bc782e..eea50d13cf 100644
--- a/lib/Analysis/SimpleSValuator.cpp
+++ b/lib/Analysis/SimpleSValuator.cpp
@@ -176,7 +176,26 @@ static SVal EvalEquality(ValueManager &ValMgr, Loc lhs, Loc rhs, bool isEqual,
SVal SimpleSValuator::EvalBinOpNN(BinaryOperator::Opcode op,
NonLoc lhs, NonLoc rhs,
- QualType resultTy) {
+ QualType resultTy) {
+
+ assert(!lhs.isUnknownOrUndef());
+ assert(!rhs.isUnknownOrUndef());
+
+ // Handle trivial case where left-side and right-side are the same.
+ if (lhs == rhs)
+ switch (op) {
+ default:
+ break;
+ case BinaryOperator::EQ:
+ case BinaryOperator::LE:
+ case BinaryOperator::GE:
+ return ValMgr.makeTruthVal(true, resultTy);
+ case BinaryOperator::LT:
+ case BinaryOperator::GT:
+ case BinaryOperator::NE:
+ return ValMgr.makeTruthVal(false, resultTy);
+ }
+
while (1) {
switch (lhs.getSubKind()) {
default:
diff --git a/test/Analysis/misc-ps-basic-store.m b/test/Analysis/misc-ps-basic-store.m
index 55e39cf92c..8e089d5000 100644
--- a/test/Analysis/misc-ps-basic-store.m
+++ b/test/Analysis/misc-ps-basic-store.m
@@ -20,3 +20,17 @@ void checkaccess_union() {
).__i))) & 0xff00) >> 8) == 1)
ret = 1;
}
+
+// BasicStore handles this case incorrectly because it doesn't reason about
+// the value pointed to by 'x' and thus creates different symbolic values
+// at the declarations of 'a' and 'b' respectively. See the companion test
+// in 'misc-ps-region-store.m'.
+void test_trivial_symbolic_comparison_pointer_parameter(int *x) {
+ int a = *x;
+ int b = *x;
+ if (a != b) {
+ int *p = 0;
+ *p = 0xDEADBEEF; // expected-warning{{null}}
+ }
+}
+
diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m
index 8c8815ea63..7231353b6b 100644
--- a/test/Analysis/misc-ps-region-store.m
+++ b/test/Analysis/misc-ps-region-store.m
@@ -1,4 +1,5 @@
// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region --verify -fblocks %s
+// XFAIL
typedef struct objc_selector *SEL;
typedef signed char BOOL;
@@ -68,3 +69,17 @@ char test2() {
return 'a';
}
+// *** THIS TEST IS CURRENTLY FAILING ***
+// BasicStore handles this case incorrectly because it doesn't reason about
+// the value pointed to by 'x' and thus creates different symbolic values
+// at the declarations of 'a' and 'b' respectively. RegionStore handles
+// it correctly. See the companion test in 'misc-ps-basic-store.m'.
+void test_trivial_symbolic_comparison_pointer_parameter(int *x) {
+ int a = *x;
+ int b = *x;
+ if (a != b) {
+ int *p = 0;
+ *p = 0xDEADBEEF; // no-warning
+ }
+}
+
diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m
index 46e8d3703f..93bb1f347c 100644
--- a/test/Analysis/misc-ps.m
+++ b/test/Analysis/misc-ps.m
@@ -371,3 +371,20 @@ void testB(BStruct *b) {
}
}
+void test_trivial_symbolic_comparison(int *x) {
+ int test_trivial_symbolic_comparison_aux();
+ int a = test_trivial_symbolic_comparison_aux();
+ int b = a;
+ if (a != b) {
+ int *p = 0;
+ *p = 0xDEADBEEF; // no-warning
+ }
+
+ a = a == 1;
+ b = b == 1;
+ if (a != b) {
+ int *p = 0;
+ *p = 0xDEADBEEF; // no-warning
+ }
+}
+