From e8f72790398cd353a9b2b76094dd68d1384de474 Mon Sep 17 00:00:00 2001 From: PKEuS Date: Fri, 5 Sep 2014 12:03:08 +0200 Subject: [PATCH] Refactorization: Moved detection of STL strings to SymbolDatabase --- lib/checkclass.cpp | 2 +- lib/checkio.cpp | 8 +------- lib/checknullpointer.cpp | 8 ++++---- lib/checkother.cpp | 4 ++-- lib/checkstl.cpp | 4 ++-- lib/symboldatabase.cpp | 1 + lib/symboldatabase.h | 21 +++++++++++++++++---- test/testsymboldatabase.cpp | 3 +++ 8 files changed, 31 insertions(+), 20 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 8849b87e3..46e12b4ec 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -779,7 +779,7 @@ void CheckClass::initializationListUsage() } if (!allowed) continue; - if (!var->isPointer() && !var->isReference() && (var->type() || Token::Match(var->typeStartToken(), "std :: string|wstring !!::") || (Token::Match(var->typeStartToken(), "std :: %type% <") && !Token::simpleMatch(var->typeStartToken()->linkAt(3), "> ::")))) + if (!var->isPointer() && !var->isReference() && (var->type() || var->isStlStringType() || (Token::Match(var->typeStartToken(), "std :: %type% <") && !Token::simpleMatch(var->typeStartToken()->linkAt(3), "> ::")))) suggestInitializationList(tok, tok->str()); } } diff --git a/lib/checkio.cpp b/lib/checkio.cpp index 78f6ff445..31b774bc8 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -1616,17 +1616,11 @@ bool CheckIO::ArgumentInfo::isComplexType() const if (variableInfo->type()) return (true); - static std::set knownTypes; - if (knownTypes.empty()) { - knownTypes.insert("string"); - knownTypes.insert("wstring"); - } - const Token* varTypeTok = typeToken; if (varTypeTok->str() == "std") varTypeTok = varTypeTok->tokAt(2); - return ((knownTypes.find(varTypeTok->str()) != knownTypes.end() || (varTypeTok->strAt(1) == "<" && varTypeTok->linkAt(1) && varTypeTok->linkAt(1)->strAt(1) != "::")) && !variableInfo->isArrayOrPointer()); + return ((variableInfo->isStlStringType() || (varTypeTok->strAt(1) == "<" && varTypeTok->linkAt(1) && varTypeTok->linkAt(1)->strAt(1) != "::")) && !variableInfo->isArrayOrPointer()); } bool CheckIO::ArgumentInfo::isKnownType() const diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 00788ea57..545d91892 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -187,7 +187,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown) return true; if (Token::Match(parent->previous(), "%var% (") && tok->strAt(1) == ")") { const Variable* var = tok->tokAt(-2)->variable(); - if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string|wstring !!::")) + if (var && !var->isPointer() && !var->isArray() && var->isStlStringType()) return true; } @@ -217,7 +217,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown) else if (parent->astOperand1() && parent->astOperand2() == tok) ovar = parent->astOperand1()->variable(); } - if (ovar && !ovar->isPointer() && !ovar->isArray() && Token::Match(ovar->typeStartToken(), "std :: string|wstring !!::")) + if (ovar && !ovar->isPointer() && !ovar->isArray() && ovar->isStlStringType()) return true; // assume that it's not a dereference (no false positives) @@ -391,7 +391,7 @@ void CheckNullPointer::nullConstantDereference() else if (Token::Match(tok->previous(), "!!. %var% (") && (tok->previous()->str() != "::" || tok->strAt(-2) == "std")) { if (Token::simpleMatch(tok->tokAt(2), "0 )") && tok->varId()) { // constructor call const Variable *var = tok->variable(); - if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string|wstring !!::")) + if (var && !var->isPointer() && !var->isArray() && var->isStlStringType()) nullPointerError(tok); } else { // function call std::list var; @@ -431,7 +431,7 @@ void CheckNullPointer::nullConstantDereference() ovar = tok->variable(); else if (Token::Match(tok, "%var% =|+ 0 )|]|,|;|+")) ovar = tok->variable(); - if (ovar && !ovar->isPointer() && !ovar->isArray() && Token::Match(ovar->typeStartToken(), "std :: string|wstring !!::")) + if (ovar && !ovar->isPointer() && !ovar->isArray() && ovar->isStlStringType()) nullPointerError(tok); } } diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 4dc0b4d1a..a22ed3229 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1608,9 +1608,9 @@ void CheckOther::checkConstantFunctionParameter() // namespace and add them to the pattern. There are // streams for example (however it seems strange with // const stream parameter). - if (Token::Match(tok, "std :: string|wstring !!::")) { + if (var->isStlStringType()) { passedByValueError(tok, var->name()); - } else if (Token::Match(tok, "std :: %type% <") && !Token::simpleMatch(tok->linkAt(3), "> ::")) { + } else if (var->isStlType() && Token::Match(tok, "std :: %type% <") && !Token::simpleMatch(tok->linkAt(3), "> ::")) { passedByValueError(tok, var->name()); } else if (var->type()) { // Check if type is a struct or class. passedByValueError(tok, var->name()); diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index 33eed26f5..418933836 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -801,7 +801,7 @@ void CheckStl::if_find() const Token * decl = var->typeStartToken(); const unsigned int varid = tok->varId(); - bool str = Token::Match(decl, "std :: string|wstring &| %varid%", varid); + bool str = var->isStlStringType() && !var->isArrayOrPointer(); if (if_findCompare(tok->linkAt(3), str)) continue; @@ -858,7 +858,7 @@ void CheckStl::if_find() if_findError(tok, true); } - else if (decl && decl->str() == "string") { + else if (var->isStlStringType()) { decl = decl->next(); if ((Token::Match(decl, "* &| %varid%", varid) || Token::Match(decl, "&| %varid% [ ]| %any% ]| ", varid)) && performance) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 3d963adff..10d67515e 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1174,6 +1174,7 @@ void Variable::evaluate() if (_start) { setFlag(fIsClass, !_start->isStandardType() && !isPointer() && !isReference()); setFlag(fIsStlType, Token::simpleMatch(_start, "std ::")); + setFlag(fIsStlString, isStlType() && (Token::Match(_start->tokAt(2), "string|wstring|u16string|u32string !!::") || (Token::simpleMatch(_start->tokAt(2), "basic_string <") && !Token::simpleMatch(_start->linkAt(3), "> ::")))); } if (_access == Argument) { tok = _name; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index e8dc44b3a..035eeda66 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -137,8 +137,9 @@ class CPPCHECKLIB Variable { fIsRValueRef = (1 << 8), /** @brief rvalue reference variable */ fHasDefault = (1 << 9), /** @brief function argument with default value */ fIsStlType = (1 << 10), /** @brief STL type ('std::') */ - fIsIntType = (1 << 11), /** @brief Integral type */ - fIsFloatType = (1 << 12) /** @brief Floating point type */ + fIsStlString = (1 << 11), /** @brief std::string|wstring|basic_string|u16string|u32string */ + fIsIntType = (1 << 12), /** @brief Integral type */ + fIsFloatType = (1 << 13) /** @brief Floating point type */ }; /** @@ -446,6 +447,18 @@ public: return _dimensions[index_].known; } + /** + * Checks if the variable is an STL type ('std::') + * E.g.: + * std::string s; + * ... + * sVar->isStlType() == true + * @return true if it is an stl type and its type matches any of the types in 'stlTypes' + */ + bool isStlType() const { + return getFlag(fIsStlType); + } + /** * Checks if the variable is an STL type ('std::') * E.g.: @@ -454,8 +467,8 @@ public: * sVar->isStlType() == true * @return true if it is an stl type and its type matches any of the types in 'stlTypes' */ - bool isStlType() const { - return getFlag(fIsStlType); + bool isStlStringType() const { + return getFlag(fIsStlString); } /** diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 9a0118df6..57f8014a7 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -640,6 +640,7 @@ private: ASSERT_EQUALS(true, v.isStlType()); ASSERT_EQUALS(true, v.isStlType(types)); ASSERT_EQUALS(false, v.isStlType(no_types)); + ASSERT_EQUALS(true, v.isStlStringType()); } { reset(); @@ -655,6 +656,7 @@ private: ASSERT_EQUALS(true, v.isStlType()); ASSERT_EQUALS(true, v.isStlType(types)); ASSERT_EQUALS(false, v.isStlType(no_types)); + ASSERT_EQUALS(false, v.isStlStringType()); } { reset(); @@ -667,6 +669,7 @@ private: const char* types[] = { "bitset", "set", "vector" }; ASSERT_EQUALS(false, v.isStlType()); ASSERT_EQUALS(false, v.isStlType(types)); + ASSERT_EQUALS(false, v.isStlStringType()); } }