From 11538c84f659446d0736638f2b4d6b4b90eec99f Mon Sep 17 00:00:00 2001 From: amai2012 Date: Mon, 29 Jun 2015 21:17:15 +0200 Subject: [PATCH] Refactoring: Distinguish between C and C++ code Refactoring: Replace CheckNonReentrantFunctions::initNonReentrantFunctions by static initialization --- lib/checkbufferoverrun.cpp | 4 +-- lib/checknonreentrantfunctions.cpp | 37 ++++++++++++++++++++++-- lib/checknonreentrantfunctions.h | 45 ++---------------------------- lib/checkunusedvar.cpp | 13 ++++----- 4 files changed, 46 insertions(+), 53 deletions(-) diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index 6e2910d75..a57dfc9d0 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -1090,7 +1090,7 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable() "Check (BufferOverrun::checkGlobalAndLocalVariable)", tok->progressValue()); - if (Token::Match(tok, "[*;{}] %var% = new %type% [ %num% ]")) { + if (_tokenizer->isCPP() && Token::Match(tok, "[*;{}] %var% = new %type% [ %num% ]")) { size = MathLib::toLongNumber(tok->strAt(6)); type = tok->strAt(4); var = tok->next()->variable(); @@ -1098,7 +1098,7 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable() if (size < 0) { negativeMemoryAllocationSizeError(tok->next()->next()); } - } else if (Token::Match(tok, "[*;{}] %var% = new %type% ( %num%|%name% )")) { + } else if (_tokenizer->isCPP() && Token::Match(tok, "[*;{}] %var% = new %type% ( %num%|%name% )")) { size = 1; type = tok->strAt(4); var = tok->next()->variable(); diff --git a/lib/checknonreentrantfunctions.cpp b/lib/checknonreentrantfunctions.cpp index ad423bced..e6fd874eb 100644 --- a/lib/checknonreentrantfunctions.cpp +++ b/lib/checknonreentrantfunctions.cpp @@ -31,6 +31,21 @@ namespace { CheckNonReentrantFunctions instance; } +namespace { + const std::set _nonReentrantFunctions = make_container< std::set > () + << "localtime" << "gmtime" << "strtok" << "gethostbyname" << "gethostbyaddr" << "getservbyname" + << "getservbyport" << "crypt" << "ttyname" << "gethostbyname2" + << "getprotobyname" << "getnetbyname" << "getnetbyaddr" << "getrpcbyname" << "getrpcbynumber" << "getrpcent" + << "ctermid" << "readdir" << "getlogin" << "getpwent" << "getpwnam" << "getpwuid" << "getspent" + << "fgetspent" << "getspnam" << "getgrnam" << "getgrgid" << "getnetgrent" << "tempnam" << "fgetpwent" + << "fgetgrent" << "ecvt" << "gcvt" << "getservent" << "gethostent" << "getgrent" << "fcvt" ; +} + +std::string CheckNonReentrantFunctions::generateErrorMessage(const std::string& function) { + return std::string("Non reentrant function '") + function + "' called. " + + "For threadsafe applications it is recommended to use the reentrant replacement function '" + function + "_r'."; +} + void CheckNonReentrantFunctions::nonReentrantFunctions() { if (!_settings->standards.posix || !_settings->isEnabled("portability")) @@ -46,7 +61,7 @@ void CheckNonReentrantFunctions::nonReentrantFunctions() continue; // Check for non-reentrant function name - std::map::const_iterator it = _nonReentrantFunctions.find(tok->str()); + std::set::const_iterator it = _nonReentrantFunctions.find(tok->str()); if (it == _nonReentrantFunctions.end()) continue; @@ -62,8 +77,26 @@ void CheckNonReentrantFunctions::nonReentrantFunctions() } // Only affecting multi threaded code, therefore this is "portability" - reportError(tok, Severity::portability, "nonreentrantFunctions" + it->first, it->second); + reportError(tok, Severity::portability, "nonreentrantFunctions" + *it, generateErrorMessage(*it)); } } } //--------------------------------------------------------------------------- + +void CheckNonReentrantFunctions::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { + CheckNonReentrantFunctions c(0, settings, errorLogger); + + std::set::const_iterator it(_nonReentrantFunctions.begin()), itend(_nonReentrantFunctions.end()); + for (; it!=itend; ++it) { + c.reportError(0, Severity::portability, "nonreentrantFunctions"+*it, generateErrorMessage(*it)); + } +} + +std::string CheckNonReentrantFunctions::classInfo() const { + std::string info = "Warn if any of these non reentrant functions are used:\n"; + std::set::const_iterator it(_nonReentrantFunctions.begin()), itend(_nonReentrantFunctions.end()); + for (; it!=itend; ++it) { + info += "- " + *it + "\n"; + } + return info; +} diff --git a/lib/checknonreentrantfunctions.h b/lib/checknonreentrantfunctions.h index 3d6dde962..b9c04a95c 100644 --- a/lib/checknonreentrantfunctions.h +++ b/lib/checknonreentrantfunctions.h @@ -38,13 +38,11 @@ class CPPCHECKLIB CheckNonReentrantFunctions : public Check { public: /** This constructor is used when registering the CheckNonReentrantFunctions */ CheckNonReentrantFunctions() : Check(myName()) { - initNonReentrantFunctions(); } /** This constructor is used when running checks. */ CheckNonReentrantFunctions(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) : Check(myName(), tokenizer, settings, errorLogger) { - initNonReentrantFunctions(); } void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) { @@ -57,52 +55,15 @@ public: private: - /* function name / error message */ - std::map _nonReentrantFunctions; + static std::string generateErrorMessage(const std::string& function); - /** init nonreentrant functions list ' */ - void initNonReentrantFunctions() { - static const char * const non_reentrant_functions_list[] = { - "localtime", "gmtime", "strtok", "gethostbyname", "gethostbyaddr", "getservbyname" - , "getservbyport", "crypt", "ttyname", "gethostbyname2" - , "getprotobyname", "getnetbyname", "getnetbyaddr", "getrpcbyname", "getrpcbynumber", "getrpcent" - , "ctermid", "readdir", "getlogin", "getpwent", "getpwnam", "getpwuid", "getspent" - , "fgetspent", "getspnam", "getgrnam", "getgrgid", "getnetgrent", "tempnam", "fgetpwent" - , "fgetgrent", "ecvt", "gcvt", "getservent", "gethostent", "getgrent", "fcvt" - }; - - // generate messages - for (unsigned int i = 0; i < (sizeof(non_reentrant_functions_list) / sizeof(char *)); ++i) { - std::string strMsg("Non reentrant function '"); - strMsg+=non_reentrant_functions_list[i]; - strMsg+= "' called. For threadsafe applications it is recommended to use the reentrant replacement function '"; - strMsg+=non_reentrant_functions_list[i]; - strMsg+="_r'."; - _nonReentrantFunctions[non_reentrant_functions_list[i]] = strMsg; - } - } - - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckNonReentrantFunctions c(0, settings, errorLogger); - - std::map::const_iterator it(_nonReentrantFunctions.begin()), itend(_nonReentrantFunctions.end()); - for (; it!=itend; ++it) { - c.reportError(0, Severity::portability, "nonreentrantFunctions"+it->first, it->second); - } - } + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const; static std::string myName() { return "Non reentrant functions"; } - std::string classInfo() const { - std::string info = "Warn if any of these non reentrant functions are used:\n"; - std::map::const_iterator it(_nonReentrantFunctions.begin()), itend(_nonReentrantFunctions.end()); - for (; it!=itend; ++it) { - info += "- " + it->first + "\n"; - } - return info; - } + std::string classInfo() const; }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 93fcde6de..4608a7b5f 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -792,7 +792,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const // C++11 std::for_each // No warning should be written if a variable is first read and // then written in the body. - else if (Token::simpleMatch(tok, "for_each (") && Token::simpleMatch(tok->linkAt(1), ") ;")) { + else if (_tokenizer->isCPP() && Token::simpleMatch(tok, "for_each (") && Token::simpleMatch(tok->linkAt(1), ") ;")) { const Token *end = tok->linkAt(1); if (end->previous()->str() == "}") { std::set readvar; @@ -829,8 +829,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const } // Freeing memory (not considered "using" the pointer if it was also allocated in this function) if (Token::Match(tok, "free|g_free|kfree|vfree ( %var% )") || - Token::Match(tok, "delete %var% ;") || - Token::Match(tok, "delete [ ] %var% ;")) { + (_tokenizer->isCPP() && (Token::Match(tok, "delete %var% ;") || Token::Match(tok, "delete [ ] %var% ;")))) { unsigned int varid = 0; if (tok->str() != "delete") { varid = tok->tokAt(2)->varId(); @@ -918,8 +917,8 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const const Token *type = start->tokAt(3); // skip nothrow - if (Token::simpleMatch(type, "( nothrow )") || - Token::simpleMatch(type, "( std :: nothrow )")) + if (_tokenizer->isCPP() && (Token::simpleMatch(type, "( nothrow )") || + Token::simpleMatch(type, "( std :: nothrow )"))) type = type->link()->next(); // is it a user defined type? @@ -1268,7 +1267,7 @@ bool CheckUnusedVar::isRecordTypeWithoutSideEffects(const Type* type) // a type that has no side effects (no constructors and no members with constructors) /** @todo false negative: check constructors for side effects */ - std::pair::iterator,bool> found=isRecordTypeWithoutSideEffectsMap.insert( + const std::pair::iterator,bool> found=isRecordTypeWithoutSideEffectsMap.insert( std::pair(type,false)); //Initialize with side effects for possible recursions bool & withoutSideEffects=found.first->second; if (!found.second) @@ -1294,7 +1293,7 @@ bool CheckUnusedVar::isEmptyType(const Type* type) { // a type that has no variables and no constructor - std::pair::iterator,bool> found=isEmptyTypeMap.insert( + const std::pair::iterator,bool> found=isEmptyTypeMap.insert( std::pair(type,false)); bool & emptyType=found.first->second; if (!found.second)