Fix (potential) multi-threading issues by moving static local vars (non-POD-type) to file scope
This commit is contained in:
parent
3986c0dc64
commit
d704e97203
|
@ -1522,12 +1522,13 @@ CheckIO::ArgumentInfo::~ArgumentInfo()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static const std::set<std::string> stl_vector = make_container< std::set<std::string> >() << "array" << "vector";
|
||||||
|
static const std::set<std::string> stl_string = make_container< std::set<std::string> >() << "string" << "u16string" << "u32string" << "wstring";
|
||||||
|
}
|
||||||
|
|
||||||
bool CheckIO::ArgumentInfo::isStdVectorOrString()
|
bool CheckIO::ArgumentInfo::isStdVectorOrString()
|
||||||
{
|
{
|
||||||
static const std::set<std::string> stl_vector = make_container< std::set<std::string> >() << "array" << "vector";
|
|
||||||
static const std::set<std::string> stl_string = make_container< std::set<std::string> >() << "string" << "u16string" << "u32string" << "wstring";
|
|
||||||
|
|
||||||
if (variableInfo->isStlType(stl_vector)) {
|
if (variableInfo->isStlType(stl_vector)) {
|
||||||
typeToken = variableInfo->typeStartToken()->tokAt(4);
|
typeToken = variableInfo->typeStartToken()->tokAt(4);
|
||||||
|
@ -1580,8 +1581,7 @@ bool CheckIO::ArgumentInfo::isStdVectorOrString()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckIO::ArgumentInfo::isStdContainer(const Token *tok)
|
namespace {
|
||||||
{
|
|
||||||
static const std::set<std::string> stl_container = make_container< std::set<std::string> >() <<
|
static const std::set<std::string> stl_container = make_container< std::set<std::string> >() <<
|
||||||
"array" << "bitset" << "deque" << "forward_list" <<
|
"array" << "bitset" << "deque" << "forward_list" <<
|
||||||
"hash_map" << "hash_multimap" << "hash_set" <<
|
"hash_map" << "hash_multimap" << "hash_set" <<
|
||||||
|
@ -1589,8 +1589,10 @@ bool CheckIO::ArgumentInfo::isStdContainer(const Token *tok)
|
||||||
"priority_queue" << "queue" << "set" << "stack" <<
|
"priority_queue" << "queue" << "set" << "stack" <<
|
||||||
"unordered_map" << "unordered_multimap" << "unordered_multiset" << "unordered_set" << "vector"
|
"unordered_map" << "unordered_multimap" << "unordered_multiset" << "unordered_set" << "vector"
|
||||||
;
|
;
|
||||||
static const std::set<std::string> stl_string= make_container< std::set<std::string> >() <<
|
}
|
||||||
"string" << "u16string" << "u32string" << "wstring";
|
|
||||||
|
bool CheckIO::ArgumentInfo::isStdContainer(const Token *tok)
|
||||||
|
{
|
||||||
|
|
||||||
if (tok && tok->variable()) {
|
if (tok && tok->variable()) {
|
||||||
const Variable* variable = tok->variable();
|
const Variable* variable = tok->variable();
|
||||||
|
|
|
@ -226,8 +226,7 @@ void CheckStl::mismatchingContainersError(const Token *tok)
|
||||||
reportError(tok, Severity::error, "mismatchingContainers", "Iterators of different containers are used together.");
|
reportError(tok, Severity::error, "mismatchingContainers", "Iterators of different containers are used together.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckStl::mismatchingContainers()
|
namespace {
|
||||||
{
|
|
||||||
static const char* const algorithm2_strings[] = { // func(begin1, end1
|
static const char* const algorithm2_strings[] = { // func(begin1, end1
|
||||||
"adjacent_find", "all_of", "any_of", "binary_search", "copy", "copy_if", "count", "count_if", "equal", "equal_range",
|
"adjacent_find", "all_of", "any_of", "binary_search", "copy", "copy_if", "count", "count_if", "equal", "equal_range",
|
||||||
"find", "find_if", "find_if_not", "for_each", "generate", "is_heap", "is_heap_until", "is_partitioned",
|
"find", "find_if", "find_if_not", "for_each", "generate", "is_heap", "is_heap_until", "is_partitioned",
|
||||||
|
@ -256,6 +255,10 @@ void CheckStl::mismatchingContainers()
|
||||||
static const std::string pattern1x1_1 = "%name% . " + iteratorBeginFuncPattern + " ( ) , ";
|
static const std::string pattern1x1_1 = "%name% . " + iteratorBeginFuncPattern + " ( ) , ";
|
||||||
static const std::string pattern1x1_2 = "%name% . " + iteratorEndFuncPattern + " ( ) ,|)";
|
static const std::string pattern1x1_2 = "%name% . " + iteratorEndFuncPattern + " ( ) ,|)";
|
||||||
static const std::string pattern2 = pattern1x1_1 + pattern1x1_2;
|
static const std::string pattern2 = pattern1x1_1 + pattern1x1_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckStl::mismatchingContainers()
|
||||||
|
{
|
||||||
|
|
||||||
// Check if different containers are used in various calls of standard functions
|
// Check if different containers are used in various calls of standard functions
|
||||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
@ -1036,14 +1039,17 @@ static bool isLocal(const Token *tok)
|
||||||
return var && !var->isStatic() && var->isLocal();
|
return var && !var->isStatic() && var->isLocal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckStl::string_c_str()
|
namespace {
|
||||||
{
|
|
||||||
const bool printInconclusive = _settings->inconclusive;
|
|
||||||
const bool printPerformance = _settings->isEnabled("performance");
|
|
||||||
static const std::set<std::string> stl_string = make_container< std::set<std::string> >() <<
|
static const std::set<std::string> stl_string = make_container< std::set<std::string> >() <<
|
||||||
"string" << "u16string" << "u32string" << "wstring" ;
|
"string" << "u16string" << "u32string" << "wstring" ;
|
||||||
static const std::set<std::string> stl_string_stream = make_container< std::set<std::string> >() <<
|
static const std::set<std::string> stl_string_stream = make_container< std::set<std::string> >() <<
|
||||||
"istringstream" << "ostringstream" << "stringstream" << "wstringstream" ;
|
"istringstream" << "ostringstream" << "stringstream" << "wstringstream" ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckStl::string_c_str()
|
||||||
|
{
|
||||||
|
const bool printInconclusive = _settings->inconclusive;
|
||||||
|
const bool printPerformance = _settings->isEnabled("performance");
|
||||||
|
|
||||||
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
|
||||||
|
@ -1340,6 +1346,15 @@ void CheckStl::autoPointerMallocError(const Token *tok, const std::string& alloc
|
||||||
reportError(tok, Severity::error, "useAutoPointerMalloc", summary + "\n" + verbose);
|
reportError(tok, Severity::error, "useAutoPointerMalloc", summary + "\n" + verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static const std::set<std::string> stl_containers_with_empty_and_clear = make_container< std::set<std::string> >() <<
|
||||||
|
"deque" << "forward_list" << "list" <<
|
||||||
|
"map" << "multimap" << "multiset" << "set" << "string" <<
|
||||||
|
"unordered_map" << "unordered_multimap" << "unordered_multiset" <<
|
||||||
|
"unordered_set" << "vector" << "wstring";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void CheckStl::uselessCalls()
|
void CheckStl::uselessCalls()
|
||||||
{
|
{
|
||||||
const bool printPerformance = _settings->isEnabled("performance");
|
const bool printPerformance = _settings->isEnabled("performance");
|
||||||
|
@ -1347,13 +1362,6 @@ void CheckStl::uselessCalls()
|
||||||
if (!printPerformance && !printWarning)
|
if (!printPerformance && !printWarning)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static const std::set<std::string> stl_string = make_container< std::set<std::string> >() <<
|
|
||||||
"string" << "u16string" << "u32string" << "wstring";
|
|
||||||
static const std::set<std::string> stl_containers_with_empty_and_clear = make_container< std::set<std::string> >() <<
|
|
||||||
"deque" << "forward_list" << "list" <<
|
|
||||||
"map" << "multimap" << "multiset" << "set" << "string" <<
|
|
||||||
"unordered_map" << "unordered_multimap" << "unordered_multiset" <<
|
|
||||||
"unordered_set" << "vector" << "wstring";
|
|
||||||
|
|
||||||
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
|
@ -1531,6 +1539,13 @@ void CheckStl::readingEmptyStlContainer_parseUsage(const Token* tok, bool map, s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static const std::set<std::string> MAP_STL_CONTAINERS = make_container< std::set<std::string> >() <<
|
||||||
|
"map" << "multimap" << "unordered_map" << "unordered_multimap" ;
|
||||||
|
static const std::set<std::string> NONMAP_STL_CONTAINERS = make_container< std::set<std::string> >() <<
|
||||||
|
"deque" << "forward_list" << "list" << "multiset" << "queue" << "set" << "stack" << "string" << "unordered_multiset" << "unordered_set" << "vector";
|
||||||
|
}
|
||||||
|
|
||||||
void CheckStl::readingEmptyStlContainer()
|
void CheckStl::readingEmptyStlContainer()
|
||||||
{
|
{
|
||||||
if (!_settings->isEnabled("style"))
|
if (!_settings->isEnabled("style"))
|
||||||
|
@ -1542,11 +1557,6 @@ void CheckStl::readingEmptyStlContainer()
|
||||||
std::set<unsigned int> empty_map; // empty std::map-like instances of STL containers
|
std::set<unsigned int> empty_map; // empty std::map-like instances of STL containers
|
||||||
std::set<unsigned int> empty_nonmap; // empty non-std::map-like instances of STL containers
|
std::set<unsigned int> empty_nonmap; // empty non-std::map-like instances of STL containers
|
||||||
|
|
||||||
static const std::set<std::string> MAP_STL_CONTAINERS = make_container< std::set<std::string> >() <<
|
|
||||||
"map" << "multimap" << "unordered_map" << "unordered_multimap" ;
|
|
||||||
static const std::set<std::string> NONMAP_STL_CONTAINERS = make_container< std::set<std::string> >() <<
|
|
||||||
"deque" << "forward_list" << "list" << "multiset" << "queue" << "set" << "stack" << "string" << "unordered_multiset" << "unordered_set" << "vector";
|
|
||||||
|
|
||||||
const std::list<Scope>& scopeList = _tokenizer->getSymbolDatabase()->scopeList;
|
const std::list<Scope>& scopeList = _tokenizer->getSymbolDatabase()->scopeList;
|
||||||
|
|
||||||
for (std::list<Scope>::const_iterator i = scopeList.begin(); i != scopeList.end(); ++i) {
|
for (std::list<Scope>::const_iterator i = scopeList.begin(); i != scopeList.end(); ++i) {
|
||||||
|
|
|
@ -111,6 +111,11 @@ void Token::update_property_info()
|
||||||
update_property_isStandardType();
|
update_property_isStandardType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static const std::set<std::string> stdTypes = make_container<std::set<std::string> >() <<
|
||||||
|
"bool" << "char" << "char16_t" << "char32_t" << "double" << "float" << "int" << "long" << "short" << "size_t" << "void" << "wchar_t";
|
||||||
|
}
|
||||||
|
|
||||||
void Token::update_property_isStandardType()
|
void Token::update_property_isStandardType()
|
||||||
{
|
{
|
||||||
isStandardType(false);
|
isStandardType(false);
|
||||||
|
@ -118,9 +123,6 @@ void Token::update_property_isStandardType()
|
||||||
if (_str.size() < 3)
|
if (_str.size() < 3)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static const std::set<std::string> stdTypes = make_container<std::set<std::string> >() <<
|
|
||||||
"bool" << "char" << "char16_t" << "char32_t" << "double" << "float" << "int" << "long" << "short" << "size_t" << "void" << "wchar_t";
|
|
||||||
|
|
||||||
if (stdTypes.find(_str)!=stdTypes.end()) {
|
if (stdTypes.find(_str)!=stdTypes.end()) {
|
||||||
isStandardType(true);
|
isStandardType(true);
|
||||||
_type = eType;
|
_type = eType;
|
||||||
|
|
|
@ -6176,14 +6176,18 @@ void Tokenizer::simplifyIfSameInnerCondition()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Binary operators simplification map
|
// Binary operators simplification map
|
||||||
static const std::pair<std::string, std::string> cAlternativeTokens_[] = {
|
namespace {
|
||||||
std::make_pair("and", "&&"), std::make_pair("and_eq", "&="), std::make_pair("bitand", "&"),
|
static const std::map<std::string, std::string> cAlternativeTokens = make_container< std::map<std::string, std::string> >()
|
||||||
std::make_pair("bitor", "|"), std::make_pair("not_eq", "!="), std::make_pair("or", "||"),
|
<< std::make_pair("and", "&&")
|
||||||
std::make_pair("or_eq", "|="), std::make_pair("xor", "^"), std::make_pair("xor_eq", "^=")
|
<< std::make_pair("and_eq", "&=")
|
||||||
};
|
<< std::make_pair("bitand", "&")
|
||||||
|
<< std::make_pair("bitor", "|")
|
||||||
static const std::map<std::string, std::string> cAlternativeTokens(cAlternativeTokens_,
|
<< std::make_pair("not_eq", "!=")
|
||||||
cAlternativeTokens_ + sizeof(cAlternativeTokens_)/sizeof(*cAlternativeTokens_));
|
<< std::make_pair("or", "||")
|
||||||
|
<< std::make_pair("or_eq", "|=")
|
||||||
|
<< std::make_pair("xor", "^")
|
||||||
|
<< std::make_pair("xor_eq", "^=") ;
|
||||||
|
}
|
||||||
|
|
||||||
// Simplify the C alternative tokens:
|
// Simplify the C alternative tokens:
|
||||||
// and => &&
|
// and => &&
|
||||||
|
@ -7995,12 +7999,8 @@ void Tokenizer::simplifyEnum()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tokenizer::simplifyStd()
|
namespace {
|
||||||
{
|
static const std::set<std::string> f = make_container< std::set<std::string> > () <<
|
||||||
if (isC())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const static std::set<std::string> f = make_container< std::set<std::string> > () <<
|
|
||||||
"strcat" <<
|
"strcat" <<
|
||||||
"strcpy" <<
|
"strcpy" <<
|
||||||
"strncat" <<
|
"strncat" <<
|
||||||
|
@ -8008,6 +8008,13 @@ void Tokenizer::simplifyStd()
|
||||||
"free" <<
|
"free" <<
|
||||||
"malloc" <<
|
"malloc" <<
|
||||||
"strdup";
|
"strdup";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tokenizer::simplifyStd()
|
||||||
|
{
|
||||||
|
if (isC())
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||||
if (tok->str() != "std")
|
if (tok->str() != "std")
|
||||||
|
@ -9281,21 +9288,23 @@ void Tokenizer::simplifyAttribute()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static const std::set<std::string> keywords = make_container< std::set<std::string> >()
|
||||||
|
<< "volatile"
|
||||||
|
<< "inline"
|
||||||
|
<< "_inline"
|
||||||
|
<< "__inline"
|
||||||
|
<< "__forceinline"
|
||||||
|
<< "register"
|
||||||
|
<< "__restrict"
|
||||||
|
<< "__restrict__" ;
|
||||||
|
}
|
||||||
// Remove "volatile", "inline", "register", "restrict", "override", "final", "static" and "constexpr"
|
// Remove "volatile", "inline", "register", "restrict", "override", "final", "static" and "constexpr"
|
||||||
// "restrict" keyword
|
// "restrict" keyword
|
||||||
// - New to 1999 ANSI/ISO C standard
|
// - New to 1999 ANSI/ISO C standard
|
||||||
// - Not in C++ standard yet
|
// - Not in C++ standard yet
|
||||||
void Tokenizer::simplifyKeyword()
|
void Tokenizer::simplifyKeyword()
|
||||||
{
|
{
|
||||||
std::set<std::string> keywords;
|
|
||||||
keywords.insert("volatile");
|
|
||||||
keywords.insert("inline");
|
|
||||||
keywords.insert("_inline");
|
|
||||||
keywords.insert("__inline");
|
|
||||||
keywords.insert("__forceinline");
|
|
||||||
keywords.insert("register");
|
|
||||||
keywords.insert("__restrict");
|
|
||||||
keywords.insert("__restrict__");
|
|
||||||
|
|
||||||
// FIXME: There is a risk that "keywords" are removed by mistake. This
|
// FIXME: There is a risk that "keywords" are removed by mistake. This
|
||||||
// code should be fixed so it doesn't remove variables etc. Nonstandard
|
// code should be fixed so it doesn't remove variables etc. Nonstandard
|
||||||
|
@ -9592,13 +9601,7 @@ void Tokenizer::simplifyBuiltinExpect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
// Add std:: in front of std classes, when using namespace std; was given
|
|
||||||
void Tokenizer::simplifyNamespaceStd()
|
|
||||||
{
|
|
||||||
if (!isCPP())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Types and objects in std namespace that are neither functions nor templates
|
// Types and objects in std namespace that are neither functions nor templates
|
||||||
static const std::set<std::string> stdTypes = make_container<std::set<std::string> >() <<
|
static const std::set<std::string> stdTypes = make_container<std::set<std::string> >() <<
|
||||||
"string"<< "wstring"<< "u16string"<< "u32string" <<
|
"string"<< "wstring"<< "u16string"<< "u32string" <<
|
||||||
|
@ -9643,6 +9646,15 @@ void Tokenizer::simplifyNamespaceStd()
|
||||||
"min"<< "max"<< "min_element"<< "max_element"<< "lexicographical_compare"<< "next_permutation"<< "prev_permutation" <<
|
"min"<< "max"<< "min_element"<< "max_element"<< "lexicographical_compare"<< "next_permutation"<< "prev_permutation" <<
|
||||||
"advance"<< "back_inserter"<< "distance"<< "front_inserter"<< "inserter" <<
|
"advance"<< "back_inserter"<< "distance"<< "front_inserter"<< "inserter" <<
|
||||||
"make_pair"<< "make_shared"<< "make_tuple";
|
"make_pair"<< "make_shared"<< "make_tuple";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add std:: in front of std classes, when using namespace std; was given
|
||||||
|
void Tokenizer::simplifyNamespaceStd()
|
||||||
|
{
|
||||||
|
if (!isCPP())
|
||||||
|
return;
|
||||||
|
|
||||||
const bool isCPP11 = _settings->standards.cpp == Standards::CPP11;
|
const bool isCPP11 = _settings->standards.cpp == Standards::CPP11;
|
||||||
|
|
||||||
for (const Token* tok = Token::findsimplematch(list.front(), "using namespace std ;"); tok; tok = tok->next()) {
|
for (const Token* tok = Token::findsimplematch(list.front(), "using namespace std ;"); tok; tok = tok->next()) {
|
||||||
|
@ -9743,14 +9755,7 @@ void Tokenizer::simplifyMicrosoftMemoryFunctions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tokenizer::simplifyMicrosoftStringFunctions()
|
namespace {
|
||||||
{
|
|
||||||
// skip if not Windows
|
|
||||||
if (_settings->platformType != Settings::Win32A &&
|
|
||||||
_settings->platformType != Settings::Win32W &&
|
|
||||||
_settings->platformType != Settings::Win64)
|
|
||||||
return;
|
|
||||||
|
|
||||||
struct triplet {
|
struct triplet {
|
||||||
triplet(const char* t, const char* m="", const char* u="") : tchar(t), mbcs(m), unicode(u) {}
|
triplet(const char* t, const char* m="", const char* u="") : tchar(t), mbcs(m), unicode(u) {}
|
||||||
bool operator <(const triplet& rhs) const {
|
bool operator <(const triplet& rhs) const {
|
||||||
|
@ -9758,7 +9763,8 @@ void Tokenizer::simplifyMicrosoftStringFunctions()
|
||||||
}
|
}
|
||||||
std::string tchar, mbcs, unicode;
|
std::string tchar, mbcs, unicode;
|
||||||
};
|
};
|
||||||
const static std::set<triplet> apis = make_container< std::set<triplet> >() <<
|
|
||||||
|
static const std::set<triplet> apis = make_container< std::set<triplet> >() <<
|
||||||
triplet("_topen", "open", "_wopen") <<
|
triplet("_topen", "open", "_wopen") <<
|
||||||
triplet("_tsopen_s", "_sopen_s", "_wsopen_s") <<
|
triplet("_tsopen_s", "_sopen_s", "_wsopen_s") <<
|
||||||
triplet("_tfopen", "fopen", "_wfopen") <<
|
triplet("_tfopen", "fopen", "_wfopen") <<
|
||||||
|
@ -9792,6 +9798,15 @@ void Tokenizer::simplifyMicrosoftStringFunctions()
|
||||||
triplet("_tscanf_s", "scanf_s", "wscanf_s") <<
|
triplet("_tscanf_s", "scanf_s", "wscanf_s") <<
|
||||||
triplet("_stscanf_s", "sscanf_s", "swscanf_s")
|
triplet("_stscanf_s", "sscanf_s", "swscanf_s")
|
||||||
;
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tokenizer::simplifyMicrosoftStringFunctions()
|
||||||
|
{
|
||||||
|
// skip if not Windows
|
||||||
|
if (_settings->platformType != Settings::Win32A &&
|
||||||
|
_settings->platformType != Settings::Win32W &&
|
||||||
|
_settings->platformType != Settings::Win64)
|
||||||
|
return;
|
||||||
|
|
||||||
const bool ansi = _settings->platformType == Settings::Win32A;
|
const bool ansi = _settings->platformType == Settings::Win32A;
|
||||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||||
|
|
Loading…
Reference in New Issue