diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:49 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:49 +0000 | 
| commit | 2298981669bf3bd63335a4be179bc0f96823a8f4 (patch) | |
| tree | 1cbe2eb27f030d2d70b80ee5ca3c86bee7326a9f /lib/StaticAnalyzer/Core/RangeConstraintManager.cpp | |
| parent | 9a83721404652cea39e9f02ae3e3b5c964602a5c (diff) | |
Notes
Diffstat (limited to 'lib/StaticAnalyzer/Core/RangeConstraintManager.cpp')
| -rw-r--r-- | lib/StaticAnalyzer/Core/RangeConstraintManager.cpp | 86 | 
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;  } | 
