2009-02-10 20:40:21 +01:00
/*
* Cppcheck - A tool for static C / C + + code analysis
2010-04-13 21:23:17 +02:00
* Copyright ( C ) 2007 - 2010 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 ;
class TestStl : public TestFixture
{
public :
TestStl ( ) : TestFixture ( " TestStl " )
{ }
private :
void run ( )
{
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 ) ;
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 ) ;
2009-02-11 06:08:29 +01:00
TEST_CASE ( erase ) ;
2009-12-18 20:55:51 +01:00
TEST_CASE ( erase2 ) ;
2010-01-23 22:03:38 +01:00
TEST_CASE ( erase3 ) ;
2009-02-11 06:08:29 +01:00
TEST_CASE ( eraseBreak ) ;
2009-02-11 17:20:32 +01:00
TEST_CASE ( eraseReturn ) ;
TEST_CASE ( eraseGoto ) ;
2009-02-11 06:08:29 +01:00
TEST_CASE ( eraseAssign ) ;
2009-05-02 20:39:51 +02:00
TEST_CASE ( eraseErase ) ;
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 ) ;
2009-04-25 16:32:37 +02:00
2009-05-02 20:49:58 +02:00
TEST_CASE ( insert1 ) ;
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 ) ;
2009-02-10 20:40:21 +01:00
}
2009-11-02 21:17:33 +01:00
void check ( const std : : string & code )
2009-03-19 19:35:47 +01:00
{
// Tokenize..
Tokenizer tokenizer ;
2009-11-02 21:17:33 +01:00
std : : istringstream istr ( code . c_str ( ) ) ;
2009-03-19 19:35:47 +01:00
tokenizer . tokenize ( istr , " test.cpp " ) ;
2010-02-09 18:11:06 +01:00
tokenizer . simplifyTokenList ( ) ;
2009-03-18 22:40:38 +01:00
2009-03-19 19:35:47 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
2009-03-18 22:40:38 +01:00
2009-03-19 19:35:47 +01:00
// Check..
2010-04-17 09:23:54 +02:00
Settings settings ;
settings . inconclusive = true ;
2009-12-28 18:06:26 +01:00
settings . _checkCodingStyle = true ;
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
}
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 ( ) ) ;
2009-03-19 19:35:47 +01:00
}
void iterator2 ( )
{
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
2009-04-29 17:32:38 +02:00
void iterator3 ( )
{
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
}
2009-09-01 18:49:17 +02:00
void iterator4 ( )
{
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
}
void iterator5 ( )
{
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
2010-04-10 10:22:34 +02:00
void iterator6 ( )
{
// 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 ( ) ) ;
}
2010-04-16 16:56:55 +02:00
void iterator7 ( )
{
// 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 ( ) ) ;
// 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 " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:14] (error) After insert, the iterator 'aI' may be invalid " , errout . str ( ) ) ;
}
2009-05-03 07:37:39 +02:00
// Dereferencing invalid pointer
void dereference ( )
{
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
}
2009-07-30 19:49:38 +02:00
void dereference_member ( )
{
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 ( ) ) ;
2009-07-30 19:49:38 +02:00
}
2009-05-03 07:37:39 +02:00
2009-03-19 19:35:47 +01:00
void STLSize ( )
{
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
}
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
2009-03-19 19:35:47 +01:00
void erase ( )
{
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 " ) ;
2009-12-21 20:49:16 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Dangerous iterator usage. After erase the iterator is invalid so dereferencing it or comparing it with another iterator is invalid. \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 " ) ;
2009-12-21 20:49:16 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous iterator usage. After erase the iterator is invalid so dereferencing it or comparing it with another iterator is invalid. \n "
" [test.cpp:7]: (error) Dangerous iterator usage. After erase the iterator is invalid so dereferencing it or comparing it with another iterator is invalid. \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
2009-03-19 19:35:47 +01:00
}
2009-02-11 17:20:32 +01:00
2009-12-18 20:55:51 +01:00
void erase2 ( )
{
check ( " static void f() \n "
" { \n "
" for (it = foo.begin(); it != foo.end(); it = next) \n "
" { \n "
" next = it; \n "
" next++; \n "
" foo.erase(it); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-01-23 22:03:38 +01:00
void erase3 ( )
{
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 ( ) ) ;
}
2009-03-19 19:35:47 +01:00
void eraseBreak ( )
{
check ( " void f() \n "
" { \n "
" for (it = foo.begin(); it != foo.end(); ++it) \n "
" { \n "
" foo.erase(it); \n "
" break; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-03-18 22:40:38 +01:00
2009-03-19 19:35:47 +01:00
void eraseReturn ( )
{
check ( " void f() \n "
" { \n "
" 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
2009-03-19 19:35:47 +01:00
void eraseGoto ( )
{
check ( " void f() \n "
" { \n "
" for (it = foo.begin(); it != foo.end(); ++it) \n "
" { \n "
" foo.erase(it); \n "
" goto abc; \n "
" } \n "
" bar: \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-02-11 06:08:29 +01:00
2009-03-19 19:35:47 +01:00
void eraseAssign ( )
{
check ( " void f() \n "
" { \n "
" for (it = foo.begin(); it != foo.end(); ++it) \n "
" { \n "
" foo.erase(it); \n "
" it = foo.begin(); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-02-11 06:08:29 +01:00
2009-05-02 20:39:51 +02:00
void eraseErase ( )
{
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
}
2009-02-18 20:57:43 +01:00
2009-03-19 19:35:47 +01: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
2009-04-25 16:32:37 +02:00
void pushback2 ( )
{
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
}
void pushback3 ( )
{
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
}
void pushback4 ( )
{
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
}
2009-09-26 11:49:09 +02:00
void pushback5 ( )
{
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
2009-09-27 09:59:19 +02:00
void pushback6 ( )
{
// 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
2009-09-27 10:10:21 +02:00
void pushback7 ( )
{
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
}
2009-10-13 20:55:33 +02:00
void pushback8 ( )
{
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
}
2009-11-10 19:07:04 +01:00
void pushback9 ( )
{
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 ( ) ) ;
}
2009-05-02 20:49:58 +02:00
void insert1 ( )
{
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
}
2009-03-19 19:35:47 +01: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 " ;
2009-07-13 19:11:31 +02:00
Tokenizer tokenizer ( 0 , 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
void stlBoundries1 ( )
{
2009-08-07 16:23:28 +02:00
const int STL_CONTAINER_LIST = 9 ;
2009-07-25 00:36:15 +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
2010-04-02 07:30:58 +02:00
for ( int i = 0 ; i < STL_CONTAINER_LIST ; + + i )
2009-07-25 00:36:15 +02:00
{
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
ASSERT_EQUALS ( " [test.cpp:4]: (error) " + stlCont [ i ] + " range check should use != and not < since the order of the pointers isn't guaranteed \n " , errout . str ( ) ) ;
}
2009-04-13 17:48:13 +02:00
}
2009-07-28 22:55:23 +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
2009-08-08 21:07:33 +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
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 " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) 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 " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Suspicious condition. The result of find is an iterator, but it is not properly checked. \n " , errout . str ( ) ) ;
// 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
}
2010-05-01 21:56:39 +02:00
void if_str_find ( )
{
// error
check ( " void f(const std::string &s) \n "
" { \n "
" if (s.find( \" abc \" )) { } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Suspicious condition. string::find will return 0 if the string is found at position 0. If this is what you want to check then string::compare is a faster alternative because it doesn't scan through the string. \n " , errout . str ( ) ) ;
}
2010-02-27 21:26:11 +01:00
2009-11-02 20:24:38 +01:00
2009-12-19 15:24:59 +01:00
void size1 ( )
{
check ( " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (x.size() == 0) {} \n "
" } \n " ) ;
2010-01-26 19:37:22 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (possible style) Use x.empty() instead of x.size() to guarantee fast code. \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-01-26 19:37:22 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (possible style) Use x.empty() instead of x.size() to guarantee fast code. \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-01-26 19:37:22 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (possible style) Use x.empty() instead of x.size() to guarantee fast code. \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-01-26 19:37:22 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (possible style) Use x.empty() instead of x.size() to guarantee fast code. \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 ( ) ) ;
}
2009-02-10 20:40:21 +01:00
} ;
REGISTER_TEST ( TestStl )