From 4f68d856332d041d609ef3b6abdb728ab868438f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Tue, 26 May 2020 20:13:56 +0200 Subject: [PATCH] optimized non-matchcompiled Token::simpleMatch() a bit (#2640) --- lib/checkclass.cpp | 8 ++++--- lib/checkother.cpp | 3 ++- lib/checkunusedvar.cpp | 6 ++++-- lib/symboldatabase.cpp | 4 ++-- lib/templatesimplifier.cpp | 4 ++-- lib/token.cpp | 19 +++++++++-------- lib/token.h | 39 ++++++++++++++++++++++++++++------- lib/tokenize.cpp | 20 +++++++++--------- lib/valueflow.cpp | 9 ++++---- test/testastutils.cpp | 13 ++++++------ test/testsimplifytemplate.cpp | 4 +++- test/testsymboldatabase.cpp | 3 ++- test/testvalueflow.cpp | 3 ++- 13 files changed, 86 insertions(+), 49 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index ef3e8fe91..8f1bc4598 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -1428,7 +1428,7 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co continue; std::string cast("( " + scope->className + " & )"); - if (Token::simpleMatch(tok->next(), cast.c_str())) + if (Token::simpleMatch(tok->next(), cast.c_str(), cast.size())) tok = tok->tokAt(4); // check if a function is called @@ -1471,7 +1471,8 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co return; } if (startTok->next() == last) { - if (Token::simpleMatch(func->argDef, std::string("( const " + scope->className + " &").c_str())) { + const std::string tmp("( const " + scope->className + " &"); + if (Token::simpleMatch(func->argDef, tmp.c_str(), tmp.size())) { // Typical wrong way to suppress default assignment operator by declaring it and leaving empty operatorEqMissingReturnStatementError(func->token, func->access == AccessControl::Public); } else { @@ -1719,7 +1720,8 @@ void CheckClass::virtualDestructor() if (Token::Match(tok, "[;{}] %var% =") && baseClassPointers.find(tok->next()->varId()) != baseClassPointers.end()) { // new derived class.. - if (Token::simpleMatch(tok->tokAt(3), ("new " + derivedClass->str()).c_str())) { + const std::string tmp("new " + derivedClass->str()); + if (Token::simpleMatch(tok->tokAt(3), tmp.c_str(), tmp.size())) { dontDelete.insert(tok->next()->varId()); } } diff --git a/lib/checkother.cpp b/lib/checkother.cpp index c56affd2f..9d5250e15 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -2627,7 +2627,8 @@ void CheckOther::checkUnusedLabel() tok = tok->scope()->bodyEnd; if (Token::Match(tok, "{|}|; %name% :") && tok->strAt(1) != "default") { - if (!Token::findsimplematch(scope->bodyStart->next(), ("goto " + tok->strAt(1)).c_str(), scope->bodyEnd->previous())) + const std::string tmp("goto " + tok->strAt(1)); + if (!Token::findsimplematch(scope->bodyStart->next(), tmp.c_str(), tmp.size(), scope->bodyEnd->previous())) unusedLabelError(tok->next(), tok->next()->scope()->type == Scope::eSwitch); } } diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index ba65f8ea0..3951b9e87 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -1405,9 +1405,11 @@ void CheckUnusedVar::checkStructMemberUsage() continue; // Check if the struct member variable is used anywhere in the file - if (Token::findsimplematch(mTokenizer->tokens(), (". " + var.name()).c_str())) + std::string tmp(". " + var.name()); + if (Token::findsimplematch(mTokenizer->tokens(), tmp.c_str(), tmp.size())) continue; - if (Token::findsimplematch(mTokenizer->tokens(), (":: " + var.name()).c_str())) + tmp = (":: " + var.name()); + if (Token::findsimplematch(mTokenizer->tokens(), tmp.c_str(), tmp.size())) continue; unusedStructMemberError(var.nameToken(), scope.className, var.name(), scope.type == Scope::eUnion); diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index c5dce18d1..6164cd39b 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2356,7 +2356,7 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se else if (arg_path_length && Token::Match(first->next(), "%name%") && first->strAt(1) != "const") { std::string param = path; - if (Token::simpleMatch(second->next(), param.c_str())) { + if (Token::simpleMatch(second->next(), param.c_str(), param.size())) { second = second->tokAt(int(arg_path_length)); arg_path_length = 0; } @@ -2400,7 +2400,7 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se } param = short_path; - if (Token::simpleMatch(second->next(), param.c_str())) { + if (Token::simpleMatch(second->next(), param.c_str(), param.size())) { second = second->tokAt(int(short_path_length)); arg_path_length = 0; } diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 680e70097..51bfd36ad 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -1535,7 +1535,7 @@ bool TemplateSimplifier::alreadyHasNamespace(const TokenAndName &templateDeclara pos += 2; } - return Token::simpleMatch(tok->tokAt(offset), scope.c_str()) ; + return Token::simpleMatch(tok->tokAt(offset), scope.c_str(), scope.size()); } void TemplateSimplifier::expandTemplate( @@ -1714,7 +1714,7 @@ void TemplateSimplifier::expandTemplate( } // check if type is instantiated for (const auto & inst : mTemplateInstantiations) { - if (Token::simpleMatch(inst.token(), name.c_str())) { + if (Token::simpleMatch(inst.token(), name.c_str(), name.size())) { // use the instantiated name dst->insertToken(name, "", true); start = closing; diff --git a/lib/token.cpp b/lib/token.cpp index 0f07cde85..1cd6c1a80 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -560,14 +560,15 @@ int Token::multiCompare(const Token *tok, const char *haystack, nonneg int varid return -1; } -bool Token::simpleMatch(const Token *tok, const char pattern[]) +bool Token::simpleMatch(const Token *tok, const char pattern[], size_t pattern_len) { if (!tok) return false; // shortcut - const char *current = pattern; - const char *next = std::strchr(pattern, ' '); + const char *current = pattern; + const char *end = pattern + pattern_len; + const char *next = (const char*)std::memchr(pattern, ' ', pattern_len); if (!next) - next = pattern + std::strlen(pattern); + next = end; while (*current) { const std::size_t length = next - current; @@ -579,7 +580,7 @@ bool Token::simpleMatch(const Token *tok, const char pattern[]) if (*next) { next = std::strchr(++current, ' '); if (!next) - next = current + std::strlen(current); + next = end; } tok = tok->next(); } @@ -938,19 +939,19 @@ Token * Token::findOpeningBracket() //--------------------------------------------------------------------------- -const Token *Token::findsimplematch(const Token * const startTok, const char pattern[]) +const Token *Token::findsimplematch(const Token * const startTok, const char pattern[], size_t pattern_len) { for (const Token* tok = startTok; tok; tok = tok->next()) { - if (Token::simpleMatch(tok, pattern)) + if (Token::simpleMatch(tok, pattern, pattern_len)) return tok; } return nullptr; } -const Token *Token::findsimplematch(const Token * const startTok, const char pattern[], const Token * const end) +const Token *Token::findsimplematch(const Token * const startTok, const char pattern[], size_t pattern_len, const Token * const end) { for (const Token* tok = startTok; tok && tok != end; tok = tok->next()) { - if (Token::simpleMatch(tok, pattern)) + if (Token::simpleMatch(tok, pattern, pattern_len)) return tok; } return nullptr; diff --git a/lib/token.h b/lib/token.h index 9dd72f913..009ccb7fe 100644 --- a/lib/token.h +++ b/lib/token.h @@ -262,7 +262,12 @@ public: * @return true if given token matches with given pattern * false if given token does not match with given pattern */ - static bool simpleMatch(const Token *tok, const char pattern[]); + template + static bool simpleMatch(const Token *tok, const char (&pattern)[count]) { + return simpleMatch(tok, pattern, count-1); + } + + static bool simpleMatch(const Token *tok, const char pattern[], size_t pattern_len); /** * Match given token (or list of tokens) to a pattern list. @@ -669,16 +674,36 @@ public: setFlag(fIsTemplateArg, value); } - static const Token *findsimplematch(const Token * const startTok, const char pattern[]); - static const Token *findsimplematch(const Token * const startTok, const char pattern[], const Token * const end); + template + static const Token *findsimplematch(const Token * const startTok, const char (&pattern)[count]) { + return findsimplematch(startTok, pattern, count-1); + } + static const Token *findsimplematch(const Token * const startTok, const char pattern[], size_t pattern_len); + + template + static const Token *findsimplematch(const Token * const startTok, const char (&pattern)[count], const Token * const end) { + return findsimplematch(startTok, pattern, count-1, end); + } + static const Token *findsimplematch(const Token * const startTok, const char pattern[], size_t pattern_len, const Token * const end); + static const Token *findmatch(const Token * const startTok, const char pattern[], const nonneg int varId = 0); static const Token *findmatch(const Token * const startTok, const char pattern[], const Token * const end, const nonneg int varId = 0); - static Token *findsimplematch(Token * const startTok, const char pattern[]) { - return const_cast(findsimplematch(const_cast(startTok), pattern)); + + template + static Token *findsimplematch(Token * const startTok, const char (&pattern)[count]) { + return findsimplematch(startTok, pattern, count-1); } - static Token *findsimplematch(Token * const startTok, const char pattern[], const Token * const end) { - return const_cast(findsimplematch(const_cast(startTok), pattern, end)); + static Token *findsimplematch(Token * const startTok, const char pattern[], size_t pattern_len) { + return const_cast(findsimplematch(const_cast(startTok), pattern, pattern_len)); } + template + static Token *findsimplematch(Token * const startTok, const char (&pattern)[count], const Token * const end) { + return findsimplematch(startTok, pattern, count-1, end); + } + static Token *findsimplematch(Token * const startTok, const char pattern[], size_t pattern_len, const Token * const end) { + return const_cast(findsimplematch(const_cast(startTok), pattern, pattern_len, end)); + } + static Token *findmatch(Token * const startTok, const char pattern[], const nonneg int varId = 0) { return const_cast(findmatch(const_cast(startTok), pattern, varId)); } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 9bc84c939..8b7062f42 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1120,7 +1120,7 @@ void Tokenizer::simplifyTypedef() // check for typedef that can be substituted else if (tok2->isNameOnly() && - (Token::simpleMatch(tok2, pattern.c_str()) || + (Token::simpleMatch(tok2, pattern.c_str(), pattern.size()) || (inMemberFunc && tok2->str() == typeName->str()))) { // member function class variables don't need qualification if (!(inMemberFunc && tok2->str() == typeName->str()) && pattern.find("::") != std::string::npos) { // has a "something ::" @@ -9410,15 +9410,15 @@ void Tokenizer::findGarbageCode() const const bool isCPP11 = isCPP() && mSettings->standards.cpp >= Standards::CPP11; const std::set nonConsecutiveKeywords{ "break", - "continue", - "for", - "goto", - "if", - "return", - "switch", - "throw", - "typedef", - "while" }; + "continue", + "for", + "goto", + "if", + "return", + "switch", + "throw", + "typedef", + "while" }; for (const Token *tok = tokens(); tok; tok = tok->next()) { // initialization: = { diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index f14c91537..f33896856 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -96,6 +96,7 @@ #include #include #include +#include #include #include #include @@ -187,9 +188,9 @@ static void setConditionalValues(const Token *tok, const char* lessThan = "<="; if (invert) std::swap(greaterThan, lessThan); - if (Token::simpleMatch(tok, greaterThan)) { + if (Token::simpleMatch(tok, greaterThan, strlen(greaterThan))) { false_value = ValueFlow::Value{tok, value - 1}; - } else if (Token::simpleMatch(tok, lessThan)) { + } else if (Token::simpleMatch(tok, lessThan, strlen(lessThan))) { false_value = ValueFlow::Value{tok, value + 1}; } else { false_value = ValueFlow::Value{tok, value}; @@ -199,10 +200,10 @@ static void setConditionalValues(const Token *tok, const char* lessThan = "<"; if (invert) std::swap(greaterThan, lessThan); - if (Token::simpleMatch(tok, greaterThan)) { + if (Token::simpleMatch(tok, greaterThan, strlen(greaterThan))) { true_value = ValueFlow::Value{tok, value + 1}; false_value = ValueFlow::Value{tok, value}; - } else if (Token::simpleMatch(tok, lessThan)) { + } else if (Token::simpleMatch(tok, lessThan, strlen(lessThan))) { true_value = ValueFlow::Value{tok, value - 1}; false_value = ValueFlow::Value{tok, value}; } diff --git a/test/testastutils.cpp b/test/testastutils.cpp index b4f8576a4..80cd66e6b 100644 --- a/test/testastutils.cpp +++ b/test/testastutils.cpp @@ -24,6 +24,7 @@ #include "tokenize.h" #include "tokenlist.h" +#include class TestAstUtils : public TestFixture { public: @@ -166,8 +167,8 @@ private: std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); tokenizer.simplifyTokens1(""); - const Token * const tok1 = Token::findsimplematch(tokenizer.tokens(), tokStr1); - const Token * const tok2 = Token::findsimplematch(tok1->next(), tokStr2); + const Token * const tok1 = Token::findsimplematch(tokenizer.tokens(), tokStr1, strlen(tokStr1)); + const Token * const tok2 = Token::findsimplematch(tok1->next(), tokStr2, strlen(tokStr2)); return ::isSameExpression(false, false, tok1, tok2, library, false, true, nullptr); } @@ -203,8 +204,8 @@ private: Tokenizer tokenizer(&settings, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); - const Token * const tok1 = Token::findsimplematch(tokenizer.tokens(), startPattern); - const Token * const tok2 = Token::findsimplematch(tokenizer.tokens(), endPattern); + const Token * const tok1 = Token::findsimplematch(tokenizer.tokens(), startPattern, strlen(startPattern)); + const Token * const tok2 = Token::findsimplematch(tokenizer.tokens(), endPattern, strlen(endPattern)); return ::isVariableChanged(tok1,tok2,1,false,&settings,true); } @@ -247,8 +248,8 @@ private: Tokenizer tokenizer(&settings, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); - const Token * tok = Token::findsimplematch(tokenizer.tokens(), parentPattern); - return Token::simpleMatch(::nextAfterAstRightmostLeaf(tok), rightPattern); + const Token * tok = Token::findsimplematch(tokenizer.tokens(), parentPattern, strlen(parentPattern)); + return Token::simpleMatch(::nextAfterAstRightmostLeaf(tok), rightPattern, strlen(rightPattern)); } void nextAfterAstRightmostLeaf() { diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 9d08b74bf..77c268df6 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -25,6 +25,8 @@ #include "token.h" #include "tokenize.h" +#include + struct InternalError; @@ -4545,7 +4547,7 @@ private: const Token *tok1 = TemplateSimplifier::findTemplateDeclarationEnd(_tok); - return (tok1 == Token::findsimplematch(tokenizer.list.front(), pattern)); + return (tok1 == Token::findsimplematch(tokenizer.list.front(), pattern, strlen(pattern))); } void findTemplateDeclarationEnd() { diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 845287e1d..6ef623538 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -6548,7 +6549,7 @@ private: tokenizer.tokenize(istr, filename); const Token* tok; for (tok = tokenizer.list.back(); tok; tok = tok->previous()) - if (Token::simpleMatch(tok, pattern)) + if (Token::simpleMatch(tok, pattern, strlen(pattern))) break; return tok->valueType() ? tok->valueType()->str() : std::string(); } diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 2aa39cdeb..8a9f78ee3 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -34,6 +34,7 @@ #include #include #include +#include class TestValueFlow : public TestFixture { public: @@ -231,7 +232,7 @@ private: for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) { if (tok->str() == "x" && tok->linenr() == linenr) { for (const ValueFlow::Value &v : tok->values()) { - if (v.valueType == type && Token::simpleMatch(v.tokvalue, value)) + if (v.valueType == type && Token::simpleMatch(v.tokvalue, value, strlen(value))) return true; } }