Skip to content

Commit f0bc300

Browse files
committed
danmar#6510 False positive performance warning for std::list::size(). Fix this and other similar false positives. Refactoring of Variable::isStlType(), use fail-safe std::set instead of plain array. Run astyle
1 parent 20842fb commit f0bc300

File tree

9 files changed

+284
-215
lines changed

9 files changed

+284
-215
lines changed

lib/checkclass.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,10 +1868,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool&
18681868
if (end->varId()) {
18691869
const Variable *var = end->variable();
18701870
// The container contains the STL types whose operator[] is not a const.
1871-
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
1872-
static const char* const stl_containers [] = {
1873-
"map", "unordered_map"
1874-
};
1871+
static const std::set<std::string> stl_containers = make_container< std::set<std::string> >() << "map" << "unordered_map";
18751872
if (var && var->isStlType(stl_containers))
18761873
return false;
18771874
}

lib/checkio.cpp

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,16 +1522,12 @@ CheckIO::ArgumentInfo::~ArgumentInfo()
15221522
}
15231523
}
15241524

1525+
1526+
15251527
bool CheckIO::ArgumentInfo::isStdVectorOrString()
15261528
{
1527-
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
1528-
static const char* const stl_vector[] = {
1529-
"array", "vector"
1530-
};
1531-
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
1532-
static const char* const stl_string[] = {
1533-
"string", "u16string", "u32string", "wstring"
1534-
};
1529+
static const std::set<std::string> stl_vector = make_container< std::set<std::string> >() << "array" << "vector";
1530+
static const std::set<std::string> stl_string = make_container< std::set<std::string> >() << "string" << "u16string" << "u32string" << "wstring";
15351531

15361532
if (variableInfo->isStlType(stl_vector)) {
15371533
typeToken = variableInfo->typeStartToken()->tokAt(4);
@@ -1586,19 +1582,15 @@ bool CheckIO::ArgumentInfo::isStdVectorOrString()
15861582

15871583
bool CheckIO::ArgumentInfo::isStdContainer(const Token *tok)
15881584
{
1589-
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
1590-
static const char* const stl_container[] = {
1591-
"array", "bitset", "deque", "forward_list",
1592-
"hash_map", "hash_multimap", "hash_set",
1593-
"list", "map", "multimap", "multiset",
1594-
"priority_queue", "queue", "set", "stack",
1595-
"unordered_map", "unordered_multimap", "unordered_multiset", "unordered_set",
1596-
"vector"
1597-
};
1598-
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
1599-
static const char* const stl_string[]= {
1600-
"string", "u16string", "u32string", "wstring"
1601-
};
1585+
static const std::set<std::string> stl_container = make_container< std::set<std::string> >() <<
1586+
"array" << "bitset" << "deque" << "forward_list" <<
1587+
"hash_map" << "hash_multimap" << "hash_set" <<
1588+
"list" << "map" << "multimap" << "multiset" <<
1589+
"priority_queue" << "queue" << "set" << "stack" <<
1590+
"unordered_map" << "unordered_multimap" << "unordered_multiset" << "unordered_set" << "vector"
1591+
;
1592+
static const std::set<std::string> stl_string= make_container< std::set<std::string> >() <<
1593+
"string" << "u16string" << "u32string" << "wstring";
16021594

16031595
if (tok && tok->variable()) {
16041596
const Variable* variable = tok->variable();

lib/checknullpointer.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,10 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
148148
*/
149149
bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
150150
{
151-
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
152-
static const char* const stl_stream [] = {
153-
"fstream", "ifstream", "iostream", "istream",
154-
"istringstream", "ofstream", "ostream", "ostringstream",
155-
"stringstream", "wistringstream", "wostringstream", "wstringstream"
156-
};
151+
static const std::set<std::string> stl_stream = make_container< std::set<std::string> >() <<
152+
"fstream" << "ifstream" << "iostream" << "istream" <<
153+
"istringstream" << "ofstream" << "ostream" << "ostringstream" <<
154+
"stringstream" << "wistringstream" << "wostringstream" << "wstringstream";
157155

158156
unknown = false;
159157

@@ -379,12 +377,9 @@ void CheckNullPointer::nullPointer()
379377
void CheckNullPointer::nullConstantDereference()
380378
{
381379
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
382-
383-
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
384-
static const char* const stl_stream[] = {
385-
"fstream", "ifstream", "iostream", "istream",
386-
"istringstream", "stringstream", "wistringstream", "wstringstream"
387-
};
380+
static const std::set<std::string> stl_stream = make_container< std::set<std::string> >() <<
381+
"fstream" << "ifstream" << "iostream" << "istream" <<
382+
"istringstream" << "stringstream" << "wistringstream" << "wstringstream";
388383

389384
const std::size_t functions = symbolDatabase->functionScopes.size();
390385
for (std::size_t i = 0; i < functions; ++i) {

lib/checkstl.cpp

Lines changed: 23 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -843,28 +843,22 @@ void CheckStl::if_findError(const Token *tok, bool str)
843843
/**
844844
* Is container.size() slow?
845845
*/
846-
static bool isContainerSizeSlow(const Token *tok)
846+
static bool isCpp03ContainerSizeSlow(const Token *tok)
847847
{
848-
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
849-
static const char* stl_size_slow[] = {
850-
"array", "bitset",
851-
"forward_list", "hash_map", "hash_multimap", "hash_set",
852-
"list", "map", "multimap", "multiset",
853-
"priority_queue", "queue", "set", "stack", "unordered_map",
854-
"unordered_multimap", "unordered_multiset", "unordered_set"
855-
};
856-
857848
if (!tok)
858849
return false;
859850
const Variable* var = tok->variable();
860-
return var && var->isStlType(stl_size_slow);
851+
return var && var->isStlType("list");
861852
}
862853

863854
void CheckStl::size()
864855
{
865856
if (!_settings->isEnabled("performance"))
866857
return;
867858

859+
if (_settings->standards.cpp == Standards::CPP11)
860+
return;
861+
868862
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
869863
const std::size_t functions = symbolDatabase->functionScopes.size();
870864
for (std::size_t i = 0; i < functions; ++i) {
@@ -883,21 +877,21 @@ void CheckStl::size()
883877
// check for comparison to zero
884878
if ((tok->previous() && !tok->previous()->isArithmeticalOp() && Token::Match(end, "==|<=|!=|> 0")) ||
885879
(end->next() && !end->next()->isArithmeticalOp() && Token::Match(tok->tokAt(-2), "0 ==|>=|!=|<"))) {
886-
if (isContainerSizeSlow(tok1))
880+
if (isCpp03ContainerSizeSlow(tok1))
887881
sizeError(tok1);
888882
}
889883

890884
// check for comparison to one
891885
if ((tok->previous() && !tok->previous()->isArithmeticalOp() && Token::Match(end, ">=|< 1") && !end->tokAt(2)->isArithmeticalOp()) ||
892886
(end->next() && !end->next()->isArithmeticalOp() && Token::Match(tok->tokAt(-2), "1 <=|>") && !tok->tokAt(-3)->isArithmeticalOp())) {
893-
if (isContainerSizeSlow(tok1))
887+
if (isCpp03ContainerSizeSlow(tok1))
894888
sizeError(tok1);
895889
}
896890

897891
// check for using as boolean expression
898892
else if ((Token::Match(tok->tokAt(-2), "if|while (") && end->str() == ")") ||
899893
(tok->previous()->type() == Token::eLogicalOp && Token::Match(end, "&&|)|,|;|%oror%"))) {
900-
if (isContainerSizeSlow(tok1))
894+
if (isCpp03ContainerSizeSlow(tok1))
901895
sizeError(tok1);
902896
}
903897
}
@@ -1046,14 +1040,10 @@ void CheckStl::string_c_str()
10461040
{
10471041
const bool printInconclusive = _settings->inconclusive;
10481042
const bool printPerformance = _settings->isEnabled("performance");
1049-
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
1050-
static const char* const stl_string[] = {
1051-
"string", "u16string", "u32string", "wstring"
1052-
};
1053-
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
1054-
static const char* const stl_string_stream[] = {
1055-
"istringstream", "ostringstream", "stringstream", "wstringstream"
1056-
};
1043+
static const std::set<std::string> stl_string = make_container< std::set<std::string> >() <<
1044+
"string" << "u16string" << "u32string" << "wstring" ;
1045+
static const std::set<std::string> stl_string_stream = make_container< std::set<std::string> >() <<
1046+
"istringstream" << "ostringstream" << "stringstream" << "wstringstream" ;
10571047

10581048
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
10591049

@@ -1357,17 +1347,13 @@ void CheckStl::uselessCalls()
13571347
if (!printPerformance && !printWarning)
13581348
return;
13591349

1360-
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
1361-
static const char* const stl_string[] = {
1362-
"string", "u16string", "u32string", "wstring"
1363-
};
1364-
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
1365-
static const char* const stl_containers_with_empty_and_clear[] = {
1366-
"deque", "forward_list", "list",
1367-
"map", "multimap", "multiset", "set", "string",
1368-
"unordered_map", "unordered_multimap", "unordered_multiset",
1369-
"unordered_set", "vector", "wstring"
1370-
};
1350+
static const std::set<std::string> stl_string = make_container< std::set<std::string> >() <<
1351+
"string" << "u16string" << "u32string" << "wstring";
1352+
static const std::set<std::string> stl_containers_with_empty_and_clear = make_container< std::set<std::string> >() <<
1353+
"deque" << "forward_list" << "list" <<
1354+
"map" << "multimap" << "multiset" << "set" << "string" <<
1355+
"unordered_map" << "unordered_multimap" << "unordered_multiset" <<
1356+
"unordered_set" << "vector" << "wstring";
13711357

13721358
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
13731359
const std::size_t functions = symbolDatabase->functionScopes.size();
@@ -1556,8 +1542,10 @@ void CheckStl::readingEmptyStlContainer()
15561542
std::set<unsigned int> empty_map; // empty std::map-like instances of STL containers
15571543
std::set<unsigned int> empty_nonmap; // empty non-std::map-like instances of STL containers
15581544

1559-
static const char *MAP_STL_CONTAINERS[] = { "map", "multimap", "unordered_map", "unordered_multimap" };
1560-
static const char *NONMAP_STL_CONTAINERS[] = { "deque", "forward_list", "list", "multiset", "queue", "set", "stack", "string", "unordered_multiset", "unordered_set", "vector" };
1545+
static const std::set<std::string> MAP_STL_CONTAINERS = make_container< std::set<std::string> >() <<
1546+
"map" << "multimap" << "unordered_map" << "unordered_multimap" ;
1547+
static const std::set<std::string> NONMAP_STL_CONTAINERS = make_container< std::set<std::string> >() <<
1548+
"deque" << "forward_list" << "list" << "multiset" << "queue" << "set" << "stack" << "string" << "unordered_multiset" << "unordered_set" << "vector";
15611549

15621550
const std::list<Scope>& scopeList = _tokenizer->getSymbolDatabase()->scopeList;
15631551

lib/symboldatabase.h

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -488,12 +488,25 @@ class CPPCHECKLIB Variable {
488488
* ...
489489
* const char *str[] = {"string", "wstring"};
490490
* sVar->isStlType(str) == true
491-
* @param stlTypes array of stl types in alphabetical order
491+
* @param stlTypes set of stl types
492492
* @return true if it is an stl type and its type matches any of the types in 'stlTypes'
493493
*/
494-
template <std::size_t array_length>
495-
bool isStlType(const char* const(&stlTypes)[array_length]) const {
496-
return isStlType() && std::binary_search(stlTypes, stlTypes + array_length, _start->strAt(2));
494+
bool isStlType(const std::string& stlType) const {
495+
return isStlType() && stlType==_start->strAt(2);
496+
}
497+
498+
/**
499+
* Checks if the variable is of any of the STL types passed as arguments ('std::')
500+
* E.g.:
501+
* std::string s;
502+
* ...
503+
* const std::set<std::string> str = make_container< std::set<std::string> >() << "string" << "wstring";
504+
* sVar->isStlType(str) == true
505+
* @param stlTypes set of stl types
506+
* @return true if it is an stl type and its type matches any of the types in 'stlTypes'
507+
*/
508+
bool isStlType(const std::set<std::string>& stlTypes) const {
509+
return isStlType() && stlTypes.find(_start->strAt(2))!=stlTypes.end();
497510
}
498511

499512
/**
@@ -1003,5 +1016,23 @@ class CPPCHECKLIB SymbolDatabase {
10031016
/** list for missing types */
10041017
std::list<Type> _blankTypes;
10051018
};
1019+
1020+
template < typename Cont >
1021+
class make_container {
1022+
public:
1023+
typedef make_container< Cont > my_type;
1024+
typedef typename Cont::value_type T;
1025+
my_type& operator<< (const T& val) {
1026+
data_.insert(data_.end(), val);
1027+
return *this;
1028+
}
1029+
operator Cont() const {
1030+
return data_;
1031+
}
1032+
private:
1033+
Cont data_;
1034+
};
1035+
1036+
10061037
//---------------------------------------------------------------------------
10071038
#endif // symboldatabaseH

lib/tokenize.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9318,23 +9318,23 @@ void Tokenizer::simplifyKeyword()
93189318
// 1) struct name final { }; <- struct is final
93199319
if (Token::Match(tok, "%type% final [:{]")) {
93209320
tok->deleteNext();
9321-
continue;
9322-
}
9321+
continue;
9322+
}
93239323
// final:
93249324
// 2) void f() final; <- function is final
93259325
// override:
93269326
// void f() override;
93279327
//if (Token::Match(tok, ") override [{;]"))
9328-
if (Token::Match(tok, ") const|override|final")) {
9329-
Token* specifier = tok->tokAt(2);
9330-
while(specifier && Token::Match(specifier, "const|override|final"))
9331-
specifier=specifier->next();
9328+
if (Token::Match(tok, ") const|override|final")) {
9329+
Token* specifier = tok->tokAt(2);
9330+
while (specifier && Token::Match(specifier, "const|override|final"))
9331+
specifier=specifier->next();
93329332
if (specifier && Token::Match(specifier, "[{;]")) {
9333-
specifier=tok->next();
9334-
while (specifier->str()=="override" || specifier->str()=="final")
9335-
specifier->deleteThis();
9336-
}
9337-
}
9333+
specifier=tok->next();
9334+
while (specifier->str()=="override" || specifier->str()=="final")
9335+
specifier->deleteThis();
9336+
}
9337+
}
93389338
}
93399339
}
93409340
}

0 commit comments

Comments
 (0)