manas updated this revision to Diff 352283.
manas edited the summary of this revision.
manas added a comment.
Herald added a subscriber: martong.
Add logic for computing rangeset for an expression containing BO_Add.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D103440/new/
https://reviews.llvm.org/D103440
Files:
clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
clang/test/Analysis/constant-folding.c
Index: clang/test/Analysis/constant-folding.c
===================================================================
--- clang/test/Analysis/constant-folding.c
+++ clang/test/Analysis/constant-folding.c
@@ -251,3 +251,83 @@
clang_analyzer_eval((b % a) < x + 10); // expected-warning{{TRUE}}
}
}
+
+void testAdditionRules(unsigned int a, unsigned int b, int c, int d) {
+ if (a == 0) {
+ clang_analyzer_eval((a + 0) == 0); // expected-warning{{TRUE}}
+ }
+
+ // Checks for unsigned operands
+ clang_analyzer_eval((a + b) < 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval((a + b) <= UINT_MAX); // expected-warning{{TRUE}}
+
+ if (a == UINT_MAX && b == UINT_MAX) {
+ clang_analyzer_eval((a + b) == UINT_MAX - 1); // expected-warning{{TRUE}}
+ }
+
+ // Checks for inclusive ranges for unsigned integers
+ if (a >= 0 && a <= 10 && b >= 0 && b <= 20) {
+ clang_analyzer_eval((a + b) >= 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval((a + b) > 30); // expected-warning{{FALSE}}
+ }
+
+ // Checks for negative signed integers
+ if (c < 0 && d < 0) {
+ clang_analyzer_eval((c + d) < 0); // expected-warning{{UNKNOWN}}
+ }
+
+ if (c < 0 && c != INT_MIN && d < 0) {
+ clang_analyzer_eval((c + d) == -1); // expected-warning{{FALSE}}
+ clang_analyzer_eval((c + d) == 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval((c + d) <= -2); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval((c + d) >= 1); // expected-warning{{UNKNOWN}}
+ }
+
+ if (c == INT_MIN && d == INT_MIN) {
+ clang_analyzer_eval((c + d) == 0); // expected-warning{{TRUE}}
+ }
+
+ if (c == INT_MIN && d < 0 && d != INT_MIN) {
+ clang_analyzer_eval((c + d) > 0); // expected-warning{{TRUE}}
+ }
+
+ if (c < 0 && c >= -20 && d < 0 && d >= -40) {
+ clang_analyzer_eval((c + d) < -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval((c + d) >= -60); // expected-warning{{TRUE}}
+ }
+
+ // Checks for integers with different sign bits
+ if (c < 0 && d > 0) {
+ if (c >= -20 && d <= 10) {
+ clang_analyzer_eval((c + d) > -20); // expected-warning{{TRUE}}
+ clang_analyzer_eval((c + d) < 10); // expected-warning{{TRUE}}
+ }
+ }
+
+ // Checks for overlapping signed integers ranges
+ if (c >= -20 && c <= 20 && d >= -10 && d <= 10) {
+ clang_analyzer_eval((c + d) >= -30); // expected-warning{{TRUE}}
+ clang_analyzer_eval((c + d) <= 30); // expected-warning{{TRUE}}
+ }
+
+ // Checks for positive signed integers
+ if (c > 0 && d > 0) {
+ clang_analyzer_eval((c + d) == 1); // expected-warning{{FALSE}}
+ clang_analyzer_eval((c + d) == 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval((c + d) == -1); // expected-warning{{FALSE}}
+ clang_analyzer_eval((c + d) > 1); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval((c + d) < -1); // expected-warning{{UNKNOWN}}
+ }
+
+ // Checks producing overflowing range with different signs
+ int HALF_INT_MAX = INT_MAX / 2;
+ if (c >= HALF_INT_MAX - 10 && c <= HALF_INT_MAX + 10 &&
+ d >= HALF_INT_MAX - 10 && d <= HALF_INT_MAX + 10) {
+ // The resulting range for (c + d) will be:
+ // [INT_MIN, INT_MIN + 18] U [INT_MAX - 21, INT_MAX]
+ clang_analyzer_eval((c + d) <= INT_MIN + 18); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval((c + d) >= INT_MAX - 21); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval((c + d) == INT_MIN + 19); // expected-warning{{FALSE}}
+ clang_analyzer_eval((c + d) == INT_MAX - 22); // expected-warning{{FALSE}}
+ }
+}
Index: clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -954,6 +954,8 @@
return VisitBinaryOperator<BO_And>(LHS, RHS, T);
case BO_Rem:
return VisitBinaryOperator<BO_Rem>(LHS, RHS, T);
+ case BO_Add:
+ return VisitBinaryOperator<BO_Add>(LHS, RHS, T);
default:
return infer(T);
}
@@ -1370,6 +1372,51 @@
return {RangeFactory, ValueFactory.getValue(Min), ValueFactory.getValue(Max)};
}
+template <>
+RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Add>(Range LHS,
+ Range RHS,
+ QualType T) {
+ APSIntType ResultType = ValueFactory.getAPSIntType(T);
+ llvm::APSInt Min = LHS.From() + RHS.From();
+ llvm::APSInt Max = LHS.To() + RHS.To();
+ llvm::APSInt Tmin = ValueFactory.getMinValue(ResultType);
+ llvm::APSInt Tmax = ValueFactory.getMaxValue(ResultType);
+
+ if (Min > Max) {
+ // This implies that an overflow has occured as Max would have wrapped
+ // around the limits of T.
+ //
+ // There are two possibilities while computing:
+ // 1. Range [Tmin, Max] did not overlap Min. In this case, the final
+ // RangeSet will be [Tmin, Max] U [Min, Tmax].
+ // 2. Range overlaps Min, and in this case, it will return [Tmin, Tmax].
+ //
+ if ((LHS.From() > 0 && RHS.From() > 0 && Min < 0) ||
+ (LHS.From() < 0 && RHS.From() < 0 && Min > 0) ||
+ (LHS.To() < 0 && RHS.To() < 0 && Max > 0) ||
+ (LHS.To() < 0 && RHS.To() < 0 && Max > 0)) {
+ return {RangeFactory, Tmin, Tmax};
+ }
+
+ // FIXME: This case in particular is resulting in failed assertion.
+ Range First = Range(Tmin, Max);
+ Range Second = Range(Min, Tmax);
+ RangeSet ResultRangeSet = RangeFactory.getRangeSet(First);
+ RangeSet ResultRangeSet2 = RangeFactory.add(ResultRangeSet, Second);
+ return ResultRangeSet2;
+ }
+
+ if ((LHS.From() > 0 && RHS.From() > 0 && Min < 0) ||
+ (LHS.From() < 0 && RHS.From() < 0 && Min > 0) ||
+ (LHS.To() > 0 && RHS.To() > 0 && Max < 0) ||
+ (LHS.To() < 0 && RHS.To() < 0 && Max > 0)) {
+ // return [Tmin, Tmax]
+ return {RangeFactory, Tmin, Tmax};
+ }
+
+ return {RangeFactory, ValueFactory.getValue(Min), ValueFactory.getValue(Max)};
+}
+
//===----------------------------------------------------------------------===//
// Constraint manager implementation details
//===----------------------------------------------------------------------===//
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits