aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core/RangeConstraintManager.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/RangeConstraintManager.cpp86
1 files changed, 62 insertions, 24 deletions
diff --git a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index d9b58d0f5185..64724227395d 100644
--- a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -1,9 +1,8 @@
//== RangeConstraintManager.cpp - Manage range constraints.------*- C++ -*--==//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -12,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Basic/JsonSupport.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
@@ -174,6 +174,22 @@ RangeSet RangeSet::Intersect(BasicValueFactory &BV, Factory &F,
return newRanges;
}
+// Returns a set containing the values in the receiving set, intersected with
+// the range set passed as parameter.
+RangeSet RangeSet::Intersect(BasicValueFactory &BV, Factory &F,
+ const RangeSet &Other) const {
+ PrimRangeSet newRanges = F.getEmptySet();
+
+ for (iterator i = Other.begin(), e = Other.end(); i != e; ++i) {
+ RangeSet newPiece = Intersect(BV, F, i->From(), i->To());
+ for (iterator j = newPiece.begin(), ee = newPiece.end(); j != ee; ++j) {
+ newRanges = F.add(newRanges, *j);
+ }
+ }
+
+ return newRanges;
+}
+
// Turn all [A, B] ranges to [-B, -A]. Ranges [MIN, B] are turned to range set
// [MIN, MIN] U [-B, MAX], when MIN and MAX are the minimal and the maximal
// signed values of the type.
@@ -231,6 +247,11 @@ public:
// Implementation for interface from ConstraintManager.
//===------------------------------------------------------------------===//
+ bool haveEqualConstraints(ProgramStateRef S1,
+ ProgramStateRef S2) const override {
+ return S1->get<ConstraintRange>() == S2->get<ConstraintRange>();
+ }
+
bool canReasonAbout(SVal X) const override;
ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override;
@@ -241,8 +262,8 @@ public:
ProgramStateRef removeDeadBindings(ProgramStateRef State,
SymbolReaper &SymReaper) override;
- void print(ProgramStateRef State, raw_ostream &Out, const char *nl,
- const char *sep) override;
+ void printJson(raw_ostream &Out, ProgramStateRef State, const char *NL = "\n",
+ unsigned int Space = 0, bool IsDot = false) const override;
//===------------------------------------------------------------------===//
// Implementation for interface from RangedConstraintManager.
@@ -457,14 +478,21 @@ static RangeSet applyBitwiseConstraints(
RangeSet RangeConstraintManager::getRange(ProgramStateRef State,
SymbolRef Sym) {
- if (ConstraintRangeTy::data_type *V = State->get<ConstraintRange>(Sym))
- return *V;
-
- BasicValueFactory &BV = getBasicVals();
+ ConstraintRangeTy::data_type *V = State->get<ConstraintRange>(Sym);
// If Sym is a difference of symbols A - B, then maybe we have range set
// stored for B - A.
- if (const RangeSet *R = getRangeForMinusSymbol(State, Sym))
+ BasicValueFactory &BV = getBasicVals();
+ const RangeSet *R = getRangeForMinusSymbol(State, Sym);
+
+ // If we have range set stored for both A - B and B - A then calculate the
+ // effective range set by intersecting the range set for A - B and the
+ // negated range set of B - A.
+ if (V && R)
+ return V->Intersect(BV, F, R->Negate(BV, F));
+ if (V)
+ return *V;
+ if (R)
return R->Negate(BV, F);
// Lazily generate a new RangeSet representing all possible values for the
@@ -727,25 +755,35 @@ ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange(
return New.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, New);
}
-//===------------------------------------------------------------------------===
+//===----------------------------------------------------------------------===//
// Pretty-printing.
-//===------------------------------------------------------------------------===/
-
-void RangeConstraintManager::print(ProgramStateRef St, raw_ostream &Out,
- const char *nl, const char *sep) {
+//===----------------------------------------------------------------------===//
- ConstraintRangeTy Ranges = St->get<ConstraintRange>();
+void RangeConstraintManager::printJson(raw_ostream &Out, ProgramStateRef State,
+ const char *NL, unsigned int Space,
+ bool IsDot) const {
+ ConstraintRangeTy Constraints = State->get<ConstraintRange>();
- if (Ranges.isEmpty()) {
- Out << nl << sep << "Ranges are empty." << nl;
+ Indent(Out, Space, IsDot) << "\"constraints\": ";
+ if (Constraints.isEmpty()) {
+ Out << "null," << NL;
return;
}
- Out << nl << sep << "Ranges of symbol values:";
- for (ConstraintRangeTy::iterator I = Ranges.begin(), E = Ranges.end(); I != E;
- ++I) {
- Out << nl << ' ' << I.getKey() << " : ";
+ ++Space;
+ Out << '[' << NL;
+ for (ConstraintRangeTy::iterator I = Constraints.begin();
+ I != Constraints.end(); ++I) {
+ Indent(Out, Space, IsDot)
+ << "{ \"symbol\": \"" << I.getKey() << "\", \"range\": \"";
I.getData().print(Out);
+ Out << "\" }";
+
+ if (std::next(I) != Constraints.end())
+ Out << ',';
+ Out << NL;
}
- Out << nl;
+
+ --Space;
+ Indent(Out, Space, IsDot) << "]," << NL;
}