From: Ted Kremenek Date: Mon, 13 Jul 2009 21:55:12 +0000 (+0000) Subject: Enhance SimpleSValuator::EvalBinOpNN to recognize the trivial case X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=54ca9b1d45fbfb0b3eeab581e0d10403cc922e62;p=clang Enhance SimpleSValuator::EvalBinOpNN to recognize the trivial case where we are comparing a symbolic value against itself, regardless of the nature of that symbolic value. This enhancement identified a case where RegionStoreManager is not correctly symbolicating the values of the pointees of parameters. The failing test is now in 'test/Analysis/misc-ps-region-store.m', with that test file now (temporarily) marked XFAIL. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75521 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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 + } +} +