optimized non-matchcompiled Token::simpleMatch() a bit (#2640)

This commit is contained in:
Oliver Stöneberg 2020-05-26 20:13:56 +02:00 committed by GitHub
parent dc0b68d505
commit 4f68d85633
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 86 additions and 49 deletions

View File

@ -1428,7 +1428,7 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co
continue; continue;
std::string cast("( " + scope->className + " & )"); 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); tok = tok->tokAt(4);
// check if a function is called // check if a function is called
@ -1471,7 +1471,8 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co
return; return;
} }
if (startTok->next() == last) { 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 // Typical wrong way to suppress default assignment operator by declaring it and leaving empty
operatorEqMissingReturnStatementError(func->token, func->access == AccessControl::Public); operatorEqMissingReturnStatementError(func->token, func->access == AccessControl::Public);
} else { } else {
@ -1719,7 +1720,8 @@ void CheckClass::virtualDestructor()
if (Token::Match(tok, "[;{}] %var% =") && if (Token::Match(tok, "[;{}] %var% =") &&
baseClassPointers.find(tok->next()->varId()) != baseClassPointers.end()) { baseClassPointers.find(tok->next()->varId()) != baseClassPointers.end()) {
// new derived class.. // 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()); dontDelete.insert(tok->next()->varId());
} }
} }

View File

@ -2627,7 +2627,8 @@ void CheckOther::checkUnusedLabel()
tok = tok->scope()->bodyEnd; tok = tok->scope()->bodyEnd;
if (Token::Match(tok, "{|}|; %name% :") && tok->strAt(1) != "default") { 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); unusedLabelError(tok->next(), tok->next()->scope()->type == Scope::eSwitch);
} }
} }

View File

@ -1405,9 +1405,11 @@ void CheckUnusedVar::checkStructMemberUsage()
continue; continue;
// Check if the struct member variable is used anywhere in the file // 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; continue;
if (Token::findsimplematch(mTokenizer->tokens(), (":: " + var.name()).c_str())) tmp = (":: " + var.name());
if (Token::findsimplematch(mTokenizer->tokens(), tmp.c_str(), tmp.size()))
continue; continue;
unusedStructMemberError(var.nameToken(), scope.className, var.name(), scope.type == Scope::eUnion); unusedStructMemberError(var.nameToken(), scope.className, var.name(), scope.type == Scope::eUnion);

View File

@ -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") { else if (arg_path_length && Token::Match(first->next(), "%name%") && first->strAt(1) != "const") {
std::string param = path; 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)); second = second->tokAt(int(arg_path_length));
arg_path_length = 0; arg_path_length = 0;
} }
@ -2400,7 +2400,7 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se
} }
param = short_path; 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)); second = second->tokAt(int(short_path_length));
arg_path_length = 0; arg_path_length = 0;
} }

View File

@ -1535,7 +1535,7 @@ bool TemplateSimplifier::alreadyHasNamespace(const TokenAndName &templateDeclara
pos += 2; 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( void TemplateSimplifier::expandTemplate(
@ -1714,7 +1714,7 @@ void TemplateSimplifier::expandTemplate(
} }
// check if type is instantiated // check if type is instantiated
for (const auto & inst : mTemplateInstantiations) { 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 // use the instantiated name
dst->insertToken(name, "", true); dst->insertToken(name, "", true);
start = closing; start = closing;

View File

@ -560,14 +560,15 @@ int Token::multiCompare(const Token *tok, const char *haystack, nonneg int varid
return -1; 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) if (!tok)
return false; // shortcut return false; // shortcut
const char *current = pattern; const char *current = pattern;
const char *next = std::strchr(pattern, ' '); const char *end = pattern + pattern_len;
const char *next = (const char*)std::memchr(pattern, ' ', pattern_len);
if (!next) if (!next)
next = pattern + std::strlen(pattern); next = end;
while (*current) { while (*current) {
const std::size_t length = next - current; const std::size_t length = next - current;
@ -579,7 +580,7 @@ bool Token::simpleMatch(const Token *tok, const char pattern[])
if (*next) { if (*next) {
next = std::strchr(++current, ' '); next = std::strchr(++current, ' ');
if (!next) if (!next)
next = current + std::strlen(current); next = end;
} }
tok = tok->next(); 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()) { for (const Token* tok = startTok; tok; tok = tok->next()) {
if (Token::simpleMatch(tok, pattern)) if (Token::simpleMatch(tok, pattern, pattern_len))
return tok; return tok;
} }
return nullptr; 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()) { 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 tok;
} }
return nullptr; return nullptr;

View File

@ -262,7 +262,12 @@ public:
* @return true if given token matches with given pattern * @return true if given token matches with given pattern
* false if given token does not match with given pattern * false if given token does not match with given pattern
*/ */
static bool simpleMatch(const Token *tok, const char pattern[]); template<size_t count>
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. * Match given token (or list of tokens) to a pattern list.
@ -669,16 +674,36 @@ public:
setFlag(fIsTemplateArg, value); setFlag(fIsTemplateArg, value);
} }
static const Token *findsimplematch(const Token * const startTok, const char pattern[]); template<size_t count>
static const Token *findsimplematch(const Token * const startTok, const char pattern[], const Token * const end); 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<size_t count>
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 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 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<Token *>(findsimplematch(const_cast<const Token *>(startTok), pattern)); template<size_t count>
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) { static Token *findsimplematch(Token * const startTok, const char pattern[], size_t pattern_len) {
return const_cast<Token *>(findsimplematch(const_cast<const Token *>(startTok), pattern, end)); return const_cast<Token *>(findsimplematch(const_cast<const Token *>(startTok), pattern, pattern_len));
} }
template<size_t count>
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<Token *>(findsimplematch(const_cast<const Token *>(startTok), pattern, pattern_len, end));
}
static Token *findmatch(Token * const startTok, const char pattern[], const nonneg int varId = 0) { static Token *findmatch(Token * const startTok, const char pattern[], const nonneg int varId = 0) {
return const_cast<Token *>(findmatch(const_cast<const Token *>(startTok), pattern, varId)); return const_cast<Token *>(findmatch(const_cast<const Token *>(startTok), pattern, varId));
} }

View File

@ -1120,7 +1120,7 @@ void Tokenizer::simplifyTypedef()
// check for typedef that can be substituted // check for typedef that can be substituted
else if (tok2->isNameOnly() && else if (tok2->isNameOnly() &&
(Token::simpleMatch(tok2, pattern.c_str()) || (Token::simpleMatch(tok2, pattern.c_str(), pattern.size()) ||
(inMemberFunc && tok2->str() == typeName->str()))) { (inMemberFunc && tok2->str() == typeName->str()))) {
// member function class variables don't need qualification // member function class variables don't need qualification
if (!(inMemberFunc && tok2->str() == typeName->str()) && pattern.find("::") != std::string::npos) { // has a "something ::" 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 bool isCPP11 = isCPP() && mSettings->standards.cpp >= Standards::CPP11;
const std::set<std::string> nonConsecutiveKeywords{ "break", const std::set<std::string> nonConsecutiveKeywords{ "break",
"continue", "continue",
"for", "for",
"goto", "goto",
"if", "if",
"return", "return",
"switch", "switch",
"throw", "throw",
"typedef", "typedef",
"while" }; "while" };
for (const Token *tok = tokens(); tok; tok = tok->next()) { for (const Token *tok = tokens(); tok; tok = tok->next()) {
// initialization: = { // initialization: = {

View File

@ -96,6 +96,7 @@
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <cstddef> #include <cstddef>
#include <cstring>
#include <functional> #include <functional>
#include <iterator> #include <iterator>
#include <limits> #include <limits>
@ -187,9 +188,9 @@ static void setConditionalValues(const Token *tok,
const char* lessThan = "<="; const char* lessThan = "<=";
if (invert) if (invert)
std::swap(greaterThan, lessThan); std::swap(greaterThan, lessThan);
if (Token::simpleMatch(tok, greaterThan)) { if (Token::simpleMatch(tok, greaterThan, strlen(greaterThan))) {
false_value = ValueFlow::Value{tok, value - 1}; 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}; false_value = ValueFlow::Value{tok, value + 1};
} else { } else {
false_value = ValueFlow::Value{tok, value}; false_value = ValueFlow::Value{tok, value};
@ -199,10 +200,10 @@ static void setConditionalValues(const Token *tok,
const char* lessThan = "<"; const char* lessThan = "<";
if (invert) if (invert)
std::swap(greaterThan, lessThan); std::swap(greaterThan, lessThan);
if (Token::simpleMatch(tok, greaterThan)) { if (Token::simpleMatch(tok, greaterThan, strlen(greaterThan))) {
true_value = ValueFlow::Value{tok, value + 1}; true_value = ValueFlow::Value{tok, value + 1};
false_value = ValueFlow::Value{tok, value}; 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}; true_value = ValueFlow::Value{tok, value - 1};
false_value = ValueFlow::Value{tok, value}; false_value = ValueFlow::Value{tok, value};
} }

View File

@ -24,6 +24,7 @@
#include "tokenize.h" #include "tokenize.h"
#include "tokenlist.h" #include "tokenlist.h"
#include <cstring>
class TestAstUtils : public TestFixture { class TestAstUtils : public TestFixture {
public: public:
@ -166,8 +167,8 @@ private:
std::istringstream istr(code); std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp"); tokenizer.tokenize(istr, "test.cpp");
tokenizer.simplifyTokens1(""); tokenizer.simplifyTokens1("");
const Token * const tok1 = Token::findsimplematch(tokenizer.tokens(), tokStr1); const Token * const tok1 = Token::findsimplematch(tokenizer.tokens(), tokStr1, strlen(tokStr1));
const Token * const tok2 = Token::findsimplematch(tok1->next(), tokStr2); const Token * const tok2 = Token::findsimplematch(tok1->next(), tokStr2, strlen(tokStr2));
return ::isSameExpression(false, false, tok1, tok2, library, false, true, nullptr); return ::isSameExpression(false, false, tok1, tok2, library, false, true, nullptr);
} }
@ -203,8 +204,8 @@ private:
Tokenizer tokenizer(&settings, this); Tokenizer tokenizer(&settings, this);
std::istringstream istr(code); std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp"); tokenizer.tokenize(istr, "test.cpp");
const Token * const tok1 = Token::findsimplematch(tokenizer.tokens(), startPattern); const Token * const tok1 = Token::findsimplematch(tokenizer.tokens(), startPattern, strlen(startPattern));
const Token * const tok2 = Token::findsimplematch(tokenizer.tokens(), endPattern); const Token * const tok2 = Token::findsimplematch(tokenizer.tokens(), endPattern, strlen(endPattern));
return ::isVariableChanged(tok1,tok2,1,false,&settings,true); return ::isVariableChanged(tok1,tok2,1,false,&settings,true);
} }
@ -247,8 +248,8 @@ private:
Tokenizer tokenizer(&settings, this); Tokenizer tokenizer(&settings, this);
std::istringstream istr(code); std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp"); tokenizer.tokenize(istr, "test.cpp");
const Token * tok = Token::findsimplematch(tokenizer.tokens(), parentPattern); const Token * tok = Token::findsimplematch(tokenizer.tokens(), parentPattern, strlen(parentPattern));
return Token::simpleMatch(::nextAfterAstRightmostLeaf(tok), rightPattern); return Token::simpleMatch(::nextAfterAstRightmostLeaf(tok), rightPattern, strlen(rightPattern));
} }
void nextAfterAstRightmostLeaf() { void nextAfterAstRightmostLeaf() {

View File

@ -25,6 +25,8 @@
#include "token.h" #include "token.h"
#include "tokenize.h" #include "tokenize.h"
#include <cstring>
struct InternalError; struct InternalError;
@ -4545,7 +4547,7 @@ private:
const Token *tok1 = TemplateSimplifier::findTemplateDeclarationEnd(_tok); 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() { void findTemplateDeclarationEnd() {

View File

@ -30,6 +30,7 @@
#include <climits> #include <climits>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstring>
#include <list> #include <list>
#include <map> #include <map>
#include <set> #include <set>
@ -6548,7 +6549,7 @@ private:
tokenizer.tokenize(istr, filename); tokenizer.tokenize(istr, filename);
const Token* tok; const Token* tok;
for (tok = tokenizer.list.back(); tok; tok = tok->previous()) for (tok = tokenizer.list.back(); tok; tok = tok->previous())
if (Token::simpleMatch(tok, pattern)) if (Token::simpleMatch(tok, pattern, strlen(pattern)))
break; break;
return tok->valueType() ? tok->valueType()->str() : std::string(); return tok->valueType() ? tok->valueType()->str() : std::string();
} }

View File

@ -34,6 +34,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <cstdint> #include <cstdint>
#include <cstring>
class TestValueFlow : public TestFixture { class TestValueFlow : public TestFixture {
public: public:
@ -231,7 +232,7 @@ private:
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) { for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
if (tok->str() == "x" && tok->linenr() == linenr) { if (tok->str() == "x" && tok->linenr() == linenr) {
for (const ValueFlow::Value &v : tok->values()) { 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; return true;
} }
} }