Fix (potential) multi-threading issues by moving static local vars (non-POD-type) to file scope

This commit is contained in:
Alexander Mai 2015-06-10 21:14:17 +02:00
parent 3986c0dc64
commit d704e97203
4 changed files with 96 additions and 67 deletions

View File

@ -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();

View File

@ -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) {

View File

@ -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;

View File

@ -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()) {