Use std::unordered_* containers for faster lookups (#3052)

This commit is contained in:
Oliver Stöneberg 2021-01-16 13:52:09 +01:00 committed by GitHub
parent 76f759fcc4
commit 7aa85aa408
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 35 additions and 32 deletions

View File

@ -112,7 +112,7 @@ struct Filepointer {
}; };
namespace { namespace {
const std::set<std::string> whitelist = { "clearerr", "feof", "ferror", "fgetpos", "ftell", "setbuf", "setvbuf", "ungetc", "ungetwc" }; const std::unordered_set<std::string> whitelist = { "clearerr", "feof", "ferror", "fgetpos", "ftell", "setbuf", "setvbuf", "ungetc", "ungetwc" };
} }
void CheckIO::checkFileUsage() void CheckIO::checkFileUsage()

View File

@ -54,7 +54,7 @@ static const CWE CWE772(772U); // Missing Release of Resource after Effective L
* This list contains function names with const parameters e.g.: atof(const char *) * This list contains function names with const parameters e.g.: atof(const char *)
* TODO: This list should be replaced by <leak-ignore/> in .cfg files. * TODO: This list should be replaced by <leak-ignore/> in .cfg files.
*/ */
static const std::set<std::string> call_func_white_list = { static const std::unordered_set<std::string> call_func_white_list = {
"_open", "_wopen", "access", "adjtime", "asctime_r", "asprintf", "chdir", "chmod", "chown" "_open", "_wopen", "access", "adjtime", "asctime_r", "asprintf", "chdir", "chmod", "chown"
, "creat", "ctime_r", "execl", "execle", "execlp", "execv", "execve", "fchmod", "fcntl" , "creat", "ctime_r", "execl", "execle", "execlp", "execv", "execve", "fchmod", "fcntl"
, "fdatasync", "fclose", "flock", "fmemopen", "fnmatch", "fopen", "fopencookie", "for", "free" , "fdatasync", "fclose", "flock", "fmemopen", "fnmatch", "fopen", "fopencookie", "for", "free"

View File

@ -1008,7 +1008,7 @@ bool Library::isnullargbad(const Token *ftok, int argnr) const
if (!arg) { if (!arg) {
// scan format string argument should not be null // scan format string argument should not be null
const std::string funcname = getFunctionName(ftok); const std::string funcname = getFunctionName(ftok);
const std::map<std::string, Function>::const_iterator it = functions.find(funcname); const std::unordered_map<std::string, Function>::const_iterator it = functions.find(funcname);
if (it != functions.cend() && it->second.formatstr && it->second.formatstr_scan) if (it != functions.cend() && it->second.formatstr && it->second.formatstr_scan)
return true; return true;
} }
@ -1021,7 +1021,7 @@ bool Library::isuninitargbad(const Token *ftok, int argnr, int indirect, bool *h
if (!arg) { if (!arg) {
// non-scan format string argument should not be uninitialized // non-scan format string argument should not be uninitialized
const std::string funcname = getFunctionName(ftok); const std::string funcname = getFunctionName(ftok);
const std::map<std::string, Function>::const_iterator it = functions.find(funcname); const std::unordered_map<std::string, Function>::const_iterator it = functions.find(funcname);
if (it != functions.cend() && it->second.formatstr && !it->second.formatstr_scan) if (it != functions.cend() && it->second.formatstr && !it->second.formatstr_scan)
return true; return true;
} }
@ -1078,7 +1078,7 @@ const Library::ArgumentChecks * Library::getarg(const Token *ftok, int argnr) co
{ {
if (isNotLibraryFunction(ftok)) if (isNotLibraryFunction(ftok))
return nullptr; return nullptr;
const std::map<std::string, Function>::const_iterator it1 = functions.find(getFunctionName(ftok)); const std::unordered_map<std::string, Function>::const_iterator it1 = functions.find(getFunctionName(ftok));
if (it1 == functions.cend()) if (it1 == functions.cend())
return nullptr; return nullptr;
const std::map<int,ArgumentChecks>::const_iterator it2 = it1->second.argumentChecks.find(argnr); const std::map<int,ArgumentChecks>::const_iterator it2 = it1->second.argumentChecks.find(argnr);
@ -1189,7 +1189,7 @@ bool Library::isNotLibraryFunction(const Token *ftok) const
bool Library::matchArguments(const Token *ftok, const std::string &functionName) const bool Library::matchArguments(const Token *ftok, const std::string &functionName) const
{ {
const int callargs = numberOfArguments(ftok); const int callargs = numberOfArguments(ftok);
const std::map<std::string, Function>::const_iterator it = functions.find(functionName); const std::unordered_map<std::string, Function>::const_iterator it = functions.find(functionName);
if (it == functions.cend()) if (it == functions.cend())
return (callargs == 0); return (callargs == 0);
int args = 0; int args = 0;
@ -1259,7 +1259,7 @@ bool Library::formatstr_function(const Token* ftok) const
if (isNotLibraryFunction(ftok)) if (isNotLibraryFunction(ftok))
return false; return false;
const std::map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok)); const std::unordered_map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok));
if (it != functions.cend()) if (it != functions.cend())
return it->second.formatstr; return it->second.formatstr;
return false; return false;
@ -1290,7 +1290,7 @@ Library::UseRetValType Library::getUseRetValType(const Token *ftok) const
{ {
if (isNotLibraryFunction(ftok)) if (isNotLibraryFunction(ftok))
return Library::UseRetValType::NONE; return Library::UseRetValType::NONE;
const std::map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok)); const std::unordered_map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok));
if (it != functions.cend()) if (it != functions.cend())
return it->second.useretval; return it->second.useretval;
return Library::UseRetValType::NONE; return Library::UseRetValType::NONE;
@ -1332,7 +1332,7 @@ const Library::Function *Library::getFunction(const Token *ftok) const
{ {
if (isNotLibraryFunction(ftok)) if (isNotLibraryFunction(ftok))
return nullptr; return nullptr;
const std::map<std::string, Function>::const_iterator it1 = functions.find(getFunctionName(ftok)); const std::unordered_map<std::string, Function>::const_iterator it1 = functions.find(getFunctionName(ftok));
if (it1 == functions.cend()) if (it1 == functions.cend())
return nullptr; return nullptr;
return &it1->second; return &it1->second;
@ -1343,7 +1343,7 @@ bool Library::hasminsize(const Token *ftok) const
{ {
if (isNotLibraryFunction(ftok)) if (isNotLibraryFunction(ftok))
return false; return false;
const std::map<std::string, Function>::const_iterator it1 = functions.find(getFunctionName(ftok)); const std::unordered_map<std::string, Function>::const_iterator it1 = functions.find(getFunctionName(ftok));
if (it1 == functions.cend()) if (it1 == functions.cend())
return false; return false;
for (std::map<int, ArgumentChecks>::const_iterator it2 = it1->second.argumentChecks.cbegin(); it2 != it1->second.argumentChecks.cend(); ++it2) { for (std::map<int, ArgumentChecks>::const_iterator it2 = it1->second.argumentChecks.cbegin(); it2 != it1->second.argumentChecks.cend(); ++it2) {
@ -1372,28 +1372,28 @@ Library::ArgumentChecks::Direction Library::getArgDirection(const Token* ftok, i
bool Library::ignorefunction(const std::string& functionName) const bool Library::ignorefunction(const std::string& functionName) const
{ {
const std::map<std::string, Function>::const_iterator it = functions.find(functionName); const std::unordered_map<std::string, Function>::const_iterator it = functions.find(functionName);
if (it != functions.cend()) if (it != functions.cend())
return it->second.ignore; return it->second.ignore;
return false; return false;
} }
bool Library::isUse(const std::string& functionName) const bool Library::isUse(const std::string& functionName) const
{ {
const std::map<std::string, Function>::const_iterator it = functions.find(functionName); const std::unordered_map<std::string, Function>::const_iterator it = functions.find(functionName);
if (it != functions.cend()) if (it != functions.cend())
return it->second.use; return it->second.use;
return false; return false;
} }
bool Library::isLeakIgnore(const std::string& functionName) const bool Library::isLeakIgnore(const std::string& functionName) const
{ {
const std::map<std::string, Function>::const_iterator it = functions.find(functionName); const std::unordered_map<std::string, Function>::const_iterator it = functions.find(functionName);
if (it != functions.cend()) if (it != functions.cend())
return it->second.leakignore; return it->second.leakignore;
return false; return false;
} }
bool Library::isFunctionConst(const std::string& functionName, bool pure) const bool Library::isFunctionConst(const std::string& functionName, bool pure) const
{ {
const std::map<std::string, Function>::const_iterator it = functions.find(functionName); const std::unordered_map<std::string, Function>::const_iterator it = functions.find(functionName);
if (it != functions.cend()) if (it != functions.cend())
return pure ? it->second.ispure : it->second.isconst; return pure ? it->second.ispure : it->second.isconst;
return false; return false;
@ -1404,7 +1404,7 @@ bool Library::isFunctionConst(const Token *ftok) const
return true; return true;
if (isNotLibraryFunction(ftok)) if (isNotLibraryFunction(ftok))
return false; return false;
const std::map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok)); const std::unordered_map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok));
return (it != functions.end() && it->second.isconst); return (it != functions.end() && it->second.isconst);
} }

View File

@ -30,6 +30,8 @@
#include <map> #include <map>
#include <set> #include <set>
#include <string> #include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -316,7 +318,7 @@ public:
}; };
const Function *getFunction(const Token *ftok) const; const Function *getFunction(const Token *ftok) const;
std::map<std::string, Function> functions; std::unordered_map<std::string, Function> functions;
bool isUse(const std::string& functionName) const; bool isUse(const std::string& functionName) const;
bool isLeakIgnore(const std::string& functionName) const; bool isLeakIgnore(const std::string& functionName) const;
bool isFunctionConst(const std::string& functionName, bool pure) const; bool isFunctionConst(const std::string& functionName, bool pure) const;
@ -422,7 +424,7 @@ public:
std::vector<std::string> defines; // to provide some library defines std::vector<std::string> defines; // to provide some library defines
std::set<std::string> smartPointers; std::unordered_set<std::string> smartPointers;
bool isSmartPointer(const Token *tok) const; bool isSmartPointer(const Token *tok) const;
struct PodType { struct PodType {
@ -431,7 +433,7 @@ public:
enum class Type { NO, BOOL, CHAR, SHORT, INT, LONG, LONGLONG } stdtype; enum class Type { NO, BOOL, CHAR, SHORT, INT, LONG, LONGLONG } stdtype;
}; };
const struct PodType *podtype(const std::string &name) const { const struct PodType *podtype(const std::string &name) const {
const std::map<std::string, struct PodType>::const_iterator it = mPodTypes.find(name); const std::unordered_map<std::string, struct PodType>::const_iterator it = mPodTypes.find(name);
return (it != mPodTypes.end()) ? &(it->second) : nullptr; return (it != mPodTypes.end()) ? &(it->second) : nullptr;
} }
@ -575,7 +577,7 @@ private:
std::map<std::string, ExportedFunctions> mExporters; // keywords that export variables/functions to libraries (meta-code/macros) std::map<std::string, ExportedFunctions> mExporters; // keywords that export variables/functions to libraries (meta-code/macros)
std::map<std::string, std::set<std::string> > mImporters; // keywords that import variables/functions std::map<std::string, std::set<std::string> > mImporters; // keywords that import variables/functions
std::map<std::string, int> mReflection; // invocation of reflection std::map<std::string, int> mReflection; // invocation of reflection
std::map<std::string, struct PodType> mPodTypes; // pod types std::unordered_map<std::string, struct PodType> mPodTypes; // pod types
std::map<std::string, PlatformType> mPlatformTypes; // platform independent typedefs std::map<std::string, PlatformType> mPlatformTypes; // platform independent typedefs
std::map<std::string, Platform> mPlatforms; // platform dependent typedefs std::map<std::string, Platform> mPlatforms; // platform dependent typedefs
std::map<std::pair<std::string,std::string>, TypeCheck> mTypeChecks; std::map<std::pair<std::string,std::string>, TypeCheck> mTypeChecks;

View File

@ -1308,7 +1308,7 @@ void SymbolDatabase::createSymbolDatabaseEnums()
void SymbolDatabase::createSymbolDatabaseIncompleteVars() void SymbolDatabase::createSymbolDatabaseIncompleteVars()
{ {
const std::set<std::string> cpp20keywords = { static const std::unordered_set<std::string> cpp20keywords = {
"alignas", "alignas",
"alignof", "alignof",
"axiom", "axiom",
@ -1321,7 +1321,7 @@ void SymbolDatabase::createSymbolDatabaseIncompleteVars()
"reflexpr", "reflexpr",
"requires", "requires",
}; };
const std::set<std::string> cppkeywords = { static const std::unordered_set<std::string> cppkeywords = {
"asm", "asm",
"auto", "auto",
"catch", "catch",
@ -5379,8 +5379,8 @@ namespace {
"register", "return", "short", "signed", "sizeof", "static", "struct", "switch", "typedef", \ "register", "return", "short", "signed", "sizeof", "static", "struct", "switch", "typedef", \
"union", "unsigned", "void", "volatile", "while" "union", "unsigned", "void", "volatile", "while"
const std::set<std::string> c_keywords = { C_KEYWORDS, "restrict" }; const std::unordered_set<std::string> c_keywords = { C_KEYWORDS, "restrict" };
const std::set<std::string> cpp_keywords = { const std::unordered_set<std::string> cpp_keywords = {
C_KEYWORDS, C_KEYWORDS,
"alignas", "alignof", "and", "and_eq", "asm", "bitand", "bitor", "bool", "catch", "char8_t", "char16_t", "alignas", "alignof", "and", "and_eq", "asm", "bitand", "bitor", "bool", "catch", "char8_t", "char16_t",
"char32_t", "class", "compl", "concept", "consteval", "constexpr", "constinit", "const_cast", "co_await", "char32_t", "class", "compl", "concept", "consteval", "constexpr", "constinit", "const_cast", "co_await",

View File

@ -53,7 +53,7 @@ Token::~Token()
delete mImpl; delete mImpl;
} }
static const std::set<std::string> controlFlowKeywords = { static const std::unordered_set<std::string> controlFlowKeywords = {
"goto", "goto",
"do", "do",
"if", "if",
@ -127,7 +127,7 @@ void Token::update_property_info()
update_property_isStandardType(); update_property_isStandardType();
} }
static const std::set<std::string> stdTypes = { "bool" static const std::unordered_set<std::string> stdTypes = { "bool"
, "_Bool" , "_Bool"
, "char" , "char"
, "double" , "double"

View File

@ -3369,15 +3369,15 @@ void Tokenizer::setVarId()
// Variable declarations can't start with "return" etc. // Variable declarations can't start with "return" etc.
#define NOTSTART_C "NOT", "case", "default", "goto", "not", "return", "sizeof", "typedef" #define NOTSTART_C "NOT", "case", "default", "goto", "not", "return", "sizeof", "typedef"
static const std::set<std::string> notstart_c = { NOTSTART_C }; static const std::unordered_set<std::string> notstart_c = { NOTSTART_C };
static const std::set<std::string> notstart_cpp = { NOTSTART_C, static const std::unordered_set<std::string> notstart_cpp = { NOTSTART_C,
"delete", "friend", "new", "throw", "using", "virtual", "explicit", "const_cast", "dynamic_cast", "reinterpret_cast", "static_cast", "template" "delete", "friend", "new", "throw", "using", "virtual", "explicit", "const_cast", "dynamic_cast", "reinterpret_cast", "static_cast", "template"
}; };
void Tokenizer::setVarIdPass1() void Tokenizer::setVarIdPass1()
{ {
// Variable declarations can't start with "return" etc. // Variable declarations can't start with "return" etc.
const std::set<std::string>& notstart = (isC()) ? notstart_c : notstart_cpp; const std::unordered_set<std::string>& notstart = (isC()) ? notstart_c : notstart_cpp;
VariableMap variableMap; VariableMap variableMap;
std::map<int, std::map<std::string, int> > structMembers; std::map<int, std::map<std::string, int> > structMembers;
@ -9676,7 +9676,7 @@ void Tokenizer::findGarbageCode() const
{ {
const bool isCPP11 = isCPP() && mSettings->standards.cpp >= Standards::CPP11; const bool isCPP11 = isCPP() && mSettings->standards.cpp >= Standards::CPP11;
const std::set<std::string> nonConsecutiveKeywords{ "break", static const std::unordered_set<std::string> nonConsecutiveKeywords{ "break",
"continue", "continue",
"for", "for",
"goto", "goto",
@ -9757,7 +9757,7 @@ void Tokenizer::findGarbageCode() const
} }
// Keywords in global scope // Keywords in global scope
std::set<std::string> nonGlobalKeywords{"break", static const std::unordered_set<std::string> nonGlobalKeywords{"break",
"continue", "continue",
"for", "for",
"goto", "goto",
@ -10528,7 +10528,7 @@ void Tokenizer::simplifyCPPAttribute()
} }
} }
static const std::set<std::string> keywords = { static const std::unordered_set<std::string> keywords = {
"inline" "inline"
, "_inline" , "_inline"
, "__inline" , "__inline"

View File

@ -25,6 +25,7 @@
#include "token.h" #include "token.h"
#include <string> #include <string>
#include <unordered_set>
#include <vector> #include <vector>
class Settings; class Settings;
@ -211,7 +212,7 @@ private:
/** settings */ /** settings */
const Settings* mSettings; const Settings* mSettings;
std::set<std::string> mKeywords; std::unordered_set<std::string> mKeywords;
/** File is known to be C/C++ code */ /** File is known to be C/C++ code */
bool mIsC; bool mIsC;