[clang] cac8808 - [analyzer][solver] Introduce reasoning for not equal to operator
Gabor Marton via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 22 03:00:54 PDT 2021
Author: Manas
Date: 2021-10-22T12:00:08+02:00
New Revision: cac8808f154cef6446e507d55aba5721c3bd5352
URL: https://github.com/llvm/llvm-project/commit/cac8808f154cef6446e507d55aba5721c3bd5352
DIFF: https://github.com/llvm/llvm-project/commit/cac8808f154cef6446e507d55aba5721c3bd5352.diff
LOG: [analyzer][solver] Introduce reasoning for not equal to operator
Prior to this, the solver was only able to verify whether two symbols
are equal/unequal, only when constants were involved. This patch allows
the solver to work over ranges as well.
Reviewed By: steakhal, martong
Differential Revision: https://reviews.llvm.org/D106102
Patch by: @manas (Manas Gupta)
Added:
Modified:
clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
clang/test/Analysis/constant-folding.c
Removed:
################################################################################
diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index e75a207ee86a..2f69191a1792 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -20,8 +20,8 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableSet.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -955,18 +955,7 @@ class SymbolicRangeInferrer
}
RangeSet VisitBinaryOperator(RangeSet LHS, BinaryOperator::Opcode Op,
- RangeSet RHS, QualType T) {
- switch (Op) {
- case BO_Or:
- return VisitBinaryOperator<BO_Or>(LHS, RHS, T);
- case BO_And:
- return VisitBinaryOperator<BO_And>(LHS, RHS, T);
- case BO_Rem:
- return VisitBinaryOperator<BO_Rem>(LHS, RHS, T);
- default:
- return infer(T);
- }
- }
+ RangeSet RHS, QualType T);
//===----------------------------------------------------------------------===//
// Ranges and operators
@@ -1231,6 +1220,29 @@ class SymbolicRangeInferrer
// Range-based reasoning about symbolic operations
//===----------------------------------------------------------------------===//
+template <>
+RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_NE>(RangeSet LHS,
+ RangeSet RHS,
+ QualType T) {
+ // When both the RangeSets are non-overlapping then all possible pairs of
+ // (x, y) in LHS, RHS respectively, will satisfy expression (x != y).
+ if ((LHS.getMaxValue() < RHS.getMinValue()) ||
+ (LHS.getMinValue() > RHS.getMaxValue())) {
+ return getTrueRange(T);
+ }
+
+ // If both RangeSets contain only one Point which is equal then the
+ // expression will always return true.
+ if ((LHS.getMinValue() == RHS.getMaxValue()) &&
+ (LHS.getMaxValue() == RHS.getMaxValue()) &&
+ (LHS.getMinValue() == RHS.getMinValue())) {
+ return getFalseRange(T);
+ }
+
+ // In all other cases, the resulting range cannot be deduced.
+ return infer(T);
+}
+
template <>
RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Or>(Range LHS, Range RHS,
QualType T) {
@@ -1391,6 +1403,23 @@ RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Rem>(Range LHS,
return {RangeFactory, ValueFactory.getValue(Min), ValueFactory.getValue(Max)};
}
+RangeSet SymbolicRangeInferrer::VisitBinaryOperator(RangeSet LHS,
+ BinaryOperator::Opcode Op,
+ RangeSet RHS, QualType T) {
+ switch (Op) {
+ case BO_NE:
+ return VisitBinaryOperator<BO_NE>(LHS, RHS, T);
+ case BO_Or:
+ return VisitBinaryOperator<BO_Or>(LHS, RHS, T);
+ case BO_And:
+ return VisitBinaryOperator<BO_And>(LHS, RHS, T);
+ case BO_Rem:
+ return VisitBinaryOperator<BO_Rem>(LHS, RHS, T);
+ default:
+ return infer(T);
+ }
+}
+
//===----------------------------------------------------------------------===//
// Constraint manager implementation details
//===----------------------------------------------------------------------===//
diff --git a/clang/test/Analysis/constant-folding.c b/clang/test/Analysis/constant-folding.c
index 116e74b746b4..9dab78e3e198 100644
--- a/clang/test/Analysis/constant-folding.c
+++ b/clang/test/Analysis/constant-folding.c
@@ -281,3 +281,49 @@ void testRemainderRules(unsigned int a, unsigned int b, int c, int d) {
clang_analyzer_eval((b % a) < x + 10); // expected-warning{{TRUE}}
}
}
+
+void testDisequalityRules(unsigned int u1, unsigned int u2, int s1, int s2) {
+ // Checks when ranges are not overlapping
+ if (u1 <= 10 && u2 >= 20) {
+ // u1: [0,10], u2: [20,UINT_MAX]
+ clang_analyzer_eval((u1 != u2) != 0); // expected-warning{{TRUE}}
+ }
+
+ if (s1 <= INT_MIN + 10 && s2 >= INT_MAX - 10) {
+ // s1: [INT_MIN,INT_MIN + 10], s2: [INT_MAX - 10,INT_MAX]
+ clang_analyzer_eval((s1 != s2) == 0); // expected-warning{{FALSE}}
+ }
+
+ // Checks when ranges are completely overlapping and have more than one point
+ if (u1 >= 20 && u1 <= 50 && u2 >= 20 && u2 <= 50) {
+ // u1: [20,50], u2: [20,50]
+ clang_analyzer_eval((u1 != u2) != 0); // expected-warning{{UNKNOWN}}
+ }
+
+ if (s1 >= -20 && s1 <= 20 && s2 >= -20 && s2 <= 20) {
+ // s1: [-20,20], s2: [-20,20]
+ clang_analyzer_eval((s1 != s2) != 0); // expected-warning{{UNKNOWN}}
+ }
+
+ // Checks when ranges are partially overlapping
+ if (u1 >= 100 && u1 <= 200 && u2 >= 150 && u2 <= 300) {
+ // u1: [100,200], u2: [150,300]
+ clang_analyzer_eval((u1 != u2) != 0); // expected-warning{{UNKNOWN}}
+ }
+
+ if (s1 >= -80 && s1 <= -50 && s2 >= -100 && s2 <= -75) {
+ // s1: [-80,-50], s2: [-100,-75]
+ clang_analyzer_eval((s1 != s2) == 0); // expected-warning{{UNKNOWN}}
+ }
+
+ // Checks for ranges which are subset of one-another
+ if (u1 >= 500 && u1 <= 1000 && u2 >= 750 && u2 <= 1000) {
+ // u1: [500,1000], u2: [750,1000]
+ clang_analyzer_eval((u1 != u2) == 0); // expected-warning{{UNKNOWN}}
+ }
+
+ if (s1 >= -1000 && s1 <= -500 && s2 <= -500 && s2 >= -750) {
+ // s1: [-1000,-500], s2: [-500,-750]
+ clang_analyzer_eval((s1 != s2) == 0); // expected-warning{{UNKNOWN}}
+ }
+}
More information about the cfe-commits
mailing list