2009-02-10 20:40:21 +01:00
/*
* Cppcheck - A tool for static C / C + + code analysis
2023-01-28 10:16:34 +01:00
* Copyright ( C ) 2007 - 2023 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"
2022-01-27 19:03:20 +01:00
# include "errortypes.h"
2017-05-27 04:33:47 +02:00
# include "settings.h"
# include "standards.h"
2023-01-27 08:18:32 +01:00
# include "fixture.h"
2017-05-27 04:33:47 +02:00
# include "tokenize.h"
2022-09-27 20:03:25 +02:00
# include "utils.h"
2017-05-27 04:33:47 +02:00
# include <cstddef>
2023-03-02 21:50:14 +01:00
# include <list>
2022-09-16 07:15:49 +02:00
# include <sstream> // IWYU pragma: keep
2017-05-27 04:33:47 +02:00
# 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 :
2021-08-07 20:51:18 +02:00
TestStl ( ) : TestFixture ( " TestStl " ) { }
2009-02-10 20:40:21 +01:00
private :
2015-01-03 22:17:35 +01:00
Settings settings ;
2022-02-10 23:02:24 +01:00
void run ( ) override {
2021-02-24 22:00:06 +01:00
settings . severity . enable ( Severity : : warning ) ;
settings . severity . enable ( Severity : : style ) ;
settings . severity . enable ( Severity : : performance ) ;
2015-01-03 22:17:35 +01:00
LOAD_LIB_2 ( settings . library , " std.cfg " ) ;
2018-08-11 11:40:48 +02:00
TEST_CASE ( outOfBounds ) ;
2021-11-13 07:45:29 +01:00
TEST_CASE ( outOfBoundsSymbolic ) ;
2018-11-28 19:27:28 +01:00
TEST_CASE ( outOfBoundsIndexExpression ) ;
2020-08-26 21:05:17 +02:00
TEST_CASE ( outOfBoundsIterator ) ;
2018-08-11 11:40:48 +02:00
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
2018-09-02 21:04:45 +02:00
TEST_CASE ( iterator15 ) ; // #8341
2018-10-17 06:36:51 +02:00
TEST_CASE ( iterator16 ) ;
TEST_CASE ( iterator17 ) ;
TEST_CASE ( iterator18 ) ;
TEST_CASE ( iterator19 ) ;
TEST_CASE ( iterator20 ) ;
TEST_CASE ( iterator21 ) ;
2019-12-20 12:13:15 +01:00
TEST_CASE ( iterator22 ) ;
2019-12-31 08:09:04 +01:00
TEST_CASE ( iterator23 ) ;
2020-01-01 12:02:21 +01:00
TEST_CASE ( iterator24 ) ;
2020-06-01 08:53:08 +02:00
TEST_CASE ( iterator25 ) ; // #9742
2021-07-01 13:58:00 +02:00
TEST_CASE ( iterator26 ) ; // #9176
2021-07-24 22:44:18 +02:00
TEST_CASE ( iterator27 ) ; // #10378
2021-09-05 07:35:33 +02:00
TEST_CASE ( iterator28 ) ; // #10450
2018-07-26 22:00:48 +02:00
TEST_CASE ( iteratorExpression ) ;
2018-08-05 09:10:54 +02:00
TEST_CASE ( iteratorSameExpression ) ;
2020-06-06 17:54:56 +02:00
TEST_CASE ( mismatchingContainerIterator ) ;
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 ) ;
2023-02-24 01:10:19 +01:00
TEST_CASE ( popback1 ) ;
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
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-11 09:31:16 +01:00
TEST_CASE ( dereferenceInvalidIterator2 ) ; // #6572
2013-09-28 11:50:45 +02:00
TEST_CASE ( dereference_auto ) ;
2018-09-19 18:58:59 +02:00
TEST_CASE ( loopAlgoElementAssign ) ;
TEST_CASE ( loopAlgoAccumulateAssign ) ;
TEST_CASE ( loopAlgoContainerInsert ) ;
TEST_CASE ( loopAlgoIncrement ) ;
TEST_CASE ( loopAlgoConditional ) ;
TEST_CASE ( loopAlgoMinMax ) ;
2023-03-09 17:06:27 +01:00
TEST_CASE ( loopAlgoMultipleReturn ) ;
2019-07-18 10:56:44 +02:00
TEST_CASE ( invalidContainer ) ;
2020-04-04 11:47:02 +02:00
TEST_CASE ( invalidContainerLoop ) ;
2019-05-02 11:04:23 +02:00
TEST_CASE ( findInsert ) ;
2020-06-25 22:06:34 +02:00
2020-09-02 07:11:23 +02:00
TEST_CASE ( checkKnownEmptyContainer ) ;
2020-06-16 02:40:54 +02:00
TEST_CASE ( checkMutexes ) ;
2009-02-10 20:40:21 +01:00
}
2021-11-29 07:34:39 +01:00
# define check(...) check_(__FILE__, __LINE__, __VA_ARGS__)
void check_ ( const char * file , int line , const char code [ ] , const bool inconclusive = false , const Standards : : cppstd_t cppstandard = Standards : : CPPLatest ) {
2009-03-19 19:35:47 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
2009-03-18 22:40:38 +01:00
2021-02-24 22:00:06 +01:00
settings . certainty . setEnabled ( Certainty : : inconclusive , inconclusive ) ;
2015-05-17 20:02:41 +02:00
settings . standards . cpp = cppstandard ;
2010-12-01 18:00:55 +01:00
2019-03-08 20:19:40 +01:00
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 ) ;
2019-03-08 20:19:40 +01:00
2021-11-29 07:34:39 +01:00
ASSERT_LOC ( tokenizer . tokenize ( istr , " test.cpp " ) , file , line ) ;
2023-01-29 17:23:03 +01:00
runChecks < CheckStl > ( & tokenizer , & settings , this ) ;
2009-03-19 19:35:47 +01:00
}
2019-03-16 09:17:50 +01:00
2021-11-29 07:34:39 +01:00
void check_ ( const char * file , int line , const std : : string & code , const bool inconclusive = false ) {
check_ ( file , line , code . c_str ( ) , inconclusive ) ;
2012-07-16 13:17:14 +02:00
}
2009-03-19 19:35:47 +01:00
2021-11-29 07:34:39 +01:00
# define checkNormal(code) checkNormal_(code, __FILE__, __LINE__)
void checkNormal_ ( const char code [ ] , const char * file , int line ) {
2018-08-11 11:40:48 +02:00
// Clear the error buffer..
errout . str ( " " ) ;
// Tokenize..
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
2021-11-29 07:34:39 +01:00
ASSERT_LOC ( tokenizer . tokenize ( istr , " test.cpp " ) , file , line ) ;
2018-08-11 11:40:48 +02:00
// Check..
2023-01-29 17:23:03 +01:00
runChecks < CheckStl > ( & tokenizer , & settings , this ) ;
2018-08-11 11:40:48 +02:00
}
void outOfBounds ( ) {
setMultiline ( ) ;
2021-12-05 17:44:57 +01:00
checkNormal ( " bool f(const int a, const int b) \n " // #8648
" { \n "
" std::cout << a << b; \n "
" return true; \n "
" } \n "
" void f(const std::vector<int> &v) \n "
" { \n "
" if(v.size() >=2 && \n "
" bar(v[2], v[3]) ) \n " // v[3] is accessed
" {;} \n "
" } \n " ) ;
ASSERT_EQUALS ( " test.cpp:9:warning:Either the condition 'v.size()>=2' is redundant or v size can be 2. Expression 'v[2]' cause access out of bounds. \n "
" test.cpp:8:note:condition 'v.size()>=2' \n "
" test.cpp:9:note:Access out of bounds \n "
" test.cpp:9:warning:Either the condition 'v.size()>=2' is redundant or v size can be 2. Expression 'v[3]' cause access out of bounds. \n "
" test.cpp:8:note:condition 'v.size()>=2' \n "
" test.cpp:9:note:Access out of bounds \n " , errout . str ( ) ) ;
2018-11-28 07:03:56 +01:00
checkNormal ( " void f() { \n "
" std::string s; \n "
" s[10] = 1; \n "
" } " ) ;
2019-03-29 11:13:25 +01:00
ASSERT_EQUALS ( " test.cpp:3:error:Out of bounds access in expression 's[10]' because 's' is empty. \n " , errout . str ( ) ) ;
2018-11-28 07:03:56 +01:00
checkNormal ( " void f() { \n "
" std::string s = \" abcd \" ; \n "
" s[10] = 1; \n "
" } " ) ;
2019-03-29 11:13:25 +01:00
ASSERT_EQUALS ( " test.cpp:3:error:Out of bounds access in 's[10]', if 's' size is 4 and '10' is 10 \n " , errout . str ( ) ) ;
2018-11-28 07:03:56 +01:00
2018-08-11 11:40:48 +02:00
checkNormal ( " void f(std::vector<int> v) { \n "
" v.front(); \n "
" if (v.empty()) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-29 11:13:25 +01:00
ASSERT_EQUALS ( " test.cpp:2:warning:Either the condition 'v.empty()' is redundant or expression 'v.front()' cause access out of bounds. \n "
2018-08-11 11:40:48 +02:00
" test.cpp:3:note:condition 'v.empty()' \n "
" test.cpp:2:note:Access out of bounds \n " , errout . str ( ) ) ;
checkNormal ( " void f(std::vector<int> v) { \n "
" if (v.size() == 3) {} \n "
" v[16] = 0; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-29 11:13:25 +01:00
ASSERT_EQUALS ( " test.cpp:3:warning:Either the condition 'v.size()==3' is redundant or v size can be 3. Expression 'v[16]' cause access out of bounds. \n "
2018-08-11 11:40:48 +02:00
" test.cpp:2:note:condition 'v.size()==3' \n "
" test.cpp:3:note:Access out of bounds \n " , errout . str ( ) ) ;
checkNormal ( " void f(std::vector<int> v) { \n "
" int i = 16; \n "
" if (v.size() == 3) { \n "
" v[i] = 0; \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-29 11:13:25 +01:00
ASSERT_EQUALS ( " test.cpp:4:warning:Either the condition 'v.size()==3' is redundant or v size can be 3. Expression 'v[i]' cause access out of bounds. \n "
2018-08-11 11:40:48 +02:00
" test.cpp:3:note:condition 'v.size()==3' \n "
" test.cpp:4:note:Access out of bounds \n " , errout . str ( ) ) ;
checkNormal ( " void f(std::vector<int> v, int i) { \n "
" if (v.size() == 3 || i == 16) {} \n "
" v[i] = 0; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-08-11 11:40:48 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-08-11 18:57:21 +02:00
checkNormal ( " void f(std::map<int,int> x) { \n "
" if (x.empty()) { x[1] = 2; } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-08-11 18:57:21 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
checkNormal ( " void f(std::string s) { \n "
" if (s.size() == 1) { \n "
" s[2] = 0; \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-29 11:13:25 +01:00
ASSERT_EQUALS ( " test.cpp:3:warning:Either the condition 's.size()==1' is redundant or s size can be 1. Expression 's[2]' cause access out of bounds. \n "
2018-08-11 18:57:21 +02:00
" test.cpp:2:note:condition 's.size()==1' \n "
" test.cpp:3:note:Access out of bounds \n " , errout . str ( ) ) ;
2018-11-24 10:07:12 +01:00
// Do not crash
checkNormal ( " void a() { \n "
" std::string b[]; \n "
" for (auto c : b) \n "
" c.data(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-24 10:07:12 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-12-14 18:31:10 +01:00
checkNormal ( " std::string f(std::string x) { \n "
" if (x.empty()) return {}; \n "
" x[0]; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-12-14 18:31:10 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
checkNormal ( " std::string f(std::string x) { \n "
" if (x.empty()) return std::string{}; \n "
" x[0]; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-12-14 18:31:10 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-03-28 12:49:52 +01:00
checkNormal ( " void f() { \n "
" std::string s; \n "
" x = s.begin() + 1; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-29 11:13:25 +01:00
ASSERT_EQUALS ( " test.cpp:3:error:Out of bounds access in expression 's.begin()+1' because 's' is empty. \n " , errout . str ( ) ) ;
2019-03-29 15:20:17 +01:00
checkNormal ( " void f(int x) { \n "
" std::string s; \n "
" x = s.begin() + x; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-29 15:20:17 +01:00
ASSERT_EQUALS ( " test.cpp:3:error:Out of bounds access in expression 's.begin()+x' because 's' is empty and 'x' may be non-zero. \n " , errout . str ( ) ) ;
2019-08-12 12:58:53 +02:00
2019-08-12 20:24:16 +02:00
checkNormal ( " char fstr1(){const std::string s = \" <a><b> \" ; return s[42]; } \n "
2021-02-20 12:58:42 +01:00
" wchar_t fwstr1(){const std::wstring s = L \" <a><b> \" ; return s[42]; } " ) ;
2019-08-12 20:24:16 +02:00
ASSERT_EQUALS ( " test.cpp:1:error:Out of bounds access in 's[42]', if 's' size is 6 and '42' is 42 \n "
" test.cpp:2:error:Out of bounds access in 's[42]', if 's' size is 6 and '42' is 42 \n " , errout . str ( ) ) ;
checkNormal ( " char fstr1(){const std::string s = \" <a><b> \" ; return s[1]; } \n "
2021-02-20 12:58:42 +01:00
" wchar_t fwstr1(){const std::wstring s = L \" <a><b> \" ; return s[1]; } " ) ;
2019-08-12 20:24:16 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-08-12 12:58:53 +02:00
checkNormal ( " int f() { \n "
" std::vector<int> v; \n "
" std::vector<int> * pv = &v; \n "
" return (*pv)[42]; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-08-12 12:58:53 +02:00
ASSERT_EQUALS ( " test.cpp:4:error:Out of bounds access in expression '(*pv)[42]' because '*pv' is empty. \n " , errout . str ( ) ) ;
2019-08-24 15:40:29 +02:00
checkNormal ( " void f() { \n "
" std::string s; \n "
" ++abc[s]; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-09-01 09:44:34 +02:00
2019-09-03 06:43:54 +02:00
// # 9274
checkNormal ( " char f(bool b) { \n "
" const std::string s = \" <a><b> \" ; \n "
" int x = 6; \n "
" if(b) ++x; \n "
" return s[x]; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-09-03 06:43:54 +02:00
ASSERT_EQUALS ( " test.cpp:5:error:Out of bounds access in 's[x]', if 's' size is 6 and 'x' is 6 \n " , errout . str ( ) ) ;
2019-09-01 09:44:34 +02:00
checkNormal ( " void f() { \n "
" static const int N = 4; \n "
" std::array<int, N> x; \n "
" x[0] = 0; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-09-01 09:44:34 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-08-11 03:08:49 +02:00
checkNormal ( " void f(bool b) { \n "
" std::vector<int> x; \n "
" if (b) \n "
" x.push_back(1); \n "
" if (x.size() < 2) \n "
" return; \n "
" x[0] = 2; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-07 06:46:31 +02:00
checkNormal ( " void f(bool b) { \n "
" std::vector<int> v; \n "
" if(v.at(b?42:0)) {} \n "
" } \n " ) ;
2020-09-07 06:48:05 +02:00
ASSERT_EQUALS (
2021-11-13 07:45:29 +01:00
" test.cpp:3:error:Out of bounds access in expression 'v.at(b?42:0)' because 'v' is empty and 'b?42:0' may be non-zero. \n " ,
2020-09-07 06:48:05 +02:00
errout . str ( ) ) ;
2020-09-07 06:46:31 +02:00
checkNormal ( " void f(std::vector<int> v, bool b){ \n "
" if (v.size() == 1) \n "
" if(v.at(b?42:0)) {} \n "
" } \n " ) ;
2020-09-07 06:48:05 +02:00
ASSERT_EQUALS (
2021-11-13 07:45:29 +01:00
" test.cpp:3:warning:Either the condition 'v.size()==1' is redundant or v size can be 1. Expression 'v.at(b?42:0)' cause access out of bounds. \n "
2020-09-07 06:48:05 +02:00
" test.cpp:2:note:condition 'v.size()==1' \n "
" test.cpp:3:note:Access out of bounds \n " ,
errout . str ( ) ) ;
2021-01-08 10:29:32 +01:00
check ( " struct T { \n "
" std::vector<int>* v; \n "
" }; \n "
" struct S { \n "
" T t; \n "
" }; \n "
" long g(S& s); \n "
" int f() { \n "
" std::vector<int> ArrS; \n "
" S s = { { &ArrS } }; \n "
" g(s); \n "
" return ArrS[0]; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-01-21 19:50:57 +01:00
2021-06-03 07:31:46 +02:00
check ( " struct T { \n "
" std::vector<int>* v; \n "
" }; \n "
" struct S { \n "
" std::vector<T> t; \n "
" }; \n "
" long g(S& s); \n "
" int f() { \n "
" std::vector<int> ArrS; \n "
" S s = { { { &ArrS } } }; \n "
" g(s); \n "
" return ArrS[0]; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct T { \n "
" std::vector<int>* v; \n "
" }; \n "
" struct S { \n "
" std::vector<std::vector<T>> t; \n "
" }; \n "
" long g(S& s); \n "
" int f() { \n "
" std::vector<int> ArrS; \n "
" S s = { { { { &ArrS } } } }; \n "
" g(s); \n "
" return ArrS[0]; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct T { \n "
" std::vector<int>* v; \n "
" }; \n "
" struct S { \n "
" T t; \n "
" }; \n "
" long g(S& s); \n "
" int f() { \n "
" std::vector<int> ArrS; \n "
" S s { { &ArrS } }; \n "
" g(s); \n "
" return ArrS[0]; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct T { \n "
" std::vector<int>* v; \n "
" }; \n "
" struct S { \n "
" std::vector<T> t; \n "
" }; \n "
" long g(S& s); \n "
" int f() { \n "
" std::vector<int> ArrS; \n "
" S s { { { &ArrS } } }; \n "
" g(s); \n "
" return ArrS[0]; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct T { \n "
" std::vector<int>* v; \n "
" }; \n "
" struct S { \n "
" std::vector<std::vector<T>> t; \n "
" }; \n "
" long g(S& s); \n "
" int f() { \n "
" std::vector<int> ArrS; \n "
" S s { { { { &ArrS } } } }; \n "
" g(s); \n "
" return ArrS[0]; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-01-21 19:50:57 +01:00
checkNormal ( " extern void Bar(const double, const double); \n "
" void f(std::vector<double> &r, const double ) { \n "
" std::vector<double> result; \n "
" double d = 0.0; \n "
" const double inc = 0.1; \n "
" for(unsigned int i = 0; i < 10; ++i) { \n "
" result.push_back(d); \n "
" d = (i + 1) * inc; \n "
" } \n "
" Bar(1.0, d); \n "
" Bar(10U, result.size()); \n "
" Bar(0.0, result[0]); \n "
" Bar(0.34, result[1]); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-03-30 14:02:28 +02:00
checkNormal ( " void f(size_t entries) { \n "
" std::vector<uint8_t> v; \n "
" if (v.size() < entries + 2) \n "
" v.resize(entries + 2); \n "
" v[0] = 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
checkNormal ( " void f(size_t entries) { \n "
" std::vector<uint8_t> v; \n "
" if (v.size() < entries) \n "
" v.resize(entries); \n "
" v[0] = 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " test.cpp:5:error:Out of bounds access in expression 'v[0]' because 'v' is empty. \n " , errout . str ( ) ) ;
checkNormal ( " void f(size_t entries) { \n "
" if (entries < 2) return; \n "
" std::vector<uint8_t> v; \n "
" if (v.size() < entries) \n "
" v.resize(entries); \n "
" v[0] = 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
checkNormal ( " void f(size_t entries) { \n "
" if (entries == 0) return; \n "
" std::vector<uint8_t> v; \n "
" if (v.size() < entries) \n "
" v.resize(entries); \n "
" v[0] = 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-05-22 08:36:51 +02:00
checkNormal ( " void foo(std::vector<int>* PArr, int n) { \n "
" std::vector<int> Arr; \n "
" if (!PArr) \n "
" PArr = &Arr; \n "
" PArr->resize(n); \n "
" for (int i = 0; i < n; ++i) \n "
" (*PArr)[i] = 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-05-22 23:33:13 +02:00
checkNormal ( " int f() { \n "
" std::vector<int> v; \n "
" std::vector<int> * pv = &v; \n "
" return (*pv).at(42); \n "
" } \n " ) ;
2021-11-13 07:45:29 +01:00
ASSERT_EQUALS ( " test.cpp:4:error:Out of bounds access in expression '(*pv).at(42)' because '*pv' is empty. \n " ,
errout . str ( ) ) ;
2021-06-04 17:22:05 +02:00
checkNormal ( " std::string f(const char* DirName) { \n "
" if (DirName == nullptr) \n "
" return {}; \n "
" std::string Name{ DirName }; \n "
2021-10-11 19:16:51 +02:00
" if (!Name.empty() && Name.back() != ' \\ \\ ') \n "
" Name += ' \\ \\ '; \n "
2021-06-04 17:22:05 +02:00
" return Name; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-07-16 18:49:07 +02:00
checkNormal ( " bool f(bool b) { \n "
" std::vector<int> v; \n "
" if (b) \n "
" v.push_back(0); \n "
" for(auto i:v) \n "
" if (v[i] > 0) \n "
" return true; \n "
" return false; \n "
" } \n " ) ;
2023-03-09 17:06:27 +01:00
ASSERT_EQUALS ( " test.cpp:5:style:Consider using std::any_of algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
2021-07-16 18:49:07 +02:00
checkNormal ( " std::vector<int> range(int n); \n "
" bool f(bool b) { \n "
" std::vector<int> v; \n "
" if (b) \n "
" v.push_back(1); \n "
" assert(range(v.size()).size() == v.size()); \n "
" for(auto i:range(v.size())) \n "
" if (v[i] > 0) \n "
" return true; \n "
" return false; \n "
" } \n " ) ;
2023-03-09 17:06:27 +01:00
ASSERT_EQUALS ( " test.cpp:7:style:Consider using std::any_of algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
2021-07-26 22:22:23 +02:00
checkNormal ( " bool g(); \n "
" int f(int x) { \n "
" std::vector<int> v; \n "
" if (g()) \n "
" v.emplace_back(x); \n "
" const auto n = (int)v.size(); \n "
" for (int i = 0; i < n; ++i) \n "
" if (v[i] > 0) \n "
" return i; \n "
" return 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
checkNormal ( " bool g(); \n "
" int f(int x) { \n "
" std::vector<int> v; \n "
" if (g()) \n "
" v.emplace_back(x); \n "
" const auto n = static_cast<int>(v.size()); \n "
" for (int i = 0; i < n; ++i) \n "
" if (v[i] > 0) \n "
" return i; \n "
" return 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-08-02 10:51:34 +02:00
2021-08-26 19:37:29 +02:00
checkNormal ( " bool g(); \n "
" void f(int x) { \n "
" std::vector<int> v; \n "
" if (g()) \n "
" v.emplace_back(x); \n "
" const int n = v.size(); \n "
" h(n); \n "
" for (int i = 0; i < n; ++i) \n "
" h(v[i]); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-08-02 10:51:34 +02:00
checkNormal ( " void foo(const std::vector<int> &v) { \n "
" if(v.size() >=1 && v[0] == 4 && v[1] == 2){} \n "
" } \n " ) ;
ASSERT_EQUALS ( " test.cpp:2:warning:Either the condition 'v.size()>=1' is redundant or v size can be 1. Expression 'v[1]' cause access out of bounds. \n "
" test.cpp:2:note:condition 'v.size()>=1' \n "
" test.cpp:2:note:Access out of bounds \n " , errout . str ( ) ) ;
2021-08-16 09:19:07 +02:00
checkNormal ( " int f(int x, int y) { \n "
" std::vector<int> a = {0,1,2}; \n "
" if(x<2) \n "
" y = a[x] + 1; \n "
" else \n "
" y = a[x]; \n "
" return y; \n "
" } \n " ) ;
ASSERT_EQUALS (
" test.cpp:6:warning:Either the condition 'x<2' is redundant or 'x' can have the value greater or equal to 3. Expression 'a[x]' cause access out of bounds. \n "
" test.cpp:3:note:condition 'x<2' \n "
" test.cpp:6:note:Access out of bounds \n " ,
errout . str ( ) ) ;
checkNormal ( " int f(std::vector<int> v) { \n "
" if (v.size() > 3) \n "
" return v[v.size() - 3]; \n "
" return 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
checkNormal ( " void f(std::vector<int> v) { \n "
" v[v.size() - 1]; \n "
" if (v.size() == 1) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
checkNormal ( " void f(int n) { \n "
" std::vector<int> v = {1, 2, 3, 4}; \n "
" const int i = qMin(n, v.size()); \n "
" if (i > 1) \n "
" v[i] = 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-20 08:53:18 +01:00
2021-11-25 22:34:00 +01:00
checkNormal ( " void f(std::vector<int>& v, int i) { \n "
" if (i > -1) { \n "
" v.erase(v.begin() + i); \n "
" if (v.empty()) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-20 08:53:18 +01:00
checkNormal ( " void g(const char *, ...) { exit(1); } \n " // #10025
" void f(const char c[]) { \n "
" std::vector<int> v = get(); \n "
" if (v.empty()) \n "
" g( \" \" , c[0]); \n "
" return h(&v[0], v.size()); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-01-13 08:03:24 +01:00
checkNormal ( " void f(int i, std::vector<int> v) { \n " // #9157
" if (i <= (int)v.size()) { \n "
" if (v[i]) {} \n "
" } \n "
2022-09-30 14:43:21 +02:00
" if (i <= static_cast<int>(v.size())) { \n "
" if (v[i]) {} \n "
" } \n "
2022-01-13 08:03:24 +01:00
" } \n " ) ;
ASSERT_EQUALS ( " test.cpp:3:warning:Either the condition 'i<=(int)v.size()' is redundant or 'i' can have the value v.size(). Expression 'v[i]' cause access out of bounds. \n "
" test.cpp:2:note:condition 'i<=(int)v.size()' \n "
2022-09-30 14:43:21 +02:00
" test.cpp:3:note:Access out of bounds \n "
" test.cpp:6:warning:Either the condition 'i<=static_cast<int>(v.size())' is redundant or 'i' can have the value v.size(). Expression 'v[i]' cause access out of bounds. \n "
" test.cpp:5:note:condition 'i<=static_cast<int>(v.size())' \n "
" test.cpp:6:note:Access out of bounds \n " ,
2022-01-13 08:03:24 +01:00
errout . str ( ) ) ;
2022-01-18 14:48:02 +01:00
check ( " template<class Iterator> \n "
" void b(Iterator d) { \n "
" std::string c = \" a \" ; \n "
" d + c.length(); \n "
" } \n "
" void f() { \n "
" std::string buf; \n "
" b(buf.begin()); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " test.cpp:4:error:Out of bounds access in expression 'd+c.length()' because 'buf' is empty. \n " ,
errout . str ( ) ) ;
2022-01-21 09:56:41 +01:00
check ( " template<class Iterator> \n "
" void b(Iterator d) { \n "
" std::string c = \" a \" ; \n "
" sort(d, d + c.length()); \n "
" } \n "
" void f() { \n "
" std::string buf; \n "
" b(buf.begin()); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-02-25 05:53:51 +01:00
check ( " int f(const std::vector<int> &v) { \n "
" return !v.empty() ? 42 : v.back(); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS (
" test.cpp:2:warning:Either the condition 'v.empty()' is redundant or expression 'v.back()' cause access out of bounds. \n "
" test.cpp:2:note:condition 'v.empty()' \n "
" test.cpp:2:note:Access out of bounds \n " ,
errout . str ( ) ) ;
2022-03-04 17:13:13 +01:00
check ( " std::vector<int> g() { \n " // #10779
" std::vector<int> v(10); \n "
" for(int i = 0; i <= 10; ++i) \n "
" v[i] = 42; \n "
" return v; \n "
" } \n " ) ;
ASSERT_EQUALS ( " test.cpp:4:error:Out of bounds access in 'v[i]', if 'v' size is 10 and 'i' is 10 \n " ,
errout . str ( ) ) ;
check ( " void f() { \n "
" int s = 2; \n "
" std::vector <int> v(s); \n "
" v[100] = 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " test.cpp:4:error:Out of bounds access in 'v[100]', if 'v' size is 2 and '100' is 100 \n " ,
errout . str ( ) ) ;
check ( " void f() { \n "
" std::vector <int> v({ 1, 2, 3 }); \n "
" v[100] = 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " test.cpp:3:error:Out of bounds access in 'v[100]', if 'v' size is 3 and '100' is 100 \n " ,
errout . str ( ) ) ;
2022-03-06 07:41:09 +01:00
check ( " void f() { \n "
" char c[] = { 1, 2, 3 }; \n "
" std::vector<char> v(c, sizeof(c) + c); \n "
" v[100] = 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " test.cpp:4:error:Out of bounds access in 'v[100]', if 'v' size is 3 and '100' is 100 \n " ,
errout . str ( ) ) ;
check ( " void f() { \n "
" char c[] = { 1, 2, 3 }; \n "
" std::vector<char> v{ c, c + sizeof(c) }; \n "
" v[100] = 1; \n "
" } \n " ) ;
2022-04-06 06:25:28 +02:00
ASSERT_EQUALS ( " test.cpp:4:error:Out of bounds access in 'v[100]', if 'v' size is 3 and '100' is 100 \n " ,
errout . str ( ) ) ;
2022-03-06 07:41:09 +01:00
check ( " void f() { \n "
" int i[] = { 1, 2, 3 }; \n "
" std::vector<int> v(i, i + sizeof(i) / 4); \n "
" v[100] = 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " test.cpp:4:error:Out of bounds access in 'v[100]', if 'v' size is 3 and '100' is 100 \n " ,
errout . str ( ) ) ;
check ( " void f() { \n " // #6615
" int i[] = { 1, 2, 3 }; \n "
" std::vector<int> v(i, i + sizeof(i) / sizeof(int)); \n "
" v[100] = 1; \n "
" } \n " ) ;
TODO_ASSERT_EQUALS ( " test.cpp:4:error:Out of bounds access in 'v[100]', if 'v' size is 3 and '100' is 100 \n " ,
" " ,
errout . str ( ) ) ;
2022-04-05 07:34:20 +02:00
check ( " void f() { \n "
" std::array<int, 10> a = {}; \n "
" a[10]; \n "
" constexpr std::array<int, 10> b = {}; \n "
" b[10]; \n "
" const std::array<int, 10> c = {}; \n "
" c[10]; \n "
" static constexpr std::array<int, 10> d = {}; \n "
" d[10]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " test.cpp:3:error:Out of bounds access in 'a[10]', if 'a' size is 10 and '10' is 10 \n "
" test.cpp:5:error:Out of bounds access in 'b[10]', if 'b' size is 10 and '10' is 10 \n "
" test.cpp:7:error:Out of bounds access in 'c[10]', if 'c' size is 10 and '10' is 10 \n "
" test.cpp:9:error:Out of bounds access in 'd[10]', if 'd' size is 10 and '10' is 10 \n " ,
errout . str ( ) ) ;
2022-04-06 06:25:28 +02:00
check ( " struct test_fixed { \n "
" std::array<int, 10> array = {}; \n "
" void index(int i) { array[i]; } \n "
" }; \n "
" void f() { \n "
" test_fixed x = test_fixed(); \n "
" x.index(10); \n "
" } \n " ) ;
ASSERT_EQUALS ( " test.cpp:3:error:Out of bounds access in 'array[i]', if 'array' size is 10 and 'i' is 10 \n " ,
errout . str ( ) ) ;
check ( " struct test_constexpr { \n "
" static constexpr std::array<int, 10> array = {}; \n "
" void index(int i) { array[i]; } \n "
" }; \n "
" void f() { \n "
" test_constexpr x = test_constexpr(); \n "
" x.index(10); \n "
" } \n " ) ;
ASSERT_EQUALS ( " test.cpp:3:error:Out of bounds access in 'array[i]', if 'array' size is 10 and 'i' is 10 \n " ,
errout . str ( ) ) ;
2022-04-12 08:07:55 +02:00
checkNormal ( " struct A { \n "
" const std::vector<int>& v; \n "
" A(const std::vector<int>& x) : v(x) \n "
" {} \n "
" int f() const { \n "
" return v[0]; \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
checkNormal ( " struct A { \n "
" static const std::vector<int> v; \n "
" int f() const { \n "
" return v[0]; \n "
" } \n "
" }; \n "
" const std::vector<int> A::v = {1, 2}; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-05-05 06:54:44 +02:00
checkNormal ( " struct a { \n "
" std::vector<int> g() const; \n "
" }; \n "
" int f(const a& b) { \n "
" auto c = b.g(); \n "
" assert(not c.empty()); \n "
" int d = c.front(); \n "
" return d; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-06-23 20:26:47 +02:00
checkNormal ( " std::string f() { \n "
" std::map<int, std::string> m = { { 1, \" 1 \" } }; \n "
" return m.at(1); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-12-08 20:10:58 +01:00
checkNormal ( " struct A { \n "
" virtual void init_v(std::vector<int> *v) = 0; \n "
" }; \n "
" A* create_a(); \n "
" struct B { \n "
" B() : a(create_a()) {} \n "
" void init_v(std::vector<int> *v) { \n "
" a->init_v(v); \n "
" } \n "
" A* a; \n "
" }; \n "
" void f() { \n "
" B b; \n "
" std::vector<int> v; \n "
" b.init_v(&v); \n "
" v[0]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-12-09 19:43:21 +01:00
checkNormal ( " void f(std::vector<int>* v) { \n "
" if (v->empty()) \n "
" v->push_back(1); \n "
" auto x = v->back(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-28 19:27:28 +01:00
}
2018-11-24 10:07:12 +01:00
2021-11-13 07:45:29 +01:00
void outOfBoundsSymbolic ( )
{
check ( " void foo(std::string textline, int col) { \n "
" if(col > textline.size()) \n "
" return false; \n "
" int x = textline[col]; \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'col>textline.size()' is redundant or 'col' can have the value textline.size(). Expression 'textline[col]' cause access out of bounds. \n " ,
errout . str ( ) ) ;
}
2018-11-28 19:27:28 +01:00
void outOfBoundsIndexExpression ( ) {
setMultiline ( ) ;
2018-11-24 10:07:12 +01:00
2018-11-28 19:27:28 +01:00
checkNormal ( " void f(std::string s) { \n "
" s[s.size()] = 1; \n "
" } " ) ;
ASSERT_EQUALS ( " test.cpp:2:error:Out of bounds access of s, index 's.size()' is out of bounds. \n " , errout . str ( ) ) ;
checkNormal ( " void f(std::string s) { \n "
" s[s.size()+1] = 1; \n "
" } " ) ;
ASSERT_EQUALS ( " test.cpp:2:error:Out of bounds access of s, index 's.size()+1' is out of bounds. \n " , errout . str ( ) ) ;
checkNormal ( " void f(std::string s) { \n "
" s[1+s.size()] = 1; \n "
" } " ) ;
ASSERT_EQUALS ( " test.cpp:2:error:Out of bounds access of s, index '1+s.size()' is out of bounds. \n " , errout . str ( ) ) ;
checkNormal ( " void f(std::string s) { \n "
" s[x*s.size()] = 1; \n "
" } " ) ;
ASSERT_EQUALS ( " test.cpp:2:error:Out of bounds access of s, index 'x*s.size()' is out of bounds. \n " , errout . str ( ) ) ;
2022-07-30 16:15:32 +02:00
checkNormal ( " bool f(std::string_view& sv) { \n " // #10031
" return sv[sv.size()] == ' \\ 0'; \n "
" } \n " ) ;
ASSERT_EQUALS ( " test.cpp:2:error:Out of bounds access of sv, index 'sv.size()' is out of bounds. \n " , errout . str ( ) ) ;
2018-08-11 11:40:48 +02:00
}
2020-08-26 21:05:17 +02:00
void outOfBoundsIterator ( ) {
check ( " int f() { \n "
" std::vector<int> v; \n "
" auto it = v.begin(); \n "
" return *it; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Out of bounds access in expression 'it' because 'v' is empty. \n " ,
errout . str ( ) ) ;
check ( " int f() { \n "
" std::vector<int> v; \n "
" v.push_back(0); \n "
" auto it = v.begin() + 1; \n "
" return *it; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Out of bounds access in 'it', if 'v' size is 1 and 'it' is at position 1 from the beginning \n " ,
errout . str ( ) ) ;
check ( " int f() { \n "
" std::vector<int> v; \n "
" v.push_back(0); \n "
" auto it = v.end() - 1; \n "
" return *it; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f() { \n "
" std::vector<int> v; \n "
" v.push_back(0); \n "
" auto it = v.end() - 2; \n "
" return *it; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Out of bounds access in 'it', if 'v' size is 1 and 'it' is at position 2 from the end \n " ,
errout . str ( ) ) ;
check ( " void g(int); \n "
" void f(std::vector<int> x) { \n "
" std::map<int, int> m; \n "
" if (!m.empty()) { \n "
" g(m.begin()->second); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-04-07 06:47:15 +02:00
check ( " void f() { \n "
" std::vector<int> vec; \n "
" std::vector<int>::iterator it = vec.begin(); \n "
" *it = 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Out of bounds access in expression 'it' because 'vec' is empty. \n " ,
errout . str ( ) ) ;
check ( " void f() { \n "
" std::vector<int> vec; \n "
" auto it = vec.begin(); \n "
" *it = 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Out of bounds access in expression 'it' because 'vec' is empty. \n " ,
errout . str ( ) ) ;
2020-08-26 21:05:17 +02:00
}
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 "
2019-12-25 09:32:50 +01:00
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" for (std::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
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers 'l1' and 'l2' are used together. \n " ,
errout . str ( ) ) ;
2011-10-14 19:54:20 +02:00
2017-07-26 23:13:01 +02:00
check ( " void f() \n "
" { \n "
2019-12-25 09:32:50 +01:00
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" for (std::list<int>::iterator it = l1.begin(); l2.end() != it; ++it) \n "
2017-07-26 23:13:01 +02:00
" { } \n "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers 'l2' and 'l1' are used together. \n " ,
errout . str ( ) ) ;
2017-07-26 23:13:01 +02:00
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 "
2019-12-25 09:32:50 +01:00
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" for (std::list<int>::const_reverse_iterator it = l1.rbegin(); it != l2.rend(); ++it) \n "
2011-10-14 19:54:20 +02:00
" { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers 'l1' and 'l2' are used together. \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 "
2019-12-25 09:32:50 +01:00
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it = l1.begin(); \n "
2009-04-29 20:16:04 +02:00
" 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
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers 'l1' and 'l2' are used together. \n " ,
errout . str ( ) ) ;
2018-10-17 06:36:51 +02:00
check ( " void foo() \n "
" { \n "
2019-12-25 09:32:50 +01:00
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it = l1.begin(); \n "
2018-10-17 06:36:51 +02:00
" while (l2.end() != it) \n "
" { \n "
" ++it; \n "
" } \n "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Iterators of different containers 'l2' and 'l1' are used together. \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 "
2019-12-25 09:32:50 +01:00
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it = l1.begin(); \n "
2009-04-29 20:16:04 +02:00
" l2.insert(it, 0); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2022-04-07 06:47:15 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Same iterator is used with different containers 'l1' and 'l2'. \n "
" [test.cpp:6]: (error) Iterator 'it' from different container 'l2' are used together. \n " ,
errout . str ( ) ) ;
2016-08-04 09:35:16 +02:00
check ( " void foo() { \n " // #5803
2019-12-25 09:32:50 +01:00
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it = l1.begin(); \n "
2016-08-04 09:35:16 +02:00
" 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
2019-12-25 09:32:50 +01:00
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it = l1.begin(); \n "
" std::list<int>::iterator end = l1.end(); \n "
2016-08-14 10:49:48 +02:00
" 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 "
2019-12-25 09:32:50 +01:00
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it = l1.begin(); \n "
2016-08-06 18:07:41 +02:00
" l2.insert(it); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() { \n "
2019-12-25 09:32:50 +01:00
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it = l1.begin(); \n "
2016-08-06 18:07:41 +02:00
" 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 ( ) {
2020-09-02 07:11:23 +02:00
check ( " void foo(std::vector<int> ints1, std::vector<int> ints2) \n "
2009-10-18 18:42:01 +02:00
" { \n "
" std::vector<int>::iterator it = std::find(ints1.begin(), ints2.end(), 22); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2020-09-02 07:11:23 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Iterators of different containers 'ints1' and 'ints2' are used together. \n " ,
2019-12-25 09:32:50 +01:00
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 ( ) {
2020-09-02 07:11:23 +02:00
check ( " void foo(std::vector<int> ints1, std::vector<int> ints2) \n "
2011-10-18 21:55:41 +02:00
" { \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
" } " ) ;
2020-09-02 07:11:23 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Iterators of different containers 'ints1' and 'ints2' are used together. \n " ,
2019-12-25 09:32:50 +01:00
errout . str ( ) ) ;
2011-10-18 21:55:41 +02:00
2020-09-02 07:11:23 +02:00
check ( " void foo(std::vector<int> ints1, std::vector<int> ints2) \n "
2011-10-18 21:55:41 +02:00
" { \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 ( ) {
2020-09-02 07:11:23 +02:00
check ( " void foo(std::vector<int> ints1, std::vector<int> ints2) \n "
2011-10-18 21:55:41 +02:00
" { \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
" } " ) ;
2020-09-02 07:11:23 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Iterators of different containers 'ints1' and 'ints2' are used together. \n " ,
2019-12-25 09:32:50 +01:00
errout . str ( ) ) ;
2011-10-18 21:55:41 +02:00
2020-09-02 07:11:23 +02:00
check ( " void foo(std::vector<int> ints1, std::vector<int> ints2) \n "
2011-10-18 21:55:41 +02:00
" { \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
" } " ) ;
2020-09-02 07:11:23 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Iterators of different containers 'ints2' and 'ints1' are used together. \n " ,
2019-12-25 09:32:50 +01:00
errout . str ( ) ) ;
2012-04-17 12:21:41 +02:00
2020-09-02 07:11:23 +02:00
check ( " void foo(std::vector<int> ints1, std::vector<int> ints2) \n "
2012-04-17 12:21:41 +02:00
" { \n "
" std::vector<int>::iterator it = std::find_first_of(foo.bar.begin(), foo.bar.end()-6, ints2.begin(), ints1.end()); \n "
" } " ) ;
2020-09-02 07:11:23 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Iterators of different containers 'ints2' and 'ints1' are used together. \n " ,
2019-12-25 09:32:50 +01:00
errout . str ( ) ) ;
2011-10-18 21:55:41 +02:00
2020-09-02 07:11:23 +02:00
check ( " void foo(std::vector<int> ints1, std::vector<int> ints2) \n "
2011-10-18 21:55:41 +02:00
" { \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 "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( // TODO "[test.cpp:2]: (error) Iterators of different containers are used together.\n"
2019-12-26 15:48:17 +01:00
// TODO "[test.cpp:3]: (error) Iterators of different containers are used together.\n"
2019-12-25 09:32:50 +01:00
" [test.cpp:4]: (error) Iterators of different containers 'tp3' and 'a' are used together. \n "
" [test.cpp:5]: (error) Iterators of different containers 'tp4' and 'b' 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
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers 's1' and 's2' are used together. \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
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Iterators of different containers 'map1' and 'map2' are used together. \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) { } "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers 'map2' and 'map1' are used together. \n " ,
errout . str ( ) ) ;
2017-07-26 23:13:01 +02:00
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 "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Iterators of different containers 't' and 'a' are used together. \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 ( ) ) ;
}
2018-09-02 21:04:45 +02:00
void iterator15 ( ) {
check ( " void f(C1* x, std::list<int> a) { \n "
" std::list<int>::iterator pos = a.begin(); \n "
" for(pos = x[0]->plist.begin(); pos != x[0]->plist.end(); ++pos) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2018-10-17 06:36:51 +02:00
void iterator16 ( ) {
check ( " void foo() \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it1 = l1.begin(); \n "
" std::list<int>::iterator it2 = l2.end(); \n "
" while (it1 != it2) \n "
" { \n "
" ++it1; \n "
" } \n "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers 'l1' and 'l2' are used together. \n " ,
errout . str ( ) ) ;
2018-10-17 06:36:51 +02:00
check ( " void foo() \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it1 = l1.end(); \n "
" std::list<int>::iterator it2 = l2.begin(); \n "
" while (it2 != it1) \n "
" { \n "
" ++it2; \n "
" } \n "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Iterators of different containers 'l2' and 'l1' are used together. \n " ,
errout . str ( ) ) ;
2018-10-17 06:36:51 +02:00
check ( " void foo() \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it2 = l2.end(); \n "
" std::list<int>::iterator it1 = l1.begin(); \n "
" while (it1 != it2) \n "
" { \n "
" ++it1; \n "
" } \n "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Iterators of different containers 'l1' and 'l2' are used together. \n " ,
errout . str ( ) ) ;
2018-10-17 06:36:51 +02:00
check ( " void foo() \n "
" { \n "
2019-12-25 09:32:50 +01:00
" std::set<int> l1; \n "
" std::set<int> l2(10, 4); \n "
" std::set<int>::iterator it1 = l1.begin(); \n "
" std::set<int>::iterator it2 = l2.find(4); \n "
2018-10-17 06:36:51 +02:00
" while (it1 != it2) \n "
" { \n "
" ++it1; \n "
" } \n "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers 'l1' and 'l2' are used together. \n " ,
errout . str ( ) ) ;
2018-10-17 06:36:51 +02:00
}
void iterator17 ( ) {
check ( " void foo() \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it1 = l1.begin(); \n "
" std::list<int>::iterator it2 = l1.end(); \n "
" { it2 = l2.end(); } \n "
" while (it1 != it2) \n "
" { \n "
" ++it1; \n "
" } \n "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers 'l1' and 'l2' are used together. \n " ,
errout . str ( ) ) ;
2018-10-17 06:36:51 +02:00
check ( " void foo() \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it1 = l1.begin(); \n "
" std::list<int>::iterator it2 = l1.end(); \n "
" while (it1 != it2) \n "
" { \n "
" ++it1; \n "
" } \n "
" it2 = l2.end(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it1 = l1.begin(); \n "
" std::list<int>::iterator it2 = l1.end(); \n "
" it1 = l2.end(); \n "
" it1 = l1.end(); \n "
" if (it1 != it2) \n "
" { \n "
" ++it1; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it1 = l1.begin(); \n "
" std::list<int>::iterator it2 = l1.end(); \n "
" { it2 = l2.end(); } \n "
" it2 = l1.end(); \n "
" { it2 = l2.end(); } \n "
" while (it1 != it2) \n "
" { \n "
" ++it1; \n "
" } \n "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers 'l1' and 'l2' are used together. \n " ,
errout . str ( ) ) ;
2018-10-17 06:36:51 +02:00
}
void iterator18 ( ) {
2022-04-07 06:47:15 +02:00
check ( " void foo(std::list<int> l1, std::list<int> l2) \n "
2018-10-18 20:08:32 +02:00
" { \n "
" std::list<int>::iterator it1 = l1.begin(); \n "
" std::list<int>::iterator it2 = l1.end(); \n "
" while (++it1 != --it2) \n "
" { \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-04-07 06:47:15 +02:00
check ( " void foo(std::list<int> l1, std::list<int> l2) \n "
2018-10-18 20:08:32 +02:00
" { \n "
" std::list<int>::iterator it1 = l1.begin(); \n "
" std::list<int>::iterator it2 = l1.end(); \n "
" while (it1++ != --it2) \n "
" { \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-04-07 06:47:15 +02:00
check ( " void foo(std::list<int> l1, std::list<int> l2) \n "
2018-10-18 20:08:32 +02:00
" { \n "
" std::list<int>::iterator it1 = l1.begin(); \n "
" std::list<int>::iterator it2 = l1.end(); \n "
" if (--it2 > it1++) \n "
" { \n "
" } \n "
" } " ) ;
2022-04-07 06:47:15 +02:00
TODO_ASSERT_EQUALS ( " " , " [test.cpp:5]: (error) Dangerous comparison using operator< on iterator. \n " , errout . str ( ) ) ;
2018-10-17 06:36:51 +02:00
}
void iterator19 ( ) {
2018-10-18 20:08:32 +02:00
check ( " void foo() \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int>::iterator it1 = l1.begin(); \n "
" { \n "
" std::list<int> l1; \n "
" if (it1 != l1.end()) \n "
" { \n "
" } \n "
" } \n "
" } " ) ;
2021-12-04 12:55:56 +01:00
ASSERT_EQUALS (
" [test.cpp:7] -> [test.cpp:4]: (error) Same iterator is used with containers 'l1' that are temporaries or defined in different scopes. \n " ,
errout . str ( ) ) ;
2018-10-18 20:08:32 +02:00
check ( " void foo() \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int>::iterator it1 = l1.begin(); \n "
" { \n "
" std::list<int> l1; \n "
" if (l1.end() > it1) \n "
" { \n "
" } \n "
" } \n "
" } " ) ;
2019-12-25 09:32:50 +01:00
TODO_ASSERT_EQUALS (
" [test.cpp:7] -> [test.cpp:4]: (error) Same iterator is used with containers 'l1' that are defined in different scopes. \n " ,
2021-12-04 12:55:56 +01:00
" [test.cpp:7] -> [test.cpp:7]: (error) Same iterator is used with containers 'l1' that are temporaries or defined in different scopes. \n [test.cpp:7]: (error) Dangerous comparison using operator< on iterator. \n " ,
2019-12-25 09:32:50 +01:00
errout . str ( ) ) ;
2018-10-18 20:08:32 +02:00
check ( " void foo() \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int>::iterator it1 = l1.begin(); \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int>::iterator it2 = l1.begin(); \n "
" if (it1 != it2) \n "
" { \n "
" } \n "
" } \n "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS (
2021-12-04 12:55:56 +01:00
" [test.cpp:8] -> [test.cpp:4]: (error) Same iterator is used with containers 'l1' that are temporaries or defined in different scopes. \n " ,
2019-12-25 09:32:50 +01:00
errout . str ( ) ) ;
2018-10-18 20:08:32 +02:00
check ( " void foo() \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int>::iterator it1 = l1.begin(); \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int>::iterator it2 = l1.begin(); \n "
" if (it2 != it1) \n "
" { \n "
" } \n "
" } \n "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS (
2021-12-04 12:55:56 +01:00
" [test.cpp:8] -> [test.cpp:7]: (error) Same iterator is used with containers 'l1' that are temporaries or defined in different scopes. \n " ,
errout . str ( ) ) ;
check ( " std::set<int> g() { \n "
" static const std::set<int> s = {1}; \n "
" return s; \n "
" } \n "
" void f() { \n "
" if (g().find(2) == g().end()) {} \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:6] -> [test.cpp:6]: (error) Same iterator is used with containers 'g()' that are temporaries or defined in different scopes. \n " ,
2019-12-25 09:32:50 +01:00
errout . str ( ) ) ;
2022-07-30 16:15:32 +02:00
check ( " std::set<long> f() { \n " // #5804
" std::set<long> s; \n "
" return s; \n "
" } \n "
" void g() { \n "
" for (std::set<long>::iterator it = f().begin(); it != f().end(); ++it) {} \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:6] -> [test.cpp:6]: (error) Same iterator is used with containers 'f()' that are temporaries or defined in different scopes. \n " ,
errout . str ( ) ) ;
2018-10-17 06:36:51 +02:00
}
void iterator20 ( ) {
check ( " void foo() \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it1 = l1.begin(); \n "
" std::list<int>::iterator it2 = l2.begin(); \n "
" it1 = it2; \n "
" while (it1 != l1.end()) \n "
" { \n "
" ++it1; \n "
" } \n "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Iterators of different containers 'l2' and 'l1' are used together. \n " ,
errout . str ( ) ) ;
2018-10-17 06:36:51 +02:00
check ( " std::list<int> l3; \n "
" std::list<int>::iterator bar() \n "
" { \n "
" return l3.end(); \n "
" } \n "
" void foo() \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it1 = l1.begin(); \n "
" std::list<int>::iterator it2 = l2.begin(); \n "
" it1 = bar(); \n "
" while (it1 != it2) \n "
" { \n "
" ++it1; \n "
" } \n "
" } " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:13] -> [test.cpp:10] -> [test.cpp:11]: (error) Comparison of iterators from containers 'l1' and 'l2'. \n " , " " , errout . str ( ) ) ;
}
void iterator21 ( ) {
check ( " void foo() \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it1 = l1.end(); \n "
" std::list<int>::iterator it2 = l2.begin(); \n "
" if (it1 != it2) \n "
" { \n "
" } \n "
" if (it2 != it1) \n "
" { \n "
" } \n "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers 'l1' and 'l2' are used together. \n "
" [test.cpp:6]: (error) Iterators of different containers 'l2' and 'l1' are used together. \n " ,
errout . str ( ) ) ;
2018-10-17 06:36:51 +02:00
check ( " void foo() \n "
" { \n "
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>::iterator it1 = l1.end(); \n "
" std::list<int>::iterator it2 = l2.begin(); \n "
" if (it1 != it2 && it1 != it2) \n "
" { \n "
" } \n "
" } " ) ;
2019-12-25 09:32:50 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Iterators of different containers 'l1' and 'l2' are used together. \n " ,
errout . str ( ) ) ;
2019-12-20 12:13:15 +01:00
}
2018-10-17 06:36:51 +02:00
2019-12-20 12:13:15 +01:00
void iterator22 ( ) { // #7107
check ( " void foo() { \n "
" std::list<int> &l = x.l; \n "
" std::list<int>::iterator it = l.find(123); \n "
" x.l.erase(it); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-12-31 08:09:04 +01:00
}
void iterator23 ( ) { // #9550
check ( " struct A { \n "
" struct B { \n "
" bool operator==(const A::B& b) const; \n "
" int x; \n "
" int y; \n "
" int z; \n "
" }; \n "
" }; \n "
" bool A::B::operator==(const A::B& b) const { \n "
" return std::tie(x, y, z) == std::tie(b.x, b.y, b.z); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-12-31 08:09:04 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-01-01 12:02:21 +01:00
}
2020-01-04 00:25:37 +01:00
void iterator24 ( ) {
2020-01-04 00:06:27 +01:00
// #9556
2020-01-01 12:02:21 +01:00
check ( " void f(int a, int b) { \n "
" if (&a == &b) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-01-01 12:02:21 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int a, int b) { \n "
" if (std::for_each(&a, &b + 1, [](auto) {})) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-01-01 12:02:21 +01:00
ASSERT_EQUALS ( " [test.cpp:2]: (error) Iterators of different containers 'a' and 'b' are used together. \n " ,
errout . str ( ) ) ;
check ( " void f(int a, int b) { \n "
" if (std::for_each(&a, &b, [](auto) {})) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-01-01 12:02:21 +01:00
ASSERT_EQUALS ( " [test.cpp:2]: (error) Iterators of different containers 'a' and 'b' are used together. \n " ,
errout . str ( ) ) ;
check ( " void f(int a) { \n "
" if (std::for_each(&a, &a, [](auto) {})) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-01-01 12:02:21 +01:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Same iterators expression are used for algorithm. \n " , errout . str ( ) ) ;
check ( " void f(int a) { \n "
" if (std::for_each(&a, &a + 1, [](auto) {})) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-01-01 12:02:21 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-10-17 06:36:51 +02:00
}
2020-06-01 08:53:08 +02:00
void iterator25 ( ) {
// #9742
check ( " struct S { \n "
" std::vector<int>& v; \n "
" }; \n "
" struct T { \n "
" bool operator()(const S& lhs, const S& rhs) const { \n "
" return &lhs.v != &rhs.v; \n "
" } \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2020-06-01 08:53:08 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2021-07-01 21:09:32 +02:00
void iterator26 ( ) { // #9176
check (
" #include <map> \n "
" int main() \n "
" { "
" std::map<char const*, int> m{ { \" a \" , 1} }; \n "
" if (auto iter = m.find( \" x \" ); iter != m.end()) { \n "
" return iter->second; \n "
" } \n "
" return 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-07-01 13:58:00 +02:00
}
2021-08-01 14:05:30 +02:00
void iterator27 ( ) {
2021-07-26 16:32:00 +02:00
// #10378
2021-07-24 22:44:18 +02:00
check ( " struct A { \n "
" int a; \n "
" int b; \n "
" }; \n "
" int f(std::map<int, A> m) { \n "
" auto it = m.find( 1 ); \n "
" const int a( it == m.cend() ? 0 : it->second.a ); \n "
" const int b( it == m.cend() ? 0 : it->second.b ); \n "
" return a + b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2021-09-05 07:35:33 +02:00
void iterator28 ( )
{
// #10450
check ( " struct S { \n "
" struct Private { \n "
" std::list<int> l; \n "
" }; \n "
" std::unique_ptr<Private> p; \n "
" int foo(); \n "
" }; \n "
" int S::foo() { \n "
" for(auto iter = p->l.begin(); iter != p->l.end(); ++iter) { \n "
" if(*iter == 1) { \n "
" p->l.erase(iter); \n "
" return 1; \n "
" } \n "
" } \n "
" return 0; \n "
" } \n " ) ;
2022-10-16 13:46:26 +02:00
ASSERT_EQUALS ( " [test.cpp:10]: (style) Consider using std::find_if algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
2021-09-05 07:35:33 +02:00
}
2018-07-26 22:00:48 +02:00
void iteratorExpression ( ) {
check ( " std::vector<int>& f(); \n "
" std::vector<int>& g(); \n "
" void foo() { \n "
" (void)std::find(f().begin(), g().end(), 0); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2021-11-13 07:45:29 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Iterators of different containers 'f()' and 'g()' are used together. \n " ,
errout . str ( ) ) ;
2018-07-26 22:00:48 +02:00
2018-08-21 06:34:30 +02:00
check ( " std::vector<int>& f(); \n "
" std::vector<int>& g(); \n "
" void foo() { \n "
" if(f().begin() == g().end()) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2021-11-13 07:45:29 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Iterators of different containers 'f()' and 'g()' are used together. \n " ,
errout . str ( ) ) ;
2018-08-21 06:34:30 +02:00
check ( " std::vector<int>& f(); \n "
" std::vector<int>& g(); \n "
" void foo() { \n "
" auto size = f().end() - g().begin(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2021-11-13 07:45:29 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Iterators of different containers 'f()' and 'g()' are used together. \n " ,
errout . str ( ) ) ;
2018-08-21 06:34:30 +02:00
2018-07-26 22:00:48 +02:00
check ( " struct A { \n "
" std::vector<int>& f(); \n "
" std::vector<int>& g(); \n "
" }; \n "
" void foo() { \n "
" (void)std::find(A().f().begin(), A().g().end(), 0); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2021-12-04 17:00:55 +01:00
ASSERT_EQUALS (
" [test.cpp:6]: (error) Iterators of different containers 'A().f()' and 'A().g()' are used together. \n " ,
errout . str ( ) ) ;
2018-07-26 22:00:48 +02:00
check ( " struct A { \n "
" std::vector<int>& f(); \n "
" std::vector<int>& g(); \n "
" }; \n "
" void foo() { \n "
2018-11-24 10:07:12 +01:00
" (void)std::find(A{} .f().begin(), A{} .g().end(), 0); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2021-12-04 17:00:55 +01:00
ASSERT_EQUALS (
" [test.cpp:6]: (error) Iterators of different containers 'A{}.f()' and 'A{}.g()' are used together. \n " ,
errout . str ( ) ) ;
2018-07-26 22:00:48 +02:00
check ( " std::vector<int>& f(); \n "
" std::vector<int>& g(); \n "
" void foo() { \n "
" (void)std::find(begin(f()), end(g()), 0); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-07-26 22:00:48 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) Iterators to containers from different expressions 'f()' and 'g()' are used together. \n " , errout . str ( ) ) ;
check ( " struct A { \n "
" std::vector<int>& f(); \n "
" std::vector<int>& g(); \n "
" }; \n "
" void foo() { \n "
" (void)std::find(A().f().begin(), A().f().end(), 0); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-07-26 22:00:48 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::vector<int>& f(); \n "
" std::vector<int>& g(); \n "
" void foo() { \n "
2018-08-21 06:34:30 +02:00
" if(bar(f().begin()) == g().end()) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-08-21 06:34:30 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::vector<int>& f(); \n "
" void foo() { \n "
2021-11-13 07:45:29 +01:00
" auto it = f().end() - 1; \n "
2022-01-16 12:35:51 +01:00
" f().begin() - it; \n "
" f().begin()+1 - it; \n "
" f().begin() - (it + 1); \n "
" f().begin() - f().end(); \n "
" f().begin()+1 - f().end(); \n "
" f().begin() - (f().end() + 1); \n "
2018-07-26 22:00:48 +02:00
" (void)std::find(f().begin(), it, 0); \n "
" (void)std::find(f().begin(), it + 1, 0); \n "
" (void)std::find(f().begin() + 1, it + 1, 0); \n "
" (void)std::find(f().begin() + 1, it, 0); \n "
" (void)std::find(f().begin(), f().end(), 0); \n "
" (void)std::find(f().begin() + 1, f().end(), 0); \n "
" (void)std::find(f().begin(), f().end() - 1, 0); \n "
" (void)std::find(f().begin() + 1, f().end() - 1, 0); \n "
" (void)std::find(begin(f()), end(f())); \n "
" (void)std::find(begin(f()) + 1, end(f()), 0); \n "
" (void)std::find(begin(f()), end(f()) - 1, 0); \n "
" (void)std::find(begin(f()) + 1, end(f()) - 1, 0); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2023-03-09 17:06:53 +01:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Dereference of an invalid iterator: f().end()+1 \n " , errout . str ( ) ) ;
2018-08-21 06:34:30 +02:00
check ( " std::vector<int>& f(); \n "
" void foo() { \n "
" if(f().begin() == f().end()) {} \n "
" if(f().begin() == f().end()+1) {} \n "
" if(f().begin()+1 == f().end()) {} \n "
" if(f().begin()+1 == f().end()+1) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2023-03-09 17:06:53 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Dereference of an invalid iterator: f().end()+1 \n "
" [test.cpp:6]: (error) Dereference of an invalid iterator: f().end()+1 \n " ,
errout . str ( ) ) ;
check ( " std::vector<int>& f(); \n "
" void foo() { \n "
" if(std::begin(f()) == std::end(f())) {} \n "
" if(std::begin(f()) == std::end(f())+1) {} \n "
" if(std::begin(f())+1 == std::end(f())) {} \n "
" if(std::begin(f())+1 == std::end(f())+1) {} \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Dereference of an invalid iterator: std::end(f())+1 \n "
" [test.cpp:6]: (error) Dereference of an invalid iterator: std::end(f())+1 \n " ,
2021-11-13 07:45:29 +01:00
errout . str ( ) ) ;
2018-09-07 07:08:02 +02:00
2018-09-30 14:49:58 +02:00
check ( " template<int N> \n "
" std::vector<int>& f(); \n "
" void foo() { \n "
" if(f<1>().begin() == f<1>().end()) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-09-30 14:49:58 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-09-07 07:08:02 +02:00
check ( " void f() { \n "
" if (a.begin().x == b.begin().x) {} \n "
" if (begin(a).x == begin(b).x) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-09-07 07:08:02 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-09-12 17:33:53 +02:00
2020-08-26 21:05:17 +02:00
check ( " void f(std::list<int*> a, std::list<int*> b) { \n "
2018-09-12 17:33:53 +02:00
" if (*a.begin() == *b.begin()) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-09-30 14:49:58 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() { \n "
" if(f().begin(1) == f().end()) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-09-12 17:33:53 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-23 22:50:32 +01:00
check ( " void foo(const uint8_t* data, const uint32_t dataLength) { \n "
" const uint32_t minimumLength = sizeof(uint16_t) + sizeof(uint16_t); \n "
" if (dataLength >= minimumLength) { \n "
" char* payload = new char[dataLength - minimumLength]; \n "
" std::copy(&data[minimumLength], &data[dataLength], payload); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-07-26 22:00:48 +02:00
}
2018-08-05 09:10:54 +02:00
void iteratorSameExpression ( ) {
check ( " void f(std::vector<int> v) { \n "
" std::for_each(v.begin(), v.begin(), [](int){}); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-08-05 09:10:54 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Same iterators expression are used for algorithm. \n " , errout . str ( ) ) ;
check ( " std::vector<int>& g(); \n "
" void f() { \n "
" std::for_each(g().begin(), g().begin(), [](int){}); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-08-05 09:10:54 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Same iterators expression are used for algorithm. \n " , errout . str ( ) ) ;
check ( " void f(std::vector<int> v) { \n "
" std::for_each(v.end(), v.end(), [](int){}); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-08-05 09:10:54 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Same iterators expression are used for algorithm. \n " , errout . str ( ) ) ;
check ( " std::vector<int>& g(); \n "
" void f() { \n "
" std::for_each(g().end(), g().end(), [](int){}); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-08-05 09:10:54 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Same iterators expression are used for algorithm. \n " , errout . str ( ) ) ;
check ( " std::vector<int>::iterator g(); \n "
" void f(std::vector<int> v) { \n "
" std::for_each(g(), g(), [](int){}); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-08-05 09:10:54 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Same iterators expression are used for algorithm. \n " , errout . str ( ) ) ;
check ( " void f(std::vector<int>::iterator it) { \n "
" std::for_each(it, it, [](int){}); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-08-05 09:10:54 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Same iterators expression are used for algorithm. \n " , errout . str ( ) ) ;
}
2020-06-06 17:54:56 +02:00
void mismatchingContainerIterator ( ) {
check ( " std::vector<int> to_vector(int value) { \n "
" std::vector<int> a, b; \n "
" a.insert(b.end(), value); \n "
" return a; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-06-06 17:54:56 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Iterator 'b.end()' from different container 'a' are used together. \n " , errout . str ( ) ) ;
check ( " std::vector<int> f(std::vector<int> a, std::vector<int> b) { \n "
" a.erase(b.begin()); \n "
" return a; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-06-06 17:54:56 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (error) Iterator 'b.begin()' from different container 'a' are used together. \n " , errout . str ( ) ) ;
2020-11-10 09:38:05 +01:00
// #9973
check ( " void f() { \n "
" std::list<int> l1; \n "
" std::list<int> l2; \n "
" std::list<int>& l = l2; \n "
" for (auto it = l.begin(); it != l.end(); ++it) { \n "
" if (*it == 1) { \n "
" l.erase(it); \n "
" break; \n "
" } \n "
" } \n "
" } \n " ) ;
2022-10-16 13:46:26 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (style) Consider using std::find_if algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
2021-04-19 09:17:02 +02:00
// #10012
check ( " struct a { \n "
" int b; \n "
" int end() { return b; } \n "
" }; \n "
" void f(a c, a d) { \n "
" if (c.end() == d.end()) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-09-09 20:43:46 +02:00
// #10467
check ( " void f(std::array<std::vector<int>, N>& A) { \n "
" for (auto& a : A) { \n "
" auto it = std::find_if(a.begin(), a.end(), \n "
" [](auto i) { return i == 0; }); \n "
" if (it != a.end()) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-23 22:50:32 +01:00
// #10604
check ( " struct S { \n "
" std::vector<int> v; \n "
" }; \n "
" void f(S& s, int m) { \n "
" s.v.erase(s.v.begin() + m); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-06-06 17:54:56 +02:00
}
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 "
2019-03-28 12:49:52 +01:00
" std::vector<int> ints{1,2,3,4,5}; \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 "
2019-09-11 19:25:09 +02:00
" } " , true ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:6] -> [test.cpp:3] -> [test.cpp:7]: (error) Using iterator to local container 'ints' that may be invalid. \n " , " [test.cpp:5] -> [test.cpp:6] -> [test.cpp:3] -> [test.cpp:7]: (error, inconclusive) Using iterator to local container 'ints' that may be invalid. \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 ( ) ) ;
2018-04-26 08:57:25 +02:00
2018-04-27 10:29:10 +02:00
// #8509 Uniform initialization ignored for iterator
check ( " void f() { \n "
2018-04-26 08:57:25 +02:00
" std::vector<int> ints; \n "
" std::vector<int>::const_iterator iter {ints.cbegin()}; \n "
" std::cout << (*iter) << std::endl; \n "
" } " ) ;
2018-04-27 10:29:10 +02:00
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 "
2019-03-28 12:49:52 +01:00
" std::vector<int> ints{1,2,3,4,5}; \n "
2013-09-28 11:50:45 +02:00
" auto iter = ints.begin() + 2; \n "
" ints.erase(iter); \n "
" std::cout << (*iter) << std::endl; \n "
2019-09-11 19:25:09 +02:00
" } " , true ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:5] -> [test.cpp:3] -> [test.cpp:6]: (error) Using iterator to local container 'ints' that may be invalid. \n " , " [test.cpp:4] -> [test.cpp:5] -> [test.cpp:3] -> [test.cpp:6]: (error, inconclusive) Using iterator to local container 'ints' that may be invalid. \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
" } " ) ;
2021-11-13 07:45:29 +01:00
ASSERT_EQUALS (
" [test.cpp:6]: (error) Out of bounds access in expression 'foo[ii]' because 'foo' is empty and 'ii' may be non-zero. \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 ( ) ) ;
2020-01-05 16:24:25 +01:00
check ( " void foo(std::vector<int> foo) { \n "
" for (unsigned int ii = 0; ii <= foo.size() + 1; ++ii) { \n "
" foo.at(ii) = 0; \n "
" } \n "
" } " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:3]: (error) When ii==foo.size(), foo.at(ii) is out of bounds. \n " , " " , 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
" } " ) ;
2021-11-13 07:45:29 +01:00
ASSERT_EQUALS (
" [test.cpp:11]: (error) Out of bounds access in expression 'foo[ii]' because 'foo' is empty and 'ii' may be non-zero. \n " ,
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 ( ) ) ;
}
2020-01-05 16:24:25 +01:00
{
check ( " void foo(std::vector<int> foo) { \n "
" for (unsigned int ii = 0; ii <= foo.size() - 1; ++ii) { \n "
" foo.at(ii) = 0; \n "
" } \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 ( ) ) ;
2019-08-14 06:32:31 +02:00
check ( " int f(int x, const std::vector<int>& a) { \n "
" if (!(x < 5)) \n "
" return a[x - 5]; \n "
" else \n "
" return a[4 - x]; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-08-14 06:32:31 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-01-04 10:21:54 +01:00
check ( " std::array<int,6> values; \n "
" int get_value(); \n "
" int compute() { \n "
" int i = get_value(); \n "
" if( i < 0 || i > 5) \n "
" return -1; \n "
" int sum = 0; \n "
" for( int j = i+1; j < 7; ++j) \n "
" sum += values[j-1]; \n "
" return sum; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-08-22 11:04:02 +02:00
}
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
2019-12-25 09:32:50 +01:00
check ( " void f(vector< std::list<int> > &ints, unsigned int i) \n "
2010-10-15 18:11:41 +02:00
" { \n "
2019-12-25 09:32:50 +01:00
" std::list<int>::iterator it; \n "
2010-10-15 18:11:41 +02:00
" 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 "
2022-06-16 19:26:23 +02:00
" foo.erase(it); \n " // <- TODO: erase shound't cause inconclusive valueflow
2010-09-18 20:08:34 +02:00
" else \n "
" *it = 0; \n "
" } \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2022-06-16 19:26:23 +02:00
TODO_ASSERT_EQUALS (
" [test.cpp:5] -> [test.cpp:7] -> [test.cpp:8] -> [test.cpp:8] -> [test.cpp:7] -> [test.cpp:5] -> [test.cpp:9] -> [test.cpp:3] -> [test.cpp:5]: (error) Using iterator to local container 'foo' that may be invalid. \n " ,
" [test.cpp:5] -> [test.cpp:7] -> [test.cpp:8] -> [test.cpp:8] -> [test.cpp:7] -> [test.cpp:5] -> [test.cpp:9] -> [test.cpp:3] -> [test.cpp:5]: (error, inconclusive) Using iterator to local container 'foo' that may be invalid. \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 ( ) {
2019-12-25 09:32:50 +01:00
check ( " void f(std::list<int> &ints) \n "
2010-08-17 18:56:11 +02:00
" { \n "
2019-12-25 09:32:50 +01:00
" for (std::list<int>::iterator it = ints.begin(); it != ints.end();) { \n "
2010-08-17 18:56:11 +02:00
" if (*it == 123) { \n "
2019-12-25 09:32:50 +01:00
" std::list<int>::iterator copy = it; \n "
2010-08-17 18:56:11 +02:00
" ++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 "
2019-09-11 19:25:09 +02:00
" } " , true ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:4] -> [test.cpp:5] -> [test.cpp:1] -> [test.cpp:6]: (error) Using iterator to local container 'ints' that may be invalid. \n " , " [test.cpp:1] -> [test.cpp:4] -> [test.cpp:5] -> [test.cpp:1] -> [test.cpp:6]: (error, inconclusive) Using iterator to local container 'ints' that may be invalid. \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
2020-08-26 21:05:17 +02:00
check ( " void f(std::set<int> foo) \n "
2010-12-24 10:33:48 +01:00
" { \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 "
2019-07-18 10:56:44 +02:00
" std::list<int>::iterator aIt = m_ImplementationMap.begin(); \n "
2014-04-12 19:44:37 +02:00
" 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 "
2019-07-18 10:56:44 +02:00
" std::list<int>::iterator aIt = m_ImplementationMap.begin(); \n "
" std::list<int>::iterator bIt = m_ImplementationMap.begin(); \n "
2014-04-12 19:44:37 +02:00
" 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 "
2021-12-14 07:22:57 +01:00
" strlist.erase(str); \n "
2015-07-23 20:53:50 +02:00
" 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 "
2019-07-18 10:56:44 +02:00
" std::vector<int>::iterator aIt = m_ImplementationMap.begin(); \n "
2014-04-12 19:44:37 +02:00
" m_ImplementationMap.erase(something(unknown)); \n " // All iterators become invalidated when erasing from std::vector
" m_ImplementationMap.erase(aIt); \n "
" } " ) ;
2019-08-15 21:14:27 +02:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:2] -> [test.cpp:3] -> [test.cpp:1] -> [test.cpp:4]: (error) Using iterator to local container 'm_ImplementationMap' that may be invalid. \n " , errout . str ( ) ) ;
2014-04-12 19:44:37 +02:00
check ( " void f(const std::vector<int>& m_ImplementationMap) { \n "
2019-07-18 10:56:44 +02:00
" std::vector<int>::iterator aIt = m_ImplementationMap.begin(); \n "
2014-04-12 19:44:37 +02:00
" m_ImplementationMap.erase(*aIt); \n " // All iterators become invalidated when erasing from std::vector
" m_ImplementationMap.erase(aIt); \n "
" } " ) ;
2019-08-15 21:14:27 +02:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:2] -> [test.cpp:3] -> [test.cpp:1] -> [test.cpp:4]: (error) Using iterator to local container 'm_ImplementationMap' that may be invalid. \n " , errout . str ( ) ) ;
2014-04-12 19:44:37 +02:00
check ( " void f(const std::vector<int>& m_ImplementationMap) { \n "
2019-07-18 10:56:44 +02:00
" std::vector<int>::iterator aIt = m_ImplementationMap.begin(); \n "
" std::vector<int>::iterator bIt = m_ImplementationMap.begin(); \n "
2014-04-12 19:44:37 +02:00
" m_ImplementationMap.erase(*bIt); \n " // All iterators become invalidated when erasing from std::vector
" aIt = m_ImplementationMap.erase(aIt); \n "
" } " ) ;
2019-08-15 21:14:27 +02:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:2] -> [test.cpp:4] -> [test.cpp:1] -> [test.cpp:5]: (error) Using iterator to local container 'm_ImplementationMap' that may be invalid. \n " , errout . str ( ) ) ;
2014-04-12 19:44:37 +02:00
}
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
" } " ) ;
2019-08-15 21:14:27 +02:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:3] -> [test.cpp:4] -> [test.cpp:1] -> [test.cpp:5]: (error) Using iterator to local container 'foo' that 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
" } " ) ;
2019-07-18 10:56:44 +02:00
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:6] -> [test.cpp:8] -> [test.cpp:3] -> [test.cpp:6]: (error) Using iterator to local container 'foo' that 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
" } " ) ;
2019-07-18 10:56:44 +02:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:6] -> [test.cpp:3] -> [test.cpp:7]: (error) Using pointer to local variable 'ints' that may be invalid. \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 "
2019-07-18 10:56:44 +02:00
" std::vector<int> v; \n "
2019-05-11 19:11:40 +02:00
" v.push_back(1); \n "
" v.push_back(2); \n "
2019-07-18 10:56:44 +02:00
" for (std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) \n "
2009-09-27 09:59:19 +02:00
" { \n "
" if (*it == 1) \n "
" v.push_back(10); \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2019-07-18 10:56:44 +02:00
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:8] -> [test.cpp:8] -> [test.cpp:6] -> [test.cpp:9] -> [test.cpp:3] -> [test.cpp:6]: (error) Using iterator to local container 'v' that 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
" } " ) ;
2019-07-18 10:56:44 +02:00
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:8] -> [test.cpp:8] -> [test.cpp:6] -> [test.cpp:9] -> [test.cpp:3] -> [test.cpp:6]: (error) Using iterator to local container 'v' that 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
" } " ) ;
2019-07-18 10:56:44 +02:00
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:6] -> [test.cpp:8] -> [test.cpp:3] -> [test.cpp:6]: (error) Using iterator to local container 'foo' that 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
" } " ) ;
2022-10-16 13:46:26 +02:00
ASSERT_EQUALS ( " [test.cpp:10]: (style) Consider using std::accumulate algorithm instead of a raw loop. \n "
" [test.cpp:4] -> [test.cpp:5] -> [test.cpp:3] -> [test.cpp:8]: (error) Using iterator to local container 'ints' that 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
" } " ) ;
2019-08-15 21:14:27 +02:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:3] -> [test.cpp:4] -> [test.cpp:1] -> [test.cpp:5]: (error) Using iterator to local container 'foo' that 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
" } " ) ;
2019-07-18 10:56:44 +02:00
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:6] -> [test.cpp:8] -> [test.cpp:3] -> [test.cpp:6]: (error) Using iterator to local container 'foo' that 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 "
" } " ) ;
2020-02-13 16:27:06 +01:00
ASSERT_EQUALS (
" [test.cpp:4] -> [test.cpp:6] -> [test.cpp:3] -> [test.cpp:9]: (error, inconclusive) Using iterator to local container 'vec' that may be invalid. \n " ,
errout . str ( ) ) ;
2012-11-10 16:59:31 +01:00
}
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
" } " ) ;
2019-08-15 21:14:27 +02:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:3] -> [test.cpp:4] -> [test.cpp:1] -> [test.cpp:5]: (error) Using iterator to local container 'ints' that 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 "
2019-09-11 19:25:09 +02:00
" } " , true ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:5] -> [test.cpp:3] -> [test.cpp:6]: (error) Using iterator to local container 'ints' that may be invalid. \n " , " [test.cpp:4] -> [test.cpp:5] -> [test.cpp:3] -> [test.cpp:6]: (error, inconclusive) Using iterator to local container 'ints' that 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 "
" } " ) ;
2019-08-15 21:14:27 +02:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:2] -> [test.cpp:3] -> [test.cpp:1] -> [test.cpp:4]: (error) Using iterator to local container 'bars' that may be invalid. \n " , errout . str ( ) ) ;
2012-11-11 13:03:58 +01:00
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 "
" } " ) ;
2019-08-15 21:14:27 +02:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:2] -> [test.cpp:3] -> [test.cpp:1] -> [test.cpp:4]: (error) Using iterator to local container 'bars' that 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 ( ) ) ;
2020-02-13 16:27:06 +01:00
// TODO: This shouldn't be inconclusive
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 "
" bars.insert(i, bar); \n "
" i = bars.insert(i, bar); \n "
" } \n "
" } " ) ;
2020-02-13 16:27:06 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:2] -> [test.cpp:3] -> [test.cpp:1] -> [test.cpp:4]: (error, inconclusive) Using iterator to local container 'bars' that may be invalid. \n " , errout . str ( ) ) ;
2013-03-04 11:57:09 +01:00
2020-02-13 16:27:06 +01:00
// TODO: This shouldn't be inconclusive
2013-03-04 11:57:09 +01:00
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 "
" } " ) ;
2020-02-13 16:27:06 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:2] -> [test.cpp:3] -> [test.cpp:1] -> [test.cpp:4]: (error, inconclusive) Using iterator to local container 'bars' that 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
2023-02-24 01:10:19 +01:00
void popback1 ( ) { // #11553
check ( " void f() { \n "
" std::vector<int> v; \n "
" v.pop_back(); \n "
" std::list<int> l; \n "
" l.pop_front(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Out of bounds access in expression 'v.pop_back()' because 'v' is empty. \n "
" [test.cpp:5]: (error) Out of bounds access in expression 'l.pop_front()' because 'l' is empty. \n " ,
errout . str ( ) ) ;
check ( " void f(std::vector<int>& v) { \n "
" if (v.empty()) {} \n "
" v.pop_back(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'v.empty()' is redundant or expression 'v.pop_back()' cause access out of bounds. \n " ,
errout . str ( ) ) ;
check ( " void f(std::vector<int>& v) { \n "
" v.pop_back(); \n "
" if (v.empty()) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
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
2022-09-27 20:03:25 +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 "
2018-10-09 20:10:43 +02:00
" } " , true ) ;
2013-03-14 17:00:22 +01:00
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-10-09 20:10:43 +02:00
" } " , true ) ;
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 "
2018-10-09 20:10:43 +02:00
" } " , true ) ;
2015-11-08 09:42:28 +01:00
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 "
2021-11-13 07:45:29 +01:00
" 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 "
2021-11-13 07:45:29 +01:00
" 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 "
2021-11-13 07:45:29 +01:00
" 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 ( ) ) ;
2020-02-18 19:02:54 +01:00
check ( " void f(std::set<int> s) { \n "
" if (auto result = s.find(123); result != s.end()) {} \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
2019-12-01 14:53:03 +01:00
ASSERT_THROW ( check ( " void f() { \n "
" if (()) { } \n "
" } " ) ,
InternalError ) ;
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
" } " ) ;
2019-07-17 16:06:10 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Inefficient usage of string::find() in condition; string::starts_with() could 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 "
" } " ) ;
2019-07-17 16:06:10 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Inefficient usage of string::find() in condition; string::starts_with() could be faster. \n " , errout . str ( ) ) ;
2015-01-03 11:06:44 +01:00
// error (pointer)
check ( " void f(const std::string *s) \n "
" { \n "
" if (s->find( \" abc \" )) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2019-07-17 16:06:10 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Inefficient usage of string::find() in condition; string::starts_with() could 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
" } " ) ;
2019-07-17 16:06:10 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Inefficient usage of string::find() in condition; string::starts_with() could 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 "
" } " ) ;
2019-07-17 16:06:10 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Inefficient usage of string::find() in condition; string::starts_with() could 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 ( ) ) ;
2021-01-31 12:05:38 +01:00
// # 10153
check ( " int main() { \n "
" for (;;) { \n "
" std::string line = getLine(); \n "
" if (line.find( \" GL_EXTENSIONS = \" ) < 12) \n "
" return 1; \n "
" } \n "
" return 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 "
2021-08-07 20:51:18 +02:00
" { \n "
" std::list<int> x; \n "
" if (x.size() >= 1) {} \n "
" } " ;
2015-05-17 20:02:41 +02:00
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 "
2021-08-07 20:51:18 +02: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 ( ) ) ;
2021-01-04 10:07:07 +01:00
check ( " void f(const std::vector<std::string> &v) { \n "
" for(std::vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it) { \n "
2021-01-18 08:11:37 +01:00
" if(it+2 != v.end()) \n "
" { \n "
" ++it; \n "
2021-01-04 10:07:07 +01:00
" ++it; \n "
2021-01-18 08:11:37 +01:00
" } \n "
2021-01-04 10:07:07 +01:00
" } \n "
" } " ) ;
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 "
" } " ) ;
2022-10-16 13:46:26 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Consider using std::find_if algorithm instead of a raw loop. \n " , 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 "
" } " ) ;
2022-10-16 13:46:26 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Consider using std::find_if algorithm instead of a raw loop. \n " , 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 "
2021-02-20 12:52:39 +01:00
" void Foo2(const char* c, const std::string str) {} \n "
2012-02-25 12:43:27 +01:00
" 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 "
" } " ) ;
2021-02-20 12:52:39 +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:10]: (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. 1 is slow and redundant. \n " ,
errout . str ( ) ) ;
2012-02-25 12:43:27 +01:00
2022-08-21 13:04:43 +02:00
check ( " void f(const std::string& s); \n " // #8336
2022-08-22 14:06:10 +02:00
" struct T { \n "
" std::string g(); \n "
" std::string a[1]; \n "
2022-08-23 15:00:27 +02:00
" struct U { std::string s; } u; "
2022-08-22 14:06:10 +02:00
" }; \n "
2022-08-23 20:26:36 +02:00
" namespace N { namespace O { std::string s; } } \n "
2022-08-22 14:06:10 +02:00
" void g(const std::vector<std::string>& v, T& t) { \n "
2022-08-21 13:04:43 +02:00
" for (std::vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it) \n "
" f(it->c_str()); \n "
2022-08-22 14:06:10 +02:00
" f(v.begin()->c_str()); \n "
" f(t.g().c_str()); \n "
" f(t.a[0].c_str()); \n "
2022-08-23 15:00:27 +02:00
" f(t.u.s.c_str()); \n "
2022-08-23 20:26:36 +02:00
" f(N::O::s.c_str()); \n "
2022-08-21 13:04:43 +02:00
" } \n " ) ;
2022-08-23 20:26:36 +02: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 "
2022-08-22 14:06:10 +02:00
" [test.cpp:10]: (performance) Passing the result of c_str() to a function that takes std::string as argument no. 1 is slow and redundant. \n "
2022-08-23 15:00:27 +02:00
" [test.cpp:11]: (performance) Passing the result of c_str() to a function that takes std::string as argument no. 1 is slow and redundant. \n "
2022-08-23 20:26:36 +02:00
" [test.cpp:12]: (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:13]: (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:14]: (performance) Passing the result of c_str() to a function that takes std::string as argument no. 1 is slow and redundant. \n " ,
2022-08-21 13:04:43 +02:00
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 ( ) ) ;
2022-02-10 11:17:06 +01:00
check ( " void f(const wchar_t* w, int i = 0, ...); \n " // #10357
" void f(const std::string& s, int i = 0); \n "
" void g(const std::wstring& p) { \n "
" f(p.c_str()); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-03-13 06:27:17 +01:00
check ( " struct S { \n " //#9161
" const char* f() const noexcept { \n "
" return ( \" \" + m).c_str(); \n "
" } \n "
" std::string m; \n "
" }; \n " , /*inconclusive*/ true ) ;
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 ( ) ) ;
2022-04-13 12:25:53 +02:00
check ( " struct S { \n " // #10493
" void f(const char** pp); \n "
" std::string s; \n "
" }; \n "
" void S::f(const char** pp) { \n "
" try { \n "
" *pp = member.c_str(); \n "
" } \n "
" catch (...) { \n "
" s = \" xyz \" ; \n "
" *pp = member.c_str(); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-07-10 11:38:01 +02:00
check ( " std::string f(const std::string& a) { \n "
" std::string b(a.c_str()); \n "
" return b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (performance) Constructing a std::string from the result of c_str() is slow and redundant. \n " , errout . str ( ) ) ;
check ( " std::string f(const std::string& a) { \n "
" std::string b{ a.c_str() }; \n "
" return b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (performance) Constructing a std::string from the result of c_str() is slow and redundant. \n " , errout . str ( ) ) ;
check ( " std::string f(const std::string& a) { \n "
" std::string b = a.c_str(); \n "
" return b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (performance) Assigning the result of c_str() to a std::string is slow and redundant. \n " , errout . str ( ) ) ;
check ( " std::string g(const std::string& a, const std::string& b) { \n "
" return a + b.c_str(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (performance) Concatenating the result of c_str() and a std::string is slow and redundant. \n " , errout . str ( ) ) ;
check ( " std::string g(const std::string& a, const std::string& b) { \n "
" return a.c_str() + b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (performance) Concatenating the result of c_str() and a std::string is slow and redundant. \n " , errout . str ( ) ) ;
2022-07-11 22:58:08 +02:00
check ( " std::vector<double> v; \n " // don't crash
" int i; \n "
" void f() { \n "
" const double* const QM_R__ buf(v.data() + i); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-08-20 20:52:10 +02:00
2022-08-21 13:04:43 +02:00
check ( " struct T { \n " // #7515
" std::string g(); \n "
" std::string a[1]; \n "
" std::vector<std::string> v; \n "
" }; \n "
2022-08-20 20:52:10 +02:00
" void f(std::stringstream& strm, const std::string& s, T& t) { \n "
" strm << s.c_str(); \n "
" strm << \" abc \" << s.c_str(); \n "
" strm << \" abc \" << s.c_str() << \" def \" ; \n "
" strm << \" abc \" << t.g().c_str() << \" def \" ; \n "
" strm << t.a[0].c_str(); \n "
2022-08-21 13:04:43 +02:00
" strm << t.v.begin()->c_str(); \n "
" auto it = t.v.begin() \n "
" strm << it->c_str(); \n "
2022-08-20 20:52:10 +02:00
" } \n " ) ;
2022-08-21 13:04:43 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (performance) Passing the result of c_str() to a stream is slow and redundant. \n "
" [test.cpp:8]: (performance) Passing the result of c_str() to a stream is slow and redundant. \n "
" [test.cpp:9]: (performance) Passing the result of c_str() to a stream is slow and redundant. \n "
" [test.cpp:10]: (performance) Passing the result of c_str() to a stream is slow and redundant. \n "
" [test.cpp:11]: (performance) Passing the result of c_str() to a stream is slow and redundant. \n "
" [test.cpp:12]: (performance) Passing the result of c_str() to a stream is slow and redundant. \n "
" [test.cpp:14]: (performance) Passing the result of c_str() to a stream is slow and redundant. \n " ,
2022-08-20 20:52:10 +02:00
errout . str ( ) ) ;
2023-02-03 14:10:27 +01:00
check ( " struct S { std::string str; }; \n "
" struct T { S s; }; \n "
" struct U { T t[1]; }; \n "
" void f(const T& t, const U& u, std::string& str) { \n "
" if (str.empty()) \n "
" str = t.s.str.c_str(); \n "
" else \n "
" str = u.t[0].s.str.c_str(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (performance) Assigning the result of c_str() to a std::string is slow and redundant. \n "
" [test.cpp:8]: (performance) Assigning the result of c_str() to a std::string is slow and redundant. \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 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
2020-09-02 07:11:23 +02:00
check ( " void f(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
" } " ) ;
2020-09-02 07:11:23 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Return value of std::remove() ignored. Elements remain in container. \n "
" [test.cpp:3]: (warning) Return value of std::remove_if() ignored. Elements remain in container. \n "
" [test.cpp:4]: (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 ( ) ) ;
2018-07-10 22:57:59 +02:00
// #8360
check ( " void f(std::string s) { \n "
" for (;s.empty();) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-07-11 23:07:37 +02:00
// #11166
check ( " std::string f(std::string s) { \n "
" s = s.substr(0, s.size() - 1); \n "
" return s; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (performance) Ineffective call of function 'substr' because a prefix of the string is assigned to itself. Use resize() or pop_back() instead. \n " ,
errout . str ( ) ) ;
check ( " std::string f(std::string s, std::size_t start, std::size_t end, const std::string& i) { \n "
" s = s.substr(0, start) + i + s.substr(end + 1); \n "
" return s; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (performance) Ineffective call of function 'substr' because a prefix of the string is assigned to itself. Use replace() instead. \n " ,
errout . str ( ) ) ;
2022-07-12 17:40:14 +02:00
check ( " std::string f(std::string s, std::size_t end) { \n "
" s = { s.begin(), s.begin() + end }; \n "
" return s; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (performance) Inefficient constructor call: container 's' is assigned a partial copy of itself. Use erase() or resize() instead. \n " ,
errout . str ( ) ) ;
check ( " std::list<int> f(std::list<int> l, std::size_t end) { \n "
" l = { l.begin(), l.begin() + end }; \n "
" return l; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (performance) Inefficient constructor call: container 'l' is assigned a partial copy of itself. Use erase() or resize() instead. \n " ,
errout . str ( ) ) ;
check ( " std::string f(std::string s, std::size_t end) { \n "
" s = std::string{ s.begin(), s.begin() + end }; \n "
" return s; \n "
" } \n " ) ;
2022-07-21 22:15:16 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (performance) Inefficient constructor call: container 's' is assigned a partial copy of itself. Use erase() or resize() instead. \n " ,
errout . str ( ) ) ;
2022-07-12 17:40:14 +02:00
check ( " std::string f(std::string s, std::size_t end) { \n "
" s = std::string(s.begin(), s.begin() + end); \n "
" return s; \n "
" } \n " ) ;
2022-07-21 22:15:16 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (performance) Inefficient constructor call: container 's' is assigned a partial copy of itself. Use erase() or resize() instead. \n " ,
errout . str ( ) ) ;
check ( " std::vector<int> f(std::vector<int> v, std::size_t end) { \n "
" v = std::vector<int>(v.begin(), v.begin() + end); \n "
" return v; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (performance) Inefficient constructor call: container 'v' is assigned a partial copy of itself. Use erase() or resize() instead. \n " ,
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 "
2021-02-20 12:58:42 +01:00
" void shift() { EffectivityRangeData<int>::iterator it; } \n "
" }; " ) ;
2013-03-29 19:29:23 +01:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2013-04-05 06:14:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2014-04-12 19:54:31 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2013-04-05 06:14:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2013-04-05 06:14:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2014-04-12 19:54:31 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2013-04-05 06:14:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2013-04-05 06:14:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2013-04-05 06:14:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2013-04-05 06:14:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2013-04-05 06:14:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2013-04-05 06:14:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2013-04-05 06:14:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2013-04-05 06:14:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2013-04-05 06:14:59 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-08-17 23:36:45 +02:00
check ( " void f() { \n "
" std::vector <int> v; \n "
" std::vector <int>::iterator i = v.end(); \n "
" *i=0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Dereference of an invalid iterator: i \n " , errout . str ( ) ) ;
2023-03-09 17:06:53 +01:00
check ( " void f() { \n "
" std::vector <int> v; \n "
" std::vector <int>::iterator i = std::end(v); \n "
" *i=0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Dereference of an invalid iterator: i \n " , errout . str ( ) ) ;
2020-08-17 23:36:45 +02:00
check ( " void f(std::vector <int> v) { \n "
" std::vector <int>::iterator i = v.end(); \n "
" *i=0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dereference of an invalid iterator: i \n " , errout . str ( ) ) ;
check ( " void f(std::vector <int> v) { \n "
" std::vector <int>::iterator i = v.end(); \n "
" *(i+1)=0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dereference of an invalid iterator: i+1 \n " , errout . str ( ) ) ;
check ( " void f(std::vector <int> v) { \n "
" std::vector <int>::iterator i = v.end(); \n "
" *(i-1)=0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(std::vector <int> v) { \n "
" std::vector <int>::iterator i = v.begin(); \n "
" *(i-1)=0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dereference of an invalid iterator: i-1 \n " , errout . str ( ) ) ;
2023-03-09 17:06:53 +01:00
check ( " void f(std::vector <int> v) { \n "
" std::vector <int>::iterator i = std::begin(v); \n "
" *(i-1)=0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Dereference of an invalid iterator: i-1 \n " , errout . str ( ) ) ;
2020-08-17 23:36:45 +02:00
check ( " void f(std::vector <int> v, bool b) { \n "
" std::vector <int>::iterator i = v.begin(); \n "
" if (b) \n "
" i = v.end(); \n "
" *i=0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (warning) Possible dereference of an invalid iterator: i \n " , errout . str ( ) ) ;
check ( " void f(std::vector <int> v, bool b) { \n "
" std::vector <int>::iterator i = v.begin(); \n "
" if (b) \n "
" i = v.end(); \n "
" *(i+1)=0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (warning) Possible dereference of an invalid iterator: i+1 \n " , errout . str ( ) ) ;
check ( " void f(std::vector <int> v, bool b) { \n "
" std::vector <int>::iterator i = v.begin(); \n "
" if (b) \n "
" i = v.end(); \n "
" *(i-1)=0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (warning) Possible dereference of an invalid iterator: i-1 \n " , errout . str ( ) ) ;
2020-08-26 06:58:53 +02:00
check ( " int f(std::vector<int> v, int pos) { \n "
" if (pos >= 0) \n "
" return *(v.begin() + pos); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-08-28 19:29:09 +02:00
check ( " int f(std::vector<int> v, int i) { \n "
" auto it = std::find(v.begin(), v.end(), i); \n "
" if (it != v.end()) {} \n "
" return *it; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (warning) Either the condition 'it!=v.end()' is redundant or there is possible dereference of an invalid iterator: it. \n " , errout . str ( ) ) ;
check ( " void f(std::vector<int> & v) { \n "
" std::vector<int>::iterator i= v.begin(); \n "
" if(i == v.end() && *(i+1) == *i) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3]: (warning) Either the condition 'i==v.end()' is redundant or there is possible dereference of an invalid iterator: i+1. \n "
" [test.cpp:3] -> [test.cpp:3]: (warning) Either the condition 'i==v.end()' is redundant or there is possible dereference of an invalid iterator: i. \n " , errout . str ( ) ) ;
2020-08-31 08:46:56 +02:00
2020-08-28 19:29:09 +02:00
check ( " void f(std::vector<int> & v) { \n "
" std::vector<int>::iterator i= v.begin(); \n "
" if(i == v.end() && *i == *(i+1)) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3]: (warning) Either the condition 'i==v.end()' is redundant or there is possible dereference of an invalid iterator: i. \n "
" [test.cpp:3] -> [test.cpp:3]: (warning) Either the condition 'i==v.end()' is redundant or there is possible dereference of an invalid iterator: i+1. \n " , errout . str ( ) ) ;
2020-08-31 08:46:56 +02:00
check ( " void f(std::vector<int> & v) { \n "
" std::vector<int>::iterator i= v.begin(); \n "
" if(i != v.end() && *i == *(i+1)) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3]: (warning) Either the condition 'i!=v.end()' is redundant or there is possible dereference of an invalid iterator: i+1. \n " , errout . str ( ) ) ;
check ( " void f(std::vector<int> & v) { \n "
" std::vector<int>::iterator i= v.begin(); \n "
" if(i != v.end()) { \n "
" if (*(i+1) == *i) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (warning) Either the condition 'i!=v.end()' is redundant or there is possible dereference of an invalid iterator: i+1. \n " , errout . str ( ) ) ;
check ( " void f(std::vector<int> & v) { \n "
" std::vector<int>::iterator i= v.begin(); \n "
" if(i == v.end()) { return; } \n "
" if (*(i+1) == *i) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (warning) Either the condition 'i==v.end()' is redundant or there is possible dereference of an invalid iterator: i+1. \n " , errout . str ( ) ) ;
2020-09-01 20:00:04 +02:00
2020-08-31 08:46:56 +02:00
check ( " void f(std::vector<int> & v) { \n "
" std::vector<int>::iterator i= v.begin(); \n "
" if(i != v.end() && (i+1) != v.end() && *(i+1) == *i) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(std::string s) { \n "
" for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) { \n "
" if (i != s.end() && (i + 1) != s.end() && *(i + 1) == *i) { \n "
" if (!isalpha(*(i + 2))) { \n "
" std::string modifier; \n "
" modifier += *i; \n "
" modifier += *(i + 1); \n "
" } \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '(i+1)!=s.end()' is redundant or there is possible dereference of an invalid iterator: i+2. \n " , errout . str ( ) ) ;
2021-04-05 11:10:43 +02:00
check ( " void f(int v, std::map<int, int> &items) { \n "
" for (auto it = items.begin(); it != items.end();) \n "
" (it->first == v) ? it = items.erase(it) : ++it; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-08-31 08:46:56 +02:00
check ( " void f(std::string s) { \n "
" for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) { \n "
" if (i != s.end() && (i + 1) != s.end() && *(i + 1) == *i) { \n "
" if ((i + 2) != s.end() && !isalpha(*(i + 2))) { \n "
" std::string modifier; \n "
" modifier += *i; \n "
" modifier += *(i + 1); \n "
" } \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-04-06 11:04:37 +02:00
check ( " int f(std::vector<int>::iterator it, const std::vector<int>& vector) { \n "
" if (!(it != vector.end() && it != vector.begin())) \n "
" throw std::out_of_range(); \n "
" if (it != vector.end() && *it == 0) \n "
" return -1; \n "
" return *it; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-10-05 08:23:47 +02:00
check ( " int f(std::vector<int> &vect) { \n "
" const int &v = *vect.emplace(vect.end()); \n "
" return v; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-12-05 15:46:52 +01:00
check ( " extern bool bar(int); \n "
" void f(std::vector<int> & v) { \n "
" std::vector<int>::iterator i= v.begin(); \n "
" if(i == v.end() && bar(*(i+1)) ) {} \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:4] -> [test.cpp:4]: (warning) Either the condition 'i==v.end()' is redundant or there is possible dereference of an invalid iterator: i+1. \n " ,
errout . str ( ) ) ;
2021-12-15 19:31:28 +01:00
2021-12-16 22:34:51 +01:00
// #10657
check ( " std::list<int> mValues; \n "
" typedef std::list<int>::iterator ValueIterator; \n "
" void foo(ValueIterator beginValue, ValueIterator endValue) { \n "
" ValueIterator prevValue = beginValue; \n "
" ValueIterator curValue = beginValue; \n "
" for (++curValue; prevValue != endValue && curValue != mValues.end(); ++curValue) { \n "
" a = bar(*curValue); \n "
" prevValue = curValue; \n "
" } \n "
" if (endValue == mValues.end()) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-12-15 19:31:28 +01:00
// #10642
check ( " int f(std::vector<int> v) { \n "
" return *(v.begin() + v.size() - 1); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-01-14 23:50:33 +01:00
// #10716
check ( " struct a; \n "
" class b { \n "
" void c(std::map<std::string, a *> &); \n "
" std::string d; \n "
" std::map<std::string, std::set<std::string>> e; \n "
" }; \n "
" void b::c(std::map<std::string, a *> &) { \n "
" e.clear(); \n "
" auto f = *e[d].begin(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:9]: (error) Out of bounds access in expression 'e[d].begin()' because 'e[d]' is empty. \n " ,
errout . str ( ) ) ;
2022-02-03 21:13:48 +01:00
// #10151
check ( " std::set<int>::iterator f(std::set<int>& s) { \n "
" for (auto it = s.begin(); it != s.end(); ++it) \n "
" if (*it == 42) \n "
" return s.erase(it); \n "
" return s.end(); \n "
" } \n " ) ;
2022-10-16 13:46:26 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Consider using std::find_if algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
2022-12-20 20:29:19 +01:00
// #11381
check ( " int f(std::map<int, int>& map) { \n "
" auto it = map.find(1); \n "
" if (it == map.end()) { \n "
" bool bInserted; \n "
" std::tie(it, bInserted) = map.emplace(1, 42); \n "
" } \n "
" return debug_valueflow(it)->second; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-04-05 06:14:59 +02:00
}
2018-01-11 09:31:16 +01:00
void dereferenceInvalidIterator2 ( ) {
2018-01-10 09:37:21 +01:00
// 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 "
2021-02-20 12:58:42 +01:00
" }; \n "
2018-01-10 09:37:21 +01:00
" iterator begin() { \n "
2021-02-20 12:58:42 +01:00
" iterator it; \n "
2018-01-10 09:37:21 +01:00
" it->m_place = 0; \n "
2021-02-20 12:58:42 +01:00
" return it; \n "
2018-10-09 20:10:43 +02:00
" } \n " , true ) ;
2018-01-10 09:37:21 +01:00
ASSERT_EQUALS ( " [test.cpp:18]: (error, inconclusive) Invalid iterator 'it' used. \n " , errout . str ( ) ) ;
}
2018-09-19 18:58:59 +02:00
2018-09-21 08:53:09 +02:00
void loopAlgoElementAssign ( ) {
2018-09-19 18:58:59 +02:00
check ( " void foo() { \n "
" for(int& x:v) \n "
" x = 1; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Consider using std::fill algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" for(int& x:v) \n "
" x = x + 1; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Consider using std::transform algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " void foo(int a, int b) { \n "
" for(int& x:v) \n "
" x = a + b; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Consider using std::fill or std::generate algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" for(int& x:v) \n "
" x += 1; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Consider using std::transform algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" for(int& x:v) \n "
" x = f(); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Consider using std::generate algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" for(int& x:v) { \n "
" f(); \n "
" x = 1; \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() { \n "
" for(int& x:v) { \n "
" x = 1; \n "
" f(); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// There should probably be a message for unconditional break
check ( " void foo() { \n "
" for(int& x:v) { \n "
" x = 1; \n "
" break; \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() { \n "
" for(int& x:v) \n "
" x = ++x; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2018-09-21 08:53:09 +02:00
void loopAlgoAccumulateAssign ( ) {
2018-09-19 18:58:59 +02:00
check ( " void foo() { \n "
" int n = 0; \n "
" for(int x:v) \n "
" n += x; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::accumulate algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" int n = 0; \n "
" for(int x:v) \n "
" n = n + x; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::accumulate algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" int n = 0; \n "
" for(int x:v) \n "
" n += 1; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::distance algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" int n = 0; \n "
" for(int x:v) \n "
" n = n + 1; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::distance algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " bool f(int); \n "
" void foo() { \n "
" bool b = false; \n "
" for(int x:v) \n "
" b &= f(x); \n "
" } \n " ,
true ) ;
2022-10-16 13:46:26 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
check ( " bool f(int); \n "
" void foo() { \n "
" bool b = false; \n "
" for(int x:v) \n "
" b |= f(x); \n "
" } \n " ,
true ) ;
2022-10-16 13:46:26 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
check ( " bool f(int); \n "
" void foo() { \n "
" bool b = false; \n "
" for(int x:v) \n "
" b = b && f(x); \n "
" } \n " ,
true ) ;
2022-10-16 13:46:26 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
check ( " bool f(int); \n "
" void foo() { \n "
" bool b = false; \n "
" for(int x:v) \n "
" b = b || f(x); \n "
" } \n " ,
true ) ;
2022-10-16 13:46:26 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
check ( " void foo() { \n "
" int n = 0; \n "
" for(int& x:v) \n "
" n = ++x; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-10-16 13:46:26 +02:00
check ( " std::size_t f(const std::map<std::string, std::size_t>& m) { \n " // #10412
" std::size_t t = 0; \n "
" for (std::map<std::string, std::size_t>::const_iterator i = m.begin(); i != m.end(); ++i) { \n "
" t += i->second; \n "
" } \n "
" for (std::map<std::string, std::size_t>::const_iterator i = m.begin(); i != m.end(); i++) { \n "
" t += i->second; \n "
" } \n "
" return t; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::accumulate algorithm instead of a raw loop. \n "
" [test.cpp:7]: (style) Consider using std::accumulate algorithm instead of a raw loop. \n " ,
errout . str ( ) ) ;
check ( " int g(const std::vector<int>& v) { \n "
" int t = 0; \n "
" for (auto i = v.begin(); i != v.end(); ++i) { \n "
" t += *i; \n "
" } \n "
" return t; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::accumulate algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " auto g(const std::vector<int>& v) { \n "
" std::vector<std::vector<int>::iterator> r; \n "
" for (auto i = v.begin(); i != v.end(); ++i) { \n "
" r.push_back(i); \n "
" } \n "
" return r; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::string f(std::vector<std::string> v) { \n "
" std::string ret; \n "
" for (const std::string& s : v) \n "
" ret += s + ' \\ n'; \n "
" return ret; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::string f(const std::string& s) { \n "
" std::string ret; \n "
" for (char c : s) \n "
" if (c != ' ') \n "
" ret += i; \n "
" return ret; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f(const std::vector<int>& v) { \n "
" int sum = 0; \n "
" for (auto it = v.begin(); it != v.end(); it += 2) \n "
" sum += *it; \n "
" return sum; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
}
2018-09-21 08:53:09 +02:00
void loopAlgoContainerInsert ( ) {
2018-09-19 18:58:59 +02:00
check ( " void foo() { \n "
" std::vector<int> c; \n "
" for(int x:v) \n "
" c.push_back(x); \n "
" } \n " ,
true ) ;
2018-09-21 10:38:30 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::copy algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
check ( " void foo() { \n "
" std::vector<int> c; \n "
" for(int x:v) \n "
" c.push_back(f(x)); \n "
" } \n " ,
true ) ;
2018-09-21 10:38:30 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::transform algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
check ( " void foo() { \n "
" std::vector<int> c; \n "
" for(int x:v) \n "
" c.push_back(x + 1); \n "
" } \n " ,
true ) ;
2018-09-21 10:38:30 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::transform algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
check ( " void foo() { \n "
" std::vector<int> c; \n "
" for(int x:v) \n "
" c.push_front(x); \n "
" } \n " ,
true ) ;
2018-09-21 10:38:30 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::copy algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
check ( " void foo() { \n "
" std::vector<int> c; \n "
" for(int x:v) \n "
" c.push_front(f(x)); \n "
" } \n " ,
true ) ;
2018-09-21 10:38:30 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::transform algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
check ( " void foo() { \n "
" std::vector<int> c; \n "
" for(int x:v) \n "
" c.push_front(x + 1); \n "
" } \n " ,
true ) ;
2018-09-21 10:38:30 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::transform algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
check ( " void foo() { \n "
" std::vector<int> c; \n "
" for(int x:v) \n "
" c.push_back(v); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() { \n "
" std::vector<int> c; \n "
" for(int x:v) \n "
" c.push_back(0); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2018-09-21 08:53:09 +02:00
void loopAlgoIncrement ( ) {
2018-09-19 18:58:59 +02:00
check ( " void foo() { \n "
" int n = 0; \n "
" for(int x:v) \n "
" n++; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::distance algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" int n = 0; \n "
" for(int x:v) \n "
" ++n; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::distance algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" for(int& x:v) \n "
" x++; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Consider using std::transform algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" for(int& x:v) \n "
" ++x; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Consider using std::transform algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
}
2018-09-21 08:53:09 +02:00
void loopAlgoConditional ( ) {
2018-09-19 18:58:59 +02:00
check ( " bool pred(int x); \n "
" void foo() { \n "
" for(int& x:v) { \n "
" if (pred(x)) { \n "
2021-02-20 12:58:42 +01:00
" x = 1; \n "
2018-09-19 18:58:59 +02:00
" } \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (style) Consider using std::replace_if algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " bool pred(int x); \n "
" void foo() { \n "
" int n = 0; \n "
" for(int x:v) { \n "
" if (pred(x)) { \n "
2021-02-20 12:58:42 +01:00
" n += x; \n "
2018-09-19 18:58:59 +02:00
" } \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (style) Consider using std::accumulate algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " bool pred(int x); \n "
" void foo() { \n "
" int n = 0; \n "
" for(int x:v) { \n "
" if (pred(x)) { \n "
2021-02-20 12:58:42 +01:00
" n += 1; \n "
2018-09-19 18:58:59 +02:00
" } \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (style) Consider using std::count_if algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " bool pred(int x); \n "
" void foo() { \n "
" int n = 0; \n "
" for(int x:v) { \n "
" if (pred(x)) { \n "
2021-02-20 12:58:42 +01:00
" n++; \n "
2018-09-19 18:58:59 +02:00
" } \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (style) Consider using std::count_if algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " bool pred(int x); \n "
" void foo() { \n "
" for(int& x:v) { \n "
" if (pred(x)) { \n "
2021-02-20 12:58:42 +01:00
" x = x + 1; \n "
2018-09-19 18:58:59 +02:00
" } \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (style) Consider using std::transform algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " bool pred(int x); \n "
" void foo() { \n "
" std::vector<int> c; \n "
" for(int x:v) { \n "
" if (pred(x)) { \n "
2021-02-20 12:58:42 +01:00
" c.push_back(x); \n "
2018-09-19 18:58:59 +02:00
" } \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (style) Consider using std::copy_if algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " bool pred(int x); \n "
" bool foo() { \n "
" for(int x:v) { \n "
" if (pred(x)) { \n "
2021-02-20 12:58:42 +01:00
" return false; \n "
2018-09-19 18:58:59 +02:00
" } \n "
" } \n "
" return true; \n "
" } \n " ,
true ) ;
2023-03-09 17:06:27 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Consider using std::all_of or std::none_of algorithm instead of a raw loop. \n " ,
errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
check ( " bool pred(int x); \n "
" bool foo() { \n "
" for(int x:v) { \n "
" if (pred(x)) { \n "
2021-02-20 12:58:42 +01:00
" break; \n "
2018-09-19 18:58:59 +02:00
" } \n "
" } \n "
" return true; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::any_of algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " bool pred(int x); \n "
" void f(); \n "
" void foo() { \n "
" for(int x:v) { \n "
" if (pred(x)) { \n "
2021-02-20 12:58:42 +01:00
" f(); \n "
" break; \n "
2018-09-19 18:58:59 +02:00
" } \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (style) Consider using std::any_of algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " bool pred(int x); \n "
" void f(int x); \n "
" void foo() { \n "
" for(int x:v) { \n "
" if (pred(x)) { \n "
2021-02-20 12:58:42 +01:00
" f(x); \n "
" break; \n "
2018-09-19 18:58:59 +02:00
" } \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (style) Consider using std::find_if algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " bool pred(int x); \n "
" bool foo() { \n "
" bool b = false; \n "
" for(int x:v) { \n "
" if (pred(x)) { \n "
" b = true; \n "
" } \n "
" } \n "
" if(b) {} \n "
" return true; \n "
" } \n " ,
true ) ;
2022-10-16 13:46:26 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
check ( " bool pred(int x); \n "
" bool foo() { \n "
" bool b = false; \n "
" for(int x:v) { \n "
" if (pred(x)) { \n "
" b |= true; \n "
" } \n "
" } \n "
" return true; \n "
" } \n " ,
true ) ;
2022-10-16 13:46:26 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
check ( " bool pred(int x); \n "
" bool foo() { \n "
" bool b = false; \n "
" for(int x:v) { \n "
" if (pred(x)) { \n "
" b &= true; \n "
" } \n "
" } \n "
" return true; \n "
" } \n " ,
true ) ;
2022-10-16 13:46:26 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
check ( " bool pred(int x); \n "
" bool foo() { \n "
" for(int x:v) { \n "
" if (pred(x)) { \n "
2021-02-20 12:58:42 +01:00
" return false; \n "
2018-09-19 18:58:59 +02:00
" } \n "
" return true; \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// There is no transform_if
check ( " bool pred(int x); \n "
" void foo() { \n "
" std::vector<int> c; \n "
" for(int x:v) { \n "
" if (pred(x)) { \n "
2021-02-20 12:58:42 +01:00
" c.push_back(x + 1); \n "
2018-09-19 18:58:59 +02:00
" } \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool pred(int x); \n "
" void foo() { \n "
" for(int& x:v) { \n "
" x++; \n "
" if (pred(x)) { \n "
2021-02-20 12:58:42 +01:00
" x = 1; \n "
2018-09-19 18:58:59 +02:00
" } \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool pred(int x); \n "
" void f(); \n "
" void foo() { \n "
" for(int x:v) { \n "
" if (pred(x)) { \n "
" if(x) { return; } \n "
2021-02-20 12:58:42 +01:00
" break; \n "
2018-09-19 18:58:59 +02:00
" } \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-12-18 16:52:04 +01:00
check ( " bool g(int); \n "
" int f(const std::vector<int>& v) { \n "
" int ret = 0; \n "
" for (const auto i : v) \n "
" if (!g(i)) \n "
" ret = 1; \n "
" return ret; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f(const std::vector<int>& v) { \n "
" int ret = 0; \n "
" for (const auto i : v) \n "
" if (i < 5) \n "
" ret = 1; \n "
" return ret; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (style) Consider using std::any_of, std::all_of, std::none_of algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
2023-02-07 21:57:59 +01:00
check ( " struct T { \n "
" std::vector<int> v0, v1; \n "
" void g(); \n "
" }; \n "
" void T::g() { \n "
" for (std::vector<int>::const_iterator it0 = v0.cbegin(); it0 != v0.cend(); ++it0) { \n "
" std::vector<int>::iterator it1; \n "
" for (it1 = v1.begin(); it1 != v1.end(); ++it1) \n "
" if (*it0 == *it1) \n "
" break; \n "
" if (it1 != v1.end()) \n "
" v1.erase(it1); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:9]: (style) Consider using std::find_if algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
2023-03-04 11:58:12 +01:00
check ( " bool f(const std::set<std::string>& set, const std::string& f) { \n " // #11595
" for (const std::string& s : set) { \n "
" if (f.length() >= s.length() && f.compare(0, s.length(), s) == 0) { \n "
" return true; \n "
" } \n "
" } \n "
" return false; \n "
" } \n " ) ;
2023-03-09 17:06:27 +01:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Consider using std::any_of algorithm instead of a raw loop. \n " ,
errout . str ( ) ) ;
2018-09-19 18:58:59 +02:00
}
2018-09-21 08:53:09 +02:00
void loopAlgoMinMax ( ) {
2018-09-19 18:58:59 +02:00
check ( " void foo() { \n "
" int n = 0; \n "
" for(int x:v) \n "
" n = x > n ? x : n; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::max_element algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" int n = 0; \n "
" for(int x:v) \n "
" n = x < n ? x : n; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::min_element algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" int n = 0; \n "
" for(int x:v) \n "
" n = x > n ? n : x; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::min_element algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" int n = 0; \n "
" for(int x:v) \n "
" n = x < n ? n : x; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::max_element algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
check ( " void foo(int m) { \n "
" int n = 0; \n "
" for(int x:v) \n "
" n = x > m ? x : n; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::accumulate algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
}
2019-05-02 11:04:23 +02:00
2023-03-09 17:06:27 +01:00
void loopAlgoMultipleReturn ( )
{
check ( " bool f(const std::vector<int>& v) { \n "
" for (auto i : v) { \n "
" if (i < 0) \n "
" continue; \n "
" if (i) \n "
" return true; \n "
" } \n "
" return false; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Consider using std::any_of algorithm instead of a raw loop. \n " ,
errout . str ( ) ) ;
check ( " bool g(const std::vector<int>& v) { \n "
" for (auto i : v) { \n "
" if (i % 5 == 0) \n "
" return true; \n "
" if (i % 7 == 0) \n "
" return true; \n "
" } \n "
" return false; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Consider using std::any_of algorithm instead of a raw loop. \n " ,
errout . str ( ) ) ;
check ( " bool g(const std::vector<int>& v) { \n "
" for (auto i : v) { \n "
" if (i % 5 == 0) \n "
" return false; \n "
" if (i % 7 == 0) \n "
" return true; \n "
" } \n "
" return false; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool g(std::vector<int>& v) { \n "
" for (auto& i : v) { \n "
" if (i % 5 == 0) \n "
" return false; \n "
" if (i % 7 == 0) \n "
" i++; \n "
" } \n "
" return false; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool g(const std::vector<int>& v, int& j) { \n "
" for (auto i : v) { \n "
" if (i % 5 == 0) \n "
" return false; \n "
" if (i % 7 == 0) \n "
" j++; \n "
" } \n "
" return false; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool g(const std::vector<int>& v, int& j) { \n "
" for (auto i : v) { \n "
" int& k = j; \n "
" if (i % 5 == 0) \n "
" return false; \n "
" if (i % 7 == 0) \n "
" k++; \n "
" } \n "
" return false; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool g(const std::vector<int>& v, int& j) { \n "
" for (auto i : v) { \n "
" int* k = &j; \n "
" if (i % 5 == 0) \n "
" return false; \n "
" if (i % 7 == 0) \n "
" (*k)++; \n "
" } \n "
" return false; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool g(const std::vector<int>& v, int j) { \n "
" for (auto i : v) { \n "
" int k = j; \n "
" if (i % 5 == 0) \n "
" return false; \n "
" if (i % 7 == 0) \n "
" k++; \n "
" } \n "
" return false; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Consider using std::all_of or std::none_of algorithm instead of a raw loop. \n " ,
errout . str ( ) ) ;
}
2019-07-18 10:56:44 +02:00
void invalidContainer ( ) {
check ( " void f(std::vector<int> &v) { \n "
" auto v0 = v.begin(); \n "
" v.push_back(123); \n "
" std::cout << *v0 << std::endl; \n "
" } \n " ,
true ) ;
2019-08-15 21:14:27 +02:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:2] -> [test.cpp:3] -> [test.cpp:1] -> [test.cpp:4]: (error) Using iterator to local container 'v' that may be invalid. \n " , errout . str ( ) ) ;
2019-07-18 10:56:44 +02:00
check ( " std::string e(); \n "
" void a() { \n "
" std::vector<std::string> b; \n "
" for (std::vector<std::string>::const_iterator c; c != b.end(); ++c) { \n "
" std::string f = e(); \n "
" std::string::const_iterator d = f.begin(); \n "
" if (d != f.end()) {} \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-07-24 00:04:49 +02:00
check ( " void f(std::vector<int> &v) { \n "
" int *v0 = &v[0]; \n "
" v.push_back(123); \n "
" std::cout << (*v0)[0] << std::endl; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:2] -> [test.cpp:3] -> [test.cpp:1] -> [test.cpp:4]: (error) Using pointer to local variable 'v' that may be invalid. \n " , errout . str ( ) ) ;
2019-09-02 06:58:09 +02:00
check ( " void f() { \n "
" std::vector<int> v = {1}; \n "
" int &v0 = v.front(); \n "
" v.push_back(123); \n "
" std::cout << v0 << std::endl; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:3] -> [test.cpp:4] -> [test.cpp:5]: (error) Reference to v that may be invalid. \n " ,
errout . str ( ) ) ;
check ( " void f() { \n "
" std::vector<int> v = {1}; \n "
" int &v0 = v[0]; \n "
" v.push_back(123); \n "
" std::cout << v0 << std::endl; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4] -> [test.cpp:5]: (error) Reference to v that may be invalid. \n " ,
errout . str ( ) ) ;
check ( " void f(std::vector<int> &v) { \n "
" int &v0 = v.front(); \n "
" v.push_back(123); \n "
" std::cout << v0 << std::endl; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS (
" [test.cpp:2] -> [test.cpp:2] -> [test.cpp:1] -> [test.cpp:3] -> [test.cpp:4]: (error) Reference to v that may be invalid. \n " ,
errout . str ( ) ) ;
check ( " void f(std::vector<int> &v) { \n "
" int &v0 = v[0]; \n "
" v.push_back(123); \n "
" std::cout << v0 << std::endl; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS (
" [test.cpp:2] -> [test.cpp:1] -> [test.cpp:3] -> [test.cpp:4]: (error) Reference to v that may be invalid. \n " ,
errout . str ( ) ) ;
2019-07-24 00:04:49 +02:00
check ( " void f(std::vector<int> &v) { \n "
" std::vector<int> *v0 = &v; \n "
" v.push_back(123); \n "
" std::cout << (*v0)[0] << std::endl; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-09-02 06:58:09 +02:00
check ( " const std::vector<int> * g(int); \n "
" void f() { \n "
" const std::vector<int> *v = g(1); \n "
" if (v && v->size() == 1U) { \n "
" const int &m = v->front(); \n "
" } \n "
" \n "
" v = g(2); \n "
" if (v && v->size() == 1U) { \n "
" const int &m = v->front(); \n "
" if (m == 0) {} \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-09-03 06:41:35 +02:00
check ( " std::vector<std::string> g(); \n "
" void f() { \n "
" std::vector<std::string> x = g(); \n "
" const std::string& y = x[1]; \n "
" std::string z; \n "
" z += \" \" ; \n "
" z += y; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-02-11 11:45:10 +01:00
check ( " void f(std::vector<char> v) \n "
" { \n "
" auto *cur = v.data(); \n "
" auto *end = cur + v.size(); \n "
" while (cur < end) { \n "
" v.erase(v.begin(), FindNext(v)); \n "
" cur = v.data(); \n "
" end = cur + v.size(); \n "
" } \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-02-16 15:56:52 +01:00
// #9598
check ( " void f(std::vector<std::string> v) { \n "
" for (auto it = v.begin(); it != v.end(); it = v.erase(it)) \n "
" *it; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-05-23 07:13:55 +02:00
// #9714
check ( " void f() { \n "
" auto v = std::vector<std::string>(); \n "
" std::string x; \n "
" v.push_back(x.insert(0, \" x \" )); \n "
" v.push_back( \" y \" ); \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-07-15 19:22:36 +02:00
2020-09-02 07:13:15 +02:00
// #9783
check ( " std::string GetTaskIDPerUUID(int); \n "
" void InitializeJumpList(CString s); \n "
" void foo() { \n "
" CString sAppID = GetTaskIDPerUUID(123).c_str(); \n "
" InitializeJumpList(sAppID); \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-07-15 19:22:36 +02:00
// #9796
check ( " struct A {}; \n "
" void f() { \n "
" std::vector<A *> v; \n "
" A *a = new A(); \n "
" v.push_back(a); \n "
" A *b = v.back(); \n "
" v.pop_back(); \n "
" delete b; \n "
2020-07-23 10:09:06 +02:00
" } \n " , true ) ;
2020-07-15 19:22:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-07-16 21:33:39 +02:00
check ( " struct A {}; \n "
" void f() { \n "
" std::vector<A *, std::allocator<A*>> v; \n "
" A *a = new A(); \n "
" v.push_back(a); \n "
" A *b = v.back(); \n "
" v.pop_back(); \n "
" delete b; \n "
2020-07-23 10:09:06 +02:00
" } \n " , true ) ;
2020-07-16 21:33:39 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A {}; \n "
" void f() { \n "
" std::vector<std::shared_ptr<A>> v; \n "
" std::shared_ptr<A> a = std::make_shared<A>(); \n "
" v.push_back(a); \n "
" std::shared_ptr<A> b = v.back(); \n "
" v.pop_back(); \n "
" delete b; \n "
2020-07-23 10:09:06 +02:00
" } \n " , true ) ;
2020-07-16 21:33:39 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-08-07 04:08:30 +02:00
// #9780
check ( " int f() { \n "
" std::vector<int> vect; \n "
" MyStruct info{}; \n "
" info.vect = &vect; \n "
" vect.push_back(1); \n "
" return info.ret; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-01-11 18:47:38 +01:00
// #9133
check ( " struct Fred { \n "
" std::vector<int> v; \n "
" void foo(); \n "
" void bar(); \n "
" }; \n "
" void Fred::foo() { \n "
" std::vector<int>::iterator it = v.begin(); \n "
" bar(); \n "
" it++; \n "
" } \n "
" void Fred::bar() { \n "
" v.push_back(0); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS (
2021-11-01 19:23:15 +01:00
" [test.cpp:7] -> [test.cpp:8] -> [test.cpp:12] -> [test.cpp:9]: (error) Using iterator to member container 'v' that may be invalid. \n " ,
2021-01-11 18:47:38 +01:00
errout . str ( ) ) ;
check ( " void foo(std::vector<int>& v) { \n "
" std::vector<int>::iterator it = v.begin(); \n "
" bar(v); \n "
" it++; \n "
" } \n "
" void bar(std::vector<int>& v) { \n "
" v.push_back(0); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS (
" [test.cpp:1] -> [test.cpp:2] -> [test.cpp:3] -> [test.cpp:7] -> [test.cpp:1] -> [test.cpp:4]: (error) Using iterator to local container 'v' that may be invalid. \n " ,
errout . str ( ) ) ;
2021-06-04 17:20:47 +02:00
// #10264
check ( " void f(std::vector<std::string>& x) { \n "
" struct I { \n "
" std::vector<std::string> *px{}; \n "
" }; \n "
" I i = { &x }; \n "
" x.clear(); \n "
" Parse(i); \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-07-30 15:52:00 +02:00
check ( " void f() { \n "
" std::string x; \n "
" struct V { \n "
" std::string* pStr{}; \n "
" }; \n "
" struct I { \n "
" std::vector<V> v; \n "
" }; \n "
" I b[] = {{{{ &x }}}}; \n "
" x = \" Arial \" ; \n "
" I cb[1]; \n "
" for (long i = 0; i < 1; ++i) \n "
" cb[i] = b[i]; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-26 13:38:40 +01:00
// #9836
check ( " void f() { \n "
" auto v = std::vector<std::vector<std::string> >{ std::vector<std::string>{ \" hello \" } }; \n "
" auto p = &(v.at(0).at(0)); \n "
" v.clear(); \n "
" std::cout << *p << std::endl; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:3] -> [test.cpp:3] -> [test.cpp:4] -> [test.cpp:2] -> [test.cpp:5]: (error) Using pointer to local variable 'v' that may be invalid. \n " ,
errout . str ( ) ) ;
2022-02-28 18:54:55 +01:00
check ( " struct A { \n "
" const std::vector<int>* i; \n "
" A(const std::vector<int>& v) \n "
" : i(&v) \n "
" {} \n "
" }; \n "
" int f() { \n "
" std::vector<int> v; \n "
" A a{v}; \n "
" v.push_back(1); \n "
" return a.i->front(); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { \n "
" const std::vector<int>* i; \n "
" A(const std::vector<int>& v) \n "
" : i(&v) \n "
" {} \n "
" }; \n "
" void g(const std::vector<int>& v); \n "
" void f() { \n "
" std::vector<int> v; \n "
" A a{v}; \n "
" v.push_back(1); \n "
" g(a); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-04-30 09:36:28 +02:00
// #10984
check ( " void f() { \n "
" std::vector<int> v; \n "
" auto g = [&v]{}; \n "
" v.push_back(1); \n "
" g(); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(std::vector<int> v) { \n "
" auto it = v.begin(); \n "
" auto g = [&]{ std::cout << *it << std::endl;}; \n "
" v.push_back(1); \n "
" g(); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS (
" [test.cpp:2] -> [test.cpp:3] -> [test.cpp:4] -> [test.cpp:1] -> [test.cpp:5]: (error) Using iterator to local container 'v' that may be invalid. \n " ,
errout . str ( ) ) ;
check ( " void f(std::vector<int> v) { \n "
" auto it = v.begin(); \n "
" auto g = [=]{ std::cout << *it << std::endl;}; \n "
" v.push_back(1); \n "
" g(); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS (
" [test.cpp:2] -> [test.cpp:4] -> [test.cpp:1] -> [test.cpp:5]: (error) Using iterator to local container 'v' that may be invalid. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" int* p; \n "
" void g(); \n "
" }; \n "
" void f(std::vector<int> v) { \n "
" auto it = v.begin(); \n "
" A a{v.data()}; \n "
" v.push_back(1); \n "
" a.g(); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS (
" [test.cpp:7] -> [test.cpp:8] -> [test.cpp:5] -> [test.cpp:9]: (error) Using object that points to local variable 'v' that may be invalid. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" int*& p; \n "
" void g(); \n "
" }; \n "
" void f(std::vector<int> v) { \n "
" auto* p = v.data(); \n "
" A a{p}; \n "
" v.push_back(1); \n "
" a.g(); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS (
" [test.cpp:6] -> [test.cpp:7] -> [test.cpp:8] -> [test.cpp:5] -> [test.cpp:9]: (error) Using object that points to local variable 'v' that may be invalid. \n " ,
errout . str ( ) ) ;
2022-05-05 06:54:36 +02:00
// #11028
check ( " void f(std::vector<int> c) { \n "
" std::vector<int> d(c.begin(), c.end()); \n "
" c.erase(c.begin()); \n "
" d.push_back(0); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-08-03 19:04:44 +02:00
// #11147
check ( " void f(std::string& s) { \n "
" if (!s.empty()) { \n "
" std::string::iterator it = s.begin(); \n "
" s = s.substr(it - s.begin()); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS (
" [test.cpp:4]: (performance) Ineffective call of function 'substr' because a prefix of the string is assigned to itself. Use resize() or pop_back() instead. \n " ,
errout . str ( ) ) ;
2019-07-18 10:56:44 +02:00
}
2020-04-04 11:47:02 +02:00
void invalidContainerLoop ( ) {
// #9435
check ( " void f(std::vector<int> v) { \n "
" for (auto i : v) { \n "
" if (i < 5) \n "
" v.push_back(i * 2); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (error) Calling 'push_back' while iterating the container is invalid. \n " , errout . str ( ) ) ;
2020-05-23 07:14:45 +02:00
// #9713
check ( " void f() { \n "
" std::vector<int> v{1, 2, 3}; \n "
" for (int i : v) { \n "
" if (i == 2) { \n "
" v.clear(); \n "
" return; \n "
" } \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Consider using std::any_of algorithm instead of a raw loop. \n " , errout . str ( ) ) ;
2021-10-15 11:54:29 +02:00
check ( " struct A { \n "
" std::vector<int> v; \n "
" void add(int i) { \n "
" v.push_back(i); \n "
" } \n "
" void f() { \n "
" for(auto i:v) \n "
" add(i); \n "
" } \n "
" }; \n " ,
true ) ;
ASSERT_EQUALS (
" [test.cpp:4] -> [test.cpp:7] -> [test.cpp:8]: (error) Calling 'add' while iterating the container is invalid. \n " ,
errout . str ( ) ) ;
2020-04-04 11:47:02 +02:00
}
2019-05-02 11:04:23 +02:00
void findInsert ( ) {
check ( " void f1(std::set<unsigned>& s, unsigned x) { \n "
" if (s.find(x) == s.end()) { \n "
" s.insert(x); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Searching before insertion is not necessary. \n " , errout . str ( ) ) ;
check ( " void f2(std::map<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.find(x) == m.end()) { \n "
" m.emplace(x, 1); \n "
" } else { \n "
" m[x] = 1; \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Searching before insertion is not necessary. \n " , errout . str ( ) ) ;
check ( " void f3(std::map<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.count(x) == 0) { \n "
" m.emplace(x, 1); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Searching before insertion is not necessary. \n " , errout . str ( ) ) ;
check ( " void f4(std::set<unsigned>& s, unsigned x) { \n "
" if (s.find(x) == s.end()) { \n "
" s.insert(x); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Searching before insertion is not necessary. \n " , errout . str ( ) ) ;
check ( " void f5(std::map<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.count(x) == 0) { \n "
" m.emplace(x, 1); \n "
" } else { \n "
" m[x] = 1; \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Searching before insertion is not necessary. \n " , errout . str ( ) ) ;
check ( " void f6(std::map<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.count(x) == 0) { \n "
" m.emplace(x, 1); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Searching before insertion is not necessary. \n " , errout . str ( ) ) ;
check ( " void f1(std::unordered_set<unsigned>& s, unsigned x) { \n "
" if (s.find(x) == s.end()) { \n "
" s.insert(x); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Searching before insertion is not necessary. \n " , errout . str ( ) ) ;
check ( " void f2(std::unordered_map<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.find(x) == m.end()) { \n "
" m.emplace(x, 1); \n "
" } else { \n "
" m[x] = 1; \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Searching before insertion is not necessary. \n " , errout . str ( ) ) ;
check ( " void f3(std::unordered_map<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.count(x) == 0) { \n "
" m.emplace(x, 1); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Searching before insertion is not necessary. \n " , errout . str ( ) ) ;
check ( " void f4(std::unordered_set<unsigned>& s, unsigned x) { \n "
" if (s.find(x) == s.end()) { \n "
" s.insert(x); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Searching before insertion is not necessary. \n " , errout . str ( ) ) ;
check ( " void f5(std::unordered_map<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.count(x) == 0) { \n "
" m.emplace(x, 1); \n "
" } else { \n "
" m[x] = 1; \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Searching before insertion is not necessary. \n " , errout . str ( ) ) ;
check ( " void f6(std::unordered_map<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.count(x) == 0) { \n "
" m.emplace(x, 1); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Searching before insertion is not necessary. \n " , errout . str ( ) ) ;
check ( " void g1(std::map<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.find(x) == m.end()) { \n "
" m.emplace(x, 1); \n "
" } else { \n "
" m[x] = 2; \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void g1(std::map<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.count(x) == 0) { \n "
" m.emplace(x, 1); \n "
" } else { \n "
" m[x] = 2; \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f1(QSet<unsigned>& s, unsigned x) { \n "
" if (s.find(x) == s.end()) { \n "
" s.insert(x); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f1(std::multiset<unsigned>& s, unsigned x) { \n "
" if (s.find(x) == s.end()) { \n "
" s.insert(x); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f2(std::multimap<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.find(x) == m.end()) { \n "
" m.emplace(x, 1); \n "
" } else { \n "
" m[x] = 1; \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f3(std::multimap<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.count(x) == 0) { \n "
" m.emplace(x, 1); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f4(std::multiset<unsigned>& s, unsigned x) { \n "
" if (s.find(x) == s.end()) { \n "
" s.insert(x); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f5(std::multimap<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.count(x) == 0) { \n "
" m.emplace(x, 1); \n "
" } else { \n "
" m[x] = 1; \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f1(std::unordered_multiset<unsigned>& s, unsigned x) { \n "
" if (s.find(x) == s.end()) { \n "
" s.insert(x); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f2(std::unordered_multimap<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.find(x) == m.end()) { \n "
" m.emplace(x, 1); \n "
" } else { \n "
" m[x] = 1; \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f3(std::unordered_multimap<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.count(x) == 0) { \n "
" m.emplace(x, 1); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f4(std::unordered_multiset<unsigned>& s, unsigned x) { \n "
" if (s.find(x) == s.end()) { \n "
" s.insert(x); \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f5(std::unordered_multimap<unsigned, unsigned>& m, unsigned x) { \n "
" if (m.count(x) == 0) { \n "
" m.emplace(x, 1); \n "
" } else { \n "
" m[x] = 1; \n "
" } \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-01-14 22:31:43 +01:00
// #9218 - not small type => do not warn if cpp standard is < c++17
{
const char code [ ] = " void f1(std::set<LargeType>& s, const LargeType& x) { \n "
" if (s.find(x) == s.end()) { \n "
" s.insert(x); \n "
" } \n "
" } \n " ;
check ( code , true , Standards : : CPP11 ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( code , true , Standards : : CPP14 ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( code , true , Standards : : CPP17 ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (performance) Searching before insertion is not necessary. \n " , errout . str ( ) ) ;
}
2021-10-24 19:13:42 +02:00
2021-10-25 19:12:49 +02:00
{ // #10558
check ( " void foo() { \n "
" std::map<int, int> x; \n "
" int data = 0; \n "
" for(int i=0; i<10; ++i) { \n "
" data += 123; \n "
" if(x.find(5) == x.end()) \n "
" x[5] = data; \n "
" } \n "
" } " , false , Standards : : CPP03 ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() { \n "
" std::map<int, int> x; \n "
" int data = 0; \n "
" for(int i=0; i<10; ++i) { \n "
" data += 123; \n "
" if(x.find(5) == x.end()) \n "
" x[5] = data; \n "
" } \n "
" } " , false , Standards : : CPP11 ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (performance) Searching before insertion is not necessary. Instead of 'x[5]=data' consider using 'x.emplace(5, data);'. \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" std::map<int, int> x; \n "
" int data = 0; \n "
" for(int i=0; i<10; ++i) { \n "
" data += 123; \n "
" if(x.find(5) == x.end()) \n "
" x[5] = data; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (performance) Searching before insertion is not necessary. Instead of 'x[5]=data' consider using 'x.try_emplace(5, data);'. \n " , errout . str ( ) ) ;
}
2019-05-02 11:04:23 +02:00
}
2020-06-16 02:40:54 +02:00
2020-09-02 07:11:23 +02:00
void checkKnownEmptyContainer ( ) {
2020-08-22 09:16:26 +02:00
check ( " void f() { \n "
" std::vector<int> v; \n "
" for(auto x:v) {} \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Iterating over container 'v' that is always empty. \n " , errout . str ( ) ) ;
check ( " void f(std::vector<int> v) { \n "
" v.clear(); \n "
" for(auto x:v) {} \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Iterating over container 'v' that is always empty. \n " , errout . str ( ) ) ;
check ( " void f(std::vector<int> v) { \n "
" if (!v.empty()) { return; } \n "
" for(auto x:v) {} \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Iterating over container 'v' that is always empty. \n " , errout . str ( ) ) ;
check ( " void f(std::vector<int> v) { \n "
" if (v.empty()) { return; } \n "
" for(auto x:v) {} \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-02 07:11:23 +02:00
check ( " void f() { \n "
" std::vector<int> v; \n "
" std::sort(v.begin(), v.end()); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Using sort with iterator 'v.begin()' that is always empty. \n " , errout . str ( ) ) ;
2022-09-29 07:05:29 +02:00
check ( " void f() { \n " // #1201
" std::vector<int> v1{ 0, 1 }; \n "
" std::vector<int> v2; \n "
" std::copy(v1.begin(), v1.end(), v2.begin()); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Using copy with iterator 'v2.begin()' that is always empty. \n " , errout . str ( ) ) ;
2020-09-02 07:11:23 +02:00
check ( " void f() { \n "
" std::vector<int> v; \n "
" v.insert(v.end(), 1); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-10 05:23:42 +02:00
check ( " struct A { \n "
" explicit A(std::vector<int>*); \n "
" }; \n "
" A f() { \n "
" std::vector<int> v; \n "
" A a(&v); \n "
" for(auto&& x:v) {} \n "
" return a; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-20 22:37:28 +02:00
check ( " static void f1(std::list<std::string>& parameters) { \n "
" parameters.push_back(a); \n "
" } \n "
" int f2(std::list<std::string>& parameters) { \n "
" f1(parameters); \n "
" } \n "
" void f3() { \n "
" std::list<std::string> parameters; \n "
" int res = ::f2(parameters); \n "
" for (auto param : parameters) {} \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-12-26 13:45:17 +01:00
check ( " namespace ns { \n "
" using ArrayType = std::vector<int>; \n "
" } \n "
" using namespace ns; \n "
" static void f() { \n "
" const ArrayType arr; \n "
" for (const auto &a : arr) {} \n "
" } " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (style) Iterating over container 'arr' that is always empty. \n " , errout . str ( ) ) ;
2021-07-25 18:13:55 +02:00
check ( " struct S { \n "
" std::vector<int> v; \n "
" }; \n "
" void foo(S& s) { \n "
" s.v.clear(); \n "
" bar(s); \n "
" std::sort(s.v.begin(), s.v.end()); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-12-14 07:22:57 +01:00
check ( " void f(const std::vector<int>& v, int e) { \n "
" if (!v.empty()) { \n "
" if (e < 0 || true) { \n "
" if (e < 0) \n "
" return; \n "
" } \n "
" } \n "
" for (auto i : v) {} \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-01-21 09:56:55 +01:00
check ( " void f() { \n "
" std::vector<int> v; \n "
" auto& rv = v; \n "
" rv.push_back(42); \n "
" for (auto i : v) {} \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-05-12 06:24:16 +02:00
check ( " extern void f(std::string&&); \n "
" static void func() { \n "
" std::string s; \n "
" const std::string& s_ref = s; \n "
" f(std::move(s)); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-08-22 09:16:26 +02:00
}
2020-06-16 02:40:54 +02:00
void checkMutexes ( ) {
check ( " void f() { \n "
" static std::mutex m; \n "
" static std::lock_guard<std::mutex> g(m); \n "
" } \n " ,
true ) ;
2020-06-25 01:09:30 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Lock guard is defined globally. Lock guards are intended to be local. A global lock guard could lead to a deadlock since it won't unlock until the end of the program. \n " , errout . str ( ) ) ;
2020-06-16 02:40:54 +02:00
check ( " void f() { \n "
" static std::mutex m; \n "
" std::lock_guard<std::mutex> g(m); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-06-26 22:06:20 +02:00
check ( " void f() { \n "
" static std::mutex m; \n "
" static std::unique_lock<std::mutex> g(m, std::defer_lock); \n "
" static std::lock(g); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Lock guard is defined globally. Lock guards are intended to be local. A global lock guard could lead to a deadlock since it won't unlock until the end of the program. \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" static std::mutex m; \n "
" std::unique_lock<std::mutex> g(m, std::defer_lock); \n "
" std::lock(g); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-06-16 02:40:54 +02:00
check ( " void f() { \n "
" std::mutex m; \n "
" std::lock_guard<std::mutex> g(m); \n "
" } \n " ,
true ) ;
2020-06-16 17:32:39 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning) The lock is ineffective because the mutex is locked at the same scope as the mutex itself. \n " , errout . str ( ) ) ;
2020-06-16 02:40:54 +02:00
2020-06-26 22:06:20 +02:00
check ( " void f() { \n "
" std::mutex m; \n "
" std::unique_lock<std::mutex> g(m); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (warning) The lock is ineffective because the mutex is locked at the same scope as the mutex itself. \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" std::mutex m; \n "
" std::unique_lock<std::mutex> g(m, std::defer_lock); \n "
" std::lock(g); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (warning) The lock is ineffective because the mutex is locked at the same scope as the mutex itself. \n " , errout . str ( ) ) ;
2020-06-16 02:40:54 +02:00
check ( " void g(); \n "
" void f() { \n "
" static std::mutex m; \n "
" m.lock(); \n "
" g(); \n "
" m.unlock(); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void g(); \n "
" void f() { \n "
" std::mutex m; \n "
" m.lock(); \n "
" g(); \n "
" m.unlock(); \n "
" } \n " ,
true ) ;
2020-06-16 17:32:39 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) The lock is ineffective because the mutex is locked at the same scope as the mutex itself. \n " , errout . str ( ) ) ;
2020-06-16 02:40:54 +02:00
check ( " class A { \n "
" std::mutex m; \n "
" void f() { \n "
" std::lock_guard<std::mutex> g(m); \n "
" } \n "
" }; \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " class A { \n "
" std::mutex m; \n "
" void g(); \n "
" void f() { \n "
" m.lock(); \n "
" g(); \n "
" m.unlock(); \n "
" } \n "
" }; \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " class A { \n "
" std::mutex m; \n "
" void f() { \n "
" static std::lock_guard<std::mutex> g(m); \n "
" } \n "
" }; \n " ,
true ) ;
2020-06-25 01:09:30 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) Lock guard is defined globally. Lock guards are intended to be local. A global lock guard could lead to a deadlock since it won't unlock until the end of the program. \n " , errout . str ( ) ) ;
2020-06-18 00:06:06 +02:00
check ( " std::mutex& h(); \n "
" void f() { \n "
" auto& m = h(); \n "
" std::lock_guard<std::mutex> g(m); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void g(); \n "
" std::mutex& h(); \n "
" void f() { \n "
" auto& m = h(); \n "
" m.lock(); \n "
" g(); \n "
" m.unlock(); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::mutex& h(); \n "
" void f() { \n "
" auto m = h(); \n "
" std::lock_guard<std::mutex> g(m); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (warning) The lock is ineffective because the mutex is locked at the same scope as the mutex itself. \n " , errout . str ( ) ) ;
check ( " void g(); \n "
" std::mutex& h(); \n "
" void f() { \n "
" auto m = h(); \n "
" m.lock(); \n "
" g(); \n "
" m.unlock(); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (warning) The lock is ineffective because the mutex is locked at the same scope as the mutex itself. \n " , errout . str ( ) ) ;
2020-07-13 04:31:53 +02:00
check ( " void foo(); \n "
" void bar(); \n "
" void f() { \n "
" std::mutex m; \n "
" std::thread t([&m](){ \n "
" m.lock(); \n "
" foo(); \n "
" m.unlock(); \n "
" }); \n "
" m.lock(); \n "
" bar(); \n "
" m.unlock(); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(); \n "
" void bar(); \n "
" void f() { \n "
" std::mutex m; \n "
" std::thread t([&m](){ \n "
" std::unique_lock<std::mutex> g{m}; \n "
" foo(); \n "
" }); \n "
" std::unique_lock<std::mutex> g{m}; \n "
" bar(); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-01-23 17:56:58 +01:00
check ( " void foo() { int f = 0; auto g(f); g = g; } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-09-04 19:06:48 +02:00
check ( " struct foobar { \n "
" int foo; \n "
" std::shared_mutex foo_mtx; \n "
" int bar; \n "
" std::shared_mutex bar_mtx; \n "
" }; \n "
" void f() { \n "
" foobar xyz; \n "
" { \n "
" std::shared_lock shared_foo_lock(xyz.foo_mtx, std::defer_lock); \n "
" std::shared_lock shared_bar_lock(xyz.bar_mtx, std::defer_lock); \n "
" std::scoped_lock shared_multi_lock(shared_foo_lock, shared_bar_lock); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-06-16 02:40:54 +02:00
}
2012-08-10 18:31:22 +02:00
} ;
2009-02-10 20:40:21 +01:00
REGISTER_TEST ( TestStl )