diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/StaticAnalyzer/Core/APSIntType.cpp | 31 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/RangeConstraintManager.cpp | 16 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp | 8 |
3 files changed, 35 insertions, 20 deletions
diff --git a/lib/StaticAnalyzer/Core/APSIntType.cpp b/lib/StaticAnalyzer/Core/APSIntType.cpp index 884b0faa9e..c7e9526821 100644 --- a/lib/StaticAnalyzer/Core/APSIntType.cpp +++ b/lib/StaticAnalyzer/Core/APSIntType.cpp @@ -13,20 +13,31 @@ using namespace clang; using namespace ento; APSIntType::RangeTestResultKind -APSIntType::testInRange(const llvm::APSInt &Value) const { +APSIntType::testInRange(const llvm::APSInt &Value, + bool AllowSignConversions) const { + // Negative numbers cannot be losslessly converted to unsigned type. - if (IsUnsigned && Value.isSigned() && Value.isNegative()) + if (IsUnsigned && !AllowSignConversions && + Value.isSigned() && Value.isNegative()) return RTR_Below; - // Signed integers can be converted to signed integers of the same width - // or (if positive) unsigned integers with one fewer bit. - // Unsigned integers can be converted to unsigned integers of the same width - // or signed integers with one more bit. unsigned MinBits; - if (Value.isSigned()) - MinBits = Value.getMinSignedBits() - IsUnsigned; - else - MinBits = Value.getActiveBits() + !IsUnsigned; + if (AllowSignConversions) { + if (Value.isSigned() && !IsUnsigned) + MinBits = Value.getMinSignedBits(); + else + MinBits = Value.getActiveBits(); + + } else { + // Signed integers can be converted to signed integers of the same width + // or (if positive) unsigned integers with one fewer bit. + // Unsigned integers can be converted to unsigned integers of the same width + // or signed integers with one more bit. + if (Value.isSigned()) + MinBits = Value.getMinSignedBits() - IsUnsigned; + else + MinBits = Value.getActiveBits() + !IsUnsigned; + } if (MinBits <= BitWidth) return RTR_Within; diff --git a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp index 216fb3d4b0..3606e099ce 100644 --- a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -153,8 +153,8 @@ private: // The function returns false if the described range is entirely outside // the range of values for the associated symbol. APSIntType Type(getMinValue()); - APSIntType::RangeTestResultKind LowerTest = Type.testInRange(Lower); - APSIntType::RangeTestResultKind UpperTest = Type.testInRange(Upper); + APSIntType::RangeTestResultKind LowerTest = Type.testInRange(Lower, true); + APSIntType::RangeTestResultKind UpperTest = Type.testInRange(Upper, true); switch (LowerTest) { case APSIntType::RTR_Below: @@ -419,7 +419,7 @@ RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Adjustment) { // Before we do any real work, see if the value can even show up. APSIntType AdjustmentType(Adjustment); - if (AdjustmentType.testInRange(Int) != APSIntType::RTR_Within) + if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within) return St; llvm::APSInt Lower = AdjustmentType.convert(Int) - Adjustment; @@ -439,7 +439,7 @@ RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Adjustment) { // Before we do any real work, see if the value can even show up. APSIntType AdjustmentType(Adjustment); - if (AdjustmentType.testInRange(Int) != APSIntType::RTR_Within) + if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within) return NULL; // [Int-Adjustment, Int-Adjustment] @@ -454,7 +454,7 @@ RangeConstraintManager::assumeSymLT(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Adjustment) { // Before we do any real work, see if the value can even show up. APSIntType AdjustmentType(Adjustment); - switch (AdjustmentType.testInRange(Int)) { + switch (AdjustmentType.testInRange(Int, true)) { case APSIntType::RTR_Below: return NULL; case APSIntType::RTR_Within: @@ -483,7 +483,7 @@ RangeConstraintManager::assumeSymGT(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Adjustment) { // Before we do any real work, see if the value can even show up. APSIntType AdjustmentType(Adjustment); - switch (AdjustmentType.testInRange(Int)) { + switch (AdjustmentType.testInRange(Int, true)) { case APSIntType::RTR_Below: return St; case APSIntType::RTR_Within: @@ -512,7 +512,7 @@ RangeConstraintManager::assumeSymGE(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Adjustment) { // Before we do any real work, see if the value can even show up. APSIntType AdjustmentType(Adjustment); - switch (AdjustmentType.testInRange(Int)) { + switch (AdjustmentType.testInRange(Int, true)) { case APSIntType::RTR_Below: return St; case APSIntType::RTR_Within: @@ -541,7 +541,7 @@ RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Adjustment) { // Before we do any real work, see if the value can even show up. APSIntType AdjustmentType(Adjustment); - switch (AdjustmentType.testInRange(Int)) { + switch (AdjustmentType.testInRange(Int, true)) { case APSIntType::RTR_Below: return NULL; case APSIntType::RTR_Within: diff --git a/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp b/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp index 4ff248785a..f6404f0f77 100644 --- a/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp @@ -264,10 +264,14 @@ ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state, APSIntType ComparisonType = std::max(WraparoundType, APSIntType(Int)); llvm::APSInt ConvertedInt = ComparisonType.convert(Int); + // Prefer unsigned comparisons. + if (ComparisonType.getBitWidth() == WraparoundType.getBitWidth() && + ComparisonType.isUnsigned() && !WraparoundType.isUnsigned()) + Adjustment.setIsSigned(false); + switch (op) { default: - // No logic yet for other operators. assume the constraint is feasible. - return state; + llvm_unreachable("invalid operation not caught by assertion above"); case BO_EQ: return assumeSymEQ(state, Sym, ConvertedInt, Adjustment); |