ValueFlow: Improved analysis of container size
This commit is contained in:
parent
81f54f7094
commit
907f81d059
|
@ -3422,6 +3422,8 @@ static void valueFlowContainerReverse(const Token *tok, unsigned int containerId
|
||||||
continue;
|
continue;
|
||||||
if (!tok->valueType() || !tok->valueType()->container)
|
if (!tok->valueType() || !tok->valueType()->container)
|
||||||
continue;
|
continue;
|
||||||
|
if (Token::Match(tok, "%name% . %name% (") && tok->valueType()->container->getAction(tok->strAt(2)) != Library::Container::Action::NO_ACTION)
|
||||||
|
break;
|
||||||
setTokenValue(const_cast<Token *>(tok), value, settings);
|
setTokenValue(const_cast<Token *>(tok), value, settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3436,9 +3438,23 @@ static void valueFlowContainerSize(TokenList * /*tokenlist*/, SymbolDatabase* sy
|
||||||
continue;
|
continue;
|
||||||
if (!Token::Match(tok, "%name% . %name% ("))
|
if (!Token::Match(tok, "%name% . %name% ("))
|
||||||
continue;
|
continue;
|
||||||
if (tok->valueType()->container->getYield(tok->strAt(2)) != Library::Container::Yield::EMPTY)
|
|
||||||
|
const Token *conditionToken;
|
||||||
|
|
||||||
|
if (tok->valueType()->container->getYield(tok->strAt(2)) == Library::Container::Yield::SIZE) {
|
||||||
|
const Token *parent = tok->tokAt(3)->astParent();
|
||||||
|
if (!parent || !parent->isComparisonOp() || !parent->astOperand2())
|
||||||
continue;
|
continue;
|
||||||
ValueFlow::Value value(tok->tokAt(3), 0LL);
|
if (parent->astOperand1()->str() != "0" && parent->astOperand2()->str() != "0")
|
||||||
|
continue;
|
||||||
|
conditionToken = parent;
|
||||||
|
} else if (tok->valueType()->container->getYield(tok->strAt(2)) == Library::Container::Yield::EMPTY) {
|
||||||
|
conditionToken = tok->tokAt(3);
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueFlow::Value value(conditionToken, 0LL);
|
||||||
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
|
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
|
||||||
valueFlowContainerReverse(scope.classDef, tok->varId(), value, settings);
|
valueFlowContainerReverse(scope.classDef, tok->varId(), value, settings);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3221,6 +3221,15 @@ private:
|
||||||
ASSERT_EQUALS(true, values.empty() ? true : values.front().isContainerSizeValue());
|
ASSERT_EQUALS(true, values.empty() ? true : values.front().isContainerSizeValue());
|
||||||
ASSERT_EQUALS(0, values.empty() ? 0 : values.front().intvalue);
|
ASSERT_EQUALS(0, values.empty() ? 0 : values.front().intvalue);
|
||||||
|
|
||||||
|
code = "void f(const std::list<int> &ints) {\n"
|
||||||
|
" ints.front();\n"
|
||||||
|
" if (ints.size()==0) {}\n"
|
||||||
|
"}";
|
||||||
|
values = tokenValues(code, "ints . front");
|
||||||
|
ASSERT_EQUALS(1, values.size());
|
||||||
|
ASSERT_EQUALS(true, values.empty() ? true : values.front().isContainerSizeValue());
|
||||||
|
ASSERT_EQUALS(0, values.empty() ? 0 : values.front().intvalue);
|
||||||
|
|
||||||
code = "void f(std::list<int> ints) {\n"
|
code = "void f(std::list<int> ints) {\n"
|
||||||
" ints.front();\n"
|
" ints.front();\n"
|
||||||
" ints.pop_back();\n"
|
" ints.pop_back();\n"
|
||||||
|
|
Loading…
Reference in New Issue