From 39c5274742a35cd217eac2e12972737e1d172b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Wed, 10 Feb 2021 08:18:21 +0100 Subject: [PATCH] =?UTF-8?q?valueflow.cpp:=20optimized=20SingleValueFlowAna?= =?UTF-8?q?ylzer::isAlias()=20by=20avoidi=E2=80=A6=20(#3051)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/valueflow.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 61943824f..e004a918d 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1662,8 +1662,81 @@ static bool evalAssignment(ValueFlow::Value &lhsValue, const std::string &assign return true; } +template +struct SingleRange { + T* x; + T* begin() const { + return x; + } + T* end() const { + return x+1; + } +}; + +template +SingleRange MakeSingleRange(T& x) +{ + return {&x}; +} + +class SelectValueFromVarIdMapRange { + using M = std::unordered_map; + + 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 -static bool isAliasOf(const Variable * var, const Token *tok, nonneg int varid, const std::list& values, bool* inconclusive = nullptr) +template +static bool isAliasOf(const Variable * var, const Token *tok, nonneg int varid, const V& values, bool* inconclusive = nullptr) { if (tok->varId() == varid) return false; @@ -2101,7 +2174,7 @@ struct SingleValueFlowAnalyzer : ValueFlowAnalyzer { const Variable* var = p.second; if (tok->varId() == varid) return true; - if (isAliasOf(var, tok, varid, {value}, &inconclusive)) + if (isAliasOf(var, tok, varid, MakeSingleRange(value), &inconclusive)) return true; } } @@ -4967,15 +5040,14 @@ struct MultiValueFlowAnalyzer : ValueFlowAnalyzer { } virtual bool isAlias(const Token* tok, bool& inconclusive) const OVERRIDE { - std::list vals; - std::transform(values.begin(), values.end(), std::back_inserter(vals), SelectMapValues{}); + const auto range = SelectValueFromVarIdMapRange(&values); for (const auto& p:getVars()) { nonneg int varid = p.first; const Variable* var = p.second; if (tok->varId() == varid) return true; - if (isAliasOf(var, tok, varid, vals, &inconclusive)) + if (isAliasOf(var, tok, varid, range, &inconclusive)) return true; } return false;