refs #10663 - sped up `Library::detectContainerOrIterator()` by iterating the containers only once (#4380)
This commit is contained in:
parent
2ab8de2650
commit
1d95d1908d
2
Makefile
2
Makefile
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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()))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue