2009-02-10 20:40:21 +01:00
/*
* Cppcheck - A tool for static C / C + + code analysis
2016-01-01 14:34:45 +01:00
* Copyright ( C ) 2007 - 2016 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 "checkstl.h"
2017-05-27 04:33:47 +02:00
# include "settings.h"
# include "standards.h"
2009-02-10 20:40:21 +01:00
# include "testsuite.h"
2017-05-27 04:33:47 +02:00
# include "tokenize.h"
# include <cstddef>
# include <string>
2009-02-10 20:40:21 +01:00
2011-10-13 20:53:06 +02:00
class TestStl : public TestFixture {
2009-02-10 20:40:21 +01:00
public :
2014-11-20 14:20:09 +01:00
TestStl ( ) : TestFixture ( " TestStl " ) {
2013-08-07 16:27:37 +02:00
}
2009-02-10 20:40:21 +01:00
private :
2015-01-03 22:17:35 +01:00
Settings settings ;
2014-11-20 14:20:09 +01:00
void run ( ) {
2015-10-07 18:33:57 +02:00
settings . addEnabled ( " warning " ) ;
settings . addEnabled ( " style " ) ;
settings . addEnabled ( " performance " ) ;
2015-01-03 22:17:35 +01:00
LOAD_LIB_2 ( settings . library , " std.cfg " ) ;
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 ) ;
2011-12-21 06:16:06 +01:00
TEST_CASE ( iterator11 ) ;
2011-12-26 10:30:39 +01:00
TEST_CASE ( iterator12 ) ;
2012-08-20 13:57:24 +02:00
TEST_CASE ( iterator13 ) ;
2018-01-06 22:25:13 +01:00
TEST_CASE ( iterator14 ) ; // #8191
2009-04-29 17:32:38 +02:00
2009-05-03 07:37:39 +02:00
TEST_CASE ( dereference ) ;
2012-04-09 07:19:39 +02:00
TEST_CASE ( dereference_break ) ; // #3644 - handle "break"
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 ) ;
2017-08-22 11:04:02 +02:00
TEST_CASE ( negativeIndex ) ;
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 ) ;
2012-09-06 16:10:51 +02:00
TEST_CASE ( eraseAssign3 ) ;
2013-10-26 17:48:20 +02:00
TEST_CASE ( eraseAssign4 ) ;
2012-09-06 16:30:10 +02:00
TEST_CASE ( eraseAssignByFunctionCall ) ;
2009-05-02 20:39:51 +02:00
TEST_CASE ( eraseErase ) ;
2010-05-15 19:46:42 +02:00
TEST_CASE ( eraseByValue ) ;
2015-07-23 20:53:50 +02:00
TEST_CASE ( eraseIf ) ;
2014-04-12 19:44:37 +02:00
TEST_CASE ( eraseOnVector ) ;
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 ) ;
2012-11-10 16:59:31 +01:00
TEST_CASE ( pushback12 ) ;
2015-11-15 14:55:10 +01:00
TEST_CASE ( pushback13 ) ;
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
2013-02-10 07:43:09 +01:00
TEST_CASE ( stlBoundaries1 ) ;
TEST_CASE ( stlBoundaries2 ) ;
TEST_CASE ( stlBoundaries3 ) ;
TEST_CASE ( stlBoundaries4 ) ; // #4364
2013-03-14 17:00:22 +01:00
TEST_CASE ( stlBoundaries5 ) ; // #4352
2015-11-08 09:42:28 +01:00
TEST_CASE ( stlBoundaries6 ) ; // #7106
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 ) ;
2012-12-20 06:53:04 +01:00
TEST_CASE ( size3 ) ;
2013-02-14 16:59:58 +01:00
TEST_CASE ( size4 ) ; // #2652 - don't warn about vector/deque
2010-09-16 18:49:23 +02:00
// Redundant conditions..
// if (ints.find(123) != ints.end()) ints.remove(123);
TEST_CASE ( redundantCondition1 ) ;
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 ) ;
2013-03-29 19:29:23 +01:00
TEST_CASE ( stabilityOfChecks ) ; // #4684 cppcheck crash in template function call
2011-10-24 23:25:23 +02:00
2013-04-05 06:14:59 +02:00
TEST_CASE ( dereferenceInvalidIterator ) ;
2018-01-10 09:37:21 +01:00
TEST_CASE ( dereferenceInvalidIterator2 ) ; // #6572
2013-09-28 11:50:45 +02:00
TEST_CASE ( dereference_auto ) ;
2013-04-05 06:14:59 +02:00
2014-03-03 18:27:45 +01:00
TEST_CASE ( readingEmptyStlContainer ) ;
2009-02-10 20:40:21 +01:00
}
2015-05-17 20:02:41 +02:00
void check ( const char code [ ] , const bool inconclusive = false , const Standards : : cppstd_t cppstandard = Standards : : CPP11 ) {
2009-03-19 19:35:47 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
2009-03-18 22:40:38 +01:00
2011-11-09 21:08:53 +01:00
settings . inconclusive = inconclusive ;
2015-05-17 20:02:41 +02:00
settings . standards . cpp = cppstandard ;
2010-12-01 18:00:55 +01:00
// Tokenize..
Tokenizer tokenizer ( & settings , this ) ;
2011-12-08 21:28:34 +01:00
std : : istringstream istr ( code ) ;
2010-12-01 18:00:55 +01:00
tokenizer . tokenize ( istr , " test.cpp " ) ;
2013-12-30 17:45:28 +01:00
tokenizer . simplifyTokenList2 ( ) ;
2010-12-01 18:00:55 +01:00
// Check..
2015-10-07 18:33:57 +02:00
CheckStl checkStl ( & tokenizer , & settings , this ) ;
2009-12-28 18:06:26 +01:00
checkStl . runSimplifiedChecks ( & tokenizer , & settings , this ) ;
2009-03-19 19:35:47 +01:00
}
2014-11-20 14:20:09 +01:00
void check ( const std : : string & code , const bool inconclusive = false ) {
2012-07-16 13:17:14 +02:00
check ( code . c_str ( ) , inconclusive ) ;
}
2009-03-19 19:35:47 +01:00
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Same iterator is used with different containers 'l1' and 'l2'. \n " , errout . str ( ) ) ;
2011-10-14 19:54:20 +02:00
2017-07-26 23:13:01 +02:00
check ( " void f() \n "
" { \n "
" list<int> l1; \n "
" list<int> l2; \n "
" for (list<int>::iterator it = l1.begin(); l2.end() != it; ++it) \n "
" { } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Same iterator is used with different containers 'l1' and 'l2'. \n " , errout . str ( ) ) ;
2018-01-06 16:08:12 +01:00
check ( " struct C { std::list<int> l1; void func(); }; \n "
" void C::func() { \n "
" std::list<int>::iterator it; \n "
" for (it = l1.begin(); it != l1.end(); ++it) { } \n "
" C c; \n "
" for (it = c.l1.begin(); it != c.l1.end(); ++it) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Same iterator is used with different containers 'l1' and 'l2'. \n " , errout . str ( ) ) ;
2009-03-19 19:35:47 +01:00
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Same iterator is used with different containers 'l1' and 'l2'. \n " , errout . str ( ) ) ;
2009-03-19 19:35:47 +01:00
}
2009-02-10 20:56:00 +01:00
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Same iterator is used with different containers 'l1' and 'l2'. \n " , errout . str ( ) ) ;
2016-08-04 09:35:16 +02:00
check ( " void foo() { \n " // #5803
" list<int> l1; \n "
" list<int> l2; \n "
" list<int>::iterator it = l1.begin(); \n "
" l2.insert(it, l1.end()); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-08-06 18:07:41 +02:00
2016-08-14 10:49:48 +02:00
check ( " void foo() { \n " // #7658
" list<int> l1; \n "
" list<int> l2; \n "
" list<int>::iterator it = l1.begin(); \n "
" list<int>::iterator end = l1.end(); \n "
" l2.insert(it, end); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-08-06 18:07:41 +02:00
// only warn for insert when there are preciself 2 arguments.
check ( " void foo() { \n "
" list<int> l1; \n "
" list<int> l2; \n "
" list<int>::iterator it = l1.begin(); \n "
" l2.insert(it); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() { \n "
" list<int> l1; \n "
" list<int> l2; \n "
" list<int>::iterator it = l1.begin(); \n "
" l2.insert(it,0,1); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-04-29 17:32:38 +02:00
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-09-01 18:49:17 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-10-18 18:42:01 +02:00
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers are used together. \n " , errout . str ( ) ) ;
2009-09-01 18:49:17 +02:00
}
2009-02-10 20:56:00 +01:00
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-04-10 10:22:34 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-12-21 06:16:06 +01:00
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 = ints2.end(); \n "
" ints2.insert(it1, it2); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:6]: (error) Iterators of different containers are used together. \n " , " " , errout . str ( ) ) ;
2010-04-10 10:22:34 +02:00
}
2014-11-20 14:20:09 +01: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 "
2012-04-17 12:21:41 +02:00
" std::vector<int>::iterator it = std::inplace_merge(ints1.begin(), std::advance(ints1.rbegin(), 5), ints2.end()); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers are used together. \n " , errout . str ( ) ) ;
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(ints2.rbegin(), 5), ints1.end()); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-10-18 21:55:41 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void iterator8 ( ) {
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::find_first_of(ints1.begin(), ints2.end(), ints1.begin(), ints1.end()); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers are used together. \n " , errout . str ( ) ) ;
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::find_first_of(ints1.begin(), ints1.end(), ints2.begin(), ints1.end()); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers are used together. \n " , errout . str ( ) ) ;
2012-04-17 12:21:41 +02:00
check ( " void foo() \n "
" { \n "
" std::vector<int> ints1; \n "
" std::vector<int> ints2; \n "
" std::vector<int>::iterator it = std::find_first_of(foo.bar.begin(), foo.bar.end()-6, ints2.begin(), ints1.end()); \n "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers are used together. \n " , errout . str ( ) ) ;
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::find_first_of(ints1.begin(), ints1.end(), ints2.begin(), ints2.end()); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-10-18 21:55:41 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-07-21 14:13:26 +02:00
// #6839
check ( " void f(const std::wstring& a, const std::wstring& b) { \n "
" const std::string tp1 = std::string(a.begin(), b.end()); \n "
" const std::wstring tp2 = std::string(b.begin(), a.end()); \n "
" const std::u16string tp3(a.begin(), b.end()); \n "
" const std::u32string tp4(b.begin(), a.end()); \n "
" const std::string fp1 = std::string(a.begin(), a.end()); \n "
" const std::string tp2(a.begin(), a.end()); \n "
" } " ) ;
2016-10-27 10:25:45 +02:00
ASSERT_EQUALS ( // TODO "[test.cpp:2]: (error) Iterators of different containers are used together.\n"
2016-10-27 17:11:32 +02:00
// TODO "[test.cpp:3]: (error) Iterators of different containers are used together.\n"
" [test.cpp:4]: (error) Iterators of different containers are used together. \n "
" [test.cpp:5]: (error) Iterators of different containers are used together. \n " , errout . str ( ) ) ;
2011-10-18 21:55:41 +02:00
}
2014-11-20 14:20:09 +01:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-04-16 16:56:55 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-01-19 21:00:46 +01:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02: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
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Same iterator is used with different containers 's1' and 's2'. \n " , errout . str ( ) ) ;
2010-05-15 20:00:41 +02:00
}
2014-11-20 14:20:09 +01:00
void iterator11 ( ) {
2011-12-21 06:16:06 +01:00
// Ticket #3433
check ( " int main() { \n "
" map<int, int> myMap; \n "
" vector<string> myVector; \n "
" for(vector<int>::iterator x = myVector.begin(); x != myVector.end(); x++) \n "
" myMap.erase(*x); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-12-21 06:16:06 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void iterator12 ( ) {
2011-12-26 10:30:39 +01:00
// Ticket #3201
check ( " void f() { \n "
" std::map<int, int> map1; \n "
" std::map<int, int> map2; \n "
" std::map<int, int>::const_iterator it = map1.find(123); \n "
" if (it == map2.end()) { } "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Same iterator is used with different containers 'map1' and 'map2'. \n " , errout . str ( ) ) ;
2011-12-27 11:02:43 +01:00
2017-07-26 23:13:01 +02:00
check ( " void f() { \n "
" std::map<int, int> map1; \n "
" std::map<int, int> map2; \n "
" std::map<int, int>::const_iterator it = map1.find(123); \n "
" if (map2.end() == it) { } "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Same iterator is used with different containers 'map1' and 'map2'. \n " , errout . str ( ) ) ;
2011-12-27 11:02:43 +01:00
check ( " void f(std::string &s) { \n "
" int pos = s.find(x); \n "
" s.erase(pos); \n "
" s.erase(pos); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-12-26 10:30:39 +01:00
}
2014-11-20 14:20:09 +01:00
void iterator13 ( ) {
2012-08-20 13:57:24 +02:00
check ( " void f() { \n "
" std::vector<int> a; \n "
" std::vector<int> t; \n "
" std::vector<int>::const_iterator it; \n "
" it = a.begin(); \n "
" while (it!=a.end()) \n "
2017-07-26 23:13:01 +02:00
" ++it; \n "
2012-08-20 13:57:24 +02:00
" it = t.begin(); \n "
" while (it!=a.end()) \n "
" ++it; \n "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Same iterator is used with different containers 't' and 'a'. \n " , errout . str ( ) ) ;
2012-08-20 13:57:24 +02:00
// #4062
check ( " void f() { \n "
" std::vector<int> a; \n "
" std::vector<int> t; \n "
" std::vector<int>::const_iterator it; \n "
" it = a.begin(); \n "
" while (it!=a.end()) \n "
" v++it; \n "
" it = t.begin(); \n "
" while (it!=t.end()) \n "
" ++it; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" std::vector<int> a; \n "
" std::vector<int> t; \n "
" std::vector<int>::const_iterator it; \n "
" if(z) \n "
" it = a.begin(); \n "
" else \n "
" it = t.begin(); \n "
" while (z && it!=a.end()) \n "
" v++it; \n "
" while (!z && it!=t.end()) \n "
" v++it; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2018-01-06 22:25:13 +01:00
void iterator14 ( ) {
check ( " void f() { \n "
" std::map<int,Foo> x; \n "
" std::map<int,Foo>::const_iterator it; \n "
" for (it = x.find(0)->second.begin(); it != x.find(0)->second.end(); ++it) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-05-03 07:37:39 +02:00
// Dereferencing invalid pointer
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:7] -> [test.cpp:6]: (error) Iterator 'iter' used after element has been erased. \n " , errout . str ( ) ) ;
2015-11-10 19:03:35 +01:00
// #6554 "False positive eraseDereference - erase in while() loop"
check ( " typedef std::map<Packet> packetMap; \n "
" packetMap waitingPackets; \n "
" void ProcessRawPacket() { \n "
" packetMap::iterator wpi; \n "
" while ((wpi = waitingPackets.find(lastInOrder + 1)) != waitingPackets.end()) { \n "
" waitingPackets.erase(wpi); \n "
" for (unsigned pos = 0; pos < buf.size(); ) { } \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-03 07:37:39 +02:00
}
2014-11-20 14:20:09 +01:00
void dereference_break ( ) { // #3644
2012-04-09 07:19:39 +02:00
check ( " void f(std::vector<int> &ints) { \n "
" std::vector<int>::iterator iter; \n "
" for (iter=ints.begin();iter!=ints.end();++iter) { \n "
" if (*iter == 2) { \n "
" ints.erase(iter); \n "
" break; \n "
" } \n "
" if (*iter == 3) { \n "
" ints.erase(iter); \n "
" break; \n "
" } \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-04-09 07:19:39 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:7] -> [test.cpp:6]: (error) Iterator 'iter' used after element 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:7] -> [test.cpp:6]: (error) Iterator 'iter' used after element has been erased. \n " , errout . str ( ) ) ;
2009-07-30 19:49:38 +02:00
}
2009-05-03 07:37:39 +02:00
2014-11-20 14:20:09 +01:00
void dereference_auto ( ) {
2013-09-28 11:50:45 +02:00
check ( " void f() \n "
" { \n "
" std::vector<int> ints; \n "
" auto iter = ints.begin() + 2; \n "
" ints.erase(iter); \n "
" std::cout << (*iter) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:5]: (error) Iterator 'iter' used after element has been erased. \n " , errout . str ( ) ) ;
2014-04-09 10:32:56 +02:00
check ( " void f() { \n "
" auto x = *myList.begin(); \n "
" myList.erase(x); \n "
" auto b = x.first; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-11-15 14:40:31 +01:00
check ( " const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const { \n "
" if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) { \n "
" auto From = TD->getInstantiatedFrom(); \n "
" } \n "
" return nullptr; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-09-28 11:50:45 +02:00
}
2009-05-03 07:37:39 +02:00
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +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
2012-02-25 12:43:27 +01:00
check ( " void foo(std::vector<int> foo) { \n "
" for (unsigned int ii = 0; ii <= foo.size(); ++ii) { \n "
" foo.at(ii) = 0; \n "
" } \n "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) When ii==foo.size(), foo.at(ii) is out of bounds. \n " , errout . str ( ) ) ;
2012-02-25 12:43:27 +01:00
2013-03-04 19:59:46 +01:00
check ( " void foo(const std::string& foo) { \n "
" for (unsigned int ii = 0; ii <= foo.length(); ++ii) { \n "
" foo[ii] = 'x'; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) When ii==foo.size(), foo[ii] is out of bounds. \n " , errout . str ( ) ) ;
check ( " void foo(const std::string& foo, unsigned int ii) { \n "
" if (ii <= foo.length()) { \n "
" foo[ii] = 'x'; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) When ii==foo.size(), foo[ii] is out of bounds. \n " , errout . str ( ) ) ;
2014-10-02 15:19:01 +02:00
check ( " void foo(const std::string& foo, unsigned int ii) { \n "
" do { \n "
" foo[ii] = 'x'; \n "
" ++i; \n "
" } while(ii <= foo.length()); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) When ii==foo.size(), foo[ii] is out of bounds. \n " , errout . str ( ) ) ;
2013-03-04 19:59:46 +01:00
check ( " void foo(const std::string& foo, unsigned int ii) { \n "
" if (anything()) { \n "
" } else if (ii <= foo.length()) { \n "
" foo[ii] = 'x'; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-10-07 22:38:21 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-01-03 22:36:39 +01:00
check ( " void foo() { \n "
" for (B b : D()) {} \n " // Don't crash on range-based for-loop
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-19 19:35:47 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-18 22:40:38 +01:00
}
2012-05-07 21:03:33 +02:00
{
check ( " void f(const std::map<int,int> &data) { \n "
" int i = x; "
" for (int i = 5; i <= data.size(); i++) \n "
" data[i] = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-03-19 19:35:47 +01:00
}
2009-02-11 06:08:29 +01:00
2017-08-22 11:04:02 +02:00
void negativeIndex ( ) {
check ( " void f(const std::vector<int> &v) { \n "
" v[-11] = 123; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Array index -11 is out of bounds. \n " , errout . str ( ) ) ;
}
2009-02-11 06:08:29 +01:00
2014-11-20 14:20:09 +01:00
void erase1 ( ) {
2009-11-10 17:20:20 +01:00
check ( " void f() \n "
" { \n "
2015-07-23 18:53:31 +02:00
" std::list<int>::iterator it; \n "
2011-12-09 22:28:10 +01:00
" for (it = foo.begin(); it != foo.end(); ++it) { \n "
" foo.erase(it); \n "
" } \n "
" for (it = foo.begin(); it != foo.end(); ++it) { \n "
2009-11-10 17:20:20 +01:00
" foo.erase(it); \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2015-07-23 18:53:31 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:5]: (error) Iterator 'it' used after element has been erased. \n "
" [test.cpp:7] -> [test.cpp:8]: (error) Iterator 'it' used after element has been erased. \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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-11-10 17:20:20 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-04-10 13:27:36 +02:00
2015-07-30 10:13:49 +02:00
check ( " void f() \n "
" { \n "
" std::list<int>::iterator i; \n "
" while (i != x.y.end()) \n "
" i = x.y.erase(i); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-15 18:11:41 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-19 19:35:47 +01:00
}
2009-02-11 17:20:32 +01:00
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-12-18 20:55:51 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-01-23 22:03:38 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:6]: (error) Iterator 'it' used after element has been erased. \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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:6]: (error) Iterator 'it' used after element has been erased. \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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:6]: (error) Iterator 'it' used after element has been erased. \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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:6]: (error) Iterator 'it' used after element has been erased. \n " , errout . str ( ) ) ;
2010-05-08 20:11:15 +02:00
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:8]: (error) Iterator 'it' used after element has been erased. \n " , errout . str ( ) ) ;
2010-10-08 21:52:18 +02:00
}
2014-11-20 14:20:09 +01: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 ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void eraseBreak ( ) {
2009-03-19 19:35:47 +01:00
check ( " void f() \n "
" { \n "
2015-07-23 18:53:31 +02:00
" for (std::vector<int>::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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:5]: (error) Iterator 'it' used after element has been erased. \n " , errout . str ( ) ) ;
2010-10-05 20:54:13 +02:00
check ( " void f() \n "
" { \n "
2015-07-23 18:53:31 +02:00
" for (std::vector<int>::iterator it = foo.begin(); it != foo.end(); ++it) \n "
2010-10-05 20:54:13 +02:00
" { \n "
" if (x) { \n "
" foo.erase(it); \n "
" break; \n "
" } \n "
2009-03-19 19:35:47 +01:00
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-03-19 19:35:47 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-11-25 07:34:50 +01:00
check ( " void f(int x) \n "
" { \n "
2015-07-23 18:53:31 +02:00
" for (std::vector<int>::iterator it = foo.begin(); it != foo.end(); ++it) \n "
2011-11-25 07:34:50 +01:00
" { \n "
" foo.erase(it); \n "
" if (x) "
" return; \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:5]: (error) Iterator 'it' used after element has been erased. \n " , errout . str ( ) ) ;
2011-11-25 07:34:50 +01:00
2009-03-19 19:35:47 +01:00
}
2009-03-18 22:40:38 +01:00
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-07-14 09:42:10 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-09-08 09:45:30 +02:00
check ( " void f(std::map<uint32, uint32> my_map) { \n " // #7365
" std::map<uint32, uint32>::iterator itr = my_map.begin(); \n "
" switch (itr->first) { \n "
" case 0: \n "
" my_map.erase(itr); \n "
" continue; \n "
" case 1: \n "
" itr->second = 1; \n "
" break; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-07-14 09:42:10 +02:00
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-03-19 19:35:47 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-03-18 22:40:38 +01:00
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-09-18 16:46:38 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-07-09 10:50:24 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2015-07-23 18:53:31 +02:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:9]: (error) Iterator 'it' used after element has been erased. \n " , errout . str ( ) ) ;
2010-07-09 10:50:24 +02:00
}
2014-11-20 14:20:09 +01:00
void eraseGoto ( ) {
2009-03-19 19:35:47 +01:00
check ( " void f() \n "
" { \n "
2015-07-23 18:53:31 +02:00
" for (std::vector<int>::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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-03-19 19:35:47 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-02-11 06:08:29 +01:00
2014-11-20 14:20:09 +01:00
void eraseAssign1 ( ) {
2009-03-19 19:35:47 +01:00
check ( " void f() \n "
" { \n "
2015-07-23 18:53:31 +02:00
" for (std::vector<int>::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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-03-19 19:35:47 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-02-11 06:08:29 +01:00
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-08-17 18:56:11 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void eraseAssign3 ( ) {
2012-09-06 16:10:51 +02:00
check ( " void f(std::list<list<int> >& l) { \n "
" std::list<std::list<int> >::const_iterator i = l.begin(); \n "
" std::list<int>::const_iterator j = (*i).begin(); \n "
" cout << *j << endl; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void eraseAssign4 ( ) {
2013-10-26 17:48:20 +02:00
check ( " void f(std::list<int> data) { \n "
" std::list<int>::const_iterator it = data.begin(); \n "
" it = data.erase(it); \n "
" it = data.erase(it); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(Data data) { \n "
" std::list<int>::const_iterator it = data.ints.begin(); \n "
" it = data.ints.erase(it); \n "
" it = data.ints.erase(it); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void eraseAssignByFunctionCall ( ) {
2012-09-06 16:30:10 +02:00
check ( " void f(std::list<list<int> >& l) { \n "
" std::list<foo>::const_iterator i; \n "
" bar(i); \n "
" cout << *i; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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
}
2014-11-20 14:20:09 +01:00
void eraseByValue ( ) {
2010-05-15 19:46:42 +02:00
check ( " void f() \n "
" { \n "
" std::set<int> foo; \n "
2011-12-17 11:21:34 +01:00
" for (std::set<int>::iterator it = foo.begin(); it != foo.end(); ++it) \n "
2010-05-15 19:46:42 +02:00
" { \n "
" foo.erase(*it); \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
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
2011-12-17 11:21:34 +01:00
check ( " int f(std::set<int> foo) { \n "
" std::set<int>::iterator it = foo.begin(); \n "
" foo.erase(*it); \n "
" return *it; \n "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3]: (error) Iterator 'it' used after element has been erased. \n " , errout . str ( ) ) ;
2011-12-17 11:21:34 +01:00
2010-12-24 10:33:48 +01:00
check ( " void f() \n "
" { \n "
" std::set<int> foo; \n "
2011-12-17 11:21:34 +01:00
" std::set<int>::iterator it = foo.begin(); \n "
2010-12-24 10:33:48 +01:00
" foo.erase(*it); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-12-24 10:33:48 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-04-12 19:44:37 +02:00
// #5669
check ( " void f() { \n "
" HashSet_Ref::iterator aIt = m_ImplementationMap.find( xEle ); \n "
" m_SetLoadedFactories.erase(*aIt); \n "
" m_SetLoadedFactories.erase(aIt); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(const std::list<int>& m_ImplementationMap) { \n "
" std::list<int>::iterator aIt = m_ImplementationMap.find( xEle ); \n "
" m_ImplementationMap.erase(*aIt); \n "
" m_ImplementationMap.erase(aIt); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Invalid iterator: aIt \n " , errout . str ( ) ) ;
check ( " void f(const std::list<int>& m_ImplementationMap) { \n "
" std::list<int>::iterator aIt = m_ImplementationMap.find( xEle1 ); \n "
" std::list<int>::iterator bIt = m_ImplementationMap.find( xEle2 ); \n "
" m_ImplementationMap.erase(*bIt); \n "
" m_ImplementationMap.erase(aIt); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-05-15 19:46:42 +02:00
}
2009-02-18 20:57:43 +01:00
2015-07-23 20:53:50 +02:00
void eraseIf ( ) {
// #4816
check ( " void func(std::list<std::string> strlist) { \n "
" for (std::list<std::string>::iterator str = strlist.begin(); str != strlist.end(); str++) { \n "
" if (func2(*str)) { \n "
" strlist.erase(str); \n "
" if (strlist.empty()) \n "
" return; \n "
" } \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (error) Iterator 'str' used after element has been erased. \n " , errout . str ( ) ) ;
}
2009-02-18 20:57:43 +01:00
2014-11-20 14:20:09 +01:00
void eraseOnVector ( ) {
2014-04-12 19:44:37 +02:00
check ( " void f(const std::vector<int>& m_ImplementationMap) { \n "
" std::vector<int>::iterator aIt = m_ImplementationMap.find( xEle ); \n "
" m_ImplementationMap.erase(something(unknown)); \n " // All iterators become invalidated when erasing from std::vector
" m_ImplementationMap.erase(aIt); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) After erase(), the iterator 'aIt' may be invalid. \n " , errout . str ( ) ) ;
check ( " void f(const std::vector<int>& m_ImplementationMap) { \n "
" std::vector<int>::iterator aIt = m_ImplementationMap.find( xEle ); \n "
" m_ImplementationMap.erase(*aIt); \n " // All iterators become invalidated when erasing from std::vector
" m_ImplementationMap.erase(aIt); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Invalid iterator: aIt \n " , errout . str ( ) ) ;
check ( " void f(const std::vector<int>& m_ImplementationMap) { \n "
" std::vector<int>::iterator aIt = m_ImplementationMap.find( xEle1 ); \n "
" std::vector<int>::iterator bIt = m_ImplementationMap.find( xEle2 ); \n "
" m_ImplementationMap.erase(*bIt); \n " // All iterators become invalidated when erasing from std::vector
" aIt = m_ImplementationMap.erase(aIt); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) After erase(), the iterator 'aIt' may be invalid. \n " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +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
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-04-25 17:14:02 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-04-25 16:32:37 +02:00
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +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
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Invalid pointer 'first' after push_back(). \n " , errout . str ( ) ) ;
2009-04-25 16:32:37 +02:00
}
2014-11-20 14:20:09 +01: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
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +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
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +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
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +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
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-11-10 19:07:04 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) After reserve(), the iterator 'it' may be invalid. \n " , errout . str ( ) ) ;
2010-06-15 19:53:09 +02:00
// 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) After reserve(), the iterator 'it' may be invalid. \n " , errout . str ( ) ) ;
2010-06-15 19:53:09 +02:00
}
2009-11-10 19:07:04 +01:00
2014-11-20 14:20:09 +01: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
2014-11-20 14:20:09 +01:00
void pushback12 ( ) {
2012-11-10 16:59:31 +01:00
// #4197
check ( " void foo(double s) \n "
" { \n "
" std::vector<double> vec; \n "
" for( std::vector<double>::iterator it = vec.begin(); it != vec.end(); ++it ) \n "
" { \n "
" vec.insert( it, s ); \n "
" for(unsigned int i = 0; i < 42; i++) \n "
" {} \n "
" *it; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) After insert(), the iterator 'it' may be invalid. \n "
" [test.cpp:9]: (error) After insert(), the iterator 'it' may be invalid. \n " , errout . str ( ) ) ;
}
2015-11-15 14:55:10 +01:00
void pushback13 ( ) {
check ( " bool Preprocessor::ConcatenateIncludeName(SmallString<128> &FilenameBuffer, SourceLocation &End) { \n "
" unsigned PreAppendSize = FilenameBuffer.size(); \n "
" FilenameBuffer.resize(PreAppendSize + CurTok.getLength()); \n "
" const char *BufPtr = &FilenameBuffer[PreAppendSize]; \n "
" return true; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-10-31 15:27:33 +01:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) After insert(), the iterator 'iter' may be invalid. \n " , errout . str ( ) ) ;
2012-11-11 13:03:58 +01:00
check ( " void* f(const std::vector<Bar>& bars) { \n "
" std::vector<Bar>::iterator i = bars.begin(); \n "
" bars.insert(Bar()); \n "
" void* v = &i->foo; \n "
" return v; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) After insert(), the iterator 'i' may be invalid. \n " , errout . str ( ) ) ;
check ( " Foo f(const std::vector<Bar>& bars) { \n "
" std::vector<Bar>::iterator i = bars.begin(); \n "
" bars.insert(Bar()); \n "
" return i->foo; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) After insert(), the iterator 'i' may be invalid. \n " , errout . str ( ) ) ;
2013-03-04 11:57:09 +01:00
check ( " void f(const std::vector<Bar>& bars) { \n "
" for(std::vector<Bar>::iterator i = bars.begin(); i != bars.end(); ++i) { \n "
" i = bars.insert(i, bar); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(const std::vector<Bar>& bars) { \n "
" for(std::vector<Bar>::iterator i = bars.begin(); i != bars.end(); ++i) { \n "
" bars.insert(i, bar); \n "
" i = bars.insert(i, bar); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) After insert(), the iterator 'i' may be invalid. \n "
" [test.cpp:4]: (error) After insert(), the iterator 'i' may be invalid. \n " , errout . str ( ) ) ;
check ( " void* f(const std::vector<Bar>& bars) { \n "
" std::vector<Bar>::iterator i = bars.begin(); \n "
" bars.insert(i, Bar()); \n "
" i = bars.insert(i, Bar()); \n "
" void* v = &i->foo; \n "
" return v; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) After insert(), the iterator 'i' may be invalid. \n " , errout . str ( ) ) ;
2009-05-02 20:49:58 +02:00
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-01-20 19:26:52 +01:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-01-20 19:26:52 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-05-02 20:49:58 +02:00
2014-06-16 21:36:31 +02:00
template < size_t n , typename T >
2017-04-09 16:59:41 +02:00
static size_t getArraylength ( const T ( & ) [ n ] ) {
2014-06-16 21:36:31 +02:00
return n ;
}
2009-04-13 17:48:13 +02:00
2014-11-20 14:20:09 +01:00
void stlBoundaries1 ( ) {
2014-06-16 20:50:47 +02:00
const std : : string stlCont [ ] = {
2015-11-20 12:46:59 +01:00
" list " , " set " , " multiset " , " map " , " multimap "
2010-04-15 20:08:51 +02:00
} ;
2009-05-17 18:58:32 +02:00
2014-06-16 20:50:47 +02:00
for ( size_t i = 0 ; i < getArraylength ( stlCont ) ; + + 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-07-25 00:36:15 +02:00
2016-07-09 12:42:46 +02:00
ASSERT_EQUALS_MSG ( " [test.cpp:4]: (error) Dangerous comparison using operator< on iterator. \n " , errout . str ( ) , stlCont [ i ] ) ;
2009-07-25 00:36:15 +02:00
}
2012-04-17 12:54:01 +02:00
check ( " void f() { \n "
" std::forward_list<int>::iterator it; \n "
" for (it = ab.begin(); ab.end() > it; ++it) {} \n "
" } " ) ;
2015-11-20 12:46:59 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous comparison using operator< on iterator. \n " , errout . str ( ) ) ;
2014-06-16 20:50:47 +02:00
2015-11-20 12:46:59 +01:00
// #5926 no FP Dangerous comparison using operator< on iterator on std::deque
2014-06-16 21:36:31 +02:00
check ( " void f() { \n "
2014-06-16 20:50:47 +02:00
" std::deque<int>::iterator it; \n "
" for (it = ab.begin(); ab.end() > it; ++it) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-04-13 17:48:13 +02:00
}
2014-11-20 14:20:09 +01:00
void stlBoundaries2 ( ) {
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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
2014-11-20 14:20:09 +01:00
void stlBoundaries3 ( ) {
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-08-08 21:07:33 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-04-18 10:08:59 +02:00
check ( " bool f() { \n "
" static set<Foo>::const_iterator current; \n "
" return 25 > current->bar; \n "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Invalid iterator 'current' used. \n " , errout . str ( ) ) ;
2009-08-08 21:07:33 +02:00
}
2014-11-20 14:20:09 +01:00
void stlBoundaries4 ( ) {
2012-11-20 06:12:14 +01:00
check ( " void f() { \n "
" std::forward_list<std::vector<std::vector<int>>>::iterator it; \n "
" for (it = ab.begin(); ab.end() > it; ++it) {} \n "
" } " ) ;
2015-11-20 12:46:59 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous comparison using operator< on iterator. \n " , errout . str ( ) ) ;
2012-11-20 06:12:14 +01:00
// don't crash
check ( " void f() { \n "
" if (list < 0) ; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" if (list < 0) { \n "
" std::forward_list<std::vector<std::vector<int>>>::iterator it; \n "
" for (it = ab.begin(); ab.end() > it; ++it) {} \n "
" } \n "
" } " ) ;
2015-11-20 12:46:59 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Dangerous comparison using operator< on iterator. \n " , errout . str ( ) ) ;
2012-11-20 06:12:14 +01:00
}
2009-11-02 20:24:38 +01:00
2014-11-20 14:20:09 +01:00
void stlBoundaries5 ( ) {
2013-03-14 17:00:22 +01:00
check ( " class iterator { int foo(); }; \n "
" int foo() { \n "
" iterator i; \n "
" return i.foo();; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " class iterator { \n "
" Class operator*(); \n "
" iterator& operator++(); \n "
" int foo(); \n "
" }; \n "
" int foo() { \n "
" iterator i; \n "
" return i.foo();; \n "
" } " ) ;
2018-01-10 09:37:21 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error, inconclusive) Invalid iterator 'i' used. \n " , errout . str ( ) ) ;
2013-03-14 17:00:22 +01:00
}
2015-11-08 09:42:28 +01:00
void stlBoundaries6 ( ) { // #7106
check ( " void foo(std::vector<int>& vec) { \n "
" for (Function::iterator BB : vec) { \n "
" for (int Inst : *BB) \n "
" { \n "
" } \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-02-27 21:26:11 +01:00
2014-11-20 14:20:09 +01:00
void if_find ( ) {
2010-02-27 21:35:33 +01:00
// ---------------------------
// set::find
// ---------------------------
2012-01-02 22:52:50 +01:00
// error (simple)
2010-02-27 21:26:11 +01:00
check ( " void f(std::set<int> s) \n "
" { \n "
" if (s.find(12)) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +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
2012-01-02 22:52:50 +01:00
// error (pointer)
check ( " void f(std::set<int> *s) \n "
" { \n "
2015-01-03 11:06:44 +01:00
" if ((*s).find(12)) { } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Suspicious condition. The result of find() is an iterator, but it is not properly checked. \n " , errout . str ( ) ) ;
// error (pointer)
check ( " void f(std::set<int> *s) \n "
" { \n "
" if (s->find(12)) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +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 ( ) ) ;
2012-01-02 22:52:50 +01:00
// error (array-like pointer)
check ( " void f(std::set<int> *s) \n "
" { \n "
" if (s[0].find(12)) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +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 ( ) ) ;
2012-01-02 22:52:50 +01:00
// error (array)
check ( " void f(std::set<int> s [10]) \n "
" { \n "
" if (s[0].find(12)) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +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 ( ) ) ;
2012-01-02 22:52:50 +01:00
// error (undefined length array)
check ( " void f(std::set<int> s []) \n "
" { \n "
" if (s[0].find(12)) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +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 ( ) ) ;
2012-01-02 22:52:50 +01:00
// error (vector)
check ( " void f(std::vector<std::set<int> > s) \n "
" { \n "
" if (s[0].find(12)) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +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 ( ) ) ;
2012-01-02 22:52:50 +01:00
2015-01-03 11:29:13 +01:00
// error (assignment)
check ( " void f(std::set<int> s) \n "
" { \n "
" if (a || (x = s.find(12))) { } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Suspicious condition. The result of find() is an iterator, but it is not properly checked. \n " , errout . str ( ) ) ;
2012-01-02 22:52:50 +01:00
// ok (simple)
2010-02-27 21:35:33 +01:00
check ( " void f(std::set<int> s) \n "
" { \n "
" if (s.find(123) != s.end()) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-02-27 21:35:33 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-02-28 07:04:58 +01:00
2012-01-02 22:52:50 +01:00
// ok (pointer)
check ( " void f(std::set<int> *s) \n "
" { \n "
2015-01-03 11:06:44 +01:00
" if ((*s).find(12) != s.end()) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-01-02 22:52:50 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// ok (array-like pointer)
check ( " void f(std::set<int> *s) \n "
" { \n "
" if (s[0].find(12) != s.end()) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-01-02 22:52:50 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// ok (array)
check ( " void f(std::set<int> s [10]) \n "
" { \n "
" if (s[0].find(123) != s.end()) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-01-02 22:52:50 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// ok (undefined length array)
check ( " void f(std::set<int> s []) \n "
" { \n "
" if (s[0].find(123) != s.end()) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-01-02 22:52:50 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// ok (vector)
check ( " void f(std::vector<std::set<int> > s) \n "
" { \n "
" if (s[0].find(123) != s.end()) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-01-02 22:52:50 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-01-03 11:29:13 +01:00
// ok (assignment)
check ( " void f(std::set<int> s) \n "
" { \n "
" if (a || (x = s.find(12)) != s.end()) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-01-04 12:43:31 +01:00
// ok (dereference, #6402)
check ( " void f(std::set<Foo> s) { \n "
" if (s.find(12).member) { } \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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-02-28 07:04:58 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-04-14 18:36:19 +02:00
2015-01-03 11:06:44 +01:00
// ok (less than comparison, #6217)
check ( " void f(std::vector<int> s) \n "
" { \n "
" if (std::find(a, b, c) < d) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-04-14 18:36:19 +02:00
// #3714 - segmentation fault for syntax error
check ( " void f() { \n "
" if (()) { } \n "
" } " ) ;
2012-06-07 19:33:18 +02:00
// #3865
check ( " void f() { \n "
" if ((std::find(a,b,c)) != b) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-06-07 19:33:18 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-02-27 21:26:11 +01:00
}
2014-11-20 14:20:09 +01:00
void if_str_find ( ) {
2012-01-02 22:52:50 +01:00
// error (simple)
2010-05-01 21:56:39 +02:00
check ( " void f(const std::string &s) \n "
" { \n "
" if (s.find( \" abc \" )) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Inefficient usage of string::find() in condition; string::compare() would be faster. \n " , errout . str ( ) ) ;
2012-01-02 22:52:50 +01:00
// error (pointer)
check ( " void f(const std::string *s) \n "
" { \n "
2015-01-03 11:06:44 +01:00
" if ((*s).find( \" abc \" )) { } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Inefficient usage of string::find() in condition; string::compare() would be faster. \n " , errout . str ( ) ) ;
// error (pointer)
check ( " void f(const std::string *s) \n "
" { \n "
" if (s->find( \" abc \" )) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Inefficient usage of string::find() in condition; string::compare() would be faster. \n " , errout . str ( ) ) ;
2012-01-02 22:52:50 +01:00
// error (vector)
check ( " void f(const std::vector<std::string> &s) \n "
" { \n "
" if (s[0].find( \" abc \" )) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Inefficient usage of string::find() in condition; string::compare() would be faster. \n " , errout . str ( ) ) ;
2012-04-03 20:59:45 +02:00
// #3162
check ( " void f(const std::string& s1, const std::string& s2) \n "
" { \n "
" if ((!s1.empty()) && (0 == s1.find(s2))) { } \n "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Inefficient usage of string::find() in condition; string::compare() would be faster. \n " , errout . str ( ) ) ;
2012-10-07 12:43:14 +02:00
// #4102
check ( " void f(const std::string &define) { \n "
" if (define.find( \" = \" ) + 1U == define.size()); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-02-14 19:14:20 +01:00
check ( " void f(std::string a, std::string b) { \n " // #4480
" if (a.find( \" < \" ) < b.find( \" > \" )) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-11-20 20:08:35 +01:00
check ( " void f(const std::string &s) { \n "
" if (foo(s.find( \" abc \" ))) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-01-29 08:55:46 +01:00
// #7349 - std::string::find_first_of
check ( " void f(const std::string &s) { \n "
" if (s.find_first_of( \" abc \" )==0) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , 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
2014-11-20 14:20:09 +01:00
void size1 ( ) {
2015-05-17 20:02:41 +02:00
const char * code = " struct Fred { \n "
" void foo(); \n "
" std::list<int> x; \n "
" }; \n "
" void Fred::foo() \n "
" { \n "
" if (x.size() == 0) {} \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2011-03-08 01:49:43 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-08 01:49:43 +01:00
2015-05-17 20:02:41 +02:00
code = " std::list<int> x; \n "
" void f() \n "
" { \n "
" if (x.size() == 0) {} \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2011-03-08 01:49:43 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-08 01:49:43 +01:00
2015-05-17 20:02:41 +02:00
code = " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (x.size() == 0) {} \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2010-12-04 09:15:48 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-12-19 15:24:59 +01:00
2015-05-17 20:02:41 +02:00
code = " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (0 == x.size()) {} \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2011-03-08 01:49:43 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-08 01:49:43 +01:00
2015-05-17 20:02:41 +02:00
code = " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (x.size() != 0) {} \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2010-12-04 09:15:48 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-12-19 15:24:59 +01:00
2015-05-17 20:02:41 +02:00
code = " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (0 != x.size()) {} \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2011-03-08 01:49:43 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-08 01:49:43 +01:00
2015-05-17 20:02:41 +02:00
code = " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (x.size() > 0) {} \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2010-12-04 09:15:48 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-12-19 15:24:59 +01:00
2015-05-17 20:02:41 +02:00
code = " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (0 < x.size()) {} \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2011-03-08 01:49:43 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-11-04 16:15:26 +01:00
2015-05-17 20:02:41 +02:00
code = " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (x.size() >= 1) {} \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2012-11-04 16:15:26 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-11-04 16:15:26 +01:00
2015-05-17 20:02:41 +02:00
code = " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (x.size() < 1) {} \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2012-11-04 16:15:26 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-11-04 16:15:26 +01:00
2015-05-17 20:02:41 +02:00
code = " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (1 <= x.size()) {} \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2012-11-04 16:15:26 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-11-04 16:15:26 +01:00
2015-05-17 20:02:41 +02:00
code = " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (1 > x.size()) {} \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2012-11-04 16:15:26 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-08 01:49:43 +01:00
2015-05-17 20:02:41 +02:00
code = " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (x.size()) {} \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2010-12-04 09:15:48 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-12-19 15:24:59 +01:00
2015-05-17 20:02:41 +02:00
code = " void f() \n "
" { \n "
" std::list<int> x; \n "
" if (!x.size()) {} \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2011-03-08 01:49:43 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-08 01:49:43 +01:00
2009-12-19 15:24:59 +01:00
check ( " void f() \n "
" { \n "
" std::list<int> x; \n "
" fun(x.size()); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-12-19 15:24:59 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-08 01:49:43 +01:00
2015-05-17 20:02:41 +02:00
code = " void f() \n "
2011-03-08 01:49:43 +01:00
" { \n "
" std::list<int> x; \n "
" fun(!x.size()); \n "
2015-05-17 20:02:41 +02:00
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2012-04-04 19:44:57 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-04-04 19:44:57 +02:00
2015-05-17 20:02:41 +02:00
code = " void f() \n "
" { \n "
" std::list<int> x; \n "
" fun(a && x.size()); \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2012-04-04 19:44:57 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-08-25 12:36:13 +02:00
check ( " void f() { \n " // #4039
" std::list<int> x; \n "
" fun(width % x.size() != 0); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-02-16 11:50:25 +01:00
// #4584
check ( " void f() { \n "
" std::list<int> x; \n "
" if (foo + 1 > x.size()) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" std::list<int> x; \n "
" if (x.size() < 1 + foo) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-12-19 15:24:59 +01:00
}
2014-11-20 14:20:09 +01:00
void size2 ( ) {
2015-05-17 20:02:41 +02:00
const char * code = " 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 "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2011-03-29 01:31:23 +02:00
ASSERT_EQUALS ( " [test.cpp:10]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-29 01:31:23 +02:00
}
2014-11-20 14:20:09 +01:00
void size3 ( ) {
2015-05-17 20:02:41 +02:00
const char * code = " namespace N { \n "
" class Zzz { \n "
" public: \n "
" std::list<int> x; \n "
" }; \n "
" } \n "
" using namespace N; \n "
" Zzz * zzz; \n "
" int main() { \n "
" if (zzz->x.size() > 0) { } \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2012-12-20 06:53:04 +01:00
ASSERT_EQUALS ( " [test.cpp:10]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
code = " namespace N { \n "
" class Zzz { \n "
" public: \n "
" std::list<int> x; \n "
" }; \n "
" } \n "
" using namespace N; \n "
" int main() { \n "
" Zzz * zzz; \n "
" if (zzz->x.size() > 0) { } \n "
" } " ;
check ( code , false , Standards : : CPP03 ) ;
2012-12-20 06:53:04 +01:00
ASSERT_EQUALS ( " [test.cpp:10]: (performance) Possible inefficient checking for 'x' emptiness. \n " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-12-20 06:53:04 +01:00
}
2014-11-20 14:20:09 +01:00
void size4 ( ) { // #2652 - don't warn about vector/deque
2013-02-14 16:59:58 +01:00
check ( " void f(std::vector<int> &v) { \n "
" if (v.size() > 0U) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(std::deque<int> &v) { \n "
" if (v.size() > 0U) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-05-17 20:02:41 +02:00
check ( " void f(std::array<int,3> &a) { \n "
" if (a.size() > 0U) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-02-14 16:59:58 +01:00
}
2014-11-20 14:20:09 +01: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 "
2013-04-13 11:07:18 +02:00
" haystack.remove(needle); "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Redundant checking of STL container element existence before removing it. \n " , errout . str ( ) ) ;
2010-09-16 18:49:23 +02:00
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:2]: (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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-01-14 19:50:07 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-10 10:52:41 +02:00
}
2010-10-10 11:22:44 +02:00
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-10 11:22:44 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-10-10 14:28:14 +02:00
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-10 14:28:14 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-10-17 19:18:46 +02:00
2014-11-20 14:20:09 +01: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
}
2014-11-20 14:20:09 +01: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 ( ) ) ;
}
2014-11-20 14:20:09 +01: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 ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void cstr ( ) {
2010-10-17 19:18:46 +02:00
check ( " void f() { \n "
" std::string errmsg; \n "
" throw errmsg.c_str(); \n "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after throwing exception. \n " , errout . str ( ) ) ;
2010-10-17 19:18:46 +02:00
2011-10-26 21:07:48 +02:00
check ( " const char *get_msg() { \n "
" std::string errmsg; \n "
" return errmsg.c_str(); \n "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call. \n " , errout . str ( ) ) ;
2011-10-26 21:07:48 +02:00
check ( " const char *get_msg() { \n "
" std::ostringstream errmsg; \n "
" return errmsg.str().c_str(); \n "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call. \n " , errout . str ( ) ) ;
2011-10-26 21:07:48 +02:00
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 "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call. \n " , errout . str ( ) ) ;
2011-10-26 21:45:27 +02:00
2011-10-26 22:14:47 +02:00
check ( " const char *get_msg() { \n "
" std::string errmsg; \n "
" return ( \" ERROR: \" + errmsg).c_str(); \n "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call. \n " , errout . str ( ) ) ;
2011-10-26 22:14:47 +02:00
check ( " const char *get_msg() { \n "
" std::string errmsg; \n "
" return ( \" ERROR: \" + std::string( \" crash me \" )).c_str(); \n "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call. \n " , errout . str ( ) ) ;
2011-11-09 21:08:53 +01:00
2010-10-19 20:21:58 +02:00
check ( " void f() { \n "
" std::ostringstream errmsg; \n "
" const char *c = errmsg.str().c_str(); \n "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call. \n " , errout . str ( ) ) ;
2010-10-19 20:21:58 +02:00
2010-10-17 19:18:46 +02:00
check ( " std::string f(); \n "
" \n "
" void foo() { \n "
" const char *c = f().c_str(); \n "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call. \n " , errout . str ( ) ) ;
2011-12-23 22:31:48 +01:00
2012-03-01 18:38:20 +01:00
check ( " class Foo { \n "
" const char *f(); \n "
" }; \n "
" const char *Foo::f() { \n "
" std::string s; \n "
" return s.c_str(); \n "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call. \n " , errout . str ( ) ) ;
2012-03-01 18:38:20 +01:00
2016-05-04 11:10:12 +02:00
check ( " class Foo { \n "
" std::string GetVal() const; \n "
" }; \n "
" const char *f() { \n "
" Foo f; \n "
" return f.GetVal().c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call. \n " , errout . str ( ) ) ;
2011-12-23 22:31:48 +01:00
check ( " const char* foo() { \n "
" static std::string text; \n "
2017-09-19 23:22:17 +02:00
" text = \" hello world \\ n \" ; \n "
2011-12-23 22:31:48 +01:00
" return text.c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ; // #3427
2012-02-25 12:43:27 +01:00
// Implicit conversion back to std::string
check ( " std::string get_msg() { \n "
" std::string errmsg; \n "
" return errmsg.c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Returning the result of c_str() in a function that returns std::string is slow and redundant. \n " , errout . str ( ) ) ;
check ( " const std::string& get_msg() { \n "
" std::string errmsg; \n "
" return errmsg.c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Returning the result of c_str() in a function that returns std::string is slow and redundant. \n " , errout . str ( ) ) ;
2016-05-04 11:10:12 +02:00
check ( " class Foo { \n "
" std::string GetVal() const; \n "
" }; \n "
" std::string f() { \n "
" Foo f; \n "
" return f.GetVal().c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (performance) Returning the result of c_str() in a function that returns std::string is slow and redundant. \n " , errout . str ( ) ) ;
2012-02-25 12:43:27 +01:00
check ( " std::string get_msg() { \n "
" std::string errmsg; \n "
" return errmsg; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-11-29 07:10:56 +01:00
check ( " std::string get_msg() { \n " // #3678
" MyStringClass errmsg; \n "
" return errmsg.c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-02-25 12:43:27 +01:00
check ( " void Foo1(const std::string& str) {} \n "
" void Foo2(char* c, const std::string str) {} \n "
" void Foo3(std::string& rstr) {} \n "
" void Foo4(std::string str, const std::string& str) {} \n "
" void Bar() { \n "
" std::string str = \" bar \" ; \n "
2014-01-30 22:09:24 +01:00
" std::stringstream ss( \" foo \" ); \n "
2012-02-25 12:43:27 +01:00
" Foo1(str); \n "
" Foo1(str.c_str()); \n "
" Foo2(str.c_str(), str); \n "
" Foo2(str.c_str(), str.c_str()); \n "
" Foo3(str.c_str()); \n "
" Foo4(str, str); \n "
" Foo4(str.c_str(), str); \n "
" Foo4(str, str.c_str()); \n "
2014-01-30 22:09:24 +01:00
" Foo4(ss.str(), ss.str().c_str()); \n "
2012-02-25 12:43:27 +01:00
" Foo4(str.c_str(), str.c_str()); \n "
" } " ) ;
2014-01-30 22:09:24 +01:00
ASSERT_EQUALS ( " [test.cpp:9]: (performance) Passing the result of c_str() to a function that takes std::string as argument no. 1 is slow and redundant. \n "
" [test.cpp:11]: (performance) Passing the result of c_str() to a function that takes std::string as argument no. 2 is slow and redundant. \n "
" [test.cpp:14]: (performance) Passing the result of c_str() to a function that takes std::string as argument no. 1 is slow and redundant. \n "
" [test.cpp:15]: (performance) Passing the result of c_str() to a function that takes std::string as argument no. 2 is slow and redundant. \n "
" [test.cpp:16]: (performance) Passing the result of c_str() to a function that takes std::string as argument no. 2 is slow and redundant. \n "
" [test.cpp:17]: (performance) Passing the result of c_str() to a function that takes std::string as argument no. 1 is slow and redundant. \n "
" [test.cpp:17]: (performance) Passing the result of c_str() to a function that takes std::string as argument no. 2 is slow and redundant. \n " , errout . str ( ) ) ;
2012-02-25 12:43:27 +01:00
check ( " void Foo1(const std::string& str) {} \n "
" void Foo2(char* c, const std::string str) {} \n "
" void Bar() { \n "
" std::string str = \" bar \" ; \n "
" Foo1(str, foo); \n " // Don't crash
" Foo2(str.c_str()); \n " // Don't crash
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct Foo { \n "
" void func(std::string str) const {} \n "
" static void sfunc(std::string str) {} \n "
" }; \n "
" void func(std::string str) {} \n "
" void Bar() { \n "
" std::string str = \" bar \" ; \n "
" Foo foo; \n "
" func(str.c_str()); \n "
" Foo::sfunc(str.c_str()); \n "
" foo.func(str.c_str()); \n "
" } " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:9]: (performance) Passing the result of c_str() to a function that takes std::string as argument 1 is slow and redundant. \n "
" [test.cpp:10]: (performance) Passing the result of c_str() to a function that takes std::string as argument 1 is slow and redundant. \n " ,
" " , errout . str ( ) ) ;
2012-04-02 11:02:41 +02:00
check ( " void svgFile(const std::string &content, const std::string &fileName, const double end = 1000., const double start = 0.); \n "
" void Bar(std::string filename) { \n "
" std::string str = \" bar \" ; \n "
" std::ofstream svgFile(filename.c_str(), std::ios::trunc); \n "
" svgFile << \" test \" ; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-02-25 12:43:27 +01:00
check ( " void Foo(const char* p) {} \n "
" void Foo(const std::string& str) {Foo(str.c_str());} \n " // Overloaded
" void Bar() { \n "
" std::string str = \" bar \" ; \n "
" Foo(str); \n "
" Foo(str.c_str()); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-08-26 10:56:46 +02:00
check ( " int atoi(const std::string& str) { \n " // #3729: Don't suggest recursive call
" return atoi(str.c_str()); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-09-10 15:20:38 +02:00
check ( " std::string hello() \n "
" { \n "
" return \" hello \" ; \n "
" } \n "
" \n "
" const char *f() \n "
" { \n "
" return hello().c_str(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call. \n " , errout . str ( ) ) ;
2012-09-10 15:20:38 +02:00
check ( " class Fred { \n "
" std::string hello(); \n "
" const char *f(); \n "
" }; \n "
" std::string Fred::hello() \n "
" { \n "
" return \" hello \" ; \n "
" } \n "
" const char *Fred::f() \n "
" { \n "
" return hello().c_str(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:11]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call. \n " , errout . str ( ) ) ;
2012-11-28 08:48:48 +01:00
// #4183 - using MyStringClass.c_str()
check ( " void a(const std::string &str); \n "
" \n "
" void b() { \n "
" MyStringClass s; \n "
" a(s.c_str()); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-01-30 22:09:24 +01:00
check ( " std::string Format(const char * name) { \n " // #4938
" return String::Format( \" %s: \" , name).c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-05-06 17:24:44 +02:00
// #7480
check ( " struct InternalMapInfo { \n "
" std::string author; \n "
" }; \n "
" const char* GetMapAuthor(int index) { \n "
" const InternalMapInfo* mapInfo = &internal_getMapInfo; \n "
" return mapInfo->author.c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct InternalMapInfo { \n "
" std::string author; \n "
" }; \n "
" std::string GetMapAuthor(int index) { \n "
" const InternalMapInfo* mapInfo = &internal_getMapInfo; \n "
" return mapInfo->author.c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (performance) Returning the result of c_str() in a function that returns std::string is slow and redundant. \n " , errout . str ( ) ) ;
check ( " struct InternalMapInfo { \n "
" std::string author; \n "
" }; \n "
" const char* GetMapAuthor(int index) { \n "
" const InternalMapInfo mapInfo = internal_getMapInfo; \n "
" return mapInfo.author.c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call. \n " , errout . str ( ) ) ;
2017-02-26 17:25:32 +01:00
check ( " struct S { \n " // #7656
" std::string data; \n "
" }; \n "
" const S& getS(); \n "
" const char* test() { \n "
" const struct S &s = getS(); \n "
" return s.data.c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-03-01 02:03:08 +01:00
check ( " struct S { \n " // #7930
" std::string data; \n "
" }; \n "
" const char* test() { \n "
" S s; \n "
" std::string &ref = s.data; \n "
" return ref.c_str(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call. \n " , errout . str ( ) ) ;
2010-10-17 19:18:46 +02:00
}
2011-06-16 20:26:00 +02:00
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2011-06-17 21:09:27 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-06-16 20:26:00 +02:00
check ( " void foo() \n "
" { \n "
" auto_ptr< ns1:::MyClass > y; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-06-16 20:26:00 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-12-06 19:19:22 +01:00
check ( " void f() \n "
2011-06-16 20:26:00 +02:00
" { \n "
" auto_ptr<T> p2; \n "
" p2 = new T; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-06-16 20:26:00 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::vector< std::auto_ptr< ns1::MyClass> > v; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) You can randomly lose access to pointers if you store 'auto_ptr' pointers in an STL container. \n " , errout . str ( ) ) ;
2011-06-16 20:26:00 +02:00
check ( " void foo() \n "
" { \n "
" std::vector< auto_ptr< MyClass> > v; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) You can randomly lose access to pointers if you store 'auto_ptr' pointers in an STL container. \n " , errout . str ( ) ) ;
2011-06-16 20:26:00 +02:00
check ( " void foo() \n "
" { \n "
" int *i = new int; \n "
" auto_ptr<int> x(i); \n "
" auto_ptr<int> y; \n "
" y = x; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (style) Copying 'auto_ptr' pointer to another does not create two equal objects since one has lost its ownership of the pointer. \n " , errout . str ( ) ) ;
2011-06-16 20:26:00 +02:00
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
2012-12-06 19:19:22 +01:00
check ( " void f() \n "
2011-06-16 20:26:00 +02:00
" { \n "
" T* var = new T[10]; \n "
" auto_ptr<T> p2( var ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-06-16 20:26:00 +02:00
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 ( ) ) ;
2012-12-06 19:19:22 +01:00
check ( " void f() \n "
2011-11-06 15:32:28 +01:00
" { \n "
" foo::bar::baz* var = new foo::bar::baz[10]; \n "
" auto_ptr<foo::bar::baz> p2( var ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-06 15:32:28 +01:00
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 ( ) ) ;
2012-12-06 19:19:22 +01:00
check ( " void f() \n "
2011-06-16 20:26:00 +02:00
" { \n "
" auto_ptr<T> p2( new T[] ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-06-16 20:26:00 +02:00
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 ( ) ) ;
2012-12-06 19:19:22 +01:00
check ( " void f() \n "
2011-11-05 15:40:50 +01:00
" { \n "
" auto_ptr<T> p2( new T[5] ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-05 15:40:50 +01:00
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 ( ) ) ;
2012-12-06 19:19:22 +01:00
check ( " void f() \n "
2011-11-06 15:32:28 +01:00
" { \n "
" auto_ptr<foo::bar> p(new foo::bar[10]); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-06 15:32:28 +01:00
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 ( ) ) ;
2012-12-06 19:19:22 +01:00
check ( " void f() \n "
2011-06-16 20:26:00 +02:00
" { \n "
" auto_ptr<T> p2; \n "
" p2.reset( new T[] ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-06-16 20:26:00 +02:00
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 ( ) ) ;
2012-12-06 19:19:22 +01:00
check ( " void f() \n "
2011-06-16 20:26:00 +02:00
" { \n "
" auto_ptr<T> p2( new T[][] ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-06-16 20:26:00 +02:00
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 ( ) ) ;
2012-12-06 19:19:22 +01:00
check ( " void f() \n "
2011-06-16 20:26:00 +02:00
" { \n "
" auto_ptr<T> p2; \n "
" p2 = new T[10]; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-06-16 20:26:00 +02:00
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 ( ) ) ;
2012-12-06 19:19:22 +01:00
check ( " void f() \n "
2011-11-06 15:32:28 +01:00
" { \n "
" auto_ptr<T::B> p2; \n "
" p2 = new T::B[10]; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-06 15:32:28 +01:00
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 ( ) ) ;
2012-12-06 19:19:22 +01:00
check ( " void f() \n "
2011-06-16 20:26:00 +02:00
" { \n "
" auto_ptr<T> p2; \n "
" p2.reset( new T[10] ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-06-16 20:26:00 +02:00
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-11-06 15:32:28 +01:00
2012-12-06 19:19:22 +01:00
check ( " void f() \n "
2011-11-06 15:32:28 +01:00
" { \n "
" auto_ptr<T::B> p2; \n "
" p2.reset( new T::B[10] ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-06 15:32:28 +01:00
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-06-16 20:26:00 +02:00
2011-08-06 00:18:30 +02:00
// ticket #2887 (infinite loop)
2013-03-20 15:36:16 +01:00
check ( " A::A(std::auto_ptr<X> e){} " ) ;
2011-08-05 01:50:18 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-08-06 00:18:30 +02:00
2013-05-01 11:11:57 +02:00
// ticket #4390
check ( " auto_ptr<ConnectionStringReadStorage> CreateRegistryStringStorage() { \n "
" return auto_ptr<ConnectionStringReadStorage>(new RegistryConnectionStringStorage()); \n "
" } \n "
" \n "
" void LookupWindowsUserAccountName() { \n "
" auto_ptr_array<char> domainName(new char[42]); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-03-19 06:41:54 +01:00
// ticket #749
check ( " int main() \n "
" { \n "
" int *i = malloc(sizeof(int)); \n "
" auto_ptr<int> x(i); \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 function 'malloc'. \n " , errout . str ( ) ) ;
check ( " int main() \n "
2015-03-21 12:26:07 +01:00
" { \n "
" auto_ptr<int> x((int*)malloc(sizeof(int)*4)); \n "
" } " ) ;
2015-03-19 06:41:54 +01:00
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 function 'malloc'. \n " , errout . str ( ) ) ;
check ( " int main() \n "
2015-03-21 12:26:07 +01:00
" { \n "
" auto_ptr<int> b(static_cast<int*>(malloc(sizeof(int)*4))); \n "
" } " ) ;
2015-03-19 06:41:54 +01:00
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 function 'malloc'. \n " , errout . str ( ) ) ;
check ( " int main() \n "
2015-03-21 12:26:07 +01:00
" { \n "
" auto_ptr<int> x = (int*)malloc(sizeof(int)*4); \n "
" } " ) ;
2015-03-19 06:41:54 +01:00
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 function 'malloc'. \n " , errout . str ( ) ) ;
check ( " int main() \n "
2015-03-21 12:26:07 +01:00
" { \n "
" auto_ptr<int> x = static_cast<int*>(malloc(sizeof(int)*4)); \n "
" } " ) ;
2015-03-19 06:41:54 +01:00
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 function 'malloc'. \n " , errout . str ( ) ) ;
check ( " int main() \n "
2015-03-21 12:26:07 +01:00
" { \n "
" auto_ptr<int> x; \n "
" x.reset((int*)malloc(sizeof(int)*4)); \n "
" } " ) ;
2015-03-19 06:41:54 +01:00
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 function 'malloc'. \n " , errout . str ( ) ) ;
check ( " int main() \n "
2015-03-21 12:26:07 +01:00
" { \n "
" auto_ptr<int> x; \n "
" x.reset(static_cast<int*>(malloc(sizeof(int)*4))); \n "
" } " ) ;
2015-03-19 06:41:54 +01:00
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 function 'malloc'. \n " , errout . str ( ) ) ;
2011-06-16 20:26:00 +02:00
}
2014-11-20 14:20:09 +01:00
void uselessCalls ( ) {
2011-10-24 23:25:23 +02:00
check ( " void f() \n "
" { \n "
" string s1, s2; \n "
" s1.swap(s2); \n "
" s2.swap(s2); \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2016-02-02 20:26:02 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" std::string s1, s2; \n "
" s1.swap(s2); \n "
" s2.swap(s2); \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 "
2016-02-02 20:26:02 +01:00
" std::string s1, s2; \n "
2011-10-24 23:25:23 +02:00
" s1.compare(s2); \n "
" s2.compare(s2); \n "
" s1.compare(s2.c_str()); \n "
" s1.compare(0, s1.size(), s1); \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
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
2016-02-02 20:26:02 +01:00
// #7370 False positive uselessCallsCompare on unknown type
check ( " class ReplayIteratorImpl{ \n "
" int Compare(ReplayIteratorImpl* other) { \n "
" int cmp; \n "
" int ret = cursor_->compare(cursor_, other->cursor_, &cmp); \n "
" return (cmp); \n "
" } \n "
" WT_CURSOR *cursor_; \n "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-10-24 23:25:23 +02:00
check ( " void f() \n "
" { \n "
" int x=1; \n "
2014-04-13 19:04:35 +02:00
" std::string s1, s2; \n "
2011-10-24 23:25:23 +02:00
" s1 = s1.substr(); \n "
" s2 = s1.substr(x); \n "
" s1 = s2.substr(0, x); \n "
2012-09-05 19:46:44 +02:00
" s1 = s2.substr(0,std::string::npos); \n "
" s1 = s2.substr(x+5-n, 0); \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (performance) Ineffective call of function \' substr \' because it returns a copy of "
2012-04-04 19:40:28 +02:00
" the object. Use operator= instead. \n "
2012-10-14 11:16:48 +02:00
" [test.cpp:8]: (performance) Ineffective call of function \' substr \' because it returns a copy of "
2012-04-04 19:40:28 +02:00
" the object. Use operator= instead. \n "
2012-10-14 11:16:48 +02:00
" [test.cpp:9]: (performance) Ineffective call of function \' substr \' because it returns an empty string. \n " , errout . str ( ) ) ;
2011-10-24 23:25:23 +02:00
2014-04-13 19:04:35 +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 "
" s1 = s2.substr(x+5-n, 0); \n "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-07-07 20:21:08 +02:00
check ( " int main() \n "
2011-10-29 09:24:05 +02:00
" { \n "
" std::string str = \" a1b1 \" ; \n "
" return str.find(str[1], 2); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-07-12 12:23:52 +02:00
check ( " bool foo(std::vector<int>& v) { \n "
" v.empty(); \n "
" return v.empty(); \n "
" } " ) ;
2012-10-14 11:16:48 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Ineffective call of function 'empty()'. Did you intend to call 'clear()' instead? \n " , errout . str ( ) ) ;
2012-08-10 15:26:07 +02:00
2014-01-30 22:09:24 +01:00
check ( " void f() { \n " // #4938
" OdString str; \n "
" str.empty(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-08-10 15:26:07 +02:00
check ( " void f() { \n " // #4032
" const std::string greeting( \" Hello World !!! \" ); \n "
" const std::string::size_type npos = greeting.rfind( \" \" ); \n "
" if (npos != std::string::npos) \n "
" std::cout << greeting.substr(0, npos) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-08-21 11:30:27 +02:00
check ( " void f() { \n "
2016-02-02 20:26:02 +01:00
" std::vector<int> a; \n "
2012-08-21 11:30:27 +02:00
" std::remove(a.begin(), a.end(), val); \n "
2012-09-07 14:23:32 +02:00
" std::remove_if(a.begin(), a.end(), val); \n "
" std::unique(a.begin(), a.end(), val); \n "
2012-08-21 11:30:27 +02:00
" x = std::remove(a.begin(), a.end(), val); \n "
" a.erase(std::remove(a.begin(), a.end(), val)); \n "
2012-08-27 14:28:16 +02:00
" std::remove( \" foo.txt \" ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2016-02-02 20:26:02 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Return value of std::remove() ignored. Elements remain in container. \n "
" [test.cpp:4]: (warning) Return value of std::remove_if() ignored. Elements remain in container. \n "
" [test.cpp:5]: (warning) Return value of std::unique() ignored. Elements remain in container. \n " , errout . str ( ) ) ;
2012-12-25 12:50:38 +01:00
// #4431 - fp
check ( " bool f() { \n "
" return x ? true : (y.empty()); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-10-24 23:25:23 +02:00
}
2013-03-29 19:29:23 +01:00
2014-11-20 14:20:09 +01:00
void stabilityOfChecks ( ) {
2013-03-29 19:29:23 +01:00
// Stability test: 4684 cppcheck crash in template function call.
check ( " template<class T> \n "
" class EffectivityRangeData {}; \n "
" template<class T> \n "
" class EffectivityRange { \n "
" void unite() { \n "
" x < vector < EffectivityRangeData<int >> >(); \n "
" EffectivityRange<int> er; \n "
" } \n "
" void shift() { EffectivityRangeData<int>::iterator it; } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2013-04-05 06:14:59 +02:00
2014-11-20 14:20:09 +01:00
void dereferenceInvalidIterator ( ) {
2013-04-05 06:14:59 +02:00
// Test simplest "if" with && case
check ( " void foo(std::string::iterator& i) { \n "
" if (std::isalpha(*i) && i != str.end()) { \n "
" std::cout << *i; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Possible dereference of an invalid iterator: i \n " , errout . str ( ) ) ;
2014-04-12 19:54:31 +02:00
check ( " void foo(std::string::iterator& i) { \n "
" if(foo) { bar(); } \n "
" else if (std::isalpha(*i) && i != str.end()) { \n "
" std::cout << *i; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Possible dereference of an invalid iterator: i \n " , errout . str ( ) ) ;
2013-04-05 06:14:59 +02:00
// Test suggested correction doesn't report an error
check ( " void foo(std::string::iterator& i) { \n "
" if (i != str.end() && std::isalpha(*i)) { \n "
" std::cout << *i; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// Test "while" with "&&" case
check ( " void foo(std::string::iterator& i) { \n "
" while (std::isalpha(*i) && i != str.end()) { \n "
" std::cout << *i; \n "
" i ++; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Possible dereference of an invalid iterator: i \n " , errout . str ( ) ) ;
2014-04-12 19:54:31 +02:00
check ( " void foo(std::string::iterator& i) { \n "
" do { \n "
" std::cout << *i; \n "
" i ++; \n "
" } while (std::isalpha(*i) && i != str.end()); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (warning) Possible dereference of an invalid iterator: i \n " , errout . str ( ) ) ;
2013-04-05 06:14:59 +02:00
// Test "while" with "||" case
check ( " void foo(std::string::iterator& i) { \n "
" while (!(!std::isalpha(*i) || i == str.end())) { \n "
" std::cout << *i; \n "
" i ++; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Possible dereference of an invalid iterator: i \n " , errout . str ( ) ) ;
// Test fix for "while" with "||" case
check ( " void foo(std::string::iterator& i) { \n "
" while (!(i == str.end() || !std::isalpha(*i))) { \n "
" std::cout << *i; \n "
" i ++; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// Test "for" with "&&" case
check ( " void foo(std::string::iterator& i) { \n "
" for (; std::isalpha(*i) && i != str.end() ;) { \n "
" std::cout << *i; \n "
" i ++; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Possible dereference of an invalid iterator: i \n " , errout . str ( ) ) ;
// Test "for" with "||" case
check ( " void foo(std::string::iterator& i) { \n "
" for (; std::isalpha(*i) || i == str.end() ;) { \n "
" std::cout << *i; \n "
" i ++; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Possible dereference of an invalid iterator: i \n " , errout . str ( ) ) ;
// Test that a dereference outside the condition part of a "for"
// loop does not result in a false positive
check ( " void foo(std::string::iterator& i) { \n "
" for (char c = *i; isRunning && i != str.end() ;) { \n "
" std::cout << c; \n "
" i ++; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// Test that other "&&" terms in the condition don't invalidate the check
check ( " void foo(char* c, std::string::iterator& i) { \n "
" if (*c && std::isalpha(*i) && i != str.end()) { \n "
" std::cout << *i; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Possible dereference of an invalid iterator: i \n " , errout . str ( ) ) ;
// Test that dereference of different variable doesn't trigger a false positive
check ( " void foo(const char* c, std::string::iterator& i) { \n "
" if (std::isalpha(*c) && i != str.end()) { \n "
" std::cout << *c; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// Test case involving "rend()" instead of "end()"
check ( " void foo(std::string::iterator& i) { \n "
" while (std::isalpha(*i) && i != str.rend()) { \n "
" std::cout << *i; \n "
" i ++; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Possible dereference of an invalid iterator: i \n " , errout . str ( ) ) ;
// Test that mixed "&&" and "||" don't result in a false positive
check ( " void foo(std::string::iterator& i) { \n "
" if ((i == str.end() || *i) || (isFoo() && i != str.end())) { \n "
" std::cout << \" foo \" ; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2018-01-10 09:37:21 +01:00
void dereferenceInvalidIterator2 ( ) {
// Self-implemented iterator class
check ( " class iterator { \n "
" public: \n "
" CCommitPointer m_ptr; \n "
" iterator() {} \n "
" CCommitPointer& operator*() { \n "
" return m_ptr; \n "
" } \n "
" CCommitPointer* operator->() { \n "
" return &m_ptr; \n "
" } \n "
" iterator& operator++() { \n "
" ++m_ptr.m_place; \n "
" return *this; \n "
" } \n "
" }; \n "
" iterator begin() { \n "
" iterator it; \n "
" it->m_place = 0; \n "
" return it; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:18]: (error, inconclusive) Invalid iterator 'it' used. \n " , errout . str ( ) ) ;
}
2014-03-03 18:27:45 +01:00
2014-11-20 14:20:09 +01:00
void readingEmptyStlContainer ( ) {
2014-03-03 18:27:45 +01:00
check ( " void f() { \n "
" std::map<int, std::string> CMap; \n "
" std::string strValue = CMap[1]; \n "
" std::cout << strValue << CMap.size() << std::endl; \n "
" } \n " , true ) ;
2015-05-02 16:55:17 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style, inconclusive) Reading from empty STL container 'CMap' \n " , errout . str ( ) ) ;
2014-03-03 18:27:45 +01:00
check ( " void f() { \n "
" std::map<int,std::string> CMap; \n "
" std::string strValue = CMap[1]; "
" } \n " , true ) ;
2015-05-02 16:55:17 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style, inconclusive) Reading from empty STL container 'CMap' \n " , errout . str ( ) ) ;
2014-03-03 18:27:45 +01:00
check ( " void f() { \n "
" std::map<int,std::string> CMap; \n "
" CMap[1] = \" 123 \" ; \n "
" std::string strValue = CMap[1]; "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::vector<std::string> f() { \n "
" try { \n "
" std::vector<std::string> Vector; \n "
" std::vector<std::string> v2 = Vector; \n "
2014-03-18 12:38:22 +01:00
" std::string strValue = v2[1]; \n " // Do not complain here - this is a consecutive fault of the line above.
2014-03-03 18:27:45 +01:00
" } \n "
" return Vector; \n "
" } \n " , true ) ;
2015-05-02 16:55:17 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style, inconclusive) Reading from empty STL container 'Vector' \n " , errout . str ( ) ) ;
2014-03-03 18:27:45 +01:00
2017-01-06 11:53:17 +01:00
check ( " Vector f() { \n "
2014-03-03 18:27:45 +01:00
" try { \n "
" std::vector<std::string> Vector; \n "
" Vector.push_back( \" 123 \" ); \n "
" std::vector<std::string> v2 = Vector; \n "
" std::string strValue = v2[0]; \n "
" } \n "
" return Vector; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" std::map<std::string,std::string> mymap; \n "
" mymap[ \" Bakery \" ] = \" Barbara \" ; \n "
" std:string bakery_name = mymap[ \" Bakery \" ]; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" std::vector<int> v; \n "
" v.insert(1); \n "
" int i = v[0]; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-03-18 12:38:22 +01:00
check ( " void f() { \n "
" std::vector<int> v; \n "
" initialize(v); \n "
" int i = v[0]; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " char f() { \n "
" std::string s(foo); \n "
" return s[0]; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" std::vector<int> v = foo(); \n "
" if(bar) v.clear(); \n "
" int i = v.find(foobar); \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-11-20 14:15:00 +01:00
check ( " void f(std::set<int> v) { \n "
2014-03-18 12:38:22 +01:00
" v.clear(); \n "
" int i = v.find(foobar); \n "
" } " , true ) ;
2015-05-02 16:55:17 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style, inconclusive) Reading from empty STL container 'v' \n " , errout . str ( ) ) ;
2014-03-18 12:38:22 +01:00
2015-11-20 14:15:00 +01:00
check ( " void f(std::set<int> v) { \n "
" v.clear(); \n "
" v.begin(); \n "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style, inconclusive) Reading from empty STL container 'v' \n " , errout . str ( ) ) ;
check ( " void f(std::set<int> v) { \n "
" v.clear(); \n "
" *v.begin(); \n "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style, inconclusive) Reading from empty STL container 'v' \n " , errout . str ( ) ) ;
check ( " void f(std::set<int> v) { \n "
" v.clear(); \n "
" for(auto i = v.cbegin(); \n "
" i != v.cend(); ++i) {} \n "
" } " , true ) ;
2016-07-10 10:47:53 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style, inconclusive) Reading from empty STL container 'v' \n " , errout . str ( ) ) ;
2015-11-20 14:15:00 +01:00
check ( " void f(std::set<int> v) { \n "
" v.clear(); \n "
" foo(v.begin()); \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-03-03 18:27:45 +01:00
check ( " void f() { \n "
" std::map<int, std::string> CMap; \n "
" std::string strValue = CMap[1]; \n "
" std::string strValue2 = CMap[1]; \n "
" } \n " , true ) ;
2015-05-02 16:55:17 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style, inconclusive) Reading from empty STL container 'CMap' \n " , errout . str ( ) ) ;
2015-05-02 14:01:31 +02:00
// #4306
check ( " void f(std::vector<int> v) { \n "
" v.clear(); \n "
" for(int i = 0; i < v.size(); i++) { cout << v[i]; } \n "
" } " , true ) ;
2015-05-02 16:55:17 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style, inconclusive) Reading from empty STL container 'v' \n " , errout . str ( ) ) ;
2015-05-02 13:54:13 +02:00
2017-09-15 10:49:58 +02:00
// #7449 - nonlocal vector
check ( " std::vector<int> v; \n "
" void f() { \n "
" v.clear(); \n "
" dostuff() \n "
" if (v.empty()) { } \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::vector<int> v; \n "
" void f() { \n "
" v.clear(); \n "
" if (v.empty()) { } \n "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style, inconclusive) Reading from empty STL container 'v' \n " , errout . str ( ) ) ;
2015-05-02 13:54:13 +02:00
// #6663
check ( " void foo() { \n "
" std::set<int> container; \n "
" while (container.size() < 5) \n "
" container.insert(22); \n "
2015-05-11 13:10:11 +02:00
" } " , true ) ;
2015-05-02 13:54:13 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-05-11 13:10:11 +02:00
// #6679
check ( " class C { \n "
" C() { \n "
" switch (ret) { \n "
" case 1: \n "
" vec.clear(); \n "
" break; \n "
" case 2: \n "
" if (vec.empty()) \n "
" ; \n "
" break; \n "
" } \n "
" } \n "
" std::vector<int> vec; \n "
" }; " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " class C { \n "
" C() { \n "
" switch (ret) { \n "
" case 1: \n "
" vec.clear(); \n "
" case 2: \n "
" if (vec.empty()) \n "
" ; \n "
" break; \n "
" } \n "
" } \n "
" std::vector<int> vec; \n "
" }; " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " class C { \n "
" C() { \n "
" switch (ret) { \n "
" case 1: \n "
" vec.clear(); \n "
" if (vec.empty()) \n "
" ; \n "
" break; \n "
" } \n "
" } \n "
" std::vector<int> vec; \n "
" }; " , true ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (style, inconclusive) Reading from empty STL container 'vec' \n " , errout . str ( ) ) ;
2016-07-10 10:47:53 +02:00
// #7560
check ( " std::vector<int> test; \n "
" std::vector<int>::iterator it; \n "
" void Reset() { \n "
" test.clear(); \n "
" it = test.end(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-05-07 08:15:58 +02:00
// #8055
check ( " int main() { \n "
" std::string str; \n "
" auto l = [&]() { \n "
" if (str[0] == 'A') \n "
" std::cout << \" ! \" ; \n "
" } \n "
" str = \" A \" ; \n "
" l(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-09-02 22:22:32 +02:00
check ( " void f(const std::vector<std::string> &v) { \n "
" for (const std::string& s : v) { \n "
" if (s.find(x) != string::npos) {} \n "
" } \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-03-03 18:27:45 +01:00
}
2012-08-10 18:31:22 +02:00
} ;
2009-02-10 20:40:21 +01:00
REGISTER_TEST ( TestStl )