29 #include <unordered_set> 
   34 template<
class Predicate, 
class Compare>
 
   53         std::vector<MathLib::bigint> minvalue, maxvalue;
 
   54         std::vector<const ValueFlow::Value*> minRef, maxRef;
 
   70         bool isLessThan(
MathLib::bigint x, std::vector<const ValueFlow::Value*>* ref = 
nullptr)
 const 
   72             if (!this->maxvalue.empty() && this->maxvalue.front() < x) {
 
   80         bool isGreaterThan(
MathLib::bigint x, std::vector<const ValueFlow::Value*>* ref = 
nullptr)
 const 
   82             if (!this->minvalue.empty() && this->minvalue.front() > x) {
 
   90         bool isScalar()
 const {
 
   91             return minvalue.size() == 1 && minvalue == maxvalue;
 
   95             return minvalue.empty() && maxvalue.empty();
 
   98         bool isScalarOrEmpty()
 const {
 
   99             return empty() || isScalar();
 
  105             return minvalue.front();
 
  108         std::vector<const ValueFlow::Value*> getScalarRef()
 const 
  111             if (minRef != maxRef)
 
  112                 return merge(minRef, maxRef);
 
  119             result.setMinValue(x, ref);
 
  120             result.setMaxValue(x, ref);
 
  124         template<
class Predicate>
 
  125         static Interval fromValues(
const std::list<ValueFlow::Value>& 
values, Predicate predicate)
 
  131                     result.setMinValue(minValue->
intvalue + 1, minValue);
 
  133                     result.setMinValue(minValue->
intvalue, minValue);
 
  135                     std::count_if(
values.begin(), 
values.end(), predicate) == 1)
 
  136                     return Interval::fromInt(minValue->
intvalue, minValue);
 
  141                     result.setMaxValue(maxValue->
intvalue - 1, maxValue);
 
  143                     result.setMaxValue(maxValue->
intvalue, maxValue);
 
  149         static Interval fromValues(
const std::list<ValueFlow::Value>& 
values)
 
  157         static std::vector<MathLib::bigint> apply(
const std::vector<MathLib::bigint>& x,
 
  158                                                   const std::vector<MathLib::bigint>& y,
 
  165             return {f(x.front(), y.front())};
 
  168         static std::vector<const ValueFlow::Value*> merge(std::vector<const ValueFlow::Value*> x,
 
  169                                                           const std::vector<const ValueFlow::Value*>& y)
 
  171             x.insert(x.end(), y.cbegin(), y.cend());
 
  175         friend Interval 
operator-(
const Interval& lhs, 
const Interval& rhs)
 
  178             result.minvalue = Interval::apply(lhs.minvalue, rhs.maxvalue, std::minus<MathLib::bigint>{});
 
  179             result.maxvalue = Interval::apply(lhs.maxvalue, rhs.minvalue, std::minus<MathLib::bigint>{});
 
  180             if (!result.minvalue.empty())
 
  181                 result.minRef = merge(lhs.minRef, rhs.maxRef);
 
  182             if (!result.maxvalue.empty())
 
  183                 result.maxRef = merge(lhs.maxRef, rhs.minRef);
 
  187         static std::vector<int> equal(
const Interval& lhs,
 
  189                                       std::vector<const ValueFlow::Value*>* ref = 
nullptr)
 
  196                 *ref = merge(lhs.getScalarRef(), rhs.getScalarRef());
 
  197             return {lhs.minvalue == rhs.minvalue};
 
  200         static std::vector<int> compare(
const Interval& lhs,
 
  202                                         std::vector<const ValueFlow::Value*>* ref = 
nullptr)
 
  204             Interval diff = lhs - rhs;
 
  205             if (diff.isGreaterThan(0, ref))
 
  207             if (diff.isLessThan(0, ref))
 
  209             std::vector<int> eq = Interval::equal(lhs, rhs, ref);
 
  215             if (diff.isGreaterThan(-1, ref))
 
  217             if (diff.isLessThan(1, ref))
 
  222         static std::vector<bool> compare(
const std::string& op,
 
  225                                          std::vector<const ValueFlow::Value*>* ref = 
nullptr)
 
  227             std::vector<int> r = compare(lhs, rhs, ref);
 
  231             if (std::all_of(r.cbegin() + 1, r.cend(), [&](
int i) {
 
  232                 return b == calculate(op, i, 0);
 
  242     std::unordered_set<const Token*> locations;
 
  246         std::copy_if(ref->errorPath.cbegin(),
 
  247                      ref->errorPath.cend(),
 
  250             return locations.insert(e.first).second;
 
  252         std::copy_if(ref->debugPath.cbegin(),
 
  253                      ref->debugPath.cend(),
 
  256             return locations.insert(e.first).second;
 
  263     bool isPossible = 
false;
 
  264     bool isInconclusive = 
false;
 
  266         if (ref->isPossible())
 
  268         if (ref->isInconclusive())
 
  269             isInconclusive = 
true;
 
  281     return std::any_of(values.cbegin(), values.cend(), [&](
const ValueFlow::Value& value) {
 
  282         return value.isImpossible() && value.intvalue == x;
 
  287                                     const std::string& op,
 
  288                                     std::list<ValueFlow::Value> lhsValues,
 
  289                                     std::list<ValueFlow::Value> rhsValues)
 
  291     std::vector<ValueFlow::Value> result;
 
  293         return !model->match(value);
 
  295     lhsValues.remove_if(notMatch);
 
  296     rhsValues.remove_if(notMatch);
 
  297     if (lhsValues.empty() || rhsValues.empty())
 
  300     Interval lhs = Interval::fromValues(lhsValues);
 
  301     Interval rhs = Interval::fromValues(rhsValues);
 
  304         Interval diff = lhs - rhs;
 
  305         if (diff.isScalar()) {
 
  306             std::vector<const ValueFlow::Value*> refs = diff.getScalarRef();
 
  310             result.push_back(std::move(value));
 
  312             if (!diff.minvalue.empty()) {
 
  317                 result.push_back(std::move(value));
 
  319             if (!diff.maxvalue.empty()) {
 
  324                 result.push_back(std::move(value));
 
  327     } 
else if ((op == 
"!=" || op == 
"==") && lhs.isScalarOrEmpty() && rhs.isScalarOrEmpty()) {
 
  328         if (lhs.isScalar() && rhs.isScalar()) {
 
  329             std::vector<const ValueFlow::Value*> refs = Interval::merge(lhs.getScalarRef(), rhs.getScalarRef());
 
  333             result.push_back(std::move(value));
 
  335             std::vector<const ValueFlow::Value*> refs;
 
  336             if (lhs.isScalar() && 
inferNotEqual(rhsValues, lhs.getScalar()))
 
  337                 refs = lhs.getScalarRef();
 
  338             else if (rhs.isScalar() && 
inferNotEqual(lhsValues, rhs.getScalar()))
 
  339                 refs = rhs.getScalarRef();
 
  344                 result.push_back(std::move(value));
 
  348         std::vector<const ValueFlow::Value*> refs;
 
  349         std::vector<bool> r = Interval::compare(op, lhs, rhs, &refs);
 
  354             result.push_back(std::move(value));
 
  362                                     const std::string& op,
 
  364                                     std::list<ValueFlow::Value> rhsValues)
 
  366     return infer(model, op, {model->yield(lhs)}, std::move(rhsValues));
 
  370                                     const std::string& op,
 
  371                                     std::list<ValueFlow::Value> lhsValues,
 
  374     return infer(model, op, std::move(lhsValues), {model->yield(rhs)});
 
  380         return model->match(v);
 
  386         return model->match(v);
 
R calculate(const std::string &s, const T &x, const T &y, bool *error=nullptr)
 
The token list that the TokenList generates is a linked-list of this class.
 
const std::list< ValueFlow::Value > & values() const
 
Bound bound
The value bound
 
bool isImpossible() const
 
const Token * condition
Condition that this value depends on.
 
long long intvalue
int value (or sometimes bool value?)
 
void setInconclusive(bool inconclusive=true)
 
std::pair< const Token *, std::string > ErrorPathItem
 
MathLib::value operator-(const MathLib::value &v1, const MathLib::value &v2)
 
std::vector< MathLib::bigint > getMinValue(const ValuePtr< InferModel > &model, const std::list< ValueFlow::Value > &values)
 
static const ValueFlow::Value * getCompareValue(const std::list< ValueFlow::Value > &values, Predicate pred, Compare compare)
 
static void addToErrorPath(ValueFlow::Value &value, const std::vector< const ValueFlow::Value * > &refs)
 
static void setValueKind(ValueFlow::Value &value, const std::vector< const ValueFlow::Value * > &refs)
 
std::vector< MathLib::bigint > getMaxValue(const ValuePtr< InferModel > &model, const std::list< ValueFlow::Value > &values)
 
static bool inferNotEqual(const std::list< ValueFlow::Value > &values, MathLib::bigint x)
 
std::vector< ValueFlow::Value > infer(const ValuePtr< InferModel > &model, const std::string &op, std::list< ValueFlow::Value > lhsValues, std::list< ValueFlow::Value > rhsValues)