From 811a71aa06018d43630dca52b2d6aae244489527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 11 Aug 2018 15:08:54 +0200 Subject: [PATCH] valueFlowContainerSize: Handle guard logic --- lib/valueflow.cpp | 31 +++++++++++++++++++++++++++++-- test/testvalueflow.cpp | 6 ++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index c6f01c9d4..230d292f5 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3431,6 +3431,31 @@ static void valueFlowUninit(TokenList *tokenlist, SymbolDatabase * /*symbolDatab } } +static bool hasContainerSizeGuard(const Token *tok, unsigned int containerId) +{ + for (; tok && tok->astParent(); tok = tok->astParent()) { + const Token *parent = tok->astParent(); + if (tok != parent->astOperand2()) + continue; + if (!Token::Match(parent, "%oror%|&&|?")) + continue; + // is container found in lhs? + std::stack tokens; + tokens.push(parent->astOperand1()); + while (!tokens.empty()) { + const Token *t = tokens.top(); + tokens.pop(); + if (!t) + continue; + if (t->varId() == containerId) + return true; + tokens.push(t->astOperand1()); + tokens.push(t->astOperand2()); + } + } + return false; +} + static void valueFlowContainerReverse(const Token *tok, unsigned int containerId, const ValueFlow::Value &value, const Settings *settings) { while (nullptr != (tok = tok->previous())) { @@ -3444,7 +3469,8 @@ static void valueFlowContainerReverse(const Token *tok, unsigned int containerId break; if (Token::Match(tok, "%name% . %name% (") && tok->valueType()->container->getAction(tok->strAt(2)) != Library::Container::Action::NO_ACTION) break; - setTokenValue(const_cast(tok), value, settings); + if (!hasContainerSizeGuard(tok, containerId)) + setTokenValue(const_cast(tok), value, settings); } } @@ -3461,7 +3487,8 @@ static void valueFlowContainerForward(const Token *tok, unsigned int containerId break; if (Token::Match(tok, "%name% . %name% (") && tok->valueType()->container->getAction(tok->strAt(2)) != Library::Container::Action::NO_ACTION) break; - setTokenValue(const_cast(tok), value, settings); + if (!hasContainerSizeGuard(tok, containerId)) + setTokenValue(const_cast(tok), value, settings); } } diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 749450a09..9ac32f26f 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -3319,6 +3319,12 @@ private: " }\n" "}"; ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "ints . front"), 0)); + + code = "void f(const std::vector &v) {\n" + " if (v.empty()) {}\n" + " if (!v.empty() && v[10]==0) {}\n" // <- no container size for 'v[10]' + "}"; + ASSERT(tokenValues(code, "v [").empty()); } };