Refactor checks using Variable::isStlType()

This commit is contained in:
Lucas Manuel Rodriguez 2014-01-30 01:26:48 -03:00
parent 8db904692a
commit ad0269eeeb
8 changed files with 61 additions and 21 deletions

View File

@ -1022,7 +1022,7 @@ void CheckClass::checkMemsetType(const Scope *start, const Token *tok, const Sco
const Token *tok1 = var->typeStartToken();
// check for std:: type
if (Token::simpleMatch(tok1, "std ::"))
if (var->isStlType())
if (allocation)
mallocOnClassError(tok, tok->str(), type->classDef, "'std::" + tok1->strAt(2) + "'");
else
@ -1730,7 +1730,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool&
const Variable *var = end->variable();
if (var && Token::simpleMatch(var->typeStartToken(), "std :: map")) // operator[] changes a map
return (false);
return false;
}
if (!jumpBackToken)
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) == "(") {
const Variable *var = lastVarTok->variable();
if (!var)
return (false);
if (Token::simpleMatch(var->typeStartToken(), "std ::") // assume all std::*::size() and std::*::empty() are const
return false;
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")))
;
else if (!var->typeScope() || !isConstMemberFunc(var->typeScope(), end))

View File

@ -1446,11 +1446,20 @@ CheckIO::ArgumentInfo::~ArgumentInfo()
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);
_template = true;
return true;
} else if (Token::Match(variableInfo->typeStartToken(), "std :: string|wstring")) {
} else if (variableInfo->isStlType(stl_string)) {
tempToken = new Token(0);
tempToken->fileIndex(variableInfo->typeStartToken()->fileIndex());
tempToken->linenr(variableInfo->typeStartToken()->linenr());
@ -1485,11 +1494,25 @@ bool CheckIO::ArgumentInfo::isStdVectorOrString()
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 (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);
return true;
} else if (Token::Match(tok->variable()->typeStartToken(), "std :: string|wstring")) {
} else if (tok->variable()->isStlType(stl_string)) {
typeToken = tok->variable()->typeStartToken();
return true;
} else if (tok->variable()->type() && !tok->variable()->type()->derivedFrom.empty()) {

View File

@ -320,6 +320,13 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
*/
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;
unknown = false;
@ -379,7 +386,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
return true;
if (tok2 && tok2->varId() != 0) {
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;
}
}
@ -821,6 +828,12 @@ void CheckNullPointer::nullConstantDereference()
{
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();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
@ -874,7 +887,7 @@ void CheckNullPointer::nullConstantDereference()
nullPointerError(tok);
if (tok2 && tok2->varId() != 0) {
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);
}
}

View File

@ -1161,7 +1161,7 @@ void CheckOther::suspiciousEqualityComparisonError(const Token* tok)
//---------------------------------------------------------------------------
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)

View File

@ -294,6 +294,10 @@ void CheckStl::mismatchingContainers()
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();
// Scan through all scopes..
@ -316,7 +320,7 @@ void CheckStl::stlOutOfBounds()
const Variable *container = tok->tokAt(3)->variable();
if (!container)
continue;
if (!Token::Match(container->typeStartToken(), "std :: vector|deque|array|string|wstring|basic_string"))
if (!container->isStlType(stl_bounded_container))
continue;
// variable id for loop variable.
@ -868,7 +872,7 @@ void CheckStl::if_find()
//pretty bad limitation.. but it is there in order to avoid
//own implementations of 'find' or any container
if (!Token::simpleMatch(decl, "std ::"))
if (!var->isStlType())
continue;
decl = decl->tokAt(2);
@ -1199,7 +1203,7 @@ void CheckStl::string_c_str()
tok2 = tok2->previous();
if (tok2 && Token::simpleMatch(tok2->tokAt(-4), ". c_str ( )")) {
const Variable* var = tok2->tokAt(-5)->variable();
if (var && Token::simpleMatch(var->typeStartToken(), "std ::"))
if (var && var->isStlType())
string_c_strParam(tok, i->second);
}
}
@ -1245,7 +1249,7 @@ void CheckStl::string_c_str()
tok2 = tok2->tokAt(-5);
if (tok2->isName()) { // return var.c_str(); => check if var is a std type
const Variable *var = tok2->variable();
if (var && Token::simpleMatch(var->typeStartToken(), "std ::"))
if (var && var->isStlType())
string_c_strReturn(tok);
} else {
// TODO: determine if a error should be written or not

View File

@ -688,7 +688,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
else if (_tokenizer->isC() ||
i->typeEndToken()->isStandardType() ||
isRecordTypeWithoutSideEffects(i->type()) ||
(Token::simpleMatch(i->typeStartToken(), "std ::") &&
(i->isStlType() &&
i->typeStartToken()->strAt(2) != "lock_guard" &&
i->typeStartToken()->strAt(2) != "unique_lock"))
type = Variables::standard;
@ -1118,7 +1118,7 @@ void CheckUnusedVar::checkFunctionVariableUsage()
unusedVariableError(usage._var->nameToken(), varname);
// 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);
// variable has been written but not read
@ -1126,7 +1126,7 @@ void CheckUnusedVar::checkFunctionVariableUsage()
unreadVariableError(usage._lastAccess, varname);
// 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);
}
}

View File

@ -455,8 +455,8 @@ public:
* @return true if it is an stl type and its type matches any of the types in 'stlTypes'
*/
template <std::size_t array_length>
bool isStlType(const char* (&stlTypes)[array_length]) const {
return _stlType && std::binary_search(stlTypes, stlTypes + array_length, typeStartToken()->strAt(2));
bool isStlType(const char* const(&stlTypes)[array_length]) const {
return _stlType && std::binary_search(stlTypes, stlTypes + array_length, _start->strAt(2));
}
private:

View File

@ -707,7 +707,7 @@ static void valueFlowSubFunction(TokenList *tokenlist, ErrorLogger *errorLogger,
// Get function argument, and check if parameter is passed by value
const Function * const function = ftok->astOperand1()->function();
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;
// Function scope..