From ad0269eeebae534bfc13515130e02f2674650b31 Mon Sep 17 00:00:00 2001 From: Lucas Manuel Rodriguez Date: Thu, 30 Jan 2014 01:26:48 -0300 Subject: [PATCH] Refactor checks using Variable::isStlType() --- lib/checkclass.cpp | 8 ++++---- lib/checkio.cpp | 31 +++++++++++++++++++++++++++---- lib/checknullpointer.cpp | 17 +++++++++++++++-- lib/checkother.cpp | 2 +- lib/checkstl.cpp | 12 ++++++++---- lib/checkunusedvar.cpp | 6 +++--- lib/symboldatabase.h | 4 ++-- lib/valueflow.cpp | 2 +- 8 files changed, 61 insertions(+), 21 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 0283f81b2..abc858d3b 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -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)) diff --git a/lib/checkio.cpp b/lib/checkio.cpp index 5d6509789..5eecc769f 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -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()) { diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 4ddda7375..5d84a4a30 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -320,6 +320,13 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::listvarId() != 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); } } diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 547497e27..75b31b73a 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -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) diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index f1a1be999..b235a46da 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -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 diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 14410ac43..ab7a9e7cf 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -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); } } diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index d9fb534b3..89cca6e81 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -455,8 +455,8 @@ public: * @return true if it is an stl type and its type matches any of the types in 'stlTypes' */ template - 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: diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index eb317f750..c60066bb9 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -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..