Skip to content

Commit 7aa85aa

Browse files
authored
Use std::unordered_* containers for faster lookups (#3052)
1 parent 76f759f commit 7aa85aa

8 files changed

Lines changed: 35 additions & 32 deletions

File tree

lib/checkio.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ struct Filepointer {
112112
};
113113

114114
namespace {
115-
const std::set<std::string> whitelist = { "clearerr", "feof", "ferror", "fgetpos", "ftell", "setbuf", "setvbuf", "ungetc", "ungetwc" };
115+
const std::unordered_set<std::string> whitelist = { "clearerr", "feof", "ferror", "fgetpos", "ftell", "setbuf", "setvbuf", "ungetc", "ungetwc" };
116116
}
117117

118118
void CheckIO::checkFileUsage()

lib/checkmemoryleak.cpp

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

lib/library.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,7 +1008,7 @@ bool Library::isnullargbad(const Token *ftok, int argnr) const
10081008
if (!arg) {
10091009
// scan format string argument should not be null
10101010
const std::string funcname = getFunctionName(ftok);
1011-
const std::map<std::string, Function>::const_iterator it = functions.find(funcname);
1011+
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(funcname);
10121012
if (it != functions.cend() && it->second.formatstr && it->second.formatstr_scan)
10131013
return true;
10141014
}
@@ -1021,7 +1021,7 @@ bool Library::isuninitargbad(const Token *ftok, int argnr, int indirect, bool *h
10211021
if (!arg) {
10221022
// non-scan format string argument should not be uninitialized
10231023
const std::string funcname = getFunctionName(ftok);
1024-
const std::map<std::string, Function>::const_iterator it = functions.find(funcname);
1024+
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(funcname);
10251025
if (it != functions.cend() && it->second.formatstr && !it->second.formatstr_scan)
10261026
return true;
10271027
}
@@ -1078,7 +1078,7 @@ const Library::ArgumentChecks * Library::getarg(const Token *ftok, int argnr) co
10781078
{
10791079
if (isNotLibraryFunction(ftok))
10801080
return nullptr;
1081-
const std::map<std::string, Function>::const_iterator it1 = functions.find(getFunctionName(ftok));
1081+
const std::unordered_map<std::string, Function>::const_iterator it1 = functions.find(getFunctionName(ftok));
10821082
if (it1 == functions.cend())
10831083
return nullptr;
10841084
const std::map<int,ArgumentChecks>::const_iterator it2 = it1->second.argumentChecks.find(argnr);
@@ -1189,7 +1189,7 @@ bool Library::isNotLibraryFunction(const Token *ftok) const
11891189
bool Library::matchArguments(const Token *ftok, const std::string &functionName) const
11901190
{
11911191
const int callargs = numberOfArguments(ftok);
1192-
const std::map<std::string, Function>::const_iterator it = functions.find(functionName);
1192+
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(functionName);
11931193
if (it == functions.cend())
11941194
return (callargs == 0);
11951195
int args = 0;
@@ -1259,7 +1259,7 @@ bool Library::formatstr_function(const Token* ftok) const
12591259
if (isNotLibraryFunction(ftok))
12601260
return false;
12611261

1262-
const std::map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok));
1262+
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok));
12631263
if (it != functions.cend())
12641264
return it->second.formatstr;
12651265
return false;
@@ -1290,7 +1290,7 @@ Library::UseRetValType Library::getUseRetValType(const Token *ftok) const
12901290
{
12911291
if (isNotLibraryFunction(ftok))
12921292
return Library::UseRetValType::NONE;
1293-
const std::map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok));
1293+
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok));
12941294
if (it != functions.cend())
12951295
return it->second.useretval;
12961296
return Library::UseRetValType::NONE;
@@ -1332,7 +1332,7 @@ const Library::Function *Library::getFunction(const Token *ftok) const
13321332
{
13331333
if (isNotLibraryFunction(ftok))
13341334
return nullptr;
1335-
const std::map<std::string, Function>::const_iterator it1 = functions.find(getFunctionName(ftok));
1335+
const std::unordered_map<std::string, Function>::const_iterator it1 = functions.find(getFunctionName(ftok));
13361336
if (it1 == functions.cend())
13371337
return nullptr;
13381338
return &it1->second;
@@ -1343,7 +1343,7 @@ bool Library::hasminsize(const Token *ftok) const
13431343
{
13441344
if (isNotLibraryFunction(ftok))
13451345
return false;
1346-
const std::map<std::string, Function>::const_iterator it1 = functions.find(getFunctionName(ftok));
1346+
const std::unordered_map<std::string, Function>::const_iterator it1 = functions.find(getFunctionName(ftok));
13471347
if (it1 == functions.cend())
13481348
return false;
13491349
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
13721372

13731373
bool Library::ignorefunction(const std::string& functionName) const
13741374
{
1375-
const std::map<std::string, Function>::const_iterator it = functions.find(functionName);
1375+
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(functionName);
13761376
if (it != functions.cend())
13771377
return it->second.ignore;
13781378
return false;
13791379
}
13801380
bool Library::isUse(const std::string& functionName) const
13811381
{
1382-
const std::map<std::string, Function>::const_iterator it = functions.find(functionName);
1382+
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(functionName);
13831383
if (it != functions.cend())
13841384
return it->second.use;
13851385
return false;
13861386
}
13871387
bool Library::isLeakIgnore(const std::string& functionName) const
13881388
{
1389-
const std::map<std::string, Function>::const_iterator it = functions.find(functionName);
1389+
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(functionName);
13901390
if (it != functions.cend())
13911391
return it->second.leakignore;
13921392
return false;
13931393
}
13941394
bool Library::isFunctionConst(const std::string& functionName, bool pure) const
13951395
{
1396-
const std::map<std::string, Function>::const_iterator it = functions.find(functionName);
1396+
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(functionName);
13971397
if (it != functions.cend())
13981398
return pure ? it->second.ispure : it->second.isconst;
13991399
return false;
@@ -1404,7 +1404,7 @@ bool Library::isFunctionConst(const Token *ftok) const
14041404
return true;
14051405
if (isNotLibraryFunction(ftok))
14061406
return false;
1407-
const std::map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok));
1407+
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok));
14081408
return (it != functions.end() && it->second.isconst);
14091409
}
14101410

lib/library.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#include <map>
3131
#include <set>
3232
#include <string>
33+
#include <unordered_map>
34+
#include <unordered_set>
3335
#include <utility>
3436
#include <vector>
3537

@@ -316,7 +318,7 @@ class CPPCHECKLIB Library {
316318
};
317319

318320
const Function *getFunction(const Token *ftok) const;
319-
std::map<std::string, Function> functions;
321+
std::unordered_map<std::string, Function> functions;
320322
bool isUse(const std::string& functionName) const;
321323
bool isLeakIgnore(const std::string& functionName) const;
322324
bool isFunctionConst(const std::string& functionName, bool pure) const;
@@ -422,7 +424,7 @@ class CPPCHECKLIB Library {
422424

423425
std::vector<std::string> defines; // to provide some library defines
424426

425-
std::set<std::string> smartPointers;
427+
std::unordered_set<std::string> smartPointers;
426428
bool isSmartPointer(const Token *tok) const;
427429

428430
struct PodType {
@@ -431,7 +433,7 @@ class CPPCHECKLIB Library {
431433
enum class Type { NO, BOOL, CHAR, SHORT, INT, LONG, LONGLONG } stdtype;
432434
};
433435
const struct PodType *podtype(const std::string &name) const {
434-
const std::map<std::string, struct PodType>::const_iterator it = mPodTypes.find(name);
436+
const std::unordered_map<std::string, struct PodType>::const_iterator it = mPodTypes.find(name);
435437
return (it != mPodTypes.end()) ? &(it->second) : nullptr;
436438
}
437439

@@ -575,7 +577,7 @@ class CPPCHECKLIB Library {
575577
std::map<std::string, ExportedFunctions> mExporters; // keywords that export variables/functions to libraries (meta-code/macros)
576578
std::map<std::string, std::set<std::string> > mImporters; // keywords that import variables/functions
577579
std::map<std::string, int> mReflection; // invocation of reflection
578-
std::map<std::string, struct PodType> mPodTypes; // pod types
580+
std::unordered_map<std::string, struct PodType> mPodTypes; // pod types
579581
std::map<std::string, PlatformType> mPlatformTypes; // platform independent typedefs
580582
std::map<std::string, Platform> mPlatforms; // platform dependent typedefs
581583
std::map<std::pair<std::string,std::string>, TypeCheck> mTypeChecks;

lib/symboldatabase.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,7 +1308,7 @@ void SymbolDatabase::createSymbolDatabaseEnums()
13081308

13091309
void SymbolDatabase::createSymbolDatabaseIncompleteVars()
13101310
{
1311-
const std::set<std::string> cpp20keywords = {
1311+
static const std::unordered_set<std::string> cpp20keywords = {
13121312
"alignas",
13131313
"alignof",
13141314
"axiom",
@@ -1321,7 +1321,7 @@ void SymbolDatabase::createSymbolDatabaseIncompleteVars()
13211321
"reflexpr",
13221322
"requires",
13231323
};
1324-
const std::set<std::string> cppkeywords = {
1324+
static const std::unordered_set<std::string> cppkeywords = {
13251325
"asm",
13261326
"auto",
13271327
"catch",
@@ -5379,8 +5379,8 @@ namespace {
53795379
"register", "return", "short", "signed", "sizeof", "static", "struct", "switch", "typedef", \
53805380
"union", "unsigned", "void", "volatile", "while"
53815381

5382-
const std::set<std::string> c_keywords = { C_KEYWORDS, "restrict" };
5383-
const std::set<std::string> cpp_keywords = {
5382+
const std::unordered_set<std::string> c_keywords = { C_KEYWORDS, "restrict" };
5383+
const std::unordered_set<std::string> cpp_keywords = {
53845384
C_KEYWORDS,
53855385
"alignas", "alignof", "and", "and_eq", "asm", "bitand", "bitor", "bool", "catch", "char8_t", "char16_t",
53865386
"char32_t", "class", "compl", "concept", "consteval", "constexpr", "constinit", "const_cast", "co_await",

lib/token.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Token::~Token()
5353
delete mImpl;
5454
}
5555

56-
static const std::set<std::string> controlFlowKeywords = {
56+
static const std::unordered_set<std::string> controlFlowKeywords = {
5757
"goto",
5858
"do",
5959
"if",
@@ -127,7 +127,7 @@ void Token::update_property_info()
127127
update_property_isStandardType();
128128
}
129129

130-
static const std::set<std::string> stdTypes = { "bool"
130+
static const std::unordered_set<std::string> stdTypes = { "bool"
131131
, "_Bool"
132132
, "char"
133133
, "double"

lib/tokenize.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3369,15 +3369,15 @@ void Tokenizer::setVarId()
33693369

33703370
// Variable declarations can't start with "return" etc.
33713371
#define NOTSTART_C "NOT", "case", "default", "goto", "not", "return", "sizeof", "typedef"
3372-
static const std::set<std::string> notstart_c = { NOTSTART_C };
3373-
static const std::set<std::string> notstart_cpp = { NOTSTART_C,
3372+
static const std::unordered_set<std::string> notstart_c = { NOTSTART_C };
3373+
static const std::unordered_set<std::string> notstart_cpp = { NOTSTART_C,
33743374
"delete", "friend", "new", "throw", "using", "virtual", "explicit", "const_cast", "dynamic_cast", "reinterpret_cast", "static_cast", "template"
33753375
};
33763376

33773377
void Tokenizer::setVarIdPass1()
33783378
{
33793379
// Variable declarations can't start with "return" etc.
3380-
const std::set<std::string>& notstart = (isC()) ? notstart_c : notstart_cpp;
3380+
const std::unordered_set<std::string>& notstart = (isC()) ? notstart_c : notstart_cpp;
33813381

33823382
VariableMap variableMap;
33833383
std::map<int, std::map<std::string, int> > structMembers;
@@ -9676,7 +9676,7 @@ void Tokenizer::findGarbageCode() const
96769676
{
96779677
const bool isCPP11 = isCPP() && mSettings->standards.cpp >= Standards::CPP11;
96789678

9679-
const std::set<std::string> nonConsecutiveKeywords{ "break",
9679+
static const std::unordered_set<std::string> nonConsecutiveKeywords{ "break",
96809680
"continue",
96819681
"for",
96829682
"goto",
@@ -9757,7 +9757,7 @@ void Tokenizer::findGarbageCode() const
97579757
}
97589758

97599759
// Keywords in global scope
9760-
std::set<std::string> nonGlobalKeywords{"break",
9760+
static const std::unordered_set<std::string> nonGlobalKeywords{"break",
97619761
"continue",
97629762
"for",
97639763
"goto",
@@ -10528,7 +10528,7 @@ void Tokenizer::simplifyCPPAttribute()
1052810528
}
1052910529
}
1053010530

10531-
static const std::set<std::string> keywords = {
10531+
static const std::unordered_set<std::string> keywords = {
1053210532
"inline"
1053310533
, "_inline"
1053410534
, "__inline"

lib/tokenlist.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "token.h"
2626

2727
#include <string>
28+
#include <unordered_set>
2829
#include <vector>
2930

3031
class Settings;
@@ -211,7 +212,7 @@ class CPPCHECKLIB TokenList {
211212
/** settings */
212213
const Settings* mSettings;
213214

214-
std::set<std::string> mKeywords;
215+
std::unordered_set<std::string> mKeywords;
215216

216217
/** File is known to be C/C++ code */
217218
bool mIsC;

0 commit comments

Comments
 (0)