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()
{
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)) {
typeToken = variableInfo->typeStartToken()->tokAt(4);
@ -1580,8 +1581,7 @@ bool CheckIO::ArgumentInfo::isStdVectorOrString()
return false;
}
bool CheckIO::ArgumentInfo::isStdContainer(const Token *tok)
{
namespace {
static const std::set<std::string> stl_container = make_container< std::set<std::string> >() <<
"array" << "bitset" << "deque" << "forward_list" <<
"hash_map" << "hash_multimap" << "hash_set" <<
@ -1589,8 +1589,10 @@ bool CheckIO::ArgumentInfo::isStdContainer(const Token *tok)
"priority_queue" << "queue" << "set" << "stack" <<
"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()) {
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.");
}
void CheckStl::mismatchingContainers()
{
namespace {
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",
"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_2 = "%name% . " + iteratorEndFuncPattern + " ( ) ,|)";
static const std::string pattern2 = pattern1x1_1 + pattern1x1_2;
}
void CheckStl::mismatchingContainers()
{
// Check if different containers are used in various calls of standard functions
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
@ -1036,14 +1039,17 @@ static bool isLocal(const Token *tok)
return var && !var->isStatic() && var->isLocal();
}
void CheckStl::string_c_str()
{
const bool printInconclusive = _settings->inconclusive;
const bool printPerformance = _settings->isEnabled("performance");
namespace {
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_string_stream = make_container< std::set<std::string> >() <<
"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();
@ -1340,6 +1346,15 @@ void CheckStl::autoPointerMallocError(const Token *tok, const std::string& alloc
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()
{
const bool printPerformance = _settings->isEnabled("performance");
@ -1347,13 +1362,6 @@ void CheckStl::uselessCalls()
if (!printPerformance && !printWarning)
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 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()
{
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_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;
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();
}
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()
{
isStandardType(false);
@ -118,9 +123,6 @@ void Token::update_property_isStandardType()
if (_str.size() < 3)
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()) {
isStandardType(true);
_type = eType;

View File

@ -6176,14 +6176,18 @@ void Tokenizer::simplifyIfSameInnerCondition()
}
// Binary operators simplification map
static const std::pair<std::string, std::string> cAlternativeTokens_[] = {
std::make_pair("and", "&&"), std::make_pair("and_eq", "&="), std::make_pair("bitand", "&"),
std::make_pair("bitor", "|"), std::make_pair("not_eq", "!="), std::make_pair("or", "||"),
std::make_pair("or_eq", "|="), std::make_pair("xor", "^"), std::make_pair("xor_eq", "^=")
};
static const std::map<std::string, std::string> cAlternativeTokens(cAlternativeTokens_,
cAlternativeTokens_ + sizeof(cAlternativeTokens_)/sizeof(*cAlternativeTokens_));
namespace {
static const std::map<std::string, std::string> cAlternativeTokens = make_container< std::map<std::string, std::string> >()
<< std::make_pair("and", "&&")
<< std::make_pair("and_eq", "&=")
<< std::make_pair("bitand", "&")
<< std::make_pair("bitor", "|")
<< std::make_pair("not_eq", "!=")
<< std::make_pair("or", "||")
<< std::make_pair("or_eq", "|=")
<< std::make_pair("xor", "^")
<< std::make_pair("xor_eq", "^=") ;
}
// Simplify the C alternative tokens:
// and => &&
@ -7995,12 +7999,8 @@ void Tokenizer::simplifyEnum()
}
}
void Tokenizer::simplifyStd()
{
if (isC())
return;
const static std::set<std::string> f = make_container< std::set<std::string> > () <<
namespace {
static const std::set<std::string> f = make_container< std::set<std::string> > () <<
"strcat" <<
"strcpy" <<
"strncat" <<
@ -8008,6 +8008,13 @@ void Tokenizer::simplifyStd()
"free" <<
"malloc" <<
"strdup";
}
void Tokenizer::simplifyStd()
{
if (isC())
return;
for (Token *tok = list.front(); tok; tok = tok->next()) {
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"
// "restrict" keyword
// - New to 1999 ANSI/ISO C standard
// - Not in C++ standard yet
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
// code should be fixed so it doesn't remove variables etc. Nonstandard
@ -9592,13 +9601,7 @@ void Tokenizer::simplifyBuiltinExpect()
}
}
// Add std:: in front of std classes, when using namespace std; was given
void Tokenizer::simplifyNamespaceStd()
{
if (!isCPP())
return;
namespace {
// 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> >() <<
"string"<< "wstring"<< "u16string"<< "u32string" <<
@ -9643,6 +9646,15 @@ void Tokenizer::simplifyNamespaceStd()
"min"<< "max"<< "min_element"<< "max_element"<< "lexicographical_compare"<< "next_permutation"<< "prev_permutation" <<
"advance"<< "back_inserter"<< "distance"<< "front_inserter"<< "inserter" <<
"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;
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()
{
// skip if not Windows
if (_settings->platformType != Settings::Win32A &&
_settings->platformType != Settings::Win32W &&
_settings->platformType != Settings::Win64)
return;
namespace {
struct triplet {
triplet(const char* t, const char* m="", const char* u="") : tchar(t), mbcs(m), unicode(u) {}
bool operator <(const triplet& rhs) const {
@ -9758,7 +9763,8 @@ void Tokenizer::simplifyMicrosoftStringFunctions()
}
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("_tsopen_s", "_sopen_s", "_wsopen_s") <<
triplet("_tfopen", "fopen", "_wfopen") <<
@ -9792,6 +9798,15 @@ void Tokenizer::simplifyMicrosoftStringFunctions()
triplet("_tscanf_s", "scanf_s", "wscanf_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;
for (Token *tok = list.front(); tok; tok = tok->next()) {