Refactor checks using Variable::isStlType()
This commit is contained in:
parent
8db904692a
commit
ad0269eeeb
|
@ -1022,7 +1022,7 @@ void CheckClass::checkMemsetType(const Scope *start, const Token *tok, const Sco
|
||||||
const Token *tok1 = var->typeStartToken();
|
const Token *tok1 = var->typeStartToken();
|
||||||
|
|
||||||
// check for std:: type
|
// check for std:: type
|
||||||
if (Token::simpleMatch(tok1, "std ::"))
|
if (var->isStlType())
|
||||||
if (allocation)
|
if (allocation)
|
||||||
mallocOnClassError(tok, tok->str(), type->classDef, "'std::" + tok1->strAt(2) + "'");
|
mallocOnClassError(tok, tok->str(), type->classDef, "'std::" + tok1->strAt(2) + "'");
|
||||||
else
|
else
|
||||||
|
@ -1730,7 +1730,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool&
|
||||||
const Variable *var = end->variable();
|
const Variable *var = end->variable();
|
||||||
|
|
||||||
if (var && Token::simpleMatch(var->typeStartToken(), "std :: map")) // operator[] changes a map
|
if (var && Token::simpleMatch(var->typeStartToken(), "std :: map")) // operator[] changes a map
|
||||||
return (false);
|
return false;
|
||||||
}
|
}
|
||||||
if (!jumpBackToken)
|
if (!jumpBackToken)
|
||||||
jumpBackToken = end->next(); // Check inside the [] brackets
|
jumpBackToken = end->next(); // Check inside the [] brackets
|
||||||
|
@ -1744,8 +1744,8 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool&
|
||||||
if (end->strAt(1) == "(") {
|
if (end->strAt(1) == "(") {
|
||||||
const Variable *var = lastVarTok->variable();
|
const Variable *var = lastVarTok->variable();
|
||||||
if (!var)
|
if (!var)
|
||||||
return (false);
|
return false;
|
||||||
if (Token::simpleMatch(var->typeStartToken(), "std ::") // assume all std::*::size() and std::*::empty() are const
|
if (var->isStlType() // assume all std::*::size() and std::*::empty() are const
|
||||||
&& (Token::Match(end, "size|empty|cend|crend|cbegin|crbegin|max_size|length|count|capacity|get_allocator|c_str|str ( )") || Token::Match(end, "rfind|copy")))
|
&& (Token::Match(end, "size|empty|cend|crend|cbegin|crbegin|max_size|length|count|capacity|get_allocator|c_str|str ( )") || Token::Match(end, "rfind|copy")))
|
||||||
;
|
;
|
||||||
else if (!var->typeScope() || !isConstMemberFunc(var->typeScope(), end))
|
else if (!var->typeScope() || !isConstMemberFunc(var->typeScope(), end))
|
||||||
|
|
|
@ -1446,11 +1446,20 @@ CheckIO::ArgumentInfo::~ArgumentInfo()
|
||||||
|
|
||||||
bool CheckIO::ArgumentInfo::isStdVectorOrString()
|
bool CheckIO::ArgumentInfo::isStdVectorOrString()
|
||||||
{
|
{
|
||||||
if (Token::Match(variableInfo->typeStartToken(), "std :: vector|array <")) {
|
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
|
||||||
|
static const char* const stl_vector[] = {
|
||||||
|
"array", "vector"
|
||||||
|
};
|
||||||
|
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
|
||||||
|
static const char* const stl_string[] = {
|
||||||
|
"string", "u16string", "u32string", "wstring"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (variableInfo->isStlType(stl_vector)) {
|
||||||
typeToken = variableInfo->typeStartToken()->tokAt(4);
|
typeToken = variableInfo->typeStartToken()->tokAt(4);
|
||||||
_template = true;
|
_template = true;
|
||||||
return true;
|
return true;
|
||||||
} else if (Token::Match(variableInfo->typeStartToken(), "std :: string|wstring")) {
|
} else if (variableInfo->isStlType(stl_string)) {
|
||||||
tempToken = new Token(0);
|
tempToken = new Token(0);
|
||||||
tempToken->fileIndex(variableInfo->typeStartToken()->fileIndex());
|
tempToken->fileIndex(variableInfo->typeStartToken()->fileIndex());
|
||||||
tempToken->linenr(variableInfo->typeStartToken()->linenr());
|
tempToken->linenr(variableInfo->typeStartToken()->linenr());
|
||||||
|
@ -1485,11 +1494,25 @@ bool CheckIO::ArgumentInfo::isStdVectorOrString()
|
||||||
|
|
||||||
bool CheckIO::ArgumentInfo::isStdContainer(const Token *tok)
|
bool CheckIO::ArgumentInfo::isStdContainer(const Token *tok)
|
||||||
{
|
{
|
||||||
|
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
|
||||||
|
static const char* const stl_container[] = {
|
||||||
|
"array", "bitset", "deque", "forward_list",
|
||||||
|
"hash_map", "hash_multimap", "hash_set",
|
||||||
|
"list", "map", "multimap", "multiset",
|
||||||
|
"priority_queue", "queue", "set", "stack",
|
||||||
|
"unordered_map", "unordered_multimap", "unordered_multiset", "unordered_set",
|
||||||
|
"vector"
|
||||||
|
};
|
||||||
|
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
|
||||||
|
static const char* const stl_string[]= {
|
||||||
|
"string", "u16string", "u32string", "wstring"
|
||||||
|
};
|
||||||
|
|
||||||
if (tok && tok->variable()) {
|
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 <")) {
|
if (tok->variable()->isStlType(stl_container)) {
|
||||||
typeToken = tok->variable()->typeStartToken()->tokAt(4);
|
typeToken = tok->variable()->typeStartToken()->tokAt(4);
|
||||||
return true;
|
return true;
|
||||||
} else if (Token::Match(tok->variable()->typeStartToken(), "std :: string|wstring")) {
|
} else if (tok->variable()->isStlType(stl_string)) {
|
||||||
typeToken = tok->variable()->typeStartToken();
|
typeToken = tok->variable()->typeStartToken();
|
||||||
return true;
|
return true;
|
||||||
} else if (tok->variable()->type() && !tok->variable()->type()->derivedFrom.empty()) {
|
} else if (tok->variable()->type() && !tok->variable()->type()->derivedFrom.empty()) {
|
||||||
|
|
|
@ -320,6 +320,13 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
|
||||||
*/
|
*/
|
||||||
bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
||||||
{
|
{
|
||||||
|
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
|
||||||
|
static const char* const stl_stream [] = {
|
||||||
|
"fstream", "ifstream", "iostream", "istream",
|
||||||
|
"istringstream", "ofstream", "ostream", "ostringstream",
|
||||||
|
"stringstream", "wistringstream", "wostringstream", "wstringstream"
|
||||||
|
};
|
||||||
|
|
||||||
const bool inconclusive = unknown;
|
const bool inconclusive = unknown;
|
||||||
|
|
||||||
unknown = false;
|
unknown = false;
|
||||||
|
@ -379,7 +386,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
||||||
return true;
|
return true;
|
||||||
if (tok2 && tok2->varId() != 0) {
|
if (tok2 && tok2->varId() != 0) {
|
||||||
const Variable* var2 = tok2->variable();
|
const Variable* var2 = tok2->variable();
|
||||||
if (var2 && Token::Match(var2->typeStartToken(), "std :: istream|ifstream|istringstream|wistringstream|ostream|ofstream|ostringstream|wostringstream|stringstream|wstringstream|fstream|iostream"))
|
if (var2 && var2->isStlType(stl_stream))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -821,6 +828,12 @@ void CheckNullPointer::nullConstantDereference()
|
||||||
{
|
{
|
||||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
|
||||||
|
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
|
||||||
|
static const char* const stl_stream[] = {
|
||||||
|
"fstream", "ifstream", "iostream", "istream",
|
||||||
|
"istringstream", "stringstream", "wistringstream", "wstringstream"
|
||||||
|
};
|
||||||
|
|
||||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
for (std::size_t i = 0; i < functions; ++i) {
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
|
@ -874,7 +887,7 @@ void CheckNullPointer::nullConstantDereference()
|
||||||
nullPointerError(tok);
|
nullPointerError(tok);
|
||||||
if (tok2 && tok2->varId() != 0) {
|
if (tok2 && tok2->varId() != 0) {
|
||||||
const Variable *var = tok2->variable();
|
const Variable *var = tok2->variable();
|
||||||
if (var && Token::Match(var->typeStartToken(), "std :: istream|ifstream|istringstream|wistringstream|stringstream|wstringstream|fstream|iostream"))
|
if (var && var->isStlType(stl_stream))
|
||||||
nullPointerError(tok);
|
nullPointerError(tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1161,7 +1161,7 @@ void CheckOther::suspiciousEqualityComparisonError(const Token* tok)
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
static bool isTypeWithoutSideEffects(const Tokenizer *tokenizer, const Variable* var)
|
static bool isTypeWithoutSideEffects(const Tokenizer *tokenizer, const Variable* var)
|
||||||
{
|
{
|
||||||
return ((var && (!var->isClass() || var->isPointer() || Token::simpleMatch(var->typeStartToken(), "std ::"))) || !tokenizer->isCPP());
|
return ((var && (!var->isClass() || var->isPointer() || var->isStlType())) || !tokenizer->isCPP());
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const Token *findSelfAssignPattern(const Token *start)
|
static inline const Token *findSelfAssignPattern(const Token *start)
|
||||||
|
|
|
@ -294,6 +294,10 @@ void CheckStl::mismatchingContainers()
|
||||||
|
|
||||||
void CheckStl::stlOutOfBounds()
|
void CheckStl::stlOutOfBounds()
|
||||||
{
|
{
|
||||||
|
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
|
||||||
|
static const char* const stl_bounded_container [] = {
|
||||||
|
"array", "basic_string", "deque", "string", "vector", "wstring"
|
||||||
|
};
|
||||||
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
|
||||||
// Scan through all scopes..
|
// Scan through all scopes..
|
||||||
|
@ -316,7 +320,7 @@ void CheckStl::stlOutOfBounds()
|
||||||
const Variable *container = tok->tokAt(3)->variable();
|
const Variable *container = tok->tokAt(3)->variable();
|
||||||
if (!container)
|
if (!container)
|
||||||
continue;
|
continue;
|
||||||
if (!Token::Match(container->typeStartToken(), "std :: vector|deque|array|string|wstring|basic_string"))
|
if (!container->isStlType(stl_bounded_container))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// variable id for loop variable.
|
// variable id for loop variable.
|
||||||
|
@ -868,7 +872,7 @@ void CheckStl::if_find()
|
||||||
|
|
||||||
//pretty bad limitation.. but it is there in order to avoid
|
//pretty bad limitation.. but it is there in order to avoid
|
||||||
//own implementations of 'find' or any container
|
//own implementations of 'find' or any container
|
||||||
if (!Token::simpleMatch(decl, "std ::"))
|
if (!var->isStlType())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
decl = decl->tokAt(2);
|
decl = decl->tokAt(2);
|
||||||
|
@ -1199,7 +1203,7 @@ void CheckStl::string_c_str()
|
||||||
tok2 = tok2->previous();
|
tok2 = tok2->previous();
|
||||||
if (tok2 && Token::simpleMatch(tok2->tokAt(-4), ". c_str ( )")) {
|
if (tok2 && Token::simpleMatch(tok2->tokAt(-4), ". c_str ( )")) {
|
||||||
const Variable* var = tok2->tokAt(-5)->variable();
|
const Variable* var = tok2->tokAt(-5)->variable();
|
||||||
if (var && Token::simpleMatch(var->typeStartToken(), "std ::"))
|
if (var && var->isStlType())
|
||||||
string_c_strParam(tok, i->second);
|
string_c_strParam(tok, i->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1245,7 +1249,7 @@ void CheckStl::string_c_str()
|
||||||
tok2 = tok2->tokAt(-5);
|
tok2 = tok2->tokAt(-5);
|
||||||
if (tok2->isName()) { // return var.c_str(); => check if var is a std type
|
if (tok2->isName()) { // return var.c_str(); => check if var is a std type
|
||||||
const Variable *var = tok2->variable();
|
const Variable *var = tok2->variable();
|
||||||
if (var && Token::simpleMatch(var->typeStartToken(), "std ::"))
|
if (var && var->isStlType())
|
||||||
string_c_strReturn(tok);
|
string_c_strReturn(tok);
|
||||||
} else {
|
} else {
|
||||||
// TODO: determine if a error should be written or not
|
// TODO: determine if a error should be written or not
|
||||||
|
|
|
@ -688,7 +688,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
|
||||||
else if (_tokenizer->isC() ||
|
else if (_tokenizer->isC() ||
|
||||||
i->typeEndToken()->isStandardType() ||
|
i->typeEndToken()->isStandardType() ||
|
||||||
isRecordTypeWithoutSideEffects(i->type()) ||
|
isRecordTypeWithoutSideEffects(i->type()) ||
|
||||||
(Token::simpleMatch(i->typeStartToken(), "std ::") &&
|
(i->isStlType() &&
|
||||||
i->typeStartToken()->strAt(2) != "lock_guard" &&
|
i->typeStartToken()->strAt(2) != "lock_guard" &&
|
||||||
i->typeStartToken()->strAt(2) != "unique_lock"))
|
i->typeStartToken()->strAt(2) != "unique_lock"))
|
||||||
type = Variables::standard;
|
type = Variables::standard;
|
||||||
|
@ -1118,7 +1118,7 @@ void CheckUnusedVar::checkFunctionVariableUsage()
|
||||||
unusedVariableError(usage._var->nameToken(), varname);
|
unusedVariableError(usage._var->nameToken(), varname);
|
||||||
|
|
||||||
// variable has not been written but has been modified
|
// variable has not been written but has been modified
|
||||||
else if (usage._modified && !usage._write && !usage._allocateMemory && !Token::simpleMatch(var->typeStartToken(), "std ::"))
|
else if (usage._modified && !usage._write && !usage._allocateMemory && !var->isStlType())
|
||||||
unassignedVariableError(usage._var->nameToken(), varname);
|
unassignedVariableError(usage._var->nameToken(), varname);
|
||||||
|
|
||||||
// variable has been written but not read
|
// variable has been written but not read
|
||||||
|
@ -1126,7 +1126,7 @@ void CheckUnusedVar::checkFunctionVariableUsage()
|
||||||
unreadVariableError(usage._lastAccess, varname);
|
unreadVariableError(usage._lastAccess, varname);
|
||||||
|
|
||||||
// variable has been read but not written
|
// variable has been read but not written
|
||||||
else if (!usage._write && !usage._allocateMemory && !Token::simpleMatch(var->typeStartToken(), "std ::"))
|
else if (!usage._write && !usage._allocateMemory && !var->isStlType())
|
||||||
unassignedVariableError(usage._var->nameToken(), varname);
|
unassignedVariableError(usage._var->nameToken(), varname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -455,8 +455,8 @@ public:
|
||||||
* @return true if it is an stl type and its type matches any of the types in 'stlTypes'
|
* @return true if it is an stl type and its type matches any of the types in 'stlTypes'
|
||||||
*/
|
*/
|
||||||
template <std::size_t array_length>
|
template <std::size_t array_length>
|
||||||
bool isStlType(const char* (&stlTypes)[array_length]) const {
|
bool isStlType(const char* const(&stlTypes)[array_length]) const {
|
||||||
return _stlType && std::binary_search(stlTypes, stlTypes + array_length, typeStartToken()->strAt(2));
|
return _stlType && std::binary_search(stlTypes, stlTypes + array_length, _start->strAt(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -707,7 +707,7 @@ static void valueFlowSubFunction(TokenList *tokenlist, ErrorLogger *errorLogger,
|
||||||
// Get function argument, and check if parameter is passed by value
|
// Get function argument, and check if parameter is passed by value
|
||||||
const Function * const function = ftok->astOperand1()->function();
|
const Function * const function = ftok->astOperand1()->function();
|
||||||
const Variable * const arg = function ? function->getArgumentVar(argnr) : NULL;
|
const Variable * const arg = function ? function->getArgumentVar(argnr) : NULL;
|
||||||
if (!Token::Match(arg ? arg->typeStartToken() : NULL, "const| %type% %var% ,|)"))
|
if (!Token::Match(arg ? arg->typeStartToken() : NULL, "%type% %var% ,|)"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Function scope..
|
// Function scope..
|
||||||
|
|
Loading…
Reference in New Issue