CheckIO: Handle classes derived from STL
This commit is contained in:
parent
489a3a6e53
commit
40c5924292
@ -833,9 +833,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * tok, const Settings *settings)
|
|||||||
tok1 = tok1->link();
|
tok1 = tok1->link();
|
||||||
|
|
||||||
// check for some common well known functions
|
// check for some common well known functions
|
||||||
else if (Token::Match(tok1->previous(), "%var% . size|empty|c_str ( )") && tok1->previous()->variable() &&
|
else if (Token::Match(tok1->previous(), "%var% . size|empty|c_str ( )") && isStdContainer(tok1->previous())) {
|
||||||
(Token::Match(tok1->previous()->variable()->typeStartToken(), "std :: vector|array|bitset|deque|list|forward_list|map|multimap|multiset|priority_queue|queue|set|stack|hash_map|hash_multimap|hash_set|unordered_map|unordered_multimap|unordered_set|unordered_multiset <") ||
|
|
||||||
Token::Match(tok1->previous()->variable()->typeStartToken(), "std :: string|wstring"))) {
|
|
||||||
tempToken = new Token(0);
|
tempToken = new Token(0);
|
||||||
tempToken->fileIndex(tok1->fileIndex());
|
tempToken->fileIndex(tok1->fileIndex());
|
||||||
tempToken->linenr(tok1->linenr());
|
tempToken->linenr(tok1->linenr());
|
||||||
@ -874,8 +872,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * tok, const Settings *settings)
|
|||||||
|
|
||||||
// look for std::vector operator [] and use template type as return type
|
// look for std::vector operator [] and use template type as return type
|
||||||
if (variableInfo) {
|
if (variableInfo) {
|
||||||
if (element && Token::Match(variableInfo->typeStartToken(), "std :: vector|array <")) {
|
if (element && isStdVector()) { // isStdVector sets type token if true
|
||||||
typeToken = variableInfo->typeStartToken()->tokAt(4);
|
|
||||||
element = false; // not really an array element
|
element = false; // not really an array element
|
||||||
} else
|
} else
|
||||||
typeToken = variableInfo->typeStartToken();
|
typeToken = variableInfo->typeStartToken();
|
||||||
@ -887,6 +884,42 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * tok, const Settings *settings)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CheckIO::ArgumentInfo::isStdVector()
|
||||||
|
{
|
||||||
|
if (Token::Match(variableInfo->typeStartToken(), "std :: vector|array <")) {
|
||||||
|
typeToken = variableInfo->typeStartToken()->tokAt(4);
|
||||||
|
return true;
|
||||||
|
} else if (variableInfo->type() && !variableInfo->type()->derivedFrom.empty()) {
|
||||||
|
for (std::size_t i = 0, e = variableInfo->type()->derivedFrom.size(); i != e; ++i) {
|
||||||
|
if (Token::Match(variableInfo->type()->derivedFrom[i].nameTok, "std :: vector|array <")) {
|
||||||
|
typeToken = variableInfo->type()->derivedFrom[i].nameTok->tokAt(4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckIO::ArgumentInfo::isStdContainer(const Token *tok)
|
||||||
|
{
|
||||||
|
if (tok && tok->variable()) {
|
||||||
|
if (Token::Match(tok->variable()->typeStartToken(), "std :: vector|array|bitset|deque|list|forward_list|map|multimap|multiset|priority_queue|queue|set|stack|hash_map|hash_multimap|hash_set|unordered_map|unordered_multimap|unordered_set|unordered_multiset <") ||
|
||||||
|
Token::Match(tok->variable()->typeStartToken(), "std :: string|wstring")) {
|
||||||
|
return true;
|
||||||
|
} else if (tok->variable()->type() && !tok->variable()->type()->derivedFrom.empty()) {
|
||||||
|
for (std::size_t i = 0, e = tok->variable()->type()->derivedFrom.size(); i != e; ++i) {
|
||||||
|
if (Token::Match(tok->variable()->type()->derivedFrom[i].nameTok, "std :: vector|array|bitset|deque|list|forward_list|map|multimap|multiset|priority_queue|queue|set|stack|hash_map|hash_multimap|hash_set|unordered_map|unordered_multimap|unordered_set|unordered_multiset <") ||
|
||||||
|
Token::Match(tok->variable()->type()->derivedFrom[i].nameTok, "std :: string|wstring")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool CheckIO::ArgumentInfo::isComplexType() const
|
bool CheckIO::ArgumentInfo::isComplexType() const
|
||||||
{
|
{
|
||||||
if (variableInfo->type())
|
if (variableInfo->type())
|
||||||
|
@ -84,6 +84,8 @@ private:
|
|||||||
}
|
}
|
||||||
bool isComplexType() const;
|
bool isComplexType() const;
|
||||||
bool isKnownType() const;
|
bool isKnownType() const;
|
||||||
|
bool isStdVector();
|
||||||
|
bool isStdContainer(const Token *tok);
|
||||||
|
|
||||||
const Variable *variableInfo;
|
const Variable *variableInfo;
|
||||||
const Token *typeToken;
|
const Token *typeToken;
|
||||||
|
@ -1130,14 +1130,22 @@ private:
|
|||||||
"[test.cpp:5]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'size_t {aka unsigned long}'.\n", errout.str());
|
"[test.cpp:5]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'size_t {aka unsigned long}'.\n", errout.str());
|
||||||
|
|
||||||
check("class Fred : public std::vector<int> {} v;\n"
|
check("class Fred : public std::vector<int> {} v;\n"
|
||||||
|
"std::string s;\n"
|
||||||
"void foo() {\n"
|
"void foo() {\n"
|
||||||
" printf(\"%zu %Iu %d %f\", v.size(), v.size(), v.size(), v.size());\n"
|
" printf(\"%zu %Iu %d %f\", v.size(), v.size(), v.size(), v.size());\n"
|
||||||
" printf(\"%zu %Iu %d %f\", s.size(), s.size(), s.size(), s.size());\n"
|
" printf(\"%zu %Iu %d %f\", s.size(), s.size(), s.size(), s.size());\n"
|
||||||
"}\n", false, false, Settings::Unix64);
|
"}\n", false, false, Settings::Unix64);
|
||||||
TODO_ASSERT_EQUALS("[test.cpp:4]: (warning) %d in format string (no. 3) requires a signed integer but the argument type is 'size_t {aka unsigned long}'.\n"
|
ASSERT_EQUALS("[test.cpp:4]: (warning) %d in format string (no. 3) requires a signed integer but the argument type is 'size_t {aka unsigned long}'.\n"
|
||||||
"[test.cpp:4]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'size_t {aka unsigned long}'.\n"
|
"[test.cpp:4]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'size_t {aka unsigned long}'.\n"
|
||||||
"[test.cpp:5]: (warning) %d in format string (no. 3) requires a signed integer but the argument type is 'size_t {aka unsigned long}'.\n"
|
"[test.cpp:5]: (warning) %d in format string (no. 3) requires a signed integer but the argument type is 'size_t {aka unsigned long}'.\n"
|
||||||
"[test.cpp:5]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'size_t {aka unsigned long}'.\n", "", errout.str());
|
"[test.cpp:5]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'size_t {aka unsigned long}'.\n", errout.str());
|
||||||
|
|
||||||
|
check("class Fred : public std::vector<int> {} v;\n"
|
||||||
|
"void foo() {\n"
|
||||||
|
" printf(\"%d %u %f\", v[0], v[0], v[0]);\n"
|
||||||
|
"}\n", false, false, Settings::Unix64);
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires an unsigned integer but the argument type is 'int'.\n"
|
||||||
|
"[test.cpp:3]: (warning) %f in format string (no. 3) requires a floating point number but the argument type is 'int'.\n", errout.str());
|
||||||
|
|
||||||
check("std::string s;\n"
|
check("std::string s;\n"
|
||||||
"void foo() {\n"
|
"void foo() {\n"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user