2009-02-10 20:40:21 +01:00
/*
* Cppcheck - A tool for static C / C + + code analysis
2011-01-09 20:33:36 +01:00
* Copyright ( C ) 2007 - 2011 Daniel Marjamäki and Cppcheck team .
2009-02-10 20:40:21 +01:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2009-09-27 17:08:31 +02:00
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
2009-02-10 20:40:21 +01:00
*/
2009-10-25 12:49:06 +01:00
# include "tokenize.h"
# include "checkstl.h"
2009-02-10 20:40:21 +01:00
# include "testsuite.h"
# include <sstream>
extern std : : ostringstream errout ;
2011-10-13 20:53:06 +02:00
class TestStl : public TestFixture {
2009-02-10 20:40:21 +01:00
public :
TestStl ( ) : TestFixture ( " TestStl " )
{ }
private :
2011-10-13 20:53:06 +02:00
void run ( ) {
2009-02-10 20:40:21 +01:00
TEST_CASE ( iterator1 ) ;
2009-02-10 21:01:39 +01:00
TEST_CASE ( iterator2 ) ;
2009-04-29 17:32:38 +02:00
TEST_CASE ( iterator3 ) ;
2009-09-01 18:49:17 +02:00
TEST_CASE ( iterator4 ) ;
2009-10-18 18:42:01 +02:00
TEST_CASE ( iterator5 ) ;
2010-04-10 10:22:34 +02:00
TEST_CASE ( iterator6 ) ;
2010-04-16 16:56:55 +02:00
TEST_CASE ( iterator7 ) ;
2010-05-15 20:00:41 +02:00
TEST_CASE ( iterator8 ) ;
2011-10-18 21:55:41 +02:00
TEST_CASE ( iterator9 ) ;
TEST_CASE ( iterator10 ) ;
2009-04-29 17:32:38 +02:00
2009-05-03 07:37:39 +02:00
TEST_CASE ( dereference ) ;
2009-07-30 19:49:38 +02:00
TEST_CASE ( dereference_member ) ;
2009-05-03 07:37:39 +02:00
2009-02-10 20:56:00 +01:00
TEST_CASE ( STLSize ) ;
TEST_CASE ( STLSizeNoErr ) ;
2010-10-08 21:41:52 +02:00
TEST_CASE ( erase1 ) ;
2009-12-18 20:55:51 +01:00
TEST_CASE ( erase2 ) ;
2010-01-23 22:03:38 +01:00
TEST_CASE ( erase3 ) ;
2010-05-08 20:11:15 +02:00
TEST_CASE ( erase4 ) ;
2010-10-08 21:52:18 +02:00
TEST_CASE ( erase5 ) ;
2011-01-20 20:48:35 +01:00
TEST_CASE ( erase6 ) ;
2009-02-11 06:08:29 +01:00
TEST_CASE ( eraseBreak ) ;
2010-07-14 09:42:10 +02:00
TEST_CASE ( eraseContinue ) ;
2010-07-09 10:50:24 +02:00
TEST_CASE ( eraseReturn1 ) ;
TEST_CASE ( eraseReturn2 ) ;
2010-09-18 16:46:38 +02:00
TEST_CASE ( eraseReturn3 ) ;
2009-02-11 17:20:32 +01:00
TEST_CASE ( eraseGoto ) ;
2010-08-17 18:56:11 +02:00
TEST_CASE ( eraseAssign1 ) ;
TEST_CASE ( eraseAssign2 ) ;
2009-05-02 20:39:51 +02:00
TEST_CASE ( eraseErase ) ;
2010-05-15 19:46:42 +02:00
TEST_CASE ( eraseByValue ) ;
2009-02-18 20:57:43 +01:00
TEST_CASE ( pushback1 ) ;
2009-04-25 16:32:37 +02:00
TEST_CASE ( pushback2 ) ;
TEST_CASE ( pushback3 ) ;
TEST_CASE ( pushback4 ) ;
2009-09-26 11:49:09 +02:00
TEST_CASE ( pushback5 ) ;
2009-09-27 09:59:19 +02:00
TEST_CASE ( pushback6 ) ;
2009-09-27 10:10:21 +02:00
TEST_CASE ( pushback7 ) ;
2009-10-13 20:55:33 +02:00
TEST_CASE ( pushback8 ) ;
2009-11-10 19:07:04 +01:00
TEST_CASE ( pushback9 ) ;
2010-06-15 19:53:09 +02:00
TEST_CASE ( pushback10 ) ;
2011-05-22 17:17:24 +02:00
TEST_CASE ( pushback11 ) ;
2009-04-25 16:32:37 +02:00
2009-05-02 20:49:58 +02:00
TEST_CASE ( insert1 ) ;
2011-01-20 19:26:52 +01:00
TEST_CASE ( insert2 ) ;
2009-05-02 20:49:58 +02:00
2009-03-05 22:22:00 +01:00
TEST_CASE ( invalidcode ) ;
2009-04-13 17:48:13 +02:00
TEST_CASE ( stlBoundries1 ) ;
2009-07-28 22:55:23 +02:00
TEST_CASE ( stlBoundries2 ) ;
2009-08-08 21:07:33 +02:00
TEST_CASE ( stlBoundries3 ) ;
2009-11-02 20:25:08 +01:00
2010-02-27 21:26:11 +01:00
// if (str.find("ab"))
TEST_CASE ( if_find ) ;
2010-05-01 21:56:39 +02:00
TEST_CASE ( if_str_find ) ;
2010-02-27 21:26:11 +01:00
2009-12-19 15:24:59 +01:00
TEST_CASE ( size1 ) ;
2011-03-29 01:31:23 +02:00
TEST_CASE ( size2 ) ;
2010-09-16 18:49:23 +02:00
// Redundant conditions..
// if (ints.find(123) != ints.end()) ints.remove(123);
TEST_CASE ( redundantCondition1 ) ;
TEST_CASE ( redundantCondition2 ) ;
2010-10-10 10:52:41 +02:00
// missing inner comparison when incrementing iterator inside loop
TEST_CASE ( missingInnerComparison1 ) ;
2010-10-10 14:28:14 +02:00
TEST_CASE ( missingInnerComparison2 ) ; // no FP when there is comparison
TEST_CASE ( missingInnerComparison3 ) ; // no FP when there is iterator shadowing
2010-10-18 20:05:54 +02:00
TEST_CASE ( missingInnerComparison4 ) ; // no FP when "break;" is used
2010-10-30 11:22:30 +02:00
TEST_CASE ( missingInnerComparison5 ) ; // Ticket #2154 - FP
2011-03-12 20:29:54 +01:00
TEST_CASE ( missingInnerComparison6 ) ; // #2643 - 'it=foo.insert(++it,0);'
2010-10-17 19:18:46 +02:00
// catch common problems when using the string::c_str() function
TEST_CASE ( cstr ) ;
2011-06-16 20:26:00 +02:00
TEST_CASE ( autoPointer ) ;
2011-10-24 23:25:23 +02:00
TEST_CASE ( uselessCalls ) ;
2009-02-10 20:40:21 +01:00
}
2011-10-13 20:53:06 +02:00
void check ( const std : : string & code ) {
2009-03-19 19:35:47 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
2009-03-18 22:40:38 +01:00
2010-04-17 09:23:54 +02:00
Settings settings ;
2011-08-07 09:28:08 +02:00
settings . addEnabled ( " style " ) ;
2011-09-03 15:30:30 +02:00
settings . addEnabled ( " performance " ) ;
2010-12-01 18:00:55 +01:00
// Tokenize..
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code . c_str ( ) ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
tokenizer . simplifyTokenList ( ) ;
// Check..
2009-03-19 19:35:47 +01:00
CheckStl checkStl ;
2009-12-28 18:06:26 +01:00
checkStl . runSimplifiedChecks ( & tokenizer , & settings , this ) ;
2009-03-19 19:35:47 +01:00
}
2011-10-13 20:53:06 +02:00
void iterator1 ( ) {
2009-04-29 20:16:04 +02:00
check ( " void f() \n "
2009-03-19 19:35:47 +01:00
" { \n "
2009-04-29 20:16:04 +02:00
" list<int> l1; \n "
" list<int> l2; \n "
" for (list<int>::iterator it = l1.begin(); it != l2.end(); ++it) \n "
2009-03-19 19:35:47 +01:00
" { } \n "
" } \n " ) ;
2009-04-29 20:16:04 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Same iterator is used with both l1 and l2 \n " , errout . str ( ) ) ;
2011-10-14 19:54:20 +02:00
// Same check with reverse iterator
check ( " void f() \n "
" { \n "
" list<int> l1; \n "
" list<int> l2; \n "
" for (list<int>::const_reverse_iterator it = l1.rbegin(); it != l2.rend(); ++it) \n "
" { } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Same iterator is used with both l1 and l2 \n " , errout . str ( ) ) ;
2009-03-19 19:35:47 +01:00
}
2011-10-13 20:53:06 +02:00
void iterator2 ( ) {
2009-03-19 19:35:47 +01:00
check ( " void foo() \n "
" { \n "
2009-04-29 20:16:04 +02:00
" list<int> l1; \n "
" list<int> l2; \n "
" list<int>::iterator it = l1.begin(); \n "
" while (it != l2.end()) \n "
2009-03-19 19:35:47 +01:00
" { \n "
" ++it; \n "
" } \n "
" } \n " ) ;
2009-04-29 20:16:04 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Same iterator is used with both l1 and l2 \n " , errout . str ( ) ) ;
2009-03-19 19:35:47 +01:00
}
2009-02-10 20:56:00 +01:00
2011-10-13 20:53:06 +02:00
void iterator3 ( ) {
2009-04-29 17:32:38 +02:00
check ( " void foo() \n "
" { \n "
2009-04-29 20:16:04 +02:00
" list<int> l1; \n "
" list<int> l2; \n "
" list<int>::iterator it = l1.begin(); \n "
" l2.insert(it, 0); \n "
2009-04-29 17:32:38 +02:00
" } \n " ) ;
2009-04-29 20:16:04 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Same iterator is used with both l1 and l2 \n " , errout . str ( ) ) ;
2009-04-29 17:32:38 +02:00
}
2011-10-13 20:53:06 +02:00
void iterator4 ( ) {
2009-09-01 18:49:17 +02:00
check ( " void foo(std::vector<std::string> &test) \n "
" { \n "
" std::set<int> result; \n "
" for (std::vector<std::string>::const_iterator cit = test.begin(); \n "
" cit != test.end(); \n "
" ++cit) \n "
" { \n "
" result.insert(cit->size()); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-10-18 18:42:01 +02:00
}
2011-10-13 20:53:06 +02:00
void iterator5 ( ) {
2009-10-18 18:42:01 +02:00
check ( " void foo() \n "
" { \n "
" std::vector<int> ints1; \n "
" std::vector<int> ints2; \n "
" std::vector<int>::iterator it = std::find(ints1.begin(), ints2.end(), 22); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) mismatching containers \n " , errout . str ( ) ) ;
2009-09-01 18:49:17 +02:00
}
2009-02-10 20:56:00 +01:00
2011-10-13 20:53:06 +02:00
void iterator6 ( ) {
2010-04-10 10:22:34 +02:00
// Ticket #1357
check ( " void foo(const std::set<int> &ints1) \n "
" { \n "
" std::set<int> ints2; \n "
" std::set<int>::iterator it1 = ints1.begin(); \n "
" std::set<int>::iterator it2 = ints1.end(); \n "
" ints2.insert(it1, it2); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-10-13 20:53:06 +02:00
void iterator7 ( ) {
2011-10-18 21:55:41 +02:00
check ( " void foo() \n "
" { \n "
" std::vector<int> ints1; \n "
" std::vector<int> ints2; \n "
" std::vector<int>::iterator it = std::inplace_merge(ints1.begin(), std:.advance(ints1.rbegin(), 5), ints2.end()); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) mismatching containers \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::vector<int> ints1; \n "
" std::vector<int> ints2; \n "
" std::vector<int>::iterator it = std::inplace_merge(ints1.begin(), std::advance(ints2.rbegin(), 5), ints1.end()); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void iterator8 ( ) {
check ( " void foo() \n "
" { \n "
" std::vector<int> ints1; \n "
" std::vector<int> ints2; \n "
" std::vector<int>::iterator it = std::find_first_of(ints1.begin(), ints2.end(), ints1.begin(), ints1.end()); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) mismatching containers \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::vector<int> ints1; \n "
" std::vector<int> ints2; \n "
" std::vector<int>::iterator it = std::find_first_of(ints1.begin(), ints1.end(), ints2.begin(), ints1.end()); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) mismatching containers \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::vector<int> ints1; \n "
" std::vector<int> ints2; \n "
" std::vector<int>::iterator it = std::find_first_of(ints1.begin(), ints1.end(), ints2.begin(), ints2.end()); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void iterator9 ( ) {
2010-04-16 16:56:55 +02:00
// Ticket #1600
check ( " void foo(std::vector<int> &r) \n "
" { \n "
" std::vector<int>::iterator aI = r.begin(); \n "
" while(aI != r.end()) \n "
" { \n "
" if (*aI == 0) \n "
" { \n "
" r.insert(aI, 42); \n "
" return; \n "
" } \n "
" ++aI; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-19 21:00:46 +01:00
// Ticket #2481
check ( " void foo(std::vector<int> &r) \n "
" { \n "
" std::vector<int>::iterator aI = r.begin(); \n "
" while(aI != r.end()) \n "
" { \n "
" if (*aI == 0) \n "
" { \n "
" r.insert(aI, 42); \n "
" break; \n "
" } \n "
" ++aI; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-04-16 16:56:55 +02:00
// Execution path checking..
check ( " void foo(std::vector<int> &r, int c) \n "
" { \n "
" std::vector<int>::iterator aI = r.begin(); \n "
" while(aI != r.end()) \n "
" { \n "
" if (*aI == 0) \n "
" { \n "
" r.insert(aI, 42); \n "
" if (c) \n "
" { \n "
" return; \n "
" } \n "
" } \n "
" ++aI; \n "
" } \n "
" } \n " ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:14] (error) After insert, the iterator 'aI' may be invalid " , " " , errout . str ( ) ) ;
2010-04-16 16:56:55 +02:00
}
2011-10-18 21:55:41 +02:00
void iterator10 ( ) {
2010-05-15 20:00:41 +02:00
// Ticket #1679
check ( " void foo() \n "
" { \n "
" std::set<int> s1; \n "
" std::set<int> s2; \n "
" for (std::set<int>::iterator it = s1.begin(); it != s1.end(); ++it) \n "
" { \n "
" if (true) { } \n "
" if (it != s2.end()) continue; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:8]: (error) Same iterator is used with both s1 and s2 \n " , errout . str ( ) ) ;
}
2009-05-03 07:37:39 +02:00
// Dereferencing invalid pointer
2011-10-13 20:53:06 +02:00
void dereference ( ) {
2009-05-03 07:37:39 +02:00
check ( " void f() \n "
" { \n "
2009-11-02 21:17:33 +01:00
" std::vector<int> ints; \n "
2009-05-03 07:37:39 +02:00
" std::vector<int>::iterator iter; \n "
" iter = ints.begin() + 2; \n "
" ints.erase(iter); \n "
" std::cout << (*iter) << std::endl; \n "
" } \n " ) ;
2009-11-02 21:17:33 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Dereferenced iterator 'iter' has been erased \n " , errout . str ( ) ) ;
2009-05-03 07:37:39 +02:00
}
2011-10-13 20:53:06 +02:00
void dereference_member ( ) {
2009-07-30 19:49:38 +02:00
check ( " void f() \n "
" { \n "
2009-11-02 21:17:33 +01:00
" std::map<int, int> ints; \n "
2009-07-30 19:49:38 +02:00
" std::map<int, int>::iterator iter; \n "
" iter = ints.begin(); \n "
" ints.erase(iter); \n "
" std::cout << iter->first << std::endl; \n "
" } \n " ) ;
2009-11-02 21:17:33 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Dereferenced iterator 'iter' has been erased \n " , errout . str ( ) ) ;
2011-10-14 19:54:20 +02:00
// Reverse iterator
check ( " void f() \n "
" { \n "
" std::map<int, int> ints; \n "
" std::map<int, int>::reverse_iterator iter; \n "
" iter = ints.rbegin(); \n "
" ints.erase(iter); \n "
" std::cout << iter->first << std::endl; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (error) Dereferenced iterator 'iter' has been erased \n " , errout . str ( ) ) ;
2009-07-30 19:49:38 +02:00
}
2009-05-03 07:37:39 +02:00
2011-10-13 20:53:06 +02:00
void STLSize ( ) {
2009-03-19 19:35:47 +01:00
check ( " void foo() \n "
" { \n "
" std::vector<int> foo; \n "
" for (unsigned int ii = 0; ii <= foo.size(); ++ii) \n "
" { \n "
" foo[ii] = 0; \n "
" } \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) When ii==foo.size(), foo[ii] is out of bounds \n " , errout . str ( ) ) ;
2009-10-07 22:38:21 +02:00
check ( " void foo() \n "
" { \n "
" std::vector<int> foo; \n "
" foo.push_back(1); \n "
" for (unsigned int ii = 0; ii <= foo.size(); ++ii) \n "
" { \n "
" } \n "
" int ii = 0; \n "
" foo[ii] = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-19 19:35:47 +01:00
}
2011-10-13 20:53:06 +02:00
void STLSizeNoErr ( ) {
2009-02-10 20:56:00 +01:00
{
check ( " void foo() \n "
" { \n "
2009-03-19 19:35:47 +01:00
" std::vector<int> foo; \n "
" for (unsigned int ii = 0; ii < foo.size(); ++ii) \n "
" { \n "
" foo[ii] = 0; \n "
" } \n "
2009-02-10 20:56:00 +01:00
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-02-10 20:56:00 +01:00
}
{
check ( " void foo() \n "
" { \n "
2009-03-19 19:35:47 +01:00
" std::vector<int> foo; \n "
" for (unsigned int ii = 0; ii <= foo.size(); ++ii) \n "
2009-02-10 20:56:00 +01:00
" { \n "
" } \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-02-10 20:56:00 +01:00
}
2009-03-17 18:54:50 +01:00
{
check ( " void foo() \n "
" { \n "
" std::vector<int> foo; \n "
" for (unsigned int ii = 0; ii <= foo.size(); ++ii) \n "
" { \n "
2009-03-19 19:35:47 +01:00
" if (ii == foo.size()) \n "
" { \n "
" } \n "
" else \n "
" { \n "
" foo[ii] = 0; \n "
" } \n "
2009-03-17 18:54:50 +01:00
" } \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-18 22:40:38 +01:00
}
2009-03-19 19:35:47 +01:00
}
2009-02-11 06:08:29 +01:00
2011-10-13 20:53:06 +02:00
void erase1 ( ) {
2009-11-10 17:20:20 +01:00
check ( " void f() \n "
" { \n "
" for (it = foo.begin(); it != foo.end(); ++it) \n "
" { \n "
" foo.erase(it); \n "
" } \n "
" } \n " ) ;
2011-01-04 21:06:41 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Dangerous iterator usage after erase()-method. \n " , errout . str ( ) ) ;
2009-11-10 17:20:20 +01:00
check ( " for (it = foo.begin(); it != foo.end(); ++it) \n "
" { \n "
" foo.erase(it); \n "
" } \n "
" for (it = foo.begin(); it != foo.end(); ++it) \n "
" { \n "
" foo.erase(it); \n "
" } \n " ) ;
2011-01-04 21:06:41 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous iterator usage after erase()-method. \n "
" [test.cpp:7]: (error) Dangerous iterator usage after erase()-method. \n " , errout . str ( ) ) ;
2009-11-10 17:20:20 +01:00
check ( " void f(std::list<int> &ints) \n "
" { \n "
" std::list<int>::iterator i = ints.begin(); \n "
" i = ints.erase(i); \n "
" *i = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-04-10 13:27:36 +02:00
2010-10-15 18:11:41 +02:00
// #2101
check ( " void f(vector< list<int> > &ints, unsigned int i) \n "
" { \n "
" list<int>::iterator it; \n "
" for(it = ints[i].begin(); it != ints[i].end(); it++) { \n "
" if (*it % 2) \n "
" it = ints[i].erase(it); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-19 19:35:47 +01:00
}
2009-02-11 17:20:32 +01:00
2011-10-13 20:53:06 +02:00
void erase2 ( ) {
2009-12-18 20:55:51 +01:00
check ( " static void f() \n "
" { \n "
2010-10-05 20:54:13 +02:00
" for (iterator it = foo.begin(); it != foo.end(); it = next) \n "
2009-12-18 20:55:51 +01:00
" { \n "
" next = it; \n "
" next++; \n "
" foo.erase(it); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-10-13 20:53:06 +02:00
void erase3 ( ) {
2010-01-23 22:03:38 +01:00
check ( " static void f(std::list<abc> &foo) \n "
" { \n "
" std::list<abc>::iterator it = foo.begin(); \n "
" foo.erase(it->a); \n "
" if (it->b); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-10-13 20:53:06 +02:00
void erase4 ( ) {
2010-05-08 20:11:15 +02:00
check ( " void f() \n "
" { \n "
" std::list<int>::iterator it, it2; \n "
" for (it = foo.begin(); it != i2; ++it) \n "
" { \n "
" foo.erase(it); \n "
" } \n "
" } \n " ) ;
2011-01-04 21:06:41 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Dangerous iterator usage after erase()-method. \n " , errout . str ( ) ) ;
2010-05-08 20:11:15 +02:00
check ( " void f() \n "
" { \n "
" std::list<int>::iterator it = foo.begin(); \n "
" for (; it != i2; ++it) \n "
" { \n "
" foo.erase(it); \n "
" } \n "
" } \n " ) ;
2011-01-04 21:06:41 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Dangerous iterator usage after erase()-method. \n " , errout . str ( ) ) ;
2010-05-08 20:11:15 +02:00
check ( " void f() \n "
" { \n "
" std::list<int>::iterator it = foo.begin(); \n "
" while (it != i2) \n "
" { \n "
" foo.erase(it); \n "
" } \n "
" } \n " ) ;
2011-01-04 21:06:41 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Dangerous iterator usage after erase()-method. \n " , errout . str ( ) ) ;
2010-08-13 20:54:31 +02:00
check ( " void f() \n "
" { \n "
" std::list<int>::iterator it = foo.begin(); \n "
" while (it != i2) \n "
" { \n "
" foo.erase(++it); \n "
" } \n "
" } \n " ) ;
2011-01-04 21:06:41 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Dangerous iterator usage after erase()-method. \n " , errout . str ( ) ) ;
2010-05-08 20:11:15 +02:00
}
2011-10-13 20:53:06 +02:00
void erase5 ( ) {
2010-10-08 21:52:18 +02:00
check ( " void f() \n "
" { \n "
2010-10-09 07:15:34 +02:00
" std::list<int> foo; \n "
" std::list<int>::iterator it; \n "
2010-10-08 21:52:18 +02:00
" for (it = foo.begin(); it != foo.end(); ++it) \n "
" { \n "
2010-10-09 07:15:34 +02:00
" if (*it == 123) \n "
2010-10-08 21:52:18 +02:00
" foo.erase(it); \n "
" } \n "
" } \n " ) ;
2011-01-04 21:06:41 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Dangerous iterator usage after erase()-method. \n " , errout . str ( ) ) ;
2010-10-08 21:52:18 +02:00
}
2011-10-13 20:53:06 +02:00
void erase6 ( ) {
2011-01-20 20:48:35 +01:00
check ( " void f() { \n "
" std::vector<int> vec(3); \n "
" std::vector<int>::iterator it; \n "
" std::vector<int>::iterator itEnd = vec.end(); \n "
" for (it = vec.begin(); it != itEnd; it = vec.begin(), itEnd = vec.end()) \n "
" { \n "
" vec.erase(it); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-10-13 20:53:06 +02:00
void eraseBreak ( ) {
2009-03-19 19:35:47 +01:00
check ( " void f() \n "
" { \n "
2010-10-05 20:54:13 +02:00
" for (iterator it = foo.begin(); it != foo.end(); ++it) \n "
2009-03-19 19:35:47 +01:00
" { \n "
" foo.erase(it); \n "
2010-10-05 20:54:13 +02:00
" if (x) "
" break; \n "
" } \n "
" } \n " ) ;
2011-01-04 21:06:41 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Dangerous iterator usage after erase()-method. \n " , errout . str ( ) ) ;
2010-10-05 20:54:13 +02:00
check ( " void f() \n "
" { \n "
" for (iterator it = foo.begin(); it != foo.end(); ++it) \n "
" { \n "
" if (x) { \n "
" foo.erase(it); \n "
" break; \n "
" } \n "
2009-03-19 19:35:47 +01:00
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-03-18 22:40:38 +01:00
2011-10-13 20:53:06 +02:00
void eraseContinue ( ) {
2010-07-14 09:42:10 +02:00
check ( " void f(std::vector<int> &ints) \n "
" { \n "
" std::vector<int>::iterator it; \n "
" std::vector<int>::iterator jt = ints.begin(); \n "
" for (it = ints.begin(); it != ints.end(); it = jt) { \n "
" ++jt; \n "
" if (*it == 1) { \n "
" jt = ints.erase(it); \n "
" continue; \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-10-13 20:53:06 +02:00
void eraseReturn1 ( ) {
2009-03-19 19:35:47 +01:00
check ( " void f() \n "
" { \n "
2010-07-09 10:50:24 +02:00
" std::vector<int> foo; \n "
" std::vector<int>::iterator it; \n "
2009-03-19 19:35:47 +01:00
" for (it = foo.begin(); it != foo.end(); ++it) \n "
" { \n "
" foo.erase(it); \n "
" return; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-03-18 22:40:38 +01:00
2011-10-13 20:53:06 +02:00
void eraseReturn2 ( ) {
2010-07-09 10:50:24 +02:00
check ( " void f() \n "
" { \n "
" std::vector<int> foo; \n "
" std::vector<int>::iterator it; \n "
" for (it = foo.begin(); it != foo.end(); ++it) \n "
" { \n "
" if (*it == 1) { \n "
" foo.erase(it); \n "
" return; \n "
" } \n "
" else { \n "
" foo.erase(it); \n "
" return; \n "
2010-09-18 16:46:38 +02:00
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-10-13 20:53:06 +02:00
void eraseReturn3 ( ) {
2010-09-18 16:46:38 +02:00
check ( " void f() \n "
" { \n "
" std::vector<int> foo; \n "
" std::vector<int>::iterator it; \n "
" for (it = foo.begin(); it != foo.end(); ++it) \n "
" { \n "
" if (somecondition) { \n "
" if (*it == 1) \n "
" foo.erase(it); \n "
" else \n "
" *it = 0; \n "
" return; \n "
2010-07-09 10:50:24 +02:00
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-09-18 20:08:34 +02:00
check ( " void f() \n "
" { \n "
" std::vector<int> foo; \n "
" std::vector<int>::iterator it; \n "
" for (it = foo.begin(); it != foo.end(); ++it) \n "
" { \n "
2010-10-08 21:41:52 +02:00
" if (a) { \n "
" if (b) \n "
2010-09-18 20:08:34 +02:00
" foo.erase(it); \n "
" else \n "
" *it = 0; \n "
" } \n "
" } \n "
" } \n " ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:9]: (error) Dangerous iterator usage after erase()-method. \n " , " " , errout . str ( ) ) ;
2010-07-09 10:50:24 +02:00
}
2011-10-13 20:53:06 +02:00
void eraseGoto ( ) {
2009-03-19 19:35:47 +01:00
check ( " void f() \n "
" { \n "
2010-10-05 20:54:13 +02:00
" for (iterator it = foo.begin(); it != foo.end(); ++it) \n "
2009-03-19 19:35:47 +01:00
" { \n "
" foo.erase(it); \n "
" goto abc; \n "
" } \n "
" bar: \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-02-11 06:08:29 +01:00
2011-10-13 20:53:06 +02:00
void eraseAssign1 ( ) {
2009-03-19 19:35:47 +01:00
check ( " void f() \n "
" { \n "
2010-10-05 20:54:13 +02:00
" for (iterator it = foo.begin(); it != foo.end(); ++it) \n "
2009-03-19 19:35:47 +01:00
" { \n "
" foo.erase(it); \n "
" it = foo.begin(); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-02-11 06:08:29 +01:00
2011-10-13 20:53:06 +02:00
void eraseAssign2 ( ) {
2010-08-17 18:56:11 +02:00
check ( " void f(list<int> &ints) \n "
" { \n "
2010-10-10 10:52:41 +02:00
" for (list<int>::iterator it = ints.begin(); it != ints.end();) { \n "
2010-08-17 18:56:11 +02:00
" if (*it == 123) { \n "
" list<int>::iterator copy = it; \n "
" ++copy; \n "
" ints.erase(it); \n "
" it = copy; \n "
" } else { \n "
" it->second = 123; \n "
" ++it; \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-10-13 20:53:06 +02:00
void eraseErase ( ) {
2009-05-02 20:39:51 +02:00
check ( " void f(std::vector<ints> &ints) \n "
" { \n "
" std::vector<int>::iterator iter; \n "
" iter = ints.begin() + 2; \n "
" ints.erase(iter); \n "
" ints.erase(iter); \n "
" } \n " ) ;
2010-04-17 13:37:04 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Invalid iterator: iter \n " , errout . str ( ) ) ;
2009-05-02 20:39:51 +02:00
}
2011-10-13 20:53:06 +02:00
void eraseByValue ( ) {
2010-05-15 19:46:42 +02:00
check ( " void f() \n "
" { \n "
" std::set<int> foo; \n "
" for (std::set<int> it = foo.begin(); it != foo.end(); ++it) \n "
" { \n "
" foo.erase(*it); \n "
" } \n "
" } \n " ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:6]: (error) Iterator 'it' becomes invalid when deleted by value from 'foo' \n " , " " , errout . str ( ) ) ;
2010-12-24 10:33:48 +01:00
check ( " void f() \n "
" { \n "
" std::set<int> foo; \n "
" std::set<int> it = foo.begin(); \n "
" foo.erase(*it); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-05-15 19:46:42 +02:00
}
2009-02-18 20:57:43 +01:00
2011-10-13 20:53:06 +02:00
void pushback1 ( ) {
2009-11-10 19:07:04 +01:00
check ( " void f(const std::vector<int> &foo) \n "
2009-03-19 19:35:47 +01:00
" { \n "
" std::vector<int>::const_iterator it = foo.begin(); \n "
" foo.push_back(123); \n "
" *it; \n "
" } \n " ) ;
2009-10-15 21:29:56 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) After push_back, the iterator 'it' may be invalid \n " , errout . str ( ) ) ;
2009-03-19 19:35:47 +01:00
}
2009-03-18 22:40:38 +01:00
2011-10-13 20:53:06 +02:00
void pushback2 ( ) {
2009-04-25 16:32:37 +02:00
check ( " void f() \n "
" { \n "
" std::vector<int>::const_iterator it = foo.begin(); \n "
" foo.push_back(123); \n "
" { \n "
" int *it = &foo[0]; \n "
" *it = 456; \n "
" } \n "
" } \n " ) ;
2009-04-25 17:14:02 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-04-25 16:32:37 +02:00
}
2011-10-13 20:53:06 +02:00
void pushback3 ( ) {
2009-04-25 16:32:37 +02:00
check ( " void f() \n "
" { \n "
2009-07-18 12:06:51 +02:00
" std::vector<int> foo; \n "
" foo.push_back(10); \n "
" std::vector<int>::iterator it; \n "
2009-04-25 16:32:37 +02:00
" for (it = foo.begin(); it != foo.end(); ++it) \n "
" { \n "
" foo.push_back(123); \n "
" } \n "
" } \n " ) ;
2009-10-15 21:29:56 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) After push_back, the iterator 'it' may be invalid \n " , errout . str ( ) ) ;
2009-04-25 16:32:37 +02:00
}
2011-10-13 20:53:06 +02:00
void pushback4 ( ) {
2009-04-25 16:32:37 +02:00
check ( " void f() \n "
" { \n "
" std::vector<int> ints; \n "
" ints.push_back(1); \n "
" int *first = &ints[0]; \n "
" ints.push_back(2); \n "
" *first; \n "
" } \n " ) ;
2009-04-28 21:18:02 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Invalid pointer 'first' after push_back / push_front \n " , errout . str ( ) ) ;
2009-04-25 16:32:37 +02:00
}
2011-10-13 20:53:06 +02:00
void pushback5 ( ) {
2009-09-26 11:49:09 +02:00
check ( " void f() \n "
" { \n "
" std::vector<int>::const_iterator i; \n "
" \n "
" for (i=v.begin(); i!=v.end(); ++i) \n "
" { \n "
" } \n "
" \n "
" for (i=rhs.v.begin(); i!=rhs.v.end(); ++i) \n "
" { \n "
" v.push_back(*i); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-04-25 16:32:37 +02:00
2011-10-13 20:53:06 +02:00
void pushback6 ( ) {
2009-09-27 09:59:19 +02:00
// ticket #735
check ( " void f() \n "
" { \n "
" vector<int> v; \n "
" vector.push_back(1); \n "
" vector.push_back(2); \n "
" for (vector<int>::iterator it = v.begin(); it != v.end(); ++it) \n "
" { \n "
" if (*it == 1) \n "
" v.push_back(10); \n "
" } \n "
" } \n " ) ;
2009-10-15 21:29:56 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) After push_back, the iterator 'it' may be invalid \n " , errout . str ( ) ) ;
2009-09-27 09:59:19 +02:00
check ( " void f() \n "
" { \n "
" std::vector<int> v; \n "
" vector.push_back(1); \n "
" vector.push_back(2); \n "
" for (std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) \n "
" { \n "
" if (*it == 1) \n "
" v.push_back(10); \n "
" } \n "
" } \n " ) ;
2009-10-15 21:29:56 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) After push_back, the iterator 'it' may be invalid \n " , errout . str ( ) ) ;
2009-09-27 09:59:19 +02:00
}
2009-04-25 16:32:37 +02:00
2011-10-13 20:53:06 +02:00
void pushback7 ( ) {
2009-09-27 10:10:21 +02:00
check ( " void f() \n "
" { \n "
" std::vector<int> foo; \n "
" foo.push_back(10); \n "
" std::vector<int>::iterator it; \n "
" for (it = foo.begin(); it != foo.end(); it++) \n "
" { \n "
" foo.push_back(123); \n "
" } \n "
" } \n " ) ;
2009-10-15 21:29:56 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) After push_back, the iterator 'it' may be invalid \n " , errout . str ( ) ) ;
2009-09-27 10:10:21 +02:00
}
2011-10-13 20:53:06 +02:00
void pushback8 ( ) {
2009-10-13 20:55:33 +02:00
check ( " void f() \n "
" { \n "
" std::vector<int> ints; \n "
" std::vector<int>::const_iterator end = ints.end(); \n "
" ints.push_back(10); \n "
" std::vector<int>::iterator it; \n "
" unsigned int sum = 0; \n "
" for (it = ints.begin(); it != end; ++it) \n "
" { \n "
" sum += *it; \n "
" } \n "
" } \n " ) ;
2009-10-15 21:29:56 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) After push_back, the iterator 'end' may be invalid \n " , errout . str ( ) ) ;
2009-10-13 20:55:33 +02:00
}
2011-10-13 20:53:06 +02:00
void pushback9 ( ) {
2009-11-10 19:07:04 +01:00
check ( " struct A { \n "
" std::vector<int> ints; \n "
" }; \n "
" \n "
" void f() \n "
" { \n "
" std::vector<int> ints; \n "
" A a; \n "
" std::vector<int>::const_iterator i = ints.begin(); \n "
" std::vector<int>::const_iterator e = ints.end(); \n "
" while (i != e) \n "
" { \n "
" a.ints.push_back(*i); \n "
" ++i; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-10-13 20:53:06 +02:00
void pushback10 ( ) {
2010-06-15 19:53:09 +02:00
check ( " void f(std::vector<int> &foo) \n "
" { \n "
" std::vector<int>::const_iterator it = foo.begin(); \n "
" foo.reserve(100); \n "
" *it = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) After reserve, the iterator 'it' may be invalid \n " , errout . str ( ) ) ;
// in loop
check ( " void f() \n "
" { \n "
" std::vector<int> foo; \n "
" foo.push_back(10); \n "
" std::vector<int>::iterator it; \n "
" for (it = foo.begin(); it != foo.end(); ++it) \n "
" { \n "
" foo.reserve(123); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:8]: (error) After reserve, the iterator 'it' may be invalid \n " , errout . str ( ) ) ;
}
2009-11-10 19:07:04 +01:00
2011-10-13 20:53:06 +02:00
void pushback11 ( ) {
2011-05-22 17:17:24 +02:00
// #2798
check ( " void f() { \n "
" std::vector<int> ints; \n "
" std::vector<int>::iterator it = ints.begin(); \n "
" if (it == ints.begin()) { \n "
" ints.push_back(0); \n "
" } else { \n "
" ints.insert(it,0); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-05-02 20:49:58 +02:00
2011-10-13 20:53:06 +02:00
void insert1 ( ) {
2009-05-02 20:49:58 +02:00
check ( " void f(std::vector<int> &ints) \n "
" { \n "
" std::vector<int>::iterator iter = ints.begin() + 5; \n "
" ints.insert(ints.begin(), 1); \n "
" ++iter; \n "
" } \n " ) ;
2009-10-15 21:29:56 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) After insert, the iterator 'iter' may be invalid \n " , errout . str ( ) ) ;
2009-10-31 15:27:33 +01:00
check ( " void f() \n "
" { \n "
2009-11-02 21:53:01 +01:00
" std::vector<int> ints; \n "
2009-10-31 15:27:33 +01:00
" std::vector<int>::iterator iter = ints.begin(); \n "
" ints.insert(iter, 1); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-11-02 21:53:01 +01:00
check ( " void f() \n "
" { \n "
" std::vector<int> ints; \n "
" std::vector<int>::iterator iter = ints.begin(); \n "
" ints.insert(iter, 1); \n "
" ints.insert(iter, 2); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) After insert, the iterator 'iter' may be invalid \n " , errout . str ( ) ) ;
2009-05-02 20:49:58 +02:00
}
2011-10-13 20:53:06 +02:00
void insert2 ( ) {
2011-01-20 19:26:52 +01:00
// Ticket: #2169
check ( " void f(std::vector<int> &vec) { \n "
" for(std::vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++iter) \n "
" { \n "
" vec.insert(iter, 0); \n "
" break; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-02 20:49:58 +02:00
2011-01-20 19:26:52 +01:00
check ( " void f(std::vector<int> &vec) { \n "
" for(std::vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++iter) \n "
" { \n "
" if (*it == 0) { \n "
" vec.insert(iter, 0); \n "
" return; \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-05-02 20:49:58 +02:00
2011-10-13 20:53:06 +02:00
void invalidcode ( ) {
2009-05-11 21:52:04 +02:00
errout . str ( " " ) ;
2009-05-07 22:17:29 +02:00
const std : : string src = " void f() \n "
" { \n "
" for ( \n "
" } \n " ;
2010-12-01 18:00:55 +01:00
Settings settings ;
Tokenizer tokenizer ( & settings , this ) ;
2009-05-07 22:17:29 +02:00
std : : istringstream istr ( src ) ;
ASSERT_EQUALS ( false , tokenizer . tokenize ( istr , " test.cpp " ) ) ;
2010-01-23 22:18:11 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Invalid number of character (() when these macros are defined: ''. \n " , errout . str ( ) ) ;
2009-03-19 19:35:47 +01:00
}
2009-04-13 17:48:13 +02:00
2011-10-13 20:53:06 +02:00
void stlBoundries1 ( ) {
2009-08-07 16:23:28 +02:00
const int STL_CONTAINER_LIST = 9 ;
2011-10-13 20:53:06 +02:00
const std : : string stlCont [ STL_CONTAINER_LIST ] = {
2010-04-15 20:08:51 +02:00
" deque " , " list " , " set " , " multiset " , " map " ,
" multimap " , " hash_map " , " hash_multimap " , " hash_set "
} ;
2009-05-17 18:58:32 +02:00
2011-10-13 20:53:06 +02:00
for ( int i = 0 ; i < STL_CONTAINER_LIST ; + + i ) {
2009-11-02 21:17:33 +01:00
check ( " void f() \n "
" { \n "
" std:: " + stlCont [ i ] + " <int>::iterator it; \n "
" for (it = ab.begin(); it < ab.end(); ++it) \n "
" ; \n "
" } \n " ) ;
2009-07-25 00:36:15 +02:00
2010-12-26 21:02:20 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Dangerous container iterator compare using < operator for " + stlCont [ i ] + " \n " , errout . str ( ) ) ;
2009-07-25 00:36:15 +02:00
}
2009-04-13 17:48:13 +02:00
}
2011-10-13 20:53:06 +02:00
void stlBoundries2 ( ) {
2009-11-02 21:17:33 +01:00
check ( " void f() \n "
" { \n "
" std::vector<std::string> files; \n "
" std::vector<std::string>::const_iterator it; \n "
" for (it = files.begin(); it < files.end(); it++) { } \n "
" for (it = files.begin(); it < files.end(); it++) { }; \n "
" } \n " ) ;
2009-07-28 22:55:23 +02:00
2009-08-07 16:23:28 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-28 22:55:23 +02:00
}
2009-07-25 00:36:15 +02:00
2011-10-13 20:53:06 +02:00
void stlBoundries3 ( ) {
2009-11-02 21:17:33 +01:00
check ( " void f() \n "
" { \n "
" set<int> files; \n "
" set<int>::const_iterator current; \n "
" for (current = files.begin(); current != files.end(); ++current) \n "
" { \n "
" assert(*current < 100) \n "
" } \n "
" } \n " ) ;
2009-08-08 21:07:33 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-11-02 20:24:38 +01:00
2010-02-27 21:26:11 +01:00
2011-10-13 20:53:06 +02:00
void if_find ( ) {
2010-02-27 21:35:33 +01:00
// ---------------------------
// set::find
// ---------------------------
// error
2010-02-27 21:26:11 +01:00
check ( " void f(std::set<int> s) \n "
" { \n "
" if (s.find(12)) { } \n "
" } \n " ) ;
2010-10-17 14:41:00 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Suspicious condition. The result of find is an iterator, but it is not properly checked. \n " , errout . str ( ) ) ;
2010-02-27 21:35:33 +01:00
// ok
check ( " void f(std::set<int> s) \n "
" { \n "
" if (s.find(123) != s.end()) { } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-02-28 07:04:58 +01:00
// ---------------------------
// std::find
// ---------------------------
// error
check ( " void f() \n "
" { \n "
" if (std::find(a,b,c)) { } \n "
" } \n " ) ;
2010-10-17 14:41:00 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Suspicious condition. The result of find is an iterator, but it is not properly checked. \n " , errout . str ( ) ) ;
2010-02-28 07:04:58 +01:00
// ok
check ( " void f() \n "
" { \n "
" if (std::find(a,b,c) != c) { } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-02-27 21:26:11 +01:00
}
2011-10-13 20:53:06 +02:00
void if_str_find ( ) {
2010-05-01 21:56:39 +02:00
// error
check ( " void f(const std::string &s) \n "
" { \n "
" if (s.find( \" abc \" )) { } \n "
" } \n " ) ;
2011-01-04 22:04:01 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Suspicious checking of string::find() return value. \n " , errout . str ( ) ) ;
2010-05-01 21:56:39 +02:00
}
2010-02-27 21:26:11 +01:00
2009-11-02 20:24:38 +01:00
2011-10-13 20:53:06 +02:00
void size1 ( ) {
2011-03-08 01:49:43 +01:00
check ( " struct Fred { \n "
" void foo(); \n "
" std::list<int> x; \n "
" }; \n "
" void Fred::foo() \n "
" { \n "
" if (x.size() == 0) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
check ( " std::list<int> x; \n "
" void f() \n "
" { \n "
" if (x.size() == 0) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2009-12-19 15:24:59 +01:00
check ( " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (x.size() == 0) {} \n "
" } \n " ) ;
2010-12-04 09:15:48 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2009-12-19 15:24:59 +01:00
2011-03-08 01:49:43 +01:00
check ( " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (0 == x.size()) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2009-12-19 15:24:59 +01:00
check ( " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (x.size() != 0) {} \n "
" } \n " ) ;
2010-12-04 09:15:48 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2009-12-19 15:24:59 +01:00
2011-03-08 01:49:43 +01:00
check ( " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (0 != x.size()) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2009-12-19 15:24:59 +01:00
check ( " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (x.size() > 0) {} \n "
" } \n " ) ;
2010-12-04 09:15:48 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2009-12-19 15:24:59 +01:00
2011-03-08 01:49:43 +01:00
check ( " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (0 < x.size()) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2009-12-19 15:24:59 +01:00
check ( " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (x.size()) {} \n "
" } \n " ) ;
2010-12-04 09:15:48 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2009-12-19 15:24:59 +01:00
2011-03-08 01:49:43 +01:00
check ( " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (!x.size()) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2009-12-19 15:24:59 +01:00
check ( " void f() \n "
" { \n "
" std::list<int> x; \n "
" fun(x.size()); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-08 01:49:43 +01:00
check ( " void f() \n "
" { \n "
" std::list<int> x; \n "
" fun(!x.size()); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-12-19 15:24:59 +01:00
}
2011-10-13 20:53:06 +02:00
void redundantCondition1 ( ) {
2011-10-24 23:25:23 +02:00
check ( " void f(string haystack) \n "
2010-09-16 18:49:23 +02:00
" { \n "
" if (haystack.find(needle) != haystack.end()) \n "
" haystack.remove(needle); "
" } \n " ) ;
2010-11-29 19:24:08 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Redundant checking of STL container element. \n " , errout . str ( ) ) ;
2010-09-16 18:49:23 +02:00
}
2011-10-13 20:53:06 +02:00
void size2 ( ) {
2011-03-29 01:31:23 +02:00
check ( " struct Fred { \n "
" std::list<int> x; \n "
" }; \n "
" struct Wilma { \n "
" Fred f; \n "
" void foo(); \n "
" }; \n "
" void Wilma::foo() \n "
" { \n "
" if (f.x.size() == 0) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:10]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
}
2011-10-13 20:53:06 +02:00
void redundantCondition2 ( ) {
2011-10-24 23:25:23 +02:00
check ( " void f(string haystack) \n "
2010-09-16 18:49:23 +02:00
" { \n "
" if (haystack.find(needle) != haystack.end()) \n "
" { \n "
" haystack.remove(needle); \n "
" } \n "
" } \n " ) ;
2010-11-29 19:24:08 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Redundant checking of STL container element. \n " , errout . str ( ) ) ;
2010-09-16 18:49:23 +02:00
}
2011-10-13 20:53:06 +02:00
void missingInnerComparison1 ( ) {
2010-10-10 10:52:41 +02:00
check ( " void f(std::set<int> &ints) { \n "
" for (std::set<int>::iterator it = ints.begin(); it != ints.end(); ++it) { \n "
" if (a) { \n "
" it++; \n "
" } \n "
" } \n "
" } \n " ) ;
2010-11-27 09:57:26 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) Missing bounds check for extra iterator increment in loop. \n " , errout . str ( ) ) ;
2011-01-14 19:50:07 +01:00
check ( " void f(std::map<int,int> &ints) { \n "
" for (std::map<int,int>::iterator it = ints.begin(); it != ints.end(); ++it) { \n "
" ++it->second; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-10 10:52:41 +02:00
}
2010-10-10 11:22:44 +02:00
2011-10-13 20:53:06 +02:00
void missingInnerComparison2 ( ) {
2010-10-10 11:22:44 +02:00
check ( " void f(std::set<int> &ints) { \n "
" for (std::set<int>::iterator it = ints.begin(); it != ints.end(); ++it) { \n "
" if (a) { \n "
" it++; \n "
" if (it == ints.end()) \n "
" return; \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-10-10 14:28:14 +02:00
2011-10-13 20:53:06 +02:00
void missingInnerComparison3 ( ) {
2010-10-10 14:28:14 +02:00
check ( " void f(std::set<int> &ints) { \n "
" for (std::set<int>::iterator it = ints.begin(); it != ints.end(); ++it) { \n "
" for (std::set<int>::iterator it = ints2.begin(); it != ints2.end(); ++it) \n "
" { } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-10-17 19:18:46 +02:00
2011-10-13 20:53:06 +02:00
void missingInnerComparison4 ( ) {
2010-10-18 20:05:54 +02:00
check ( " function f1(std::list<int> &l1) { \n "
" for(std::list<int>::iterator i = l1.begin(); i != l1.end(); i++) { \n "
" if (*i == 44) { \n "
" l1.insert(++i, 55); \n "
" break; \n "
" } \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-13 20:57:44 +01:00
check ( " function f1(std::list<int> &l1) { \n "
" for(std::list<int>::iterator i = l1.begin(); i != l1.end(); i++) { \n "
" if (*i == 44) { \n "
" l1.insert(++i, 55); \n "
" return; \n "
" } \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-18 20:05:54 +02:00
}
2011-10-13 20:53:06 +02:00
void missingInnerComparison5 ( ) {
2010-10-30 11:22:30 +02:00
check ( " void f() { \n "
" for(it = map1.begin(); it != map1.end(); it++) { \n "
" str[i++] = (*it).first; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-10-13 20:53:06 +02:00
void missingInnerComparison6 ( ) {
2011-03-12 20:29:54 +01:00
check ( " void f(std::string &s) { \n "
" for(string::iterator it = s.begin(); it != s.end(); it++) { \n "
" it = s.insert(++it, 0); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-10-13 20:53:06 +02:00
void cstr ( ) {
2010-10-17 19:18:46 +02:00
check ( " void f() { \n "
" std::string errmsg; \n "
" throw errmsg.c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous usage of c_str() \n " , errout . str ( ) ) ;
2011-10-26 21:07:48 +02:00
check ( " const char *get_msg() { \n "
" std::string errmsg; \n "
" return errmsg.c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous usage of c_str() \n " , errout . str ( ) ) ;
check ( " const char *get_msg() { \n "
" std::ostringstream errmsg; \n "
" return errmsg.str().c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous usage of c_str() \n " , errout . str ( ) ) ;
2011-10-26 21:45:27 +02:00
check ( " const char *get_msg() { \n "
" std::string errmsg; \n "
" return std::string( \" ERROR: \" + errmsg).c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous usage of c_str() \n " , errout . str ( ) ) ;
2011-10-26 22:14:47 +02:00
check ( " const char *get_msg() { \n "
" std::string errmsg; \n "
" return ( \" ERROR: \" + errmsg).c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous usage of c_str() \n " , errout . str ( ) ) ;
check ( " const char *get_msg() { \n "
" std::string errmsg; \n "
" return ( \" ERROR: \" + std::string( \" crash me \" )).c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous usage of c_str() \n " , errout . str ( ) ) ;
2010-10-19 20:21:58 +02:00
check ( " void f() { \n "
" std::ostringstream errmsg; \n "
" const char *c = errmsg.str().c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous usage of c_str() \n " , errout . str ( ) ) ;
2010-10-17 19:18:46 +02:00
check ( " std::string f(); \n "
" \n "
" void foo() { \n "
" const char *c = f().c_str(); \n "
" } " ) ;
2010-10-19 20:21:58 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Dangerous usage of c_str() \n " , errout . str ( ) ) ;
2010-10-17 19:18:46 +02:00
}
2011-06-16 20:26:00 +02:00
2011-10-13 20:53:06 +02:00
void autoPointer ( ) {
2011-06-16 20:26:00 +02:00
2011-06-20 23:06:18 +02:00
// ticket 2846
check ( " void f() \n "
" { \n "
" std::vector<int*> vec; \n "
" vec.push_back(new int(3)); \n "
" std::auto_ptr<int> ret(vec[0]); \n "
" }; \n " ) ;
2011-06-20 23:02:05 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-06-17 21:09:27 +02:00
// ticket 2839
check ( " template <class MUTEX_TYPE> \n "
" class Guarded \n "
" { \n "
" typedef std::auto_ptr<MUTEX_TYPE > WriteGuardType; \n "
" virtual WriteGuardType getWriteGuard(bool enabledGuard = true); \n "
" }; \n "
" class SafeSharedMemory : public Guarded<int> \n "
" { \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-06-16 20:26:00 +02:00
check ( " void foo() \n "
" { \n "
" auto_ptr< ns1:::MyClass > y; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" auto_ptr<T> p2; \n "
" p2 = new T; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::vector< std::auto_ptr< ns1::MyClass> > v; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) You can randomly lose access to pointers if you store 'auto_ptr' pointers in a container because the copy-semantics of 'auto_ptr' are not compatible with containers. \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::vector< auto_ptr< MyClass> > v; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) You can randomly lose access to pointers if you store 'auto_ptr' pointers in a container because the copy-semantics of 'auto_ptr' are not compatible with containers. \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" int *i = new int; \n "
" auto_ptr<int> x(i); \n "
" auto_ptr<int> y; \n "
" y = x; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (style) Copy 'auto_ptr' pointer to another do not create two equal objects since one has lost its ownership of the pointer. \n " , errout . str ( ) ) ;
2011-07-20 08:04:01 +02:00
check ( " std::auto_ptr<A> function(); \n "
" int quit; "
" void f() { quit = true; } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-06-16 20:26:00 +02:00
// ticket #748
check ( " void f() \n "
" { \n "
" T* var = new T[10]; \n "
" auto_ptr<T> p2( var ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'. \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" auto_ptr<T> p2( new T[] ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'. \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" auto_ptr<T> p2; \n "
" p2.reset( new T[] ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'. \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" auto_ptr<T> p2( new T[][] ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'. \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" auto_ptr<T> p2; \n "
" p2 = new T[10]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'. \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" auto_ptr<T> p2; \n "
" p2.reset( new T[10] ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'. \n " , errout . str ( ) ) ;
2011-08-06 00:18:30 +02:00
// ticket #2887 (infinite loop)
2011-08-05 01:50:18 +02:00
check ( " A::A(std::auto_ptr<X> e){} \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-08-06 00:18:30 +02:00
// ticket #2967 (segmentation fault)
check ( " auto_ptr<x> \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-06-16 20:26:00 +02:00
}
2011-10-24 23:25:23 +02:00
void uselessCalls ( ) {
check ( " void f() \n "
" { \n "
" string s1, s2; \n "
" s1.swap(s2); \n "
" s2.swap(s2); \n "
" \n "
" }; \n " ) ;
2011-10-31 21:32:30 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (performance) It is inefficient to swap a object with itself by calling 's2.swap(s2)' \n " , errout . str ( ) ) ;
2011-06-16 20:26:00 +02:00
2011-10-24 23:25:23 +02:00
check ( " void f() \n "
" { \n "
" string s1, s2; \n "
" s1.compare(s2); \n "
" s2.compare(s2); \n "
" s1.compare(s2.c_str()); \n "
" s1.compare(0, s1.size(), s1); \n "
" \n "
" }; \n " ) ;
2011-10-31 21:32:30 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (warning) It is inefficient to call 's2.compare(s2)' as it always returns 0. \n " , errout . str ( ) ) ;
2011-10-24 23:25:23 +02:00
check ( " void f() \n "
" { \n "
" int x=1; \n "
" string s1, s2; \n "
" s1 = s1.substr(); \n "
" s2 = s1.substr(x); \n "
" s1 = s2.substr(0, x); \n "
" s1 = s2.substr(0,std::string::npos); \n "
" \n "
" }; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (performance) Function \' substr \' useless call. Function create copy "
" of the \' s1 \' object. \n "
" [test.cpp:8]: (performance) Function \' substr \' useless call. Function create copy "
" of the \' s2 \' object. \n " , errout . str ( ) ) ;
2011-10-29 09:24:05 +02:00
check ( " #include <string> \n "
" int main() \n "
" { \n "
" std::string str = \" a1b1 \" ; \n "
" return str.find(str[1], 2); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-10-24 23:25:23 +02:00
}
2009-02-10 20:40:21 +01:00
} ;
REGISTER_TEST ( TestStl )