refs #10663 - sped up `Library::detectContainerOrIterator()` by iterating the containers only once (#4380)

This commit is contained in:
Oliver Stöneberg 2022-08-20 12:14:55 +02:00 committed by GitHub
parent 2ab8de2650
commit 1d95d1908d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 101 additions and 16 deletions

View File

@ -682,7 +682,7 @@ test/testio.o: test/testio.cpp lib/check.h lib/checkio.h lib/color.h lib/config.
test/testleakautovar.o: test/testleakautovar.cpp externals/simplecpp/simplecpp.h externals/tinyxml2/tinyxml2.h lib/check.h lib/checkleakautovar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testleakautovar.o test/testleakautovar.cpp
test/testlibrary.o: test/testlibrary.cpp externals/tinyxml2/tinyxml2.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
test/testlibrary.o: test/testlibrary.cpp externals/tinyxml2/tinyxml2.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h test/testutils.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testlibrary.o test/testlibrary.cpp
test/testmathlib.o: test/testmathlib.cpp lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/mathlib.h lib/suppressions.h test/testsuite.h

View File

@ -1421,7 +1421,7 @@ void CheckStl::stlBoundaries()
if (!var || !var->scope() || !var->scope()->isExecutable())
continue;
const Library::Container* container = mSettings->library.detectContainer(var->typeStartToken(), true);
const Library::Container* container = mSettings->library.detectIterator(var->typeStartToken());
if (!container || container->opLessAllowed)
continue;

View File

@ -715,7 +715,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
else if (mTokenizer->isC() ||
i->typeEndToken()->isStandardType() ||
isRecordTypeWithoutSideEffects(i->type()) ||
mSettings->library.detectContainer(i->typeStartToken(), /*iterator*/ false) ||
mSettings->library.detectContainer(i->typeStartToken()) ||
i->isStlType())
type = Variables::standard;
if (type == Variables::none || isPartOfClassStructUnion(i->typeStartToken()))

View File

@ -1133,7 +1133,7 @@ bool Library::isScopeNoReturn(const Token *end, std::string *unknownFunc) const
return false;
}
const Library::Container* Library::detectContainer(const Token* typeStart, bool iterator) const
const Library::Container* Library::detectContainerInternal(const Token* typeStart, DetectContainer detect, bool* isIterator) const
{
for (const std::pair<const std::string, Library::Container> & c : containers) {
const Container& container = c.second;
@ -1143,14 +1143,25 @@ const Library::Container* Library::detectContainer(const Token* typeStart, bool
if (!Token::Match(typeStart, container.startPattern2.c_str()))
continue;
if (!iterator && container.endPattern.empty()) // If endPattern is undefined, it will always match, but itEndPattern has to be defined.
// If endPattern is undefined, it will always match, but itEndPattern has to be defined.
if (detect != IteratorOnly && container.endPattern.empty()) {
if (isIterator)
*isIterator = false;
return &container;
}
for (const Token* tok = typeStart; tok && !tok->varId(); tok = tok->next()) {
if (tok->link()) {
const std::string& endPattern = iterator ? container.itEndPattern : container.endPattern;
if (Token::Match(tok->link(), endPattern.c_str()))
if (detect != ContainerOnly && Token::Match(tok->link(), container.itEndPattern.c_str())) {
if (isIterator)
*isIterator = true;
return &container;
}
if (detect != IteratorOnly && Token::Match(tok->link(), container.endPattern.c_str())) {
if (isIterator)
*isIterator = false;
return &container;
}
break;
}
}
@ -1158,17 +1169,22 @@ const Library::Container* Library::detectContainer(const Token* typeStart, bool
return nullptr;
}
const Library::Container* Library::detectContainer(const Token* typeStart) const
{
return detectContainerInternal(typeStart, ContainerOnly);
}
const Library::Container* Library::detectIterator(const Token* typeStart) const
{
return detectContainerInternal(typeStart, IteratorOnly);
}
const Library::Container* Library::detectContainerOrIterator(const Token* typeStart, bool* isIterator) const
{
const Library::Container* c = detectContainer(typeStart);
if (c) {
if (isIterator)
*isIterator = false;
return c;
}
c = detectContainer(typeStart, true);
bool res;
const Library::Container* c = detectContainerInternal(typeStart, Both, &res);
if (c && isIterator)
*isIterator = true;
*isIterator = res;
return c;
}

View File

@ -283,7 +283,8 @@ public:
static Action actionFrom(const std::string& actionName);
};
std::map<std::string, Container> containers;
const Container* detectContainer(const Token* typeStart, bool iterator = false) const;
const Container* detectContainer(const Token* typeStart) const;
const Container* detectIterator(const Token* typeStart) const;
const Container* detectContainerOrIterator(const Token* typeStart, bool* isIterator = nullptr) const;
class ArgumentChecks {
@ -647,6 +648,9 @@ private:
const std::map<std::string, AllocFunc>::const_iterator it = data.find(name);
return (it == data.end()) ? nullptr : &it->second;
}
enum DetectContainer { ContainerOnly, IteratorOnly, Both };
const Library::Container* detectContainerInternal(const Token* typeStart, DetectContainer detect, bool* isIterator = nullptr) const;
};
CPPCHECKLIB const Library::Container * getLibraryContainer(const Token * tok);

View File

@ -21,6 +21,7 @@
#include "settings.h"
#include "standards.h"
#include "testsuite.h"
#include "testutils.h"
#include "token.h"
#include "tokenize.h"
#include "tokenlist.h"
@ -865,6 +866,70 @@ private:
ASSERT_EQUALS(C.size_templateArgNo, -1);
ASSERT_EQUALS(C.stdStringLike, true);
ASSERT_EQUALS(C.arrayLike_indexOp, true);
{
givenACodeSampleToTokenize var("std::A<int> a;");
ASSERT_EQUALS(&A, library.detectContainer(var.tokens()));
ASSERT(!library.detectIterator(var.tokens()));
bool isIterator;
ASSERT_EQUALS(&A, library.detectContainerOrIterator(var.tokens(), &isIterator));
ASSERT(!isIterator);
}
{
givenACodeSampleToTokenize var("std::A<int>::size_type a_s;");
ASSERT(!library.detectContainer(var.tokens()));
ASSERT(!library.detectIterator(var.tokens()));
ASSERT(!library.detectContainerOrIterator(var.tokens()));
}
{
givenACodeSampleToTokenize var("std::A<int>::iterator a_it;");
ASSERT(!library.detectContainer(var.tokens()));
ASSERT_EQUALS(&A, library.detectIterator(var.tokens()));
bool isIterator;
ASSERT_EQUALS(&A, library.detectContainerOrIterator(var.tokens(), &isIterator));
ASSERT(isIterator);
}
{
givenACodeSampleToTokenize var("std::B<int> b;");
ASSERT_EQUALS(&B, library.detectContainer(var.tokens()));
ASSERT(!library.detectIterator(var.tokens()));
bool isIterator;
ASSERT_EQUALS(&B, library.detectContainerOrIterator(var.tokens(), &isIterator));
ASSERT(!isIterator);
}
{
givenACodeSampleToTokenize var("std::B<int>::size_type b_s;");
ASSERT(!library.detectContainer(var.tokens()));
ASSERT(!library.detectIterator(var.tokens()));
ASSERT(!library.detectContainerOrIterator(var.tokens()));
}
{
givenACodeSampleToTokenize var("std::B<int>::iterator b_it;");
ASSERT(!library.detectContainer(var.tokens()));
ASSERT_EQUALS(&B, library.detectIterator(var.tokens()));
bool isIterator;
ASSERT_EQUALS(&B, library.detectContainerOrIterator(var.tokens(), &isIterator));
ASSERT(isIterator);
}
{
givenACodeSampleToTokenize var("C c;");
ASSERT(!library.detectContainer(var.tokens()));
ASSERT(!library.detectIterator(var.tokens()));
ASSERT(!library.detectContainerOrIterator(var.tokens()));
}
{
givenACodeSampleToTokenize var("D d;");
ASSERT(!library.detectContainer(var.tokens()));
ASSERT(!library.detectIterator(var.tokens()));
ASSERT(!library.detectContainerOrIterator(var.tokens()));
}
}
void version() const {