Refactoring: Distinguish between C and C++ code
Refactoring: Replace CheckNonReentrantFunctions::initNonReentrantFunctions by static initialization
This commit is contained in:
parent
d7aa65c1fc
commit
11538c84f6
|
@ -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();
|
||||
|
|
|
@ -31,6 +31,21 @@ namespace {
|
|||
CheckNonReentrantFunctions instance;
|
||||
}
|
||||
|
||||
namespace {
|
||||
const std::set<std::string> _nonReentrantFunctions = make_container< std::set<std::string> > ()
|
||||
<< "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<std::string, std::string>::const_iterator it = _nonReentrantFunctions.find(tok->str());
|
||||
std::set<std::string>::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<std::string>::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<std::string>::const_iterator it(_nonReentrantFunctions.begin()), itend(_nonReentrantFunctions.end());
|
||||
for (; it!=itend; ++it) {
|
||||
info += "- " + *it + "\n";
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
|
|
@ -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<std::string,std::string> _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<std::string,std::string>::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<std::string,std::string>::const_iterator it(_nonReentrantFunctions.begin()), itend(_nonReentrantFunctions.end());
|
||||
for (; it!=itend; ++it) {
|
||||
info += "- " + it->first + "\n";
|
||||
}
|
||||
return info;
|
||||
}
|
||||
std::string classInfo() const;
|
||||
};
|
||||
/// @}
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -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<unsigned int> 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<std::map<const Type *,bool>::iterator,bool> found=isRecordTypeWithoutSideEffectsMap.insert(
|
||||
const std::pair<std::map<const Type *,bool>::iterator,bool> found=isRecordTypeWithoutSideEffectsMap.insert(
|
||||
std::pair<const Type *,bool>(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<std::map<const Type *,bool>::iterator,bool> found=isEmptyTypeMap.insert(
|
||||
const std::pair<std::map<const Type *,bool>::iterator,bool> found=isEmptyTypeMap.insert(
|
||||
std::pair<const Type *,bool>(type,false));
|
||||
bool & emptyType=found.first->second;
|
||||
if (!found.second)
|
||||
|
|
Loading…
Reference in New Issue