valueflow.cpp: optimized SingleValueFlowAnaylzer::isAlias() by avoidi… (#3051)

This commit is contained in:
Oliver Stöneberg 2021-02-10 08:18:21 +01:00 committed by GitHub
parent 8569a970b4
commit 39c5274742
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 77 additions and 5 deletions

View File

@ -1662,8 +1662,81 @@ static bool evalAssignment(ValueFlow::Value &lhsValue, const std::string &assign
return true; return true;
} }
template<class T>
struct SingleRange {
T* x;
T* begin() const {
return x;
}
T* end() const {
return x+1;
}
};
template<class T>
SingleRange<T> MakeSingleRange(T& x)
{
return {&x};
}
class SelectValueFromVarIdMapRange {
using M = std::unordered_map<nonneg int, ValueFlow::Value>;
struct Iterator {
using iterator_category = std::forward_iterator_tag;
using value_type = const ValueFlow::Value;
using pointer = value_type *;
using reference = value_type &;
explicit Iterator(const M::const_iterator &it)
: mIt(it) {
}
reference operator*() const {
return mIt->second;
}
pointer operator->() {
return &mIt->second;
}
Iterator &operator++() {
// cppcheck-suppress postfixOperator - forward iterator needs to perform post-increment
mIt++;
return *this;
}
friend bool operator==(const Iterator &a, const Iterator &b) {
return a.mIt == b.mIt;
}
friend bool operator!=(const Iterator &a, const Iterator &b) {
return a.mIt != b.mIt;
}
private:
M::const_iterator mIt;
};
public:
explicit SelectValueFromVarIdMapRange(const M *m)
: mMap(m) {
}
Iterator begin() const {
return Iterator(mMap->begin());
}
Iterator end() const {
return Iterator(mMap->end());
}
private:
const M *mMap;
};
// Check if its an alias of the variable or is being aliased to this variable // Check if its an alias of the variable or is being aliased to this variable
static bool isAliasOf(const Variable * var, const Token *tok, nonneg int varid, const std::list<ValueFlow::Value>& values, bool* inconclusive = nullptr) template<typename V>
static bool isAliasOf(const Variable * var, const Token *tok, nonneg int varid, const V& values, bool* inconclusive = nullptr)
{ {
if (tok->varId() == varid) if (tok->varId() == varid)
return false; return false;
@ -2101,7 +2174,7 @@ struct SingleValueFlowAnalyzer : ValueFlowAnalyzer {
const Variable* var = p.second; const Variable* var = p.second;
if (tok->varId() == varid) if (tok->varId() == varid)
return true; return true;
if (isAliasOf(var, tok, varid, {value}, &inconclusive)) if (isAliasOf(var, tok, varid, MakeSingleRange(value), &inconclusive))
return true; return true;
} }
} }
@ -4967,15 +5040,14 @@ struct MultiValueFlowAnalyzer : ValueFlowAnalyzer {
} }
virtual bool isAlias(const Token* tok, bool& inconclusive) const OVERRIDE { virtual bool isAlias(const Token* tok, bool& inconclusive) const OVERRIDE {
std::list<ValueFlow::Value> vals; const auto range = SelectValueFromVarIdMapRange(&values);
std::transform(values.begin(), values.end(), std::back_inserter(vals), SelectMapValues{});
for (const auto& p:getVars()) { for (const auto& p:getVars()) {
nonneg int varid = p.first; nonneg int varid = p.first;
const Variable* var = p.second; const Variable* var = p.second;
if (tok->varId() == varid) if (tok->varId() == varid)
return true; return true;
if (isAliasOf(var, tok, varid, vals, &inconclusive)) if (isAliasOf(var, tok, varid, range, &inconclusive))
return true; return true;
} }
return false; return false;