Add tests for container changes
This commit is contained in:
parent
26693df788
commit
fec2914700
|
@ -5640,6 +5640,11 @@ struct ContainerVariableForwardAnalyzer : VariableForwardAnalyzer {
|
|||
if (std::any_of(rhs->values().begin(), rhs->values().end(), [&](const ValueFlow::Value &rhsval) { return rhsval.isKnown() && rhsval.isContainerSizeValue(); }))
|
||||
return Action::Read | Action::Write;
|
||||
}
|
||||
} else if (Token::Match(tok, "%name% . %name% (")) {
|
||||
Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2));
|
||||
if (action == Library::Container::Action::PUSH || action == Library::Container::Action::POP)
|
||||
return Action::Read | Action::Write;
|
||||
const Token* arg = tok->tokAt(4);
|
||||
}
|
||||
return Action::None;
|
||||
}
|
||||
|
@ -5664,6 +5669,12 @@ struct ContainerVariableForwardAnalyzer : VariableForwardAnalyzer {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (Token::Match(tok, "%name% . %name% (")) {
|
||||
Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2));
|
||||
if (action == Library::Container::Action::PUSH)
|
||||
value->intvalue++;
|
||||
if (action == Library::Container::Action::POP)
|
||||
value->intvalue--;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5885,6 +5896,19 @@ static void valueFlowContainerSize(TokenList *tokenlist, SymbolDatabase* symbold
|
|||
value.setKnown();
|
||||
valueFlowContainerForward(containerTok->next(), containerTok->variable(), value, tokenlist);
|
||||
}
|
||||
} else if (Token::Match(tok, "%var% . %name% (") && tok->valueType() && tok->valueType()->container) {
|
||||
Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2));
|
||||
if (action == Library::Container::Action::CLEAR) {
|
||||
ValueFlow::Value value(0);
|
||||
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
|
||||
value.setKnown();
|
||||
valueFlowContainerForward(tok->next(), tok->variable(), value, tokenlist);
|
||||
} else if (action == Library::Container::Action::RESIZE && tok->tokAt(4)->hasKnownIntValue()) {
|
||||
ValueFlow::Value value(tok->tokAt(4)->values().front());
|
||||
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
|
||||
value.setKnown();
|
||||
valueFlowContainerForward(tok->next(), tok->variable(), value, tokenlist);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ void QList1(QList<int> intListArg)
|
|||
QList<QString> qstringList2 = {"one", "two"};
|
||||
(void)qstringList2[1];
|
||||
qstringList2.clear();
|
||||
// TODO: cppcheck-suppress containerOutOfBounds #9243
|
||||
// cppcheck-suppress containerOutOfBounds
|
||||
(void)qstringList2[1];
|
||||
|
||||
QList<QString> qstringList3;
|
||||
|
@ -117,7 +117,7 @@ void QList1(QList<int> intListArg)
|
|||
qstringList4.append("a");
|
||||
(void)qstringList4[0];
|
||||
qstringList4.clear();
|
||||
// TODO: cppcheck-suppress containerOutOfBounds #9243
|
||||
// cppcheck-suppress containerOutOfBounds
|
||||
(void)qstringList4[0];
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,8 @@ wxString containerOutOfBounds_wxArrayString(void)
|
|||
wxArrayString a;
|
||||
a.Add("42");
|
||||
a.Clear();
|
||||
// cppcheck-suppress containerOutOfBounds
|
||||
// TODO: wxArrayString is defined to be a vector
|
||||
// TODO: cppcheck-suppress containerOutOfBounds
|
||||
return a[0];
|
||||
}
|
||||
|
||||
|
@ -42,7 +43,8 @@ int containerOutOfBounds_wxArrayInt(void)
|
|||
wxArrayInt a;
|
||||
a.Add(42);
|
||||
a.Clear();
|
||||
// cppcheck-suppress containerOutOfBounds
|
||||
// TODO: wxArrayString is defined to be a vector
|
||||
// TODO: cppcheck-suppress containerOutOfBounds
|
||||
return a[0];
|
||||
}
|
||||
|
||||
|
|
|
@ -324,6 +324,12 @@ private:
|
|||
return tok ? tok->values() : std::list<ValueFlow::Value>();
|
||||
}
|
||||
|
||||
std::list<ValueFlow::Value> tokenValues(const char code[], const char tokstr[], ValueFlow::Value::ValueType vt, const Settings *s = nullptr) {
|
||||
std::list<ValueFlow::Value> values = tokenValues(code, tokstr, s);
|
||||
values.remove_if([&](const ValueFlow::Value& v) { return v.valueType != vt; });
|
||||
return values;
|
||||
}
|
||||
|
||||
ValueFlow::Value valueOfTok(const char code[], const char tokstr[]) {
|
||||
std::list<ValueFlow::Value> values = tokenValues(code, tokstr);
|
||||
return values.size() == 1U && !values.front().isTokValue() ? values.front() : ValueFlow::Value();
|
||||
|
@ -4439,6 +4445,32 @@ private:
|
|||
" x = s + s;\n"
|
||||
"}";
|
||||
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "+"), 8));
|
||||
|
||||
code = "void f(const std::vector<int> &ints) {\n"
|
||||
" ints.clear();\n"
|
||||
" ints.front();\n"
|
||||
"}";
|
||||
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "ints . front", ValueFlow::Value::CONTAINER_SIZE), 0));
|
||||
|
||||
code = "void f(const std::vector<int> &ints) {\n"
|
||||
" ints.resize(3);\n"
|
||||
" ints.front();\n"
|
||||
"}";
|
||||
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "ints . front", ValueFlow::Value::CONTAINER_SIZE), 3));
|
||||
|
||||
code = "void f(const std::vector<int> &ints) {\n"
|
||||
" ints.resize(3);\n"
|
||||
" ints.push_back(3);\n"
|
||||
" ints.front();\n"
|
||||
"}";
|
||||
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "ints . front", ValueFlow::Value::CONTAINER_SIZE), 4));
|
||||
|
||||
code = "void f(const std::vector<int> &ints) {\n"
|
||||
" ints.resize(3);\n"
|
||||
" ints.pop_back();\n"
|
||||
" ints.front();\n"
|
||||
"}";
|
||||
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "ints . front", ValueFlow::Value::CONTAINER_SIZE), 2));
|
||||
}
|
||||
|
||||
void valueFlowDynamicBufferSize() {
|
||||
|
|
Loading…
Reference in New Issue