2009-03-22 12:00:21 +01:00
/*
* Cppcheck - A tool for static C / C + + code analysis
2022-02-05 11:45:17 +01:00
* Copyright ( C ) 2007 - 2022 Cppcheck team .
2009-03-22 12:00: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-03-22 12:00:21 +01:00
*/
2017-05-27 04:33:47 +02:00
2009-10-25 12:49:06 +01:00
# include "checkautovariables.h"
2022-01-27 19:03:20 +01:00
# include "errortypes.h"
2017-05-27 04:33:47 +02:00
# include "settings.h"
2009-03-22 12:00:21 +01:00
# include "testsuite.h"
2017-05-27 04:33:47 +02:00
# include "tokenize.h"
2009-03-22 12:00:21 +01:00
2022-01-27 19:03:20 +01:00
# include <iosfwd>
2009-03-22 12:00:21 +01:00
2011-10-13 20:53:06 +02:00
class TestAutoVariables : public TestFixture {
2009-03-22 12:00:21 +01:00
public :
2021-08-07 20:51:18 +02:00
TestAutoVariables ( ) : TestFixture ( " TestAutoVariables " ) { }
2009-03-22 12:00:21 +01:00
private :
2015-10-07 14:40:09 +02:00
Settings settings ;
2009-03-22 12:00: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 [ ] , bool inconclusive = false , const char * filename = " test.cpp " ) {
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
2021-02-24 22:00:06 +01:00
settings . certainty . setEnabled ( Certainty : : inconclusive , inconclusive ) ;
2010-12-01 18:00:55 +01:00
// Tokenize..
Tokenizer tokenizer ( & settings , this ) ;
2009-03-22 12:00:21 +01:00
std : : istringstream istr ( code ) ;
2021-11-29 07:34:39 +01:00
ASSERT_LOC ( tokenizer . tokenize ( istr , filename ) , file , line ) ;
2011-02-12 15:39:26 +01:00
2019-03-14 13:51:35 +01:00
CheckAutoVariables checkAutoVariables ;
checkAutoVariables . runChecks ( & tokenizer , & settings , this ) ;
2009-03-22 12:00:21 +01:00
}
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 ) ;
2015-10-07 14:40:09 +02:00
LOAD_LIB_2 ( settings . library , " std.cfg " ) ;
2019-11-03 22:02:10 +01:00
LOAD_LIB_2 ( settings . library , " qt.cfg " ) ;
2015-10-07 14:40:09 +02:00
2011-02-08 01:26:34 +01:00
TEST_CASE ( testautovar1 ) ;
TEST_CASE ( testautovar2 ) ;
2011-07-21 01:02:54 +02:00
TEST_CASE ( testautovar3 ) ; // ticket #2925
2011-07-22 00:20:19 +02:00
TEST_CASE ( testautovar4 ) ; // ticket #2928
2011-07-22 04:26:42 +02:00
TEST_CASE ( testautovar5 ) ; // ticket #2926
2011-07-27 10:43:44 +02:00
TEST_CASE ( testautovar6 ) ; // ticket #2931
2011-09-02 04:22:33 +02:00
TEST_CASE ( testautovar7 ) ; // ticket #3066
2012-03-01 18:38:20 +01:00
TEST_CASE ( testautovar8 ) ;
TEST_CASE ( testautovar9 ) ;
2013-02-01 19:16:17 +01:00
TEST_CASE ( testautovar10 ) ; // ticket #2930 - void f(char *p) { p = '\0'; }
2013-06-13 16:19:19 +02:00
TEST_CASE ( testautovar11 ) ; // ticket #4641 - fp, assign local struct member address to function parameter
2013-09-28 00:14:12 +02:00
TEST_CASE ( testautovar12 ) ; // ticket #5024 - crash
2014-03-09 08:17:24 +01:00
TEST_CASE ( testautovar13 ) ; // ticket #5537 - crash
2014-10-21 16:21:33 +02:00
TEST_CASE ( testautovar14 ) ; // ticket #4776 - assignment of function parameter, goto
2015-02-24 06:11:31 +01:00
TEST_CASE ( testautovar15 ) ; // ticket #6538
2018-12-01 10:11:02 +01:00
TEST_CASE ( testautovar16 ) ; // ticket #8114
2011-02-08 01:26:34 +01:00
TEST_CASE ( testautovar_array1 ) ;
TEST_CASE ( testautovar_array2 ) ;
2019-03-14 13:51:35 +01:00
TEST_CASE ( testautovar_normal ) ; // "normal" token list that does not remove casts etc
2015-08-28 20:29:51 +02:00
TEST_CASE ( testautovar_ptrptr ) ; // ticket #6956
2011-02-08 01:26:34 +01:00
TEST_CASE ( testautovar_return1 ) ;
TEST_CASE ( testautovar_return2 ) ;
2011-08-10 18:16:31 +02:00
TEST_CASE ( testautovar_return3 ) ;
2018-11-11 07:52:38 +01:00
TEST_CASE ( testautovar_return4 ) ;
2009-07-27 19:32:01 +02:00
TEST_CASE ( testautovar_extern ) ;
2020-09-28 22:48:57 +02:00
TEST_CASE ( testautovar_reassigned ) ;
2009-08-09 15:43:00 +02:00
TEST_CASE ( testinvaliddealloc ) ;
2021-12-09 07:16:40 +01:00
TEST_CASE ( testinvaliddealloc_input ) ; // Ticket #10600
2021-11-30 07:31:28 +01:00
TEST_CASE ( testinvaliddealloc_string ) ;
2014-05-01 07:32:37 +02:00
TEST_CASE ( testinvaliddealloc_C ) ;
2011-05-07 01:26:04 +02:00
TEST_CASE ( testassign1 ) ; // Ticket #1819
TEST_CASE ( testassign2 ) ; // Ticket #2765
2009-06-09 19:45:58 +02:00
2018-01-24 21:33:58 +01:00
TEST_CASE ( assignAddressOfLocalArrayToGlobalPointer ) ;
2018-01-25 22:50:41 +01:00
TEST_CASE ( assignAddressOfLocalVariableToGlobalPointer ) ;
2019-07-07 10:16:19 +02:00
TEST_CASE ( assignAddressOfLocalVariableToMemberVariable ) ;
2018-01-24 21:33:58 +01:00
2009-06-09 19:45:58 +02:00
TEST_CASE ( returnLocalVariable1 ) ;
TEST_CASE ( returnLocalVariable2 ) ;
2015-11-15 14:48:13 +01:00
TEST_CASE ( returnLocalVariable3 ) ; // &x[0]
TEST_CASE ( returnLocalVariable4 ) ; // x+y
TEST_CASE ( returnLocalVariable5 ) ; // cast
2018-01-27 14:48:45 +01:00
TEST_CASE ( returnLocalVariable6 ) ; // valueflow
2010-01-23 20:39:12 +01:00
// return reference..
2011-02-08 01:26:34 +01:00
TEST_CASE ( returnReference1 ) ;
TEST_CASE ( returnReference2 ) ;
2011-02-12 15:39:26 +01:00
TEST_CASE ( returnReference3 ) ;
2011-12-26 07:44:16 +01:00
TEST_CASE ( returnReference4 ) ;
2012-01-08 15:32:22 +01:00
TEST_CASE ( returnReference5 ) ;
2012-03-28 18:21:06 +02:00
TEST_CASE ( returnReference6 ) ;
2012-07-18 07:22:29 +02:00
TEST_CASE ( returnReference7 ) ;
2019-10-08 09:28:39 +02:00
TEST_CASE ( returnReference8 ) ;
TEST_CASE ( returnReference9 ) ;
TEST_CASE ( returnReference10 ) ;
TEST_CASE ( returnReference11 ) ;
TEST_CASE ( returnReference12 ) ;
2019-10-10 06:52:11 +02:00
TEST_CASE ( returnReference13 ) ;
2019-10-13 19:12:46 +02:00
TEST_CASE ( returnReference14 ) ;
2019-10-29 19:12:58 +01:00
TEST_CASE ( returnReference15 ) ; // #9432
TEST_CASE ( returnReference16 ) ; // #9433
2019-11-10 09:44:04 +01:00
TEST_CASE ( returnReference16 ) ; // #9433
TEST_CASE ( returnReference17 ) ; // #9461
2019-12-01 15:10:02 +01:00
TEST_CASE ( returnReference18 ) ; // #9482
2020-02-11 11:41:41 +01:00
TEST_CASE ( returnReference19 ) ; // #9597
2020-04-01 22:35:41 +02:00
TEST_CASE ( returnReference20 ) ; // #9536
2020-09-17 08:33:16 +02:00
TEST_CASE ( returnReference21 ) ; // #9530
2021-07-20 21:30:27 +02:00
TEST_CASE ( returnReference22 ) ;
2021-08-04 08:16:31 +02:00
TEST_CASE ( returnReference23 ) ;
2021-10-15 10:59:40 +02:00
TEST_CASE ( returnReference24 ) ; // #10098
2022-04-27 20:11:32 +02:00
TEST_CASE ( returnReference25 ) ; // #10983
2019-01-26 11:03:57 +01:00
TEST_CASE ( returnReferenceFunction ) ;
2019-02-22 06:38:56 +01:00
TEST_CASE ( returnReferenceContainer ) ;
2014-05-22 11:39:11 +02:00
TEST_CASE ( returnReferenceLiteral ) ;
TEST_CASE ( returnReferenceCalculation ) ;
2015-08-14 13:03:07 +02:00
TEST_CASE ( returnReferenceLambda ) ;
2015-08-26 13:31:51 +02:00
TEST_CASE ( returnReferenceInnerScope ) ;
2019-01-31 10:34:41 +01:00
TEST_CASE ( returnReferenceRecursive ) ;
2019-10-08 09:28:39 +02:00
TEST_CASE ( extendedLifetime ) ;
2010-01-26 22:11:34 +01:00
2019-01-23 07:29:16 +01:00
TEST_CASE ( danglingReference ) ;
2020-10-06 09:16:54 +02:00
TEST_CASE ( danglingTempReference ) ;
2019-01-23 07:29:16 +01:00
2011-04-18 06:56:39 +02:00
// global namespace
TEST_CASE ( testglobalnamespace ) ;
2011-09-01 03:36:31 +02:00
TEST_CASE ( returnParameterAddress ) ;
2014-03-01 16:30:59 +01:00
TEST_CASE ( testconstructor ) ; // ticket #5478 - crash
2014-03-22 11:14:11 +01:00
TEST_CASE ( variableIsUsedInScope ) ; // ticket #5599 crash in variableIsUsedInScope()
2018-11-10 16:40:40 +01:00
TEST_CASE ( danglingLifetimeLambda ) ;
TEST_CASE ( danglingLifetimeContainer ) ;
2021-10-05 08:28:19 +02:00
TEST_CASE ( danglingLifetimeContainerView ) ;
2021-10-06 08:46:25 +02:00
TEST_CASE ( danglingLifetimeUniquePtr ) ;
2018-11-10 16:40:40 +01:00
TEST_CASE ( danglingLifetime ) ;
2018-11-16 06:12:28 +01:00
TEST_CASE ( danglingLifetimeFunction ) ;
2022-02-28 18:54:55 +01:00
TEST_CASE ( danglingLifetimeUserConstructor ) ;
2019-03-19 06:25:10 +01:00
TEST_CASE ( danglingLifetimeAggegrateConstructor ) ;
TEST_CASE ( danglingLifetimeInitList ) ;
2019-05-05 11:40:59 +02:00
TEST_CASE ( danglingLifetimeImplicitConversion ) ;
2019-10-08 09:28:39 +02:00
TEST_CASE ( danglingTemporaryLifetime ) ;
2021-11-04 09:24:24 +01:00
TEST_CASE ( danglingLifetimeBorrowedMembers ) ;
2021-11-28 15:25:21 +01:00
TEST_CASE ( danglingLifetimeClassMemberFunctions ) ;
2018-11-11 16:43:54 +01:00
TEST_CASE ( invalidLifetime ) ;
2019-09-03 17:15:58 +02:00
TEST_CASE ( deadPointer ) ;
2021-09-13 20:46:39 +02:00
TEST_CASE ( splitNamespaceAuto ) ; // crash #10473
2009-03-22 12:00:21 +01:00
}
2014-11-20 14:20:09 +01:00
void testautovar1 ( ) {
2009-03-28 21:47:38 +01:00
check ( " void func1(int **res) \n "
2009-03-22 12:00:21 +01:00
" { \n "
2010-01-01 22:53:34 +01:00
" int num = 2; \n "
" *res = # \n "
" } " ) ;
2019-03-15 15:13:11 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
2009-06-06 21:25:41 +02:00
2011-04-27 02:16:09 +02:00
check ( " void func1(int **res) \n "
" { \n "
" int num = 2; \n "
" res = # \n "
" } " ) ;
2014-08-04 11:45:24 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it? \n " , errout . str ( ) ) ;
2011-04-27 02:16:09 +02:00
2009-06-06 21:25:41 +02:00
check ( " void func1(int **res) \n "
" { \n "
" int num = 2; \n "
" foo.res = # \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-22 12:00:21 +01:00
}
2009-07-27 19:34:17 +02:00
2014-11-20 14:20:09 +01:00
void testautovar2 ( ) {
2011-02-08 01:26:34 +01:00
check ( " class Fred { \n "
" void func1(int **res); \n "
" } \n "
" void Fred::func1(int **res) \n "
" { \n "
" int num = 2; \n "
" *res = # \n "
" } " ) ;
2019-03-15 15:13:11 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
2011-02-08 01:26:34 +01:00
2011-04-27 02:16:09 +02:00
check ( " class Fred { \n "
" void func1(int **res); \n "
" } \n "
" void Fred::func1(int **res) \n "
" { \n "
" int num = 2; \n "
" res = # \n "
" } " ) ;
2014-08-04 11:45:24 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it? \n " , errout . str ( ) ) ;
2011-04-27 02:16:09 +02:00
2011-02-08 01:26:34 +01:00
check ( " class Fred { \n "
" void func1(int **res); \n "
" } \n "
" void Fred::func1(int **res) \n "
" { \n "
" int num = 2; \n "
" foo.res = # \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void testautovar3 ( ) { // ticket #2925
2011-07-21 01:02:54 +02:00
check ( " void foo(int **p) \n "
" { \n "
" int x[100]; \n "
" *p = x; \n "
" } " ) ;
2019-03-15 15:13:11 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
2011-07-21 01:02:54 +02:00
}
2014-11-20 14:20:09 +01:00
void testautovar4 ( ) { // ticket #2928
2011-07-22 00:20:19 +02:00
check ( " void foo(int **p) \n "
" { \n "
" static int x[100]; \n "
" *p = x; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void testautovar5 ( ) { // ticket #2926
2011-07-22 04:26:42 +02:00
check ( " void foo(struct AB *ab) \n "
" { \n "
" char a; \n "
" ab->a = &a; \n "
2019-03-14 13:51:35 +01:00
" } " ) ;
2019-03-15 15:13:11 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
2011-07-22 04:26:42 +02:00
}
2014-11-20 14:20:09 +01:00
void testautovar6 ( ) { // ticket #2931
2011-07-22 14:31:31 +02:00
check ( " void foo(struct X *x) \n "
" { \n "
" char a[10]; \n "
" x->str = a; \n "
2011-08-09 18:24:39 +02:00
" } " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(struct X *x) \n "
" { \n "
" char a[10]; \n "
" x->str = a; \n "
" } " , true ) ;
2019-03-15 15:13:11 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error, inconclusive) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
2011-09-02 04:22:33 +02:00
}
2014-11-20 14:20:09 +01:00
void testautovar7 ( ) { // ticket #3066
2011-09-02 04:22:33 +02:00
check ( " struct txt_scrollpane_s * TXT_NewScrollPane(struct txt_widget_s * target) \n "
" { \n "
" struct txt_scrollpane_s * scrollpane; \n "
" target->parent = &scrollpane->widget; \n "
" return scrollpane; \n "
" } " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-07-22 14:31:31 +02:00
}
2014-11-20 14:20:09 +01:00
void testautovar8 ( ) {
2012-03-01 18:38:20 +01:00
check ( " void foo(int*& p) { \n "
" int i = 0; \n "
" p = &i; \n "
" } " , false ) ;
2019-03-15 15:13:11 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
2012-07-13 14:21:45 +02:00
check ( " void foo(std::string& s) { \n "
2013-04-13 18:38:15 +02:00
" s = foo; \n "
2012-07-13 14:21:45 +02:00
" } " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-03-01 18:38:20 +01:00
}
2014-11-20 14:20:09 +01:00
void testautovar9 ( ) {
2012-03-01 18:38:20 +01:00
check ( " struct FN {int i;}; \n "
" struct FP {FN* f}; \n "
" void foo(int*& p, FN* p_fp) { \n "
" FN fn; \n "
" FP fp; \n "
" p = &fn.i; \n "
2020-09-28 22:48:57 +02:00
" } " , false ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
check ( " struct FN {int i;}; \n "
" struct FP {FN* f}; \n "
" void foo(int*& p, FN* p_fp) { \n "
" FN fn; \n "
" FP fp; \n "
2012-03-01 18:38:20 +01:00
" p = &p_fp->i; \n "
2020-09-28 22:48:57 +02:00
" } " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct FN {int i;}; \n "
" struct FP {FN* f}; \n "
" void foo(int*& p, FN* p_fp) { \n "
" FN fn; \n "
" FP fp; \n "
2012-03-01 18:38:20 +01:00
" p = &fp.f->i; \n "
" } " , false ) ;
2020-09-28 22:48:57 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-03-01 18:38:20 +01:00
}
2014-11-20 14:20:09 +01:00
void testautovar10 ( ) { // #2930 - assignment of function parameter
2013-02-01 19:16:17 +01:00
check ( " void foo(char* p) { \n "
" p = 0; \n "
" } " ) ;
2014-08-04 11:45:24 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it? \n " , errout . str ( ) ) ;
2013-02-01 19:16:17 +01:00
2013-02-18 17:52:49 +01:00
check ( " void foo(int b) { \n "
" b = foo(b); \n "
" } " ) ;
2018-08-17 19:56:36 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Assignment of function parameter has no effect outside the function. \n " , errout . str ( ) ) ;
check ( " void foo(int b) { \n "
" b += 1; \n "
" } " ) ;
2014-08-04 11:45:24 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Assignment of function parameter has no effect outside the function. \n " , errout . str ( ) ) ;
2013-02-18 17:52:49 +01:00
2018-06-24 08:25:19 +02:00
check ( " void foo(std::string s) { \n "
" s = foo(b); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Assignment of function parameter has no effect outside the function. \n " , errout . str ( ) ) ;
2015-08-09 14:51:23 +02:00
check ( " void foo(char* p) { \n " // don't warn for self assignment, there is another warning for this
" p = p; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-02-01 19:16:17 +01:00
check ( " void foo(char* p) { \n "
" if (!p) p = buf; \n "
" *p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-02-02 15:26:14 +01:00
check ( " void foo(char* p) { \n "
" if (!p) p = buf; \n "
" do_something(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-02-18 17:52:49 +01:00
check ( " void foo(char* p) { \n "
" while (!p) p = buf; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(char* p) { \n "
" p = 0; \n "
" asm( \" somecmd \" ); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(Foo* p) { \n "
" p = 0; \n "
" } " ) ;
2014-08-04 11:45:24 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it? \n " , errout . str ( ) ) ;
2013-02-18 17:52:49 +01:00
check ( " class Foo {}; \n "
" void foo(Foo p) { \n "
" p = 0; \n "
" } " ) ;
2014-08-04 11:45:24 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Assignment of function parameter has no effect outside the function. \n " , errout . str ( ) ) ;
2013-02-18 17:52:49 +01:00
check ( " void foo(Foo p) { \n "
" p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(int& p) { \n "
" p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-10-06 16:07:27 +02:00
check ( " double foo(double d) { \n " // #5005
" int i = d; \n "
" d = i; \n "
" return d; "
2019-03-14 13:51:35 +01:00
" } " , false ) ;
2013-10-06 16:07:27 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-08-04 11:45:24 +02:00
check ( " void foo(int* ptr) { \n " // #4793
" ptr++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it? \n " , errout . str ( ) ) ;
2016-10-10 21:34:40 +02:00
check ( " void foo(int* ptr) { \n " // #3177
" --ptr; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it? \n " , errout . str ( ) ) ;
2016-12-19 15:25:36 +01:00
check ( " void foo(struct S* const x) { \n " // #7839
" ++x->n; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-02-01 19:16:17 +01:00
}
2014-11-20 14:20:09 +01:00
void testautovar11 ( ) { // #4641 - fp, assign local struct member address to function parameter
2013-06-13 16:19:19 +02:00
check ( " struct A { \n "
2015-08-25 21:19:19 +02:00
" char (*data)[10]; \n "
2013-06-13 16:19:19 +02:00
" }; \n "
" void foo(char** p) { \n "
" struct A a = bar(); \n "
2015-08-25 21:19:19 +02:00
" *p = &(*a.data)[0]; \n "
2013-06-13 16:19:19 +02:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { \n "
" char data[10]; \n "
" }; \n "
" void foo(char** p) { \n "
" struct A a = bar(); \n "
" *p = &a.data[0]; \n "
" } " ) ;
2019-03-15 15:13:11 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
2013-10-06 14:23:26 +02:00
2019-03-14 06:41:11 +01:00
check ( " void f(char **out) { \n "
" struct S *p = glob; \n "
" *out = &p->data; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-10-06 14:23:26 +02:00
// #4998
check ( " void f(s8**out) { \n "
" s8 *p; \n " // <- p is pointer => no error
" *out = &p[1]; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(s8**out) { \n "
" s8 p[10]; \n " // <- p is array => error
" *out = &p[1]; \n "
" } " ) ;
2019-03-15 15:13:11 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
2013-06-13 16:19:19 +02:00
}
2013-09-28 09:32:41 +02:00
2014-11-20 14:20:09 +01:00
void testautovar12 ( ) { // Ticket #5024, #5050 - Crash on invalid input
2018-09-08 21:10:34 +02:00
ASSERT_THROW ( check ( " void f(int* a) { a = } " ) , InternalError ) ;
2014-03-01 10:37:55 +01:00
check ( " struct custom_type { custom_type(int) {} }; \n "
" void func(int) {} \n "
" int var; \n "
" void init() { func(var); } \n "
" UNKNOWN_MACRO_EXPANDING_TO_SIGNATURE { custom_type a(var); } " ) ;
2013-09-28 00:14:12 +02:00
}
2013-06-13 16:19:19 +02:00
2014-11-20 14:20:09 +01:00
void testautovar13 ( ) { // Ticket #5537
2014-03-09 08:17:24 +01:00
check ( " class FileManager { \n "
" FileManager() : UniqueRealDirs(*new UniqueDirContainer()) \n "
" {} \n "
" ~FileManager() { \n "
" delete &UniqueRealDirs; \n "
" } \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2014-03-09 08:17:24 +01:00
}
2014-11-20 14:20:09 +01:00
void testautovar14 ( ) { // Ticket #4776
2014-10-21 16:21:33 +02:00
check ( " void f(int x) { \n "
" label: "
" if (x>0) { \n "
" x = x >> 1; \n "
" goto label; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-24 06:11:31 +01:00
}
void testautovar15 ( ) { // Ticket #6538
check ( " static const float4 darkOutline(0.05f, 0.05f, 0.05f, 0.95f); \n "
" static const float darkLuminosity = 0.05 + \n "
" 0.0722f * math::powf(darkOutline[2], 2.2); \n "
" const float4* ChooseOutlineColor(const float4& textColor) { \n "
" const float lumdiff = something; \n "
" if (lumdiff > 5.0f) \n "
" return &darkOutline; \n "
" return 0; \n "
2019-03-14 13:51:35 +01:00
" } " , false ) ;
2015-02-24 06:11:31 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-10-21 16:21:33 +02:00
}
2018-12-01 10:11:02 +01:00
void testautovar16 ( ) { // Ticket #8114
check ( " void f(const void* ptr, bool* result) { \n "
" int dummy; \n "
" *result = (&dummy < ptr); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void testautovar_array1 ( ) {
2009-03-22 12:00:21 +01:00
check ( " void func1(int* arr[2]) \n "
" { \n "
" int num=2; "
2010-01-23 20:39:12 +01:00
" arr[0]=# \n "
" } " ) ;
2019-03-15 15:13:11 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
2009-03-22 12:00:21 +01:00
}
2009-07-27 19:34:17 +02:00
2014-11-20 14:20:09 +01:00
void testautovar_array2 ( ) {
2011-02-08 01:26:34 +01:00
check ( " class Fred { \n "
" void func1(int* arr[2]); \n "
" } \n "
" void Fred::func1(int* arr[2]) \n "
" { \n "
" int num=2; "
" arr[0]=# \n "
" } " ) ;
2019-03-15 15:13:11 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
2019-03-14 13:51:35 +01:00
}
void testautovar_normal ( ) {
check ( " void f(XmDestinationCallbackStruct *ds) \n "
" { \n "
" XPoint DropPoint; \n "
" ds->location_data = (XtPointer *)&DropPoint; \n "
" } " ) ;
2019-03-15 15:13:11 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
2011-02-08 01:26:34 +01:00
}
2015-08-28 20:29:51 +02:00
void testautovar_ptrptr ( ) { // #6596
check ( " void remove_duplicate_matches (char **matches) { \n "
" char dead_slot; \n "
" matches[0] = (char *)&dead_slot; \n "
" } " ) ;
2019-03-15 15:13:11 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
2015-08-28 20:29:51 +02:00
}
2014-11-20 14:20:09 +01:00
void testautovar_return1 ( ) {
2009-03-28 21:54:12 +01:00
check ( " int* func1() \n "
" { \n "
" int num=2; "
2011-02-08 01:26:34 +01:00
" return # "
" } " ) ;
2018-11-12 10:08:17 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3] -> [test.cpp:3]: (error) Returning pointer to local variable 'num' that will be invalid when returning. \n " , errout . str ( ) ) ;
2009-03-28 21:54:12 +01:00
}
2009-06-09 19:45:58 +02:00
2014-11-20 14:20:09 +01:00
void testautovar_return2 ( ) {
2011-02-08 01:26:34 +01:00
check ( " class Fred { \n "
2015-12-05 20:55:26 +01:00
" int* func1(); \n "
2011-02-08 01:26:34 +01:00
" } \n "
" int* Fred::func1() \n "
" { \n "
" int num=2; "
" return # "
" } " ) ;
2018-11-12 10:08:17 +01:00
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:6] -> [test.cpp:6]: (error) Returning pointer to local variable 'num' that will be invalid when returning. \n " , errout . str ( ) ) ;
2011-02-08 01:26:34 +01:00
}
2014-11-20 14:20:09 +01:00
void testautovar_return3 ( ) {
2011-08-10 18:16:31 +02:00
// #2975 - FP
check ( " void** f() \n "
" { \n "
" void *&value = tls[id]; "
" return &value; "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2018-11-11 07:52:38 +01:00
void testautovar_return4 ( ) {
// #8058 - FP ignore return in lambda
check ( " void foo() { \n "
" int cond2; \n "
" dostuff([&cond2]() { return &cond2; }); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void testautovar_extern ( ) {
2009-07-27 19:32:01 +02:00
check ( " struct foo *f() \n "
" { \n "
" extern struct foo f; \n "
" return &f; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2009-07-27 19:32:01 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2020-09-28 22:48:57 +02:00
void testautovar_reassigned ( ) {
check ( " void foo(cb* pcb) { \n "
" int root0; \n "
" pcb->root0 = &root0; \n "
" dostuff(pcb); \n "
" pcb->root0 = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(cb* pcb) { \n "
" int root0; \n "
" pcb->root0 = &root0; \n "
" dostuff(pcb); \n "
" if (condition) return; \n " // <- not reassigned => error
" pcb->root0 = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
check ( " void foo(cb* pcb) { \n "
" int root0; \n "
" pcb->root0 = &root0; \n "
" dostuff(pcb); \n "
" if (condition) \n "
" pcb->root0 = 0; \n " // <- conditional reassign => error
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void testinvaliddealloc ( ) {
2012-04-26 16:44:33 +02:00
check ( " void func1() { \n "
" char tmp1[256]; \n "
" free(tmp1); \n "
" char tmp2[256]; \n "
" delete tmp2; \n "
" char tmp3[256]; \n "
2013-04-13 18:38:15 +02:00
" delete tmp3; \n "
2012-04-26 16:44:33 +02:00
" char tmp4[256]; \n "
" delete[] (tmp4); \n "
" char tmp5[256]; \n "
" delete[] tmp5; \n "
" } " ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour. \n "
" [test.cpp:5]: (error) Deallocation of an auto-variable results in undefined behaviour. \n "
" [test.cpp:7]: (error) Deallocation of an auto-variable results in undefined behaviour. \n "
" [test.cpp:9]: (error) Deallocation of an auto-variable results in undefined behaviour. \n "
" [test.cpp:11]: (error) Deallocation of an auto-variable results in undefined behaviour. \n " , errout . str ( ) ) ;
2012-04-26 16:44:33 +02:00
2021-11-30 07:31:28 +01:00
check ( " void func1(char * ptr) { \n "
" free(ptr); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-04-26 16:44:33 +02:00
check ( " void func1() { \n "
" char* tmp1[256]; \n "
" init(tmp1); \n "
" delete tmp1[34]; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-08-16 10:27:40 +02:00
2018-11-03 18:55:12 +01:00
check ( " void func1() { \n "
" static char tmp1[256]; \n "
" char *p = tmp1; \n "
" free(p); \n "
" } " ) ;
2021-12-23 20:09:55 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Deallocation of a static variable (tmp1) results in undefined behaviour. \n " , errout . str ( ) ) ;
2018-11-03 18:55:12 +01:00
check ( " char tmp1[256]; \n "
" void func1() { \n "
" char *p; if (x) p = tmp1; \n "
" free(p); \n "
" } " ) ;
2021-12-23 20:09:55 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Deallocation of a global variable (tmp1) results in undefined behaviour. \n " , errout . str ( ) ) ;
2018-11-03 18:55:12 +01:00
2009-08-16 10:27:40 +02:00
check ( " void f() \n "
" { \n "
" char psz_title[10]; \n "
" { \n "
" char *psz_title = 0; \n "
" abc(0, psz_title); \n "
" free(psz_title); \n "
" } \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2014-03-06 06:32:30 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #2298 new check: passing stack-address to free()
check ( " int main() { \n "
" int *p = malloc(4); \n "
" free(&p); \n "
" return 0; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour. \n " , errout . str ( ) ) ;
check ( " int main() { \n "
" int i; \n "
" free(&i); \n "
" return 0; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour. \n " , errout . str ( ) ) ;
2014-04-27 10:56:55 +02:00
// #5732
check ( " int main() { \n "
" long (*pKoeff)[256] = new long[9][256]; \n "
" delete[] pKoeff; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int main() { \n "
" long *pKoeff[256]; \n "
" delete[] pKoeff; \n "
" } " ) ;
2015-08-25 21:19:19 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour. \n " , errout . str ( ) ) ;
2014-05-01 07:32:37 +02:00
2014-05-12 19:53:49 +02:00
check ( " int main() { \n "
" long *pKoeff[256]; \n "
" free (pKoeff); \n "
" } " ) ;
2015-08-25 21:19:19 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour. \n " , errout . str ( ) ) ;
2014-05-12 19:53:49 +02:00
check ( " void foo() { \n "
2014-05-15 21:20:16 +02:00
" const intPtr& intref = Getter(); \n "
" delete intref; \n "
2014-05-12 19:53:49 +02:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void test() { \n "
" MyObj& obj = *new MyObj; \n "
" delete &obj; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-06-20 21:00:54 +02:00
// #6506
check ( " struct F { \n "
" void free(void*) {} \n "
" }; \n "
" void foo() { \n "
" char c1[1]; \n "
" F().free(c1); \n "
" char *c2 = 0; \n "
" F().free(&c2); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " class foo { \n "
" void free(void* ); \n "
" void someMethod() { \n "
" char **dst_copy = NULL; \n "
" free(&dst_copy); \n "
" } \n "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-11-11 16:59:13 +01:00
// #6551
check ( " bool foo( ) { \n "
" SwTxtFld * pTxtFld = GetFldTxtAttrAt(); \n "
" delete static_cast<SwFmtFld*>(&pTxtFld->GetAttr()); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-12-29 09:31:21 +01:00
// #8910
check ( " void f() { \n "
" char stack[512]; \n "
" RGNDATA *data; \n "
" if (data_size > sizeof (stack)) data = malloc (data_size); \n "
" else data = (RGNDATA *)stack; \n "
" if ((char *)data != stack) free (data); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-12-29 09:31:21 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-11-11 07:15:24 +01:00
// #8923
check ( " void f(char **args1, char *args2[]) { \n "
" free((char **)args1); \n "
" free((char **)args2); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-08 20:31:16 +01:00
// #10097
check ( " struct Array { \n "
" ~Array() { delete m_Arr; } \n "
" std::array<long, 256>* m_Arr{}; \n "
" }; \n "
" Array arr; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-05-01 07:32:37 +02:00
}
2021-12-09 07:16:40 +01:00
void testinvaliddealloc_input ( ) {
// #10600
check ( " void f(int* a[]) { \n "
" free(a); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int a[]) { \n "
" free(a); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int* a[]) { \n "
" int * p = *a; \n "
" free(p); \n "
" int ** q = a; \n "
" free(q); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int a[]) { \n "
" int * p = a; \n "
" free(p); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2021-11-30 07:31:28 +01:00
void testinvaliddealloc_string ( ) {
// #7341
check ( " void f() { \n "
" char *ptr = \" a \" ; \n "
" free( \" a \" ); \n "
" delete \" a \" ; \n "
" free(ptr); \n "
" delete ptr; \n "
" char * p = malloc(1000); \n "
" p = \" abc \" ; \n "
" free(p); \n "
" } \n " ) ;
2021-12-23 20:09:55 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Deallocation of a string literal results in undefined behaviour. \n "
" [test.cpp:4]: (error) Deallocation of a string literal results in undefined behaviour. \n "
" [test.cpp:5]: (error) Deallocation of a pointer pointing to a string literal ( \" a \" ) results in undefined behaviour. \n "
" [test.cpp:6]: (error) Deallocation of a pointer pointing to a string literal ( \" a \" ) results in undefined behaviour. \n "
" [test.cpp:9]: (error) Deallocation of a pointer pointing to a string literal ( \" abc \" ) results in undefined behaviour. \n " ,
2021-11-30 07:31:28 +01:00
errout . str ( ) ) ;
2021-12-05 15:47:21 +01:00
check ( " void f() { \n "
" char *ptr = malloc(10); \n "
" char *empty_str = \" \" ; \n "
" if (ptr == NULL) \n "
" ptr = empty_str; \n "
" if (ptr != empty_str) \n "
" free(ptr); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-30 07:31:28 +01:00
}
2014-11-20 14:20:09 +01:00
void testinvaliddealloc_C ( ) {
2014-05-01 07:32:37 +02:00
// #5691
check ( " void svn_repos_dir_delta2() { \n "
" struct context c; \n "
" SVN_ERR(delete(&c, root_baton, src_entry, pool)); \n "
2019-03-14 13:51:35 +01:00
" } \n " , false , " test.c " ) ;
2014-05-01 07:32:37 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-08-09 15:43:00 +02:00
}
2009-06-09 19:45:58 +02:00
2014-11-20 14:20:09 +01:00
void testassign1 ( ) { // Ticket #1819
2010-10-22 21:12:28 +02:00
check ( " void f(EventPtr *eventP, ActionPtr **actionsP) { \n "
" EventPtr event = *eventP; \n "
" *actionsP = &event->actions; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2011-05-07 01:26:04 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void testassign2 ( ) { // Ticket #2765
2011-05-07 01:26:04 +02:00
check ( " static void function(unsigned long **datap) { \n "
" struct my_s *mr = global_structure_pointer; \n "
" *datap = &mr->value; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2011-05-07 00:18:48 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-01-24 21:33:58 +01:00
}
void assignAddressOfLocalArrayToGlobalPointer ( ) {
check ( " int *p; \n "
" void f() { \n "
" int x[10]; \n "
" p = x; \n "
" } " ) ;
2019-07-07 10:16:19 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3] -> [test.cpp:4]: (error) Non-local variable 'p' will use pointer to local variable 'x'. \n " , errout . str ( ) ) ;
2018-01-24 21:33:58 +01:00
check ( " int *p; \n "
" void f() { \n "
" int x[10]; \n "
" p = x; \n "
" p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-01-25 22:50:41 +01:00
}
void assignAddressOfLocalVariableToGlobalPointer ( ) {
check ( " int *p; \n "
" void f() { \n "
" int x; \n "
" p = &x; \n "
" } " ) ;
2019-07-07 10:16:19 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3] -> [test.cpp:4]: (error) Non-local variable 'p' will use pointer to local variable 'x'. \n " , errout . str ( ) ) ;
2018-01-25 22:50:41 +01:00
check ( " int *p; \n "
" void f() { \n "
" int x; \n "
" p = &x; \n "
" p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-22 21:12:28 +02:00
}
2019-07-07 10:16:19 +02:00
void assignAddressOfLocalVariableToMemberVariable ( ) {
check ( " struct A { \n "
" void f() { \n "
" int x; \n "
" ptr = &x; \n "
" } \n "
" int *ptr; \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2019-07-07 10:16:19 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3] -> [test.cpp:4]: (error) Non-local variable 'ptr' will use pointer to local variable 'x'. \n " , errout . str ( ) ) ;
check ( " struct A { \n "
" void f() { \n "
" int x; \n "
" ptr = &x; \n "
" ptr = 0; \n "
" } \n "
" int *ptr; \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2019-07-07 10:16:19 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void returnLocalVariable1 ( ) {
2009-06-09 19:45:58 +02:00
check ( " char *foo() \n "
" { \n "
" char str[100] = {0}; \n "
" return str; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2018-11-21 08:43:57 +01:00
ASSERT_EQUALS (
2018-12-15 17:58:45 +01:00
" [test.cpp:4] -> [test.cpp:3] -> [test.cpp:4]: (error) Returning pointer to local variable 'str' that will be invalid when returning. \n " ,
2018-11-21 08:43:57 +01:00
errout . str ( ) ) ;
2011-02-08 01:26:34 +01:00
2015-11-15 12:10:35 +01:00
check ( " char *foo() \n " // use ValueFlow
" { \n "
" char str[100] = {0}; \n "
" char *p = str; \n "
" return p; \n "
" } " ) ;
2018-11-21 08:43:57 +01:00
ASSERT_EQUALS (
2018-12-15 17:58:45 +01:00
" [test.cpp:4] -> [test.cpp:3] -> [test.cpp:5]: (error) Returning pointer to local variable 'str' that will be invalid when returning. \n " ,
2018-11-21 08:43:57 +01:00
errout . str ( ) ) ;
2015-11-15 12:10:35 +01:00
2011-02-08 01:26:34 +01:00
check ( " class Fred { \n "
" char *foo(); \n "
" }; \n "
" char *Fred::foo() \n "
" { \n "
" char str[100] = {0}; \n "
" return str; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2018-11-21 08:43:57 +01:00
ASSERT_EQUALS (
2018-12-15 17:58:45 +01:00
" [test.cpp:7] -> [test.cpp:6] -> [test.cpp:7]: (error) Returning pointer to local variable 'str' that will be invalid when returning. \n " ,
2018-11-21 08:43:57 +01:00
errout . str ( ) ) ;
2016-01-30 20:02:39 +01:00
check ( " char * format_reg(char *outbuffer_start) { \n "
" return outbuffer_start; \n "
" } \n "
" void print_with_operands() { \n "
" char temp[42]; \n "
" char *tp = temp; \n "
" tp = format_reg(tp); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-09 19:45:58 +02:00
}
2014-11-20 14:20:09 +01:00
void returnLocalVariable2 ( ) {
2009-06-09 19:45:58 +02:00
check ( " std::string foo() \n "
" { \n "
" char str[100] = {0}; \n "
" return str; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2009-06-09 19:45:58 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-02-08 01:26:34 +01:00
check ( " class Fred { \n "
" std::string foo(); \n "
" }; \n "
" std::string Fred::foo() \n "
" { \n "
" char str[100] = {0}; \n "
" return str; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2011-02-08 01:26:34 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-09 19:45:58 +02:00
}
2010-01-23 20:39:12 +01:00
2015-11-15 14:48:13 +01:00
void returnLocalVariable3 ( ) { // &x[..]
// #3030
check ( " char *foo() { \n "
" char q[] = \" AAAAAAAAAAAA \" ; \n "
" return &q[1]; \n "
" } " ) ;
2018-11-12 10:08:17 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning pointer to local variable 'q' that will be invalid when returning. \n " , errout . str ( ) ) ;
2015-11-15 14:48:13 +01:00
check ( " char *foo() \n "
" { \n "
" static char q[] = \" AAAAAAAAAAAA \" ; \n "
" return &q[1]; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-02-22 21:10:05 +01:00
check ( " char *foo() \n "
" { \n "
" char q[] = \" AAAAAAAAAAAA \" ; \n "
" char *p; \n "
" p = &q[1]; \n "
" return p; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-02-22 21:10:05 +01:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:3] -> [test.cpp:6]: (error) Returning pointer to local variable 'q' that will be invalid when returning. \n " , errout . str ( ) ) ;
2015-11-15 14:48:13 +01:00
}
void returnLocalVariable4 ( ) { // x+y
check ( " char *foo() { \n "
" char x[10] = {0}; \n "
" return x+5; \n "
" } " ) ;
2018-11-21 08:43:57 +01:00
ASSERT_EQUALS (
2018-12-15 17:58:45 +01:00
" [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning pointer to local variable 'x' that will be invalid when returning. \n " ,
2018-11-21 08:43:57 +01:00
errout . str ( ) ) ;
2015-11-15 19:34:36 +01:00
check ( " char *foo(int y) { \n "
" char x[10] = {0}; \n "
" return (x+8)-y; \n "
" } " ) ;
2018-11-21 08:43:57 +01:00
ASSERT_EQUALS (
2018-12-15 17:58:45 +01:00
" [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning pointer to local variable 'x' that will be invalid when returning. \n " ,
2018-11-21 08:43:57 +01:00
errout . str ( ) ) ;
2015-11-15 14:48:13 +01:00
}
void returnLocalVariable5 ( ) { // cast
check ( " char *foo() { \n "
" int x[10] = {0}; \n "
" return (char *)x; \n "
" } " ) ;
2018-11-21 08:43:57 +01:00
ASSERT_EQUALS (
2018-12-15 17:58:45 +01:00
" [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning pointer to local variable 'x' that will be invalid when returning. \n " ,
2018-11-21 08:43:57 +01:00
errout . str ( ) ) ;
2015-11-15 14:48:13 +01:00
}
2018-01-27 14:48:45 +01:00
void returnLocalVariable6 ( ) { // valueflow
check ( " int *foo() { \n "
" int x = 123; \n "
" int p = &x; \n "
" return p; \n "
" } " ) ;
2018-11-12 10:08:17 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning object that points to local variable 'x' that will be invalid when returning. \n " , errout . str ( ) ) ;
2018-01-27 14:48:45 +01:00
}
2015-11-15 14:48:13 +01:00
2014-11-20 14:20:09 +01:00
void returnReference1 ( ) {
2019-01-23 07:29:16 +01:00
check ( " int &foo() \n "
" { \n "
" int s = 0; \n "
" int& x = s; \n "
" return x; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-23 07:29:16 +01:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:5]: (error) Reference to local variable returned. \n " , errout . str ( ) ) ;
2010-01-23 20:39:12 +01:00
check ( " std::string &foo() \n "
" { \n "
" std::string s; \n "
" return s; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2019-01-23 07:29:16 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Reference to local variable returned. \n " , errout . str ( ) ) ;
2010-01-23 20:39:12 +01:00
check ( " std::vector<int> &foo() \n "
" { \n "
" std::vector<int> v; \n "
" return v; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2019-01-23 07:29:16 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Reference to local variable returned. \n " , errout . str ( ) ) ;
2010-01-23 20:39:12 +01:00
check ( " std::vector<int> &foo() \n "
" { \n "
" static std::vector<int> v; \n "
" return v; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2010-01-23 20:39:12 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-03-27 12:22:53 +01:00
check ( " std::vector<int> &foo() \n "
" { \n "
" thread_local std::vector<int> v; \n "
" return v; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-01-26 22:11:34 +01:00
check ( " std::string hello() \n "
" { \n "
" return \" hello \" ; \n "
" } \n "
" \n "
" std::string &f() \n "
" { \n "
" return hello(); \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
2012-08-22 13:08:32 +02:00
2012-10-14 17:30:37 +02:00
// make sure scope is used in function lookup
check ( " class Fred { \n "
" std::string hello() { \n "
" return std::string(); \n "
" } \n "
" }; \n "
" std::string &f() { \n "
" return hello(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-08-22 13:08:32 +02:00
check ( " std::string hello() { \n "
" return std::string(); \n "
" } \n "
" \n "
" std::string &f() { \n "
" return hello(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
2012-09-10 15:20:38 +02:00
check ( " std::string hello() { \n "
" return \" foo \" ; \n "
" } \n "
" \n "
" std::string &f() { \n "
" return hello().substr(1); \n "
" } " ) ;
2020-09-02 07:13:15 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
2012-09-10 15:20:38 +02:00
2012-08-22 13:08:32 +02:00
check ( " class Foo; \n "
" Foo hello() { \n "
" return Foo(); \n "
" } \n "
" \n "
" Foo& f() { \n "
" return hello(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
2012-10-14 17:30:37 +02:00
// make sure function overloads are handled properly
check ( " class Foo; \n "
" Foo & hello(bool) { \n "
" static Foo foo; \n "
" return foo; \n "
" } \n "
" Foo hello() { \n "
" return Foo(); \n "
" } \n "
" \n "
" Foo& f() { \n "
" return hello(true); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-08-22 13:08:32 +02:00
check ( " Foo hello() { \n "
" return Foo(); \n "
" } \n "
" \n "
" Foo& f() { \n " // Unknown type - might be a reference
" return hello(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-01-23 20:39:12 +01:00
}
2010-01-26 22:11:34 +01:00
2014-11-20 14:20:09 +01:00
void returnReference2 ( ) {
2011-02-08 01:26:34 +01:00
check ( " class Fred { \n "
" std::string &foo(); \n "
" } \n "
" std::string &Fred::foo() \n "
" { \n "
" std::string s; \n "
" return s; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2019-01-23 07:29:16 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Reference to local variable returned. \n " , errout . str ( ) ) ;
2011-02-08 01:26:34 +01:00
check ( " class Fred { \n "
" std::vector<int> &foo(); \n "
" }; \n "
" std::vector<int> &Fred::foo() \n "
" { \n "
" std::vector<int> v; \n "
" return v; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2019-01-23 07:29:16 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Reference to local variable returned. \n " , errout . str ( ) ) ;
2011-02-08 01:26:34 +01:00
check ( " class Fred { \n "
" std::vector<int> &foo(); \n "
" }; \n "
" std::vector<int> &Fred::foo() \n "
" { \n "
" static std::vector<int> v; \n "
" return v; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2011-02-08 01:26:34 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " class Fred { \n "
" std::string &f(); \n "
" }; \n "
" std::string hello() \n "
" { \n "
" return \" hello \" ; \n "
" } \n "
" std::string &Fred::f() \n "
" { \n "
" return hello(); \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
2011-02-08 01:26:34 +01:00
check ( " class Fred { \n "
" std::string hello(); \n "
" std::string &f(); \n "
" }; \n "
" std::string Fred::hello() \n "
" { \n "
" return \" hello \" ; \n "
" } \n "
" std::string &Fred::f() \n "
" { \n "
" return hello(); \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:11]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
2012-08-22 13:08:32 +02:00
check ( " class Bar; \n "
" Bar foo() { \n "
" return something; \n "
" } \n "
" Bar& bar() { \n "
" return foo(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
check ( " std::map<int, string> foo() { \n "
" return something; \n "
" } \n "
" std::map<int, string>& bar() { \n "
" return foo(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
check ( " Bar foo() { \n "
" return something; \n "
" } \n "
" Bar& bar() { \n " // Unknown type - might be a typedef to a reference type
" return foo(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-08-22 19:17:23 +02:00
// Don't crash with function in unknown scope (#4076)
check ( " X& a::Bar() {} "
" X& foo() { "
" return Bar(); "
" } " ) ;
2011-02-08 01:26:34 +01:00
}
2014-11-20 14:20:09 +01:00
void returnReference3 ( ) {
2011-02-12 15:39:26 +01:00
check ( " double & f(double & rd) { \n "
" double ret = getValue(); \n "
" rd = ret; \n "
" return rd; \n "
2019-03-14 13:51:35 +01:00
" } " , false ) ;
2011-02-12 15:39:26 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-12-26 07:44:16 +01:00
// Returning reference to global variable
2014-11-20 14:20:09 +01:00
void returnReference4 ( ) {
2011-12-26 07:44:16 +01:00
check ( " double a; \n "
" double & f() { \n "
2013-04-13 18:38:15 +02:00
" return a; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2011-12-26 07:44:16 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void returnReference5 ( ) {
2012-01-08 15:32:22 +01:00
check ( " struct A { \n "
" int i; \n "
" }; \n "
" struct B { \n "
" A a; \n "
" }; \n "
" struct C { \n "
" B *b; \n "
" const A& a() const { \n "
" const B *pb = b; \n "
" const A &ra = pb->a; \n "
" return ra; \n "
" } \n "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void returnReference6 ( ) {
2012-03-28 18:21:06 +02:00
check ( " Fred & create() { \n "
" Fred &fred(*new Fred); \n "
" return fred; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void returnReference7 ( ) { // 3791 - false positive for overloaded function
2012-07-18 07:22:29 +02:00
check ( " std::string a(); \n "
" std::string &a(int); \n "
" std::string &b() { \n "
" return a(12); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-10-14 17:30:37 +02:00
check ( " std::string &a(int); \n "
" std::string a(); \n "
" std::string &b() { \n "
" return a(12); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-07-18 07:22:29 +02:00
}
2019-10-08 09:28:39 +02:00
void returnReference8 ( ) {
check ( " int& f(std::vector<int> &v) { \n "
" std::vector<int>::iterator it = v.begin(); \n "
" int& value = *it; \n "
" return value; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void returnReference9 ( ) {
check ( " int& f(bool b, int& x, int& y) { \n "
" return b ? x : y; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void returnReference10 ( ) {
check ( " class A { int f() const; }; \n "
" int& g() { \n "
" A a; \n "
" return a.f(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
check ( " class A { int& f() const; }; \n "
" int& g() { \n "
" A a; \n "
" return a.f(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void returnReference11 ( ) {
check ( " class A { static int f(); }; \n "
" int& g() { \n "
" return A::f(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
check ( " class A { static int& f(); }; \n "
" int& g() { \n "
" return A::f(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " namespace A { int& f(); } \n "
" int& g() { \n "
" return A::f(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void returnReference12 ( ) {
check ( " class A { static int& f(); }; \n "
" auto g() { \n "
" return &A::f; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " class A { static int& f(); }; \n "
" auto g() { \n "
" auto x = &A::f; \n "
" return x; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-10-10 06:52:11 +02:00
void returnReference13 ( ) {
check ( " std::vector<int> v; \n "
" void* vp = &v; \n "
" int& foo(size_t i) { \n "
" return ((std::vector<int>*)vp)->at(i); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-10 06:52:11 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::vector<int> v; \n "
" void* vp = &v; \n "
" int& foo(size_t i) { \n "
" return static_cast<std::vector<int>*>(vp)->at(i); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-10 06:52:11 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-10-14 19:41:51 +02:00
void returnReference14 ( ) {
2019-10-13 19:12:46 +02:00
check ( " struct C { void* m; }; \n "
" struct A { void* &f(); }; \n "
" C* g() { \n "
" static C c; \n "
" return &c; \n "
" } \n "
" void* &A::f() { \n "
" return g()->m; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-13 19:12:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-10-29 19:12:58 +01:00
void returnReference15 ( ) {
check ( " template <class T> \n "
" const int& f() { \n "
" static int s; \n "
" return s; \n "
" } \n "
" template <class T> \n "
" const int& f(const T&) { \n "
" return f<T>(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-29 19:12:58 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " template <class T> \n "
" int g(); \n "
" template <class T> \n "
" const int& f(const T&) { \n "
" return g<T>(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-29 19:12:58 +01:00
TODO_ASSERT_EQUALS ( " error " , " " , errout . str ( ) ) ;
}
void returnReference16 ( ) {
check ( " int& f(std::tuple<int>& x) { \n "
" return std::get<0>(x); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-29 19:12:58 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int& f(int x) { \n "
" return std::get<0>(std::make_tuple(x)); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-29 19:12:58 +01:00
TODO_ASSERT_EQUALS ( " error " , " " , errout . str ( ) ) ;
}
2019-11-10 09:44:04 +01:00
void returnReference17 ( ) {
check ( " auto g() -> int&; \n "
" int& f() { \n "
" return g(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-11-10 09:44:04 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-12-01 15:10:02 +01:00
void returnReference18 ( ) {
check ( " template<class T> \n "
" auto f(T& x) -> decltype(x); \n "
" int& g(int* x) { \n "
" return f(*x); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-12-01 15:10:02 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2020-02-11 11:41:41 +01:00
// #9597
void returnReference19 ( ) {
check ( " struct C : B { \n "
" const B &f() const { return (const B &)*this; } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-02-11 11:41:41 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2020-04-01 22:35:41 +02:00
// #9536
void returnReference20 ( ) {
check ( " struct a { \n "
" int& operator()() const; \n "
" }; \n "
" int& b() { \n "
" return a()(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-04-01 22:35:41 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " auto a() { \n "
" return []() -> int& { \n "
" static int b; \n "
" return b; \n "
" }; \n "
" } \n "
" const int& c() { \n "
" return a()(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-04-01 22:35:41 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::function<int&()> a(); \n "
" int& b() { \n "
" return a()(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-04-01 22:35:41 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-11 05:58:17 +02:00
// #9889
check ( " int f(std::vector<std::function<int&()>>& v, int i) { \n "
" auto& j = v[i](); \n "
" return j; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-04-01 22:35:41 +02:00
}
2020-09-17 08:33:16 +02:00
// #9530
void returnReference21 ( ) {
check ( " int& f(int& x) { \n "
" return {x}; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2021-07-21 20:13:38 +02:00
void returnReference22 ( ) {
2021-07-20 21:30:27 +02:00
check ( " int& f() { \n "
" std::unique_ptr<int> p = std::make_unique<int>(1); \n "
" return *p; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Reference to local variable returned. \n " , errout . str ( ) ) ;
check ( " void g(const std::unique_ptr<int>&); \n "
" int& f() { \n "
" std::unique_ptr<int> p = std::make_unique<int>(1); \n "
" g(p); \n "
" return *p; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Reference to local variable returned. \n " , errout . str ( ) ) ;
check ( " void g(std::shared_ptr<int>); \n "
" int& f() { \n "
" std::shared_ptr<int> p = std::make_shared<int>(1); \n "
" g(p); \n "
" return *p; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::shared_ptr<int> g(); \n "
" int& f() { \n "
" return *g(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::unique_ptr<int> g(); \n "
" int& f() { \n "
" return *g(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
check ( " struct A { int x; }; \n "
" int& f() { \n "
" std::unique_ptr<A> p = std::make_unique<A>(); \n "
" return p->x; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Reference to local variable returned. \n " , errout . str ( ) ) ;
}
2021-08-04 08:16:31 +02:00
void returnReference23 ( ) {
check ( " const std::vector<int> * g(); \n "
" const std::vector<int>& f() { \n "
" return *g(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2021-10-15 10:59:40 +02:00
void returnReference24 ( )
{
check ( " struct A { \n "
" A() {} \n "
" }; \n "
" const A& a() { \n "
" return A(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
}
2022-04-27 20:11:32 +02:00
void returnReference25 ( )
{
check ( " int& f(); \n " // #10983
" auto g() -> decltype(f()) { \n "
" return f(); \n "
" } \n "
" int& h() { \n "
" return g(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-01-26 11:03:57 +01:00
void returnReferenceFunction ( ) {
check ( " int& f(int& a) { \n "
" return a; \n "
" } \n "
" int& hello() { \n "
" int x = 0; \n "
" return f(x); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-26 11:03:57 +01:00
ASSERT_EQUALS (
" [test.cpp:1] -> [test.cpp:2] -> [test.cpp:6] -> [test.cpp:6]: (error) Reference to local variable returned. \n " ,
errout . str ( ) ) ;
2019-02-22 06:38:56 +01:00
check ( " int& f(int& a) { \n "
" return a; \n "
" } \n "
" int* hello() { \n "
" int x = 0; \n "
" return &f(x); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-02-22 06:38:56 +01:00
ASSERT_EQUALS (
" [test.cpp:1] -> [test.cpp:2] -> [test.cpp:6] -> [test.cpp:6] -> [test.cpp:5] -> [test.cpp:6]: (error) Returning pointer to local variable 'x' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2019-07-26 07:02:07 +02:00
check ( " int* f(int * x) { \n "
" return x; \n "
" } \n "
" int * g(int x) { \n "
" return f(&x); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-07-26 07:02:07 +02:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:5] -> [test.cpp:4] -> [test.cpp:5]: (error) Returning pointer to local variable 'x' that will be invalid when returning. \n " , errout . str ( ) ) ;
check ( " int* f(int * x) { \n "
" x = nullptr; \n "
" return x; \n "
" } \n "
" int * g(int x) { \n "
" return f(&x); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-07-26 07:02:07 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-01-26 11:03:57 +01:00
check ( " int f(int& a) { \n "
" return a; \n "
" } \n "
" int& hello() { \n "
" int x = 0; \n "
" return f(x); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
2019-01-26 11:03:57 +01:00
check ( " int& f(int a) { \n "
" return a; \n "
" } \n "
" int& hello() { \n "
" int x = 0; \n "
" return f(x); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-26 11:03:57 +01:00
ASSERT_EQUALS ( " [test.cpp:2]: (error) Reference to local variable returned. \n " , errout . str ( ) ) ;
check ( " int f(int a) { \n "
" return a; \n "
" } \n "
" int& hello() { \n "
" int x = 0; \n "
" return f(x); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
2019-01-26 11:03:57 +01:00
check ( " template<class T> \n "
" int& f(int& x, T y) { \n "
" x += y; \n "
" return x; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-26 11:03:57 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-02-22 06:38:56 +01:00
void returnReferenceContainer ( ) {
check ( " auto& f() { \n "
" std::vector<int> x; \n "
" return x[0]; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-02-22 06:38:56 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Reference to local variable returned. \n " , errout . str ( ) ) ;
2019-10-08 09:28:39 +02:00
check ( " auto& f() { \n "
" std::vector<int> x; \n "
" return x.front(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3]: (error) Reference to local variable returned. \n " , errout . str ( ) ) ;
check ( " std::vector<int> g(); \n "
" auto& f() { \n "
" return g().front(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
check ( " auto& f() { \n "
" return std::vector<int>{1}.front(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-09-09 04:54:38 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:2]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
2019-10-08 09:28:39 +02:00
2019-02-22 06:38:56 +01:00
check ( " struct A { int foo; }; \n "
" int& f(std::vector<A> v) { \n "
" auto it = v.begin(); \n "
" return it->foo; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-02-22 06:38:56 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (error) Reference to local variable returned. \n " , errout . str ( ) ) ;
2019-09-11 19:25:09 +02:00
check ( " template <class T, class K, class V> \n "
" const V& get_default(const T& t, const K& k, const V& v) { \n "
" auto it = t.find(k); \n "
" if (it == t.end()) return v; \n "
" return it->second; \n "
" } \n "
" const int& bar(const std::unordered_map<int, int>& m, int k) { \n "
" auto x = 0; \n "
" return get_default(m, k, x); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS (
" [test.cpp:2] -> [test.cpp:4] -> [test.cpp:9] -> [test.cpp:9]: (error, inconclusive) Reference to local variable returned. \n " ,
errout . str ( ) ) ;
2019-10-08 09:28:39 +02:00
check ( " template <class T, class K, class V> \n "
" const V& get_default(const T& t, const K& k, const V& v) { \n "
" auto it = t.find(k); \n "
" if (it == t.end()) return v; \n "
" return it->second; \n "
" } \n "
" const int& bar(const std::unordered_map<int, int>& m, int k) { \n "
" return get_default(m, k, 0); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS (
" [test.cpp:2] -> [test.cpp:4] -> [test.cpp:8] -> [test.cpp:8]: (error, inconclusive) Reference to temporary returned. \n " ,
errout . str ( ) ) ;
2019-02-22 06:38:56 +01:00
check ( " struct A { int foo; }; \n "
" int& f(std::vector<A>& v) { \n "
" auto it = v.begin(); \n "
" return it->foo; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-02-22 06:38:56 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void returnReferenceLiteral ( ) {
2014-05-22 11:39:11 +02:00
check ( " const std::string &a() { \n "
" return \" foo \" ; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
check ( " const std::string a() { \n "
" return \" foo \" ; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-10-08 09:28:39 +02:00
check ( " const std::string& f(const std::string& x) { return x; } \n "
" const std::string &a() { \n "
" return f( \" foo \" ); \n "
" } " ) ;
ASSERT_EQUALS (
" [test.cpp:1] -> [test.cpp:1] -> [test.cpp:3] -> [test.cpp:3]: (error) Reference to temporary returned. \n " ,
errout . str ( ) ) ;
check ( " const char * f(const char * x) { return x; } \n "
" const std::string &a() { \n "
" return f( \" foo \" ); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
2014-05-22 11:39:11 +02:00
}
2014-11-20 14:20:09 +01:00
void returnReferenceCalculation ( ) {
2014-05-22 11:39:11 +02:00
check ( " const std::string &a(const std::string& str) { \n "
" return \" foo \" + str; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
2015-01-31 10:12:20 +01:00
check ( " int& operator<<(int out, int path) { \n "
" return out << path; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
2014-05-24 12:32:44 +02:00
check ( " std::ostream& operator<<(std::ostream& out, const std::string& path) { \n "
" return out << path; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-01-31 10:12:20 +01:00
check ( " std::ostream& operator<<(std::ostream* out, const std::string& path) { \n "
" return *out << path; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-05-24 12:32:44 +02:00
check ( " Unknown1& operator<<(Unknown1 out, Unknown2 path) { \n "
" return out << path; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-05-22 11:39:11 +02:00
check ( " int& a(int b) { \n "
" return 2*(b+1); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
check ( " const std::string &a(const std::string& str) { \n "
" return str; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " const std::string &a(int bar) { \n "
" return foo(bar + 1); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " const std::string a(const std::string& str) { \n "
" return \" foo \" + str; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-12-22 11:49:59 +01:00
check ( " int& incValue(int& value) { \n "
" return ++value; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-05-22 11:39:11 +02:00
}
2015-08-14 13:03:07 +02:00
void returnReferenceLambda ( ) {
// #6787
check ( " const Item& foo(const Container& items) const { \n "
" return bar(items.begin(), items.end(), \n "
" [](const Item& lhs, const Item& rhs) { \n "
" return false; \n "
" }); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-05-20 23:46:56 +02:00
// #5844
check ( " map<string,string> const &getVariableTable() { \n "
" static map<string,string> const s_var = []{ \n "
" map<string,string> var; \n "
" return var; \n "
" }(); \n "
" return s_var; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-02-26 13:41:49 +01:00
// #7583
check ( " Command& foo() { \n "
" return f([]() -> int { return 1; }); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-08-14 13:03:07 +02:00
}
2011-04-18 06:56:39 +02:00
2015-08-26 13:31:51 +02:00
void returnReferenceInnerScope ( ) {
// #6951
check ( " const Callback& make() { \n "
" struct _Wrapper { \n "
" static ulong call(void* o, const void* f, const void*[]) { \n "
" return 1; \n "
" } \n "
" }; \n "
" return _make(_Wrapper::call, pmf); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-01-31 10:34:41 +01:00
void returnReferenceRecursive ( ) {
check ( " int& f() { return f(); } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int& g(int& i) { return i; } \n "
2021-02-20 12:58:42 +01:00
" int& f() { return g(f()); } " ) ;
2019-01-31 10:34:41 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-10-08 09:28:39 +02:00
void extendedLifetime ( ) {
check ( " void g(int*); \n "
" int h(); \n "
" auto f() { \n "
" const int& x = h(); \n "
" return [&] { return x; }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:5] -> [test.cpp:4] -> [test.cpp:5]: (error) Returning lambda that captures local variable 'x' that will be invalid when returning. \n " , errout . str ( ) ) ;
check ( " void g(int*); \n "
" int h(); \n "
" int* f() { \n "
" const int& x = h(); \n "
" return &x; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:5] -> [test.cpp:4] -> [test.cpp:5]: (error) Returning pointer to local variable 'x' that will be invalid when returning. \n " , errout . str ( ) ) ;
check ( " void g(int*); \n "
" int h(); \n "
" void f() { \n "
" int& x = h(); \n "
" g(&x); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2021-11-01 19:23:15 +01:00
ASSERT_EQUALS (
" [test.cpp:4] -> [test.cpp:5] -> [test.cpp:4] -> [test.cpp:5]: (error) Using pointer that is a temporary. \n "
" [test.cpp:4] -> [test.cpp:5]: (error) Using reference to dangling temporary. \n " ,
errout . str ( ) ) ;
2019-10-08 09:28:39 +02:00
check ( " void g(int*); \n "
" int h(); \n "
" void f() { \n "
" const int& x = h(); \n "
" g(&x); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-04-18 09:23:10 +02:00
check ( " struct Data { \n "
" std::string path; \n "
" }; \n "
" const char* foo() { \n "
" const Data& data = getData(); \n "
" return data.path.c_str(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-04-18 09:23:10 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-10-08 09:28:39 +02:00
}
2019-01-23 07:29:16 +01:00
void danglingReference ( ) {
2019-01-26 11:03:57 +01:00
check ( " int f( int k ) \n "
2019-01-23 07:29:16 +01:00
" { \n "
" static int &r = k; \n "
" return r; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-23 07:29:16 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3]: (error) Non-local reference variable 'r' to local variable 'k' \n " ,
errout . str ( ) ) ;
check ( " int &f( int & k ) \n "
" { \n "
" static int &r = k; \n "
" return r; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-23 07:29:16 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2020-09-09 01:30:45 +02:00
void danglingTempReference ( ) {
check ( " const std::string& g(const std::string& str_cref) { \n "
" return str_cref; \n "
" } \n "
" void f() { \n "
" const auto& str_cref2 = g(std::string( \" hello \" )); \n "
" std::cout << str_cref2 << std::endl; \n "
" } \n " ) ;
2020-10-06 09:16:54 +02:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:1] -> [test.cpp:2] -> [test.cpp:5] -> [test.cpp:6]: (error) Using reference to dangling temporary. \n " , errout . str ( ) ) ;
2020-09-09 01:30:45 +02:00
// Lifetime extended
check ( " std::string g(const std::string& str_cref) { \n "
" return str_cref; \n "
" } \n "
" void f() { \n "
" const auto& str_cref2 = g(std::string( \" hello \" )); \n "
" std::cout << str_cref2 << std::endl; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-11 05:38:31 +02:00
check ( " char f() { \n "
" char c = 0; \n "
" char&& cr = std::move(c); \n "
" return cr; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-11-17 06:52:12 +01:00
// #9987
check ( " void g(std::vector<int>); \n "
" void f() { \n "
" std::vector<int>&& v = {}; \n "
" g(std::move(v)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void g(std::vector<int>); \n "
2020-11-19 21:25:49 +01:00
" std::vector<int> h(); \n "
2020-11-17 06:52:12 +01:00
" void f() { \n "
" std::vector<int>&& v = h(); \n "
" g(std::move(v)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-09 01:30:45 +02:00
}
2014-11-20 14:20:09 +01:00
void testglobalnamespace ( ) {
2011-04-18 06:56:39 +02:00
check ( " class SharedPtrHolder \n "
" { \n "
" ::std::tr1::shared_ptr<int> pNum; \n "
" public: \n "
" void SetNum(const ::std::tr1::shared_ptr<int> & apNum) \n "
" { \n "
" pNum = apNum; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void returnParameterAddress ( ) {
2011-09-01 03:36:31 +02:00
check ( " int* foo(int y) \n "
" { \n "
" return &y; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2011-09-01 03:36:31 +02:00
2018-11-12 10:08:17 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning pointer to local variable 'y' that will be invalid when returning. \n " , errout . str ( ) ) ;
2011-09-02 00:30:49 +02:00
check ( " int ** foo(int * y) \n "
" { \n "
" return &y; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2011-09-02 00:30:49 +02:00
2018-11-12 10:08:17 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning pointer to local variable 'y' that will be invalid when returning. \n " , errout . str ( ) ) ;
2011-09-02 16:39:04 +02:00
check ( " const int * foo(const int & y) \n "
" { \n "
" return &y; \n "
2013-03-19 09:18:58 +01:00
" } " ) ;
2011-09-02 16:39:04 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-17 09:41:59 +01:00
check ( " int * foo(int * y) \n "
" { \n "
" return y; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-02-18 09:35:07 +01:00
check ( " struct s { void *p; }; \n "
" extern struct s* f(void); \n "
" void g(void **q) \n "
" { \n "
" struct s *r = f(); \n "
" *q = &r->p; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-02-18 09:35:07 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-09-01 03:36:31 +02:00
}
2014-11-20 14:20:09 +01:00
void testconstructor ( ) { // Ticket #5478 - crash while checking a constructor
2014-03-01 16:30:59 +01:00
check ( " class const_tree_iterator { \n "
" const_tree_iterator(bool (*_incream)(node_type*&)) {} \n "
" const_tree_iterator& parent() { \n "
" return const_tree_iterator(foo); \n "
" } \n "
" }; " ) ;
}
2014-11-20 14:20:09 +01:00
void variableIsUsedInScope ( ) {
2014-03-22 11:14:11 +01:00
check ( " void removed_cb (GList *uids) { \n "
" for (; uids; uids = uids->next) { \n "
" } \n "
" } \n "
" void opened_cb () { \n "
" g_signal_connect (G_CALLBACK (removed_cb)); \n "
" } " ) ;
}
2018-11-10 16:40:40 +01:00
void danglingLifetimeLambda ( ) {
check ( " auto f() { \n "
" int a = 1; \n "
" auto l = [&](){ return a; }; \n "
" return l; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning. \n " , errout . str ( ) ) ;
check ( " auto f() { \n "
" int a = 1; \n "
" return [&](){ return a; }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning. \n " , errout . str ( ) ) ;
check ( " auto f(int a) { \n "
" return [&](){ return a; }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:1] -> [test.cpp:2]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning. \n " , errout . str ( ) ) ;
check ( " auto f(int a) { \n "
" auto p = &a; \n "
" return [=](){ return p; }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning. \n " , errout . str ( ) ) ;
check ( " auto g(int& a) { \n "
" int p = a; \n "
" return [&](){ return p; }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning lambda that captures local variable 'p' that will be invalid when returning. \n " , errout . str ( ) ) ;
check ( " auto f() { \n "
" return [=](){ \n "
" int a = 1; \n "
" return [&](){ return a; }; \n "
" }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3] -> [test.cpp:4]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning. \n " , errout . str ( ) ) ;
check ( " auto f(int b) { \n "
" return [=](int a){ \n "
" a += b; \n "
" return [&](){ return a; }; \n "
" }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-07-05 12:30:42 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning. \n " , errout . str ( ) ) ;
2018-11-10 16:40:40 +01:00
check ( " auto g(int& a) { \n "
" return [&](){ return a; }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " auto g(int a) { \n "
" auto p = a; \n "
" return [=](){ return p; }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " auto g(int& a) { \n "
" auto p = a; \n "
" return [=](){ return p; }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " auto g(int& a) { \n "
" int& p = a; \n "
" return [&](){ return p; }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " template<class F> \n "
" void g(F); \n "
" auto f() { \n "
" int x; \n "
" return g([&]() { return x; }); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-05 07:56:01 +02:00
check ( " auto f() { \n "
" int i = 0; \n "
" return [&i] {}; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning lambda that captures local variable 'i' that will be invalid when returning. \n " , errout . str ( ) ) ;
check ( " auto f() { \n "
" int i = 0; \n "
" return [i] {}; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " auto f() { \n "
" int i = 0; \n "
" return [=, &i] {}; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning lambda that captures local variable 'i' that will be invalid when returning. \n " , errout . str ( ) ) ;
check ( " auto f() { \n "
" int i = 0; \n "
" int j = 0; \n "
" return [=, &i] { return j; }; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning lambda that captures local variable 'i' that will be invalid when returning. \n " , errout . str ( ) ) ;
check ( " auto f() { \n "
" int i = 0; \n "
" return [&, i] {}; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " auto f() { \n "
" int i = 0; \n "
" int j = 0; \n "
" return [&, i] { return j; }; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3] -> [test.cpp:4]: (error) Returning lambda that captures local variable 'j' that will be invalid when returning. \n " , errout . str ( ) ) ;
check ( " auto f(int& i) { \n "
" int j = 0; \n "
" return [=, &i] { return j; }; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-17 08:33:52 +02:00
check ( " void f(int*); \n "
" auto g(int y) { \n "
" int x = y; \n "
" return [=] { \n "
" g(&x); \n "
" }; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-08-25 04:06:03 +02:00
check ( " struct A { \n "
" int x; \n "
" }; \n "
" auto f() { \n "
" A a; \n "
" return [=] { \n "
" const A* ap = &a; \n "
" ap->x; \n "
" }; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-10 16:40:40 +01:00
}
void danglingLifetimeContainer ( ) {
check ( " auto f(const std::vector<int>& x) { \n "
" auto it = x.begin(); \n "
" return it; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " auto f() { \n "
" std::vector<int> x; \n "
" auto it = x.begin(); \n "
" return it; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning iterator to local container 'x' that will be invalid when returning. \n " , errout . str ( ) ) ;
check ( " auto f() { \n "
" std::vector<int> x; \n "
" auto p = x.data(); \n "
" return p; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2021-08-14 19:00:58 +02:00
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning pointer to local variable 'x' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2018-11-10 16:40:40 +01:00
2019-02-22 06:38:56 +01:00
check ( " auto f() { \n "
" std::vector<int> x; \n "
" auto p = &x[0]; \n "
" return p; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-02-22 06:38:56 +01:00
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning pointer to local variable 'x' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct A { int foo; }; \n "
" int* f(std::vector<A> v) { \n "
" auto it = v.begin(); \n "
" return &it->foo; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-02-22 06:38:56 +01:00
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:4] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning object that points to local variable 'v' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2018-11-10 16:40:40 +01:00
check ( " auto f(std::vector<int> x) { \n "
" auto it = x.begin(); \n "
" return it; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning iterator to local container 'x' that will be invalid when returning. \n " , errout . str ( ) ) ;
2018-11-16 06:12:28 +01:00
check ( " auto f() { \n "
" std::vector<int> x; \n "
" auto it = x.begin(); \n "
" return std::next(it); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-16 06:12:28 +01:00
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:4] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning object that points to local variable 'x' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " auto f() { \n "
" std::vector<int> x; \n "
" auto it = x.begin(); \n "
" return it + 1; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-16 06:12:28 +01:00
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning iterator to local container 'x' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " auto f() { \n "
" std::vector<int> x; \n "
" auto it = x.begin(); \n "
" return std::next(it + 1); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-16 06:12:28 +01:00
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:4] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning object that points to local variable 'x' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2018-11-21 08:43:57 +01:00
check ( " std::vector<int*> f() { \n "
" int i = 0; \n "
" std::vector<int*> v; \n "
" v.push_back(&i); \n "
" return v; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-21 08:43:57 +01:00
ASSERT_EQUALS (
" [test.cpp:4] -> [test.cpp:4] -> [test.cpp:2] -> [test.cpp:5]: (error) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " std::vector<int*> f() { \n "
" std::vector<int*> r; \n "
" int i = 0; \n "
" std::vector<int*> v; \n "
" v.push_back(&i); \n "
" r.assign(v.begin(), v.end()); \n "
" return r; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-21 08:43:57 +01:00
ASSERT_EQUALS (
" [test.cpp:5] -> [test.cpp:5] -> [test.cpp:5] -> [test.cpp:3] -> [test.cpp:7]: (error) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" std::vector<int*> v; \n "
" void f() { \n "
" int i; \n "
" v.push_back(&i); \n "
" } \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2018-11-21 08:43:57 +01:00
ASSERT_EQUALS (
" [test.cpp:5] -> [test.cpp:5] -> [test.cpp:4] -> [test.cpp:5]: (error) Non-local variable 'v' will use object that points to local variable 'i'. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" std::vector<int*> v; \n "
" void f() { \n "
" int i; \n "
" int * p = &i; \n "
" v.push_back(p); \n "
" } \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2018-11-21 08:43:57 +01:00
ASSERT_EQUALS (
" [test.cpp:5] -> [test.cpp:6] -> [test.cpp:4] -> [test.cpp:6]: (error) Non-local variable 'v' will use object that points to local variable 'i'. \n " ,
errout . str ( ) ) ;
2018-12-02 14:31:31 +01:00
check ( " struct A { \n "
" std::vector<int*> m; \n "
" void f() { \n "
" int x; \n "
" std::vector<int*> v; \n "
" v.push_back(&x); \n "
" m.insert(m.end(), v.begin(), v.end()); \n "
" } \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2018-12-02 14:31:31 +01:00
ASSERT_EQUALS (
" [test.cpp:6] -> [test.cpp:6] -> [test.cpp:6] -> [test.cpp:4] -> [test.cpp:7]: (error) Non-local variable 'm' will use object that points to local variable 'x'. \n " ,
errout . str ( ) ) ;
2019-02-22 06:37:02 +01:00
check ( " std::vector<int>::iterator f(std::vector<int> v) { \n "
" for(auto it = v.begin();it != v.end();it++) { \n "
" return it; \n "
" } \n "
" return {}; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-02-22 06:37:02 +01:00
ASSERT_EQUALS (
" [test.cpp:2] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning iterator to local container 'v' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2019-05-05 11:40:59 +02:00
check ( " const char * f() { \n "
" std::string ba( \" hello \" ); \n "
" return ba.c_str(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-05-05 11:40:59 +02:00
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning pointer to local variable 'ba' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2019-09-11 19:25:09 +02:00
check ( " template <class T, class K, class V> \n "
" const V* get_default(const T& t, const K& k, const V* v) { \n "
" auto it = t.find(k); \n "
" if (it == t.end()) return v; \n "
" return &it->second; \n "
" } \n "
" const int* bar(const std::unordered_map<int, int>& m, int k) { \n "
" auto x = 0; \n "
" return get_default(m, k, &x); \n "
" } \n " ,
true ) ;
2021-06-04 17:15:39 +02:00
ASSERT_EQUALS (
2019-09-11 19:25:09 +02:00
" [test.cpp:9] -> [test.cpp:9] -> [test.cpp:8] -> [test.cpp:9]: (error, inconclusive) Returning pointer to local variable 'x' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2019-10-08 09:28:39 +02:00
check ( " std::vector<int> g(); \n "
" auto f() { \n "
" return g().begin(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2021-11-28 15:25:21 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3]: (error) Returning iterator that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2019-10-08 09:28:39 +02:00
2022-04-07 06:48:51 +02:00
check ( " std::vector<int> g(); \n "
2019-10-08 09:28:39 +02:00
" auto f() { \n "
" auto it = g().begin(); \n "
" return it; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2022-04-07 06:48:51 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (error) Returning iterator that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2019-10-08 09:28:39 +02:00
2022-04-07 06:48:51 +02:00
check ( " std::vector<int> g(); \n "
2019-10-08 09:28:39 +02:00
" int& f() { \n "
" return *g().begin(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2022-04-07 06:48:51 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
2019-10-08 09:28:39 +02:00
2018-11-21 08:43:57 +01:00
check ( " struct A { \n "
" std::vector<std::string> v; \n "
" void f() { \n "
" char s[3]; \n "
" v.push_back(s); \n "
" } \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2018-11-21 08:43:57 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::vector<std::string> f() { \n "
" const char * s = \" hello \" ; \n "
" std::vector<std::string> v; \n "
" v.push_back(s); \n "
" return v; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-21 08:43:57 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-10 16:40:40 +01:00
check ( " auto f() { \n "
" static std::vector<int> x; \n "
" return x.begin(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::string g() { \n "
" std::vector<char> v; \n "
" return v.data(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-17 09:41:59 +01:00
check ( " std::vector<int>::iterator f(std::vector<int>* v) { \n "
" return v->begin(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-17 09:41:59 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::vector<int>::iterator f(std::vector<int>* v) { \n "
" std::vector<int>* v = new std::vector<int>(); \n "
" return v->begin(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-17 09:41:59 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f(std::vector<int> v) { \n "
" return *v.begin(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-17 09:41:59 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f(std::vector<int> v) { \n "
" return v.end() - v.begin(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-17 09:41:59 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-10 16:40:40 +01:00
check ( " auto g() { \n "
" std::vector<char> v; \n "
" return {v, [v]() { return v.data(); }}; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-11-27 06:44:43 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-10 16:40:40 +01:00
check ( " template<class F> \n "
" void g(F); \n "
" auto f() { \n "
" std::vector<char> v; \n "
" return g([&]() { return v.data(); }); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-12-02 14:31:31 +01:00
check ( " std::vector<int> g(); \n "
" struct A { \n "
" std::vector<int> m; \n "
" void f() { \n "
" std::vector<int> v = g(); \n "
" m.insert(m.end(), v.begin(), v.end()); \n "
" } \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2018-12-02 14:31:31 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-06-02 10:14:48 +02:00
check ( " void f(bool b) { \n "
" std::vector<int> v = {1}; \n "
" if (b) { \n "
" int a[] = {0}; \n "
" v.insert(a, a+1); \n "
" } \n "
" return v.back() == 0; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-06-02 10:14:48 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-12-02 14:31:31 +01:00
check ( " class A { \n "
" int f( P p ) { \n "
" std::vector< S > maps; \n "
" m2.insert( m1.begin(), m1.end() ); \n "
" } \n "
" struct B {}; \n "
" std::map< S, B > m1; \n "
" std::map< S, B > m2; \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2018-12-02 14:31:31 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-06-02 10:21:26 +02:00
check ( " struct A { \n "
" std::vector<int*> v; \n "
" int x; \n "
" void f() { \n "
" v.push_back(&x); \n "
" } \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2019-06-02 10:21:26 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-06-24 18:52:17 +02:00
check ( " size_t f(const std::string& x) { \n "
" std::string y = \" x \" ; \n "
" return y.find(x); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-06-24 18:52:17 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-07-23 21:59:05 +02:00
check ( " std::string* f(); \n "
" const char* g() { \n "
" std::string* var = f(); \n "
" return var->c_str(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-07-23 21:59:05 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-11-17 03:22:04 +01:00
check ( " std::string f() { \n "
" std::vector<char> data{}; \n "
" data.push_back('a'); \n "
" return std::string{ data.data(), data.size() }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-11-17 03:22:04 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::vector<char*> f() { \n "
" char a = 0; \n "
" return std::vector<char*>{&a}; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-11-17 03:22:04 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning object that points to local variable 'a' that will be invalid when returning. \n " , errout . str ( ) ) ;
2020-09-01 11:21:29 +02:00
2020-09-02 20:01:08 +02:00
check ( " std::vector<int>* g(); \n "
" int& f() { \n "
" auto* p = g(); \n "
" return p->front(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-01 11:21:29 +02:00
check ( " std::vector<std::vector<int>> g(); \n "
" void f() { \n "
" for(auto& x:g()) \n "
" std::sort(x.begin(), x.end()); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-04 18:56:34 +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 "
" int i = 0; \n "
" add(&i); \n "
" } \n "
" }; \n " ) ;
2020-09-04 18:59:30 +02:00
ASSERT_EQUALS (
" [test.cpp:8] -> [test.cpp:8] -> [test.cpp:4] -> [test.cpp:7] -> [test.cpp:4]: (error) Non-local variable 'v' will use object that points to local variable 'i'. \n " ,
errout . str ( ) ) ;
2020-09-07 04:59:21 +02:00
2020-09-07 04:58:36 +02:00
check ( " struct A { \n "
" std::vector<int*> v; \n "
" void add(int* i) { \n "
" v.push_back(i); \n "
" } \n "
" }; \n "
" void f() { \n "
" A a; \n "
" int i = 0; \n "
" a.add(&i); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { \n "
" std::vector<int*> v; \n "
" void add(int* i) { \n "
" v.push_back(i); \n "
" } \n "
" void f() { \n "
" A a; \n "
" int i = 0; \n "
" a.add(&i); \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-08-31 09:48:23 +02:00
check ( " int f() { \n "
" int i; \n "
" { \n "
" std::vector<int> vec; \n "
" const auto iter = vec.begin(); \n "
" i = (int)(iter - vec.begin()); \n "
" } \n "
" return i; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-09-04 19:53:14 +02:00
check ( " int* get(std::vector<int>& container) { \n "
" Sequence seq(container); \n "
" for (auto& r : seq) { \n "
" return &r; \n "
" } \n "
" return &*seq.begin(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-10-30 09:06:36 +02:00
check ( " std::string f(std::string Str, int first, int last) { \n "
" return { Str.begin() + first, Str.begin() + last + 1 }; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-06 19:08:19 +01:00
2021-11-15 20:36:38 +01:00
check ( " std::string f(std::string s) { \n "
" std::string r = { s.begin(), s.end() }; \n "
" return r; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-06 19:08:19 +01:00
check ( " struct A { \n "
" std::vector<std::unique_ptr<int>> mA; \n "
" void f(std::unique_ptr<int> a) { \n "
" auto x = a.get(); \n "
" mA.push_back(std::move(a)); \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-11 08:00:05 +01:00
check ( " struct A { \n "
" std::map<std::string, int> m; \n "
" int* f(std::string s) { \n "
" auto r = m.emplace(name, name); \n "
" return &(r.first->second); \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-03-27 10:02:30 +02:00
check ( " void f() { \n "
" std::queue<int> q; \n "
" auto& h = q.emplace(); \n "
" h = 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-04-12 08:09:13 +02:00
check ( " std::string f(std::string s) { \n "
" std::string ss = ( \" : \" + s).c_str(); \n "
" return ss; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-10 16:40:40 +01:00
}
2021-10-05 08:28:19 +02:00
void danglingLifetimeContainerView ( )
{
check ( " std::string_view f() { \n "
" std::string s = \" \" ; \n "
" return s; \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning object that points to local variable 's' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " std::string_view f() { \n "
" std::string s = \" \" ; \n "
" std::string_view sv = s; \n "
" return sv; \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning object that points to local variable 's' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " std::string_view f() { \n "
" std::string s = \" \" ; \n "
" return std::string_view{s}; \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning object that points to local variable 's' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " std::string_view f(std::string_view s) { \n "
" return s; \n "
" } \n "
" std::string_view g() { \n "
" std::string s = \" \" ; \n "
" return f(s); \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:6] -> [test.cpp:6] -> [test.cpp:5] -> [test.cpp:6]: (error) Returning object that points to local variable 's' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " const char * f() { \n "
" std::string s; \n "
" std::string_view sv = s; \n "
" return sv.begin(); \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:4] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning iterator to local container 's' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " const char * f() { \n "
" std::string s; \n "
" return std::string_view{s}.begin(); \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning iterator to local container 's' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " const char * f() { \n "
" std::string s; \n "
" return std::string_view(s).begin(); \n "
" } \n " ) ;
TODO_ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning iterator to local container 's' that will be invalid when returning. \n " ,
" " ,
errout . str ( ) ) ;
check ( " const char * f(std::string_view sv) { \n "
" return sv.begin(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " const char * f(std::string s) { \n "
" std::string_view sv = s; \n "
" return sv.begin(); \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning iterator to local container 's' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " std::string_view f(std::string s) { \n "
" return s; \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:2] -> [test.cpp:1] -> [test.cpp:2]: (error) Returning object that points to local variable 's' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " const char * f(const std::string& s) { \n "
" std::string_view sv = s; \n "
" return sv.begin(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::string_view f(const std::string_view& sv) { \n "
" return sv; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2021-10-06 08:46:25 +02:00
void danglingLifetimeUniquePtr ( )
{
check ( " int* f(std::unique_ptr<int> p) { \n "
" int * rp = p.get(); \n "
" return rp; \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:2] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning pointer to local variable 'p' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
}
2018-11-10 16:40:40 +01:00
void danglingLifetime ( ) {
check ( " auto f() { \n "
" std::vector<int> a; \n "
" auto it = a.begin(); \n "
" return [=](){ return it; }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning. \n " , errout . str ( ) ) ;
check ( " auto f(std::vector<int> a) { \n "
" auto it = a.begin(); \n "
" return [=](){ return it; }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3] -> [test.cpp:1] -> [test.cpp:3]: (error) Returning lambda that captures local variable 'a' that will be invalid when returning. \n " , errout . str ( ) ) ;
2018-12-15 17:58:45 +01:00
check ( " struct e {}; \n "
" e * j() { \n "
" e c[20]; \n "
" return c; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-12-15 17:58:45 +01:00
ASSERT_EQUALS (
" [test.cpp:4] -> [test.cpp:3] -> [test.cpp:4]: (error) Returning pointer to local variable 'c' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2018-11-10 16:40:40 +01:00
check ( " auto f(std::vector<int>& a) { \n "
" auto it = a.begin(); \n "
" return [=](){ return it; }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-10 16:40:40 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-17 09:41:59 +01:00
check ( " int * f(int a[]) { \n "
" return a; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-17 09:41:59 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-12-01 19:07:46 +01:00
check ( " void f() { \n "
" struct b { \n "
" uint32_t f[6]; \n "
" } d; \n "
" uint32_t *a = d.f; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-12-01 19:14:43 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-01-06 17:15:57 +01:00
// Don't decay std::array
2018-12-01 19:14:43 +01:00
check ( " std::array<char, 1> f() { \n "
" std::array<char, 1> x; \n "
" return x; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-12-01 19:14:43 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-01-06 17:15:57 +01:00
// Make sure we don't hang
2018-12-01 19:14:43 +01:00
check ( " struct A; \n "
" void f() { \n "
" using T = A[3]; \n "
" A &&a = T{1, 2, 3}[1]; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-12-01 19:14:43 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-01-06 17:15:57 +01:00
// Make sure we don't hang
2018-12-01 19:14:43 +01:00
check ( " struct A; \n "
" void f() { \n "
" using T = A[3]; \n "
" A &&a = T{1, 2, 3}[1](); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-12-01 19:14:43 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-01-06 17:15:57 +01:00
// Make sure we don't hang
2018-12-01 19:14:43 +01:00
check ( " struct A; \n "
" void f() { \n "
" using T = A[3]; \n "
" A &&a = T{1, 2, 3}[1]; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-12-01 19:14:43 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-01-06 17:15:57 +01:00
// Make sure we don't hang
2018-12-01 19:14:43 +01:00
check ( " struct A; \n "
" void f() { \n "
" using T = A[3]; \n "
" A &&a = T{1, 2, 3}[1](); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-12-01 19:14:43 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// Crash #8872
check ( " struct a { \n "
" void operator()(b c) override { \n "
" d(c, [&] { c->e }); \n "
" } \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2018-12-01 19:14:43 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct a { \n "
" void operator()(b c) override { \n "
" d(c, [=] { c->e }); \n "
" } \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2018-12-01 19:14:43 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-12-15 17:58:45 +01:00
check ( " struct a { \n "
" a(char* b) {} \n "
" }; \n "
" a f() { \n "
" char c[20]; \n "
" return c; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-12-15 17:58:45 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct a { \n "
" a(char* b) {} \n "
" }; \n "
" a g() { \n "
" char c[20]; \n "
" a d = c; \n "
" return d; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-12-15 17:58:45 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-01-11 09:51:02 +01:00
check ( " void f() { \n "
" struct a { \n "
" std::vector<int> v; \n "
" auto g() { return v.end(); } \n "
" }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-11 09:51:02 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-01-26 11:03:57 +01:00
check ( " int * f(std::vector<int>& v) { \n "
" for(int & x : v) \n "
" return &x; \n "
" return nullptr; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-26 11:03:57 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-08-14 20:09:33 +02:00
// #9275
check ( " struct S { \n "
" void f(); \n "
" std::string m; \n "
" } \n "
" void S::f() { \n "
" char buf[1024]; \n "
" const char* msg = buf; \n "
" m = msg; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-08-14 20:09:33 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-11-05 07:10:32 +01:00
// #9201
check ( " int* f() { \n "
" struct a { int m; }; \n "
" static a b{0}; \n "
" return &b.m; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-11-05 07:10:32 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-11-07 09:33:17 +01:00
// #9453
check ( " int *ptr; \n "
" void foo(int arr[]) { \n "
" ptr = &arr[2]; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-11-07 09:33:17 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-03-23 22:54:53 +01:00
// #9639
check ( " struct Fred { \n "
" std::string s; \n "
" }; \n "
" const Fred &getFred(); \n "
" const char * f() { \n "
" const Fred &fred = getFred(); \n "
" return fred.s.c_str(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-03-23 22:54:53 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-04-06 16:02:10 +02:00
// #9534
check ( " struct A { \n "
" int* x; \n "
" }; \n "
" int* f(int i, std::vector<A>& v) { \n "
" A& y = v[i]; \n "
" return &y.x[i]; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-04-06 16:02:10 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-05-23 23:12:00 +02:00
// #9712
check ( " std::string f(const char *str) { \n "
" char value[256]; \n "
" return value; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-05-23 23:12:00 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-08-06 06:17:35 +02:00
// #9770
check ( " class C { \n "
" std::string f(const char*); \n "
" }; \n "
" std::string C::f(const char*) { \n "
" const char data[] = \" x \" ; \n "
" return data; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-15 07:11:52 +02:00
// #9899
check ( " struct A { \n "
" std::vector<int> v; \n "
" void f(std::vector<int> w) { \n "
" v = std::move(w); \n "
" } \n "
" void g(std::vector<int> w) { \n "
" f(std::move(w)); \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-12-28 10:50:42 +01:00
//Make sure we can still take the address of a reference without warning
check ( " int* foo() { \n "
" int& x = getX(); \n "
" return &x; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct C { \n "
" int* m_x; \n "
" void foo() { \n "
" const int& x = getX(); \n "
" m_x = &x; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-02-03 10:22:31 +01:00
// #10090
check ( " struct a { \n "
" int b{}; \n "
" }; \n "
" struct c { \n "
" int* c{}; \n "
" a* d{}; \n "
" }; \n "
" a* f(); \n "
" c g() { \n "
" c e; \n "
" e.d = f(); \n "
" if (e.d) \n "
" e.c = &e.d->b; \n "
" return e; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-04-19 14:20:29 +02:00
// #10214
check ( " struct A { \n "
" std::string key; \n "
" const char *value; \n "
" }; \n "
" const char *f(const std::string &key, const std::vector<A> &lookup) { \n "
" const auto &entry = \n "
" std::find_if(lookup.begin(), lookup.end(), \n "
" [key](const auto &v) { return v.key == key; }); \n "
" return (entry == lookup.end()) ? \" \" : entry->value; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-08-31 09:48:50 +02:00
// #9811
check ( " struct Base { \n "
" virtual auto get() -> int & = 0; \n "
" }; \n "
" struct A : public Base { \n "
" int z = 42; \n "
" auto get() -> int & override { return z; } \n "
" auto getMore() -> int & { return get(); } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-01 19:22:21 +01:00
// #10575
check ( " struct Data { \n "
" int x=0; \n "
" int y=0; \n "
" }; \n "
" struct MoreData { \n "
" Data *data1; \n "
" }; \n "
" struct Fred { \n "
" Fred() { \n "
" Data data; \n "
" mMoreData.data1 = &data; \n "
" } \n "
" MoreData mMoreData; \n "
" }; \n " ) ;
ASSERT_EQUALS (
" [test.cpp:11] -> [test.cpp:10] -> [test.cpp:11]: (error) Non-local variable 'mMoreData.data1' will use pointer to local variable 'data'. \n " ,
errout . str ( ) ) ;
2022-02-08 09:03:51 +01:00
// #10784
check ( " template <class... Ts> \n "
" auto f(int i, Ts&... xs) { \n "
" return std::tie(xs[i]...); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-10 16:40:40 +01:00
}
2018-11-16 06:12:28 +01:00
void danglingLifetimeFunction ( ) {
check ( " auto f() { \n "
" int a; \n "
" return std::ref(a); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-16 06:12:28 +01:00
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning object that points to local variable 'a' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " auto f() { \n "
" int a; \n "
" return std::make_tuple(std::ref(a)); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-16 06:12:28 +01:00
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning object that points to local variable 'a' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2019-01-29 09:47:52 +01:00
check ( " template<class T> \n "
" auto by_value(T x) { \n "
" return [=] { return x; }; \n "
" } \n "
" auto g() { \n "
" std::vector<int> v; \n "
2019-05-15 07:06:04 +02:00
" return by_value(v.begin()); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-05-16 21:11:04 +02:00
ASSERT_EQUALS (
2019-01-29 09:47:52 +01:00
" [test.cpp:7] -> [test.cpp:7] -> [test.cpp:3] -> [test.cpp:3] -> [test.cpp:6] -> [test.cpp:7]: (error) Returning object that points to local variable 'v' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2020-09-17 07:23:38 +02:00
check ( " template<class T> \n "
" auto by_value(const T& x) { \n "
" return [=] { return x; }; \n "
" } \n "
" auto g() { \n "
" std::vector<int> v; \n "
" return by_value(v.begin()); \n "
" } \n " ) ;
ASSERT_EQUALS (
2021-12-04 17:00:55 +01:00
" [test.cpp:7] -> [test.cpp:7] -> [test.cpp:3] -> [test.cpp:3] -> [test.cpp:6] -> [test.cpp:7]: (error) Returning object that points to local variable 'v' that will be invalid when returning. \n " ,
2020-09-17 07:23:38 +02:00
errout . str ( ) ) ;
2019-01-29 09:47:52 +01:00
check ( " auto by_ref(int& x) { \n "
" return [&] { return x; }; \n "
" } \n "
" auto f() { \n "
" int i = 0; \n "
" return by_ref(i); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-29 09:47:52 +01:00
ASSERT_EQUALS (
" [test.cpp:2] -> [test.cpp:1] -> [test.cpp:2] -> [test.cpp:6] -> [test.cpp:5] -> [test.cpp:6]: (error) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2020-09-17 07:23:38 +02:00
check ( " auto by_ref(const int& x) { \n "
" return [=] { return x; }; \n "
" } \n "
" auto f() { \n "
" int i = 0; \n "
" return by_ref(i); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-16 06:12:28 +01:00
check ( " auto f(int x) { \n "
" int a; \n "
" std::tie(a) = x; \n "
" return a; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-16 06:12:28 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-17 07:23:38 +02:00
check ( " std::pair<std::string, std::string> \n "
" str_pair(std::string const & a, std::string const & b) { \n "
" return std::make_pair(a, b); \n "
" } \n "
" std::vector<std::pair<std::string, std::string> > create_parameters() { \n "
" std::vector<std::pair<std::string, std::string> > par; \n "
" par.push_back(str_pair( \" param1 \" , \" prop_a \" )); \n "
" par.push_back(str_pair( \" param2 \" , \" prop_b \" )); \n "
" par.push_back(str_pair( \" param3 \" , \" prop_c \" )); \n "
" return par; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-16 06:12:28 +01:00
}
2022-02-28 18:54:55 +01:00
void danglingLifetimeUserConstructor ( )
{
check ( " struct A { \n "
" int* i; \n "
" A(int& x) \n "
" : i(&x) \n "
" {} \n "
" }; \n "
" A f() { \n "
" int i = 0; \n "
" A a{i}; \n "
" return a; \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:9] -> [test.cpp:8] -> [test.cpp:10]: (error) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" int* i; \n "
" A(int& x); \n "
" }; \n "
" A f() { \n "
" int i = 0; \n "
" A a{i}; \n "
" return a; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS (
" [test.cpp:7] -> [test.cpp:6] -> [test.cpp:8]: (error, inconclusive) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" int* i; \n "
" A(const int& x); \n "
" }; \n "
" A f() { \n "
" int i = 0; \n "
" A a{i}; \n "
" return a; \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { \n "
" int& i; \n "
" A(int& x) \n "
" : i(x) \n "
" {} \n "
" }; \n "
" A f() { \n "
" int i = 0; \n "
" A a{i}; \n "
" return a; \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:9] -> [test.cpp:8] -> [test.cpp:10]: (error) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" int& i; \n "
" A(const std::vector<int>& x) \n "
" : i(x[0]) \n "
" {} \n "
" }; \n "
" A f() { \n "
" std::vector<int> v = {0}; \n "
" A a{v}; \n "
" return a; \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:9] -> [test.cpp:8] -> [test.cpp:10]: (error) Returning object that points to local variable 'v' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" int* i; \n "
" A(const std::vector<int>& x) \n "
" : i(x.data()) \n "
" {} \n "
" }; \n "
" A f() { \n "
" std::vector<int> v = {0}; \n "
" A a{v}; \n "
" return a; \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:9] -> [test.cpp:8] -> [test.cpp:10]: (error) Returning object that points to local variable 'v' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" const int* i; \n "
" A(const int& x) \n "
" : i(&x) \n "
" {} \n "
" }; \n "
" A f() { \n "
" A a{0}; \n "
" return a; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:8] -> [test.cpp:9]: (error) Returning object that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" const int* i; \n "
" A(const int& x) \n "
" : i(&x) \n "
" {} \n "
" }; \n "
" A f() { \n "
" int i = 0; \n "
" return A{i}; \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:9] -> [test.cpp:8] -> [test.cpp:9]: (error) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" std::string v; \n "
" A(const std::string& s) \n "
" : v(s) \n "
" {} \n "
" }; \n "
" A f() { \n "
" std::string s; \n "
" return A{s}; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { \n "
" std::string_view v; \n "
" A(const std::string& s) \n "
" : v(s) \n "
" {} \n "
" }; \n "
" A f() { \n "
" std::string s; \n "
" return A{s}; \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:9] -> [test.cpp:8] -> [test.cpp:9]: (error) Returning object that points to local variable 's' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" const int* i; \n "
" A(const int& x) \n "
" : i(&x) \n "
" {} \n "
" }; \n "
" A f() { \n "
" return A{0}; \n "
" } \n " ) ;
2022-04-03 20:04:18 +02:00
ASSERT_EQUALS ( " [test.cpp:8] -> [test.cpp:8]: (error) Returning object that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2022-03-16 17:11:49 +01:00
check ( " struct A { \n "
" int n; \n "
" A(const int &x) : n(x) {} \n "
" }; \n "
" A f() { \n "
" A m(4); \n "
" return m; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct B {}; \n "
" struct A { \n "
" B n; \n "
" A(const B &x) : n(x) {} \n "
" }; \n "
" A f() { \n "
" A m(B{}); \n "
" return m; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-04-14 18:59:12 +02:00
check ( " struct A { \n "
" A(std::vector<std::string> &filenames) \n "
" : files(filenames) {} \n "
" std::vector<std::string> &files; \n "
" }; \n "
" A f() { \n "
" std::vector<std::string> files; \n "
" return A(files); \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:8] -> [test.cpp:7] -> [test.cpp:8]: (error) Returning object that points to local variable 'files' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2022-04-30 08:23:58 +02:00
check ( " struct S { \n "
" explicit S(std::string& s); \n "
" } \n "
" S f() { \n "
" std::string m( \" abc \" ); \n "
" return S(m); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-05-03 11:42:32 +02:00
check ( " struct S { \n "
" std::string msg; \n "
" explicit S(const char* m) : msg(m) {} \n "
" }; \n "
" S f() { \n "
" std::string s( \" abc \" ); \n "
" return S(s.c_str()); \n "
" } \n " ,
true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-02-28 18:54:55 +01:00
}
2019-03-19 06:25:10 +01:00
void danglingLifetimeAggegrateConstructor ( ) {
check ( " struct A { \n "
" const int& x; \n "
" int y; \n "
" }; \n "
" A f() { \n "
" int i = 0; \n "
" return A{i, i}; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-19 06:25:10 +01:00
ASSERT_EQUALS (
" [test.cpp:7] -> [test.cpp:6] -> [test.cpp:7]: (error) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" const int& x; \n "
" int y; \n "
" }; \n "
" A f() { \n "
" int i = 0; \n "
" return {i, i}; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-19 06:25:10 +01:00
ASSERT_EQUALS (
" [test.cpp:7] -> [test.cpp:6] -> [test.cpp:7]: (error) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" const int& x; \n "
" int y; \n "
" }; \n "
" A f() { \n "
" int i = 0; \n "
" A r{i, i}; \n "
" return r; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-09-20 14:27:09 +02:00
ASSERT_EQUALS (
" [test.cpp:7] -> [test.cpp:6] -> [test.cpp:8]: (error) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
2019-03-19 06:25:10 +01:00
errout . str ( ) ) ;
check ( " struct A { \n "
" const int& x; \n "
" int y; \n "
" }; \n "
" A f() { \n "
" int i = 0; \n "
" A r = {i, i}; \n "
" return r; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-19 06:25:10 +01:00
ASSERT_EQUALS (
" [test.cpp:7] -> [test.cpp:6] -> [test.cpp:8]: (error) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" const int& x; \n "
" int y; \n "
" }; \n "
" A f(int& x) { \n "
" int i = 0; \n "
" return A{i, x}; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-19 06:25:10 +01:00
ASSERT_EQUALS (
" [test.cpp:7] -> [test.cpp:6] -> [test.cpp:7]: (error) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" const int& x; \n "
" int y; \n "
" }; \n "
" A f(int& x) { \n "
" int i = 0; \n "
" return A{x, i}; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-19 06:25:10 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { \n "
" const int& x; \n "
" int y; \n "
" }; \n "
" A f(int& x) { \n "
" return A{x, x}; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-19 06:25:10 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-05-01 07:52:52 +02:00
check ( " struct A { int i; const int& j; }; \n "
" A f(int& x) { \n "
" int y = 0; \n "
" return A{y, x}; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-05-01 07:52:52 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-03-19 06:25:10 +01:00
}
void danglingLifetimeInitList ( ) {
check ( " std::vector<int*> f() { \n "
" int i = 0; \n "
" std::vector<int*> v = {&i, &i}; \n "
" return v; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-19 06:25:10 +01:00
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " std::vector<int*> f() { \n "
" int i = 0; \n "
" std::vector<int*> v{&i, &i}; \n "
" return v; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2022-05-09 21:05:35 +02:00
ASSERT_EQUALS (
2019-03-19 06:25:10 +01:00
" [test.cpp:3] -> [test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " std::vector<int*> f() { \n "
" int i = 0; \n "
" return {&i, &i}; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-19 06:25:10 +01:00
ASSERT_EQUALS (
" [test.cpp:3] -> [test.cpp:3] -> [test.cpp:2] -> [test.cpp:3]: (error) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " std::vector<int*> f(int& x) { \n "
" return {&x, &x}; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-19 06:25:10 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-04-02 10:17:58 +02:00
check ( " std::vector<std::string> f() { \n "
" std::set<std::string> x; \n "
" x.insert( \" 1 \" ); \n "
" x.insert( \" 2 \" ); \n "
" return { x.begin(), x.end() }; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-04-02 10:17:58 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-03-19 06:25:10 +01:00
}
2019-05-05 11:41:29 +02:00
void danglingLifetimeImplicitConversion ( ) {
2019-05-05 11:40:59 +02:00
check ( " struct A { A(const char *a); }; \n "
" A f() { \n "
" std::string ba( \" hello \" ); \n "
" return ba.c_str(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-05-05 11:40:59 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { A(const char *a); }; \n "
" A f() { \n "
" std::string ba( \" hello \" ); \n "
" A bp = ba.c_str(); \n "
" return bp; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-05-05 11:40:59 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { A(const char *a); }; \n "
" std::vector<A> f() { \n "
" std::string ba( \" hello \" ); \n "
" std::vector<A> v; \n "
" v.push_back(ba.c_str()); \n "
" return v; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-05-05 11:40:59 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-10-05 16:32:20 +02:00
check ( " std::string f(const std::string& x) { \n "
" const char c[] = \" \" ; \n "
" if (!x.empty()) \n "
" return x + c; \n "
" return \" \" ; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-05 16:32:20 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " std::string f(const std::string& x) { \n "
" const char c[] = \" 123 \" ; \n "
" if (!x.empty()) \n "
" return c + 1; \n "
" return \" \" ; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-05 16:32:20 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-05-05 11:40:59 +02:00
}
2019-10-08 12:51:23 +02:00
void danglingTemporaryLifetime ( ) {
2019-10-08 09:28:39 +02:00
check ( " const int& g(const int& x) { \n "
" return x; \n "
" } \n "
" void f(int& i) { \n "
" int* x = &g(0); \n "
" i += *x; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-08 09:28:39 +02:00
ASSERT_EQUALS (
2021-11-01 19:23:15 +01:00
" [test.cpp:1] -> [test.cpp:2] -> [test.cpp:5] -> [test.cpp:5] -> [test.cpp:5] -> [test.cpp:6]: (error) Using pointer that is a temporary. \n " ,
2019-10-08 09:28:39 +02:00
errout . str ( ) ) ;
2019-11-03 22:02:10 +01:00
check ( " QString f() { \n "
" QString a( \" dummyValue \" ); \n "
" const char* b = a.toStdString().c_str(); \n "
" QString c = b; \n "
" return c; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2021-11-01 19:23:15 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3] -> [test.cpp:4]: (error) Using pointer that is a temporary. \n " ,
errout . str ( ) ) ;
2019-11-08 08:02:33 +01:00
check ( " auto f(std::string s) { \n "
" const char *x = s.substr(1,2).c_str(); \n "
" auto i = s.substr(4,5).begin(); \n "
" return *i; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2021-11-01 19:23:15 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3] -> [test.cpp:4]: (error) Using iterator that is a temporary. \n " ,
errout . str ( ) ) ;
2020-02-10 18:01:11 +01:00
check ( " std::string f() { \n "
" std::stringstream tmp; \n "
" const std::string &str = tmp.str(); \n "
" return std::string(str.c_str(), 1); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-02-10 18:01:11 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-07 10:52:54 +02:00
check ( " int get_value(); \n "
" const int &get_reference1() { \n "
" const int &x = get_value(); \n "
" return x; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (error) Reference to temporary returned. \n " , errout . str ( ) ) ;
check ( " int get_value(); \n "
" const int &get_reference2() { \n "
" const int &x1 = get_value(); \n "
" const int &x2 = x1; \n "
" return x2; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3] -> [test.cpp:5]: (error) Reference to temporary returned. \n " ,
errout . str ( ) ) ;
2020-10-06 09:16:54 +02:00
check ( " const std::string& getState() { \n "
" static const std::string& state = \" \" ; \n "
" return state; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-06-09 09:21:03 +02:00
check ( " struct var { \n "
" void fun(); \n "
" }x; \n "
" var* T(const char*) { \n "
" return &x; \n "
" } \n "
" std::string GetTemp(); \n "
" void f() { \n "
" auto a = T(GetTemp().c_str()); \n "
" a->fun(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-01 19:23:15 +01:00
check ( " struct A { \n "
" std::map<int, int> m_; \n "
" }; \n "
" struct B { \n "
" A a_; \n "
" }; \n "
" B func(); \n "
" void f() { \n "
" const std::map<int, int>::iterator& m = func().a_.m_.begin(); \n "
" (void)m->first; \n "
" } \n " ) ;
2021-11-04 09:24:24 +01:00
ASSERT_EQUALS ( " [test.cpp:9] -> [test.cpp:9] -> [test.cpp:10]: (error) Using iterator that is a temporary. \n " ,
errout . str ( ) ) ;
2022-01-10 07:34:26 +01:00
check ( " void f(bool b) { \n "
" std::vector<int> ints = g(); \n "
" auto *ptr = &ints; \n "
" if (b) \n "
" ptr = &ints; \n "
" for (auto it = ptr->begin(); it != ptr->end(); ++it) \n "
" {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-01-12 22:05:30 +01:00
check ( " struct String { \n " // #10469
" void Append(uint8_t Val); \n "
" String& operator+=(const char s[]); \n "
" String& operator+=(const std::string& Str) { \n "
" return operator+=(Str.c_str()); \n "
" } \n "
" void operator+=(uint8_t Val) { \n "
" Append(Val); \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-10-08 09:28:39 +02:00
}
2021-11-04 09:24:24 +01:00
void danglingLifetimeBorrowedMembers ( )
{
// #10585
check ( " struct Info { int k; }; \n "
" struct MoreInfo { \n "
" int* k; \n "
" char dat; \n "
" }; \n "
" struct Fields { \n "
" Info info; \n "
" }; \n "
" template <typename T> void func1(T val){} \n "
" template <typename T> void func2(T val){} \n "
" Fields* get(); \n "
" void doit() { \n "
" MoreInfo rech; \n "
" rech.k = &get()->info.k; \n "
" func1(&rech.dat); \n "
" func2(rech.k); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { int x; }; \n "
" A* g(); \n "
" void f() { \n "
" A** ap = &g(); \n "
" (*ap)->x; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:4] -> [test.cpp:5]: (error) Using pointer that is a temporary. \n " ,
errout . str ( ) ) ;
check ( " struct A { int* x; }; \n "
" A g(); \n "
" void f() { \n "
" int* x = g().x; \n "
" (void)*x + 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { int x; }; \n "
" struct B { A* a; } \n "
" B g(); \n "
" void f() { \n "
" int* x = &g()->a.x; \n "
" (void)*x + 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { int x; }; \n "
" struct B { A* g(); }; \n "
" A* g(); \n "
" void f(B b) { \n "
" A** ap = &b.g(); \n "
" (*ap)->x; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:5] -> [test.cpp:6]: (error) Using pointer that is a temporary. \n " ,
errout . str ( ) ) ;
}
2021-11-28 15:25:21 +01:00
void danglingLifetimeClassMemberFunctions ( )
{
check ( " struct S { \n "
" S(int i) : i(i) {} \n "
" int i; \n "
" int* ptr() { return &i; } \n "
" }; \n "
" int* fun(int i) { \n "
" return S(i).ptr(); \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:4] -> [test.cpp:4] -> [test.cpp:7] -> [test.cpp:7]: (error) Returning pointer that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct Fred \n "
" { \n "
" int x[2]; \n "
" Fred() { \n "
" x[0] = 0x41; \n "
" x[1] = 0x42; \n "
" } \n "
" const int *get_x() { \n "
" return x; \n "
" } \n "
" }; \n "
" static const int *foo() { \n "
" Fred fred; \n "
" return fred.get_x(); \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:9] -> [test.cpp:9] -> [test.cpp:14] -> [test.cpp:13] -> [test.cpp:14]: (error) Returning pointer to local variable 'fred' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2021-12-04 17:00:55 +01:00
check ( " struct A { \n "
" int i; \n "
" auto f() const { \n "
" return [=]{ return i; }; \n "
" } \n "
" }; \n "
" auto g() { \n "
" return A().f(); \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:4] -> [test.cpp:4] -> [test.cpp:8] -> [test.cpp:8]: (error) Returning object that will be invalid when returning. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" int i; \n "
" auto f() const { \n "
" return [*this]{ return i; }; \n "
" } \n "
" }; \n "
" auto g() { \n "
" return A().f(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { \n "
" int* i; \n "
" auto f() const { \n "
" return [*this]{ return i; }; \n "
" } \n "
" }; \n "
" auto g() { \n "
" int i = 0; \n "
" return A{&i}.f(); \n "
" } \n " ) ;
ASSERT_EQUALS (
" [test.cpp:9] -> [test.cpp:9] -> [test.cpp:9] -> [test.cpp:4] -> [test.cpp:4] -> [test.cpp:8] -> [test.cpp:9]: (error) Returning object that points to local variable 'i' that will be invalid when returning. \n " ,
errout . str ( ) ) ;
2021-12-07 07:43:25 +01:00
check ( " struct S { \n "
" int i{}; \n "
" }; \n "
" struct T { \n "
" S getS() const { return S{ j }; } \n "
" int j{}; \n "
" }; \n "
" void f(S* p) { \n "
" S ret; \n "
" { \n "
" T t; \n "
" ret = t.getS(); \n "
" } \n "
" *p = ret; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-28 15:25:21 +01:00
}
2018-11-11 16:43:54 +01:00
void invalidLifetime ( ) {
check ( " void foo(int a) { \n "
" std::function<void()> f; \n "
" if (a > 0) { \n "
" int b = a + 1; \n "
" f = [&]{ return b; }; \n "
" } \n "
" f(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-11 16:43:54 +01:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:4] -> [test.cpp:7]: (error) Using lambda that captures local variable 'b' that is out of scope. \n " , errout . str ( ) ) ;
2018-11-12 10:08:17 +01:00
check ( " void f(bool b) { \n "
" int* x; \n "
" if(b) { \n "
" int y[6] = {0,1,2,3,4,5}; \n "
" x = y; \n "
" } \n "
" x[3]; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-21 08:43:57 +01:00
ASSERT_EQUALS (
2018-12-15 17:58:45 +01:00
" [test.cpp:5] -> [test.cpp:4] -> [test.cpp:7]: (error) Using pointer to local variable 'y' that is out of scope. \n " ,
2018-11-21 08:43:57 +01:00
errout . str ( ) ) ;
2018-11-12 10:08:17 +01:00
2018-11-11 16:43:54 +01:00
check ( " void foo(int a) { \n "
" std::function<void()> f; \n "
" if (a > 0) { \n "
" int b = a + 1; \n "
" f = [&]{ return b; }; \n "
" f(); \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-11 16:43:54 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct a { \n "
" b(); \n "
" std::list<int> c; \n "
" }; \n "
" void a::b() { \n "
" c.end() \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-11 16:43:54 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void b(char f[], char c[]) { \n "
" std::string d(c); { \n "
" std::string e; \n "
" b(f, e.c_str()) \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-11 16:43:54 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-12 10:08:17 +01:00
2018-11-14 06:59:25 +01:00
check ( " void f(bool b) { \n "
" std::string s; \n "
" if(b) { \n "
" char buf[3]; \n "
" s = buf; \n "
" } \n "
" std::cout << s; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-14 06:59:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-12 10:08:17 +01:00
check ( " int &a[]; \n "
2021-02-20 12:58:42 +01:00
" void b(){int *c = a}; " ) ;
2018-11-12 10:08:17 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-11-05 07:10:32 +01:00
check ( " struct A { \n "
" int x; \n "
" }; \n "
" struct B { \n "
" std::function<void()> x; \n "
" void f() { \n "
" this->x = [&] { \n "
" B y; \n "
" return y.x; \n "
" }; \n "
" } \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2019-11-05 07:10:32 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-10-04 23:16:16 +02:00
check ( " namespace test { \n "
" class Foo {}; \n "
" struct Bar { \n "
" Foo *_foo; \n "
" }; \n "
" \n "
" int f(Bar *bar); \n "
" \n "
" void g(Bar *bar) { \n "
" { \n "
" Foo foo; \n "
" bar->_foo = &foo; \n "
" bar->_foo = nullptr; \n "
" } \n "
" f(bar); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " class Foo {}; \n "
" struct Bar { \n "
" Foo *_foo; \n "
" }; \n "
" \n "
" int f(Bar *bar); \n "
" \n "
" void g(Bar *bar) { \n "
" { \n "
" Foo foo; \n "
" bar->_foo = &foo; \n "
" bar->_foo = nullptr; \n "
" } \n "
" f(bar); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " namespace test { \n "
" class Foo {}; \n "
" struct Bar { \n "
" Foo *_foo; \n "
" }; \n "
" \n "
" int f(Bar *bar); \n "
" \n "
" void g(Bar *bar) { \n "
" { \n "
" Foo foo; \n "
" bar->_foo = &foo; \n "
" } \n "
" f(bar); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:12]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
check ( " class Foo {}; \n "
" struct Bar { \n "
" Foo *_foo; \n "
" }; \n "
" \n "
" int f(Bar *bar); \n "
" \n "
" void g(Bar *bar) { \n "
" { \n "
" Foo foo; \n "
" bar->_foo = &foo; \n "
" } \n "
" f(bar); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:11]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
2018-11-11 16:43:54 +01:00
}
2019-09-03 17:15:58 +02:00
void deadPointer ( ) {
check ( " void f() { \n "
" int *p = p1; \n "
" if (cond) { \n "
" int x; \n "
" p = &x; \n "
" } \n "
" *p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:4] -> [test.cpp:7]: (error) Using pointer to local variable 'x' that is out of scope. \n " , errout . str ( ) ) ;
// FP: don't warn in subfunction
check ( " void f(struct KEY *key) { \n "
" key->x = 0; \n "
" } \n "
" \n "
" int main() { \n "
" struct KEY *tmp = 0; \n "
" struct KEY k; \n "
" \n "
" if (condition) { \n "
" tmp = &k; \n "
" } else { \n "
" } \n "
" f(tmp); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// Don't warn about references (#6399)
check ( " void f() { \n "
" wxAuiToolBarItem* former_hover = NULL; \n "
" for (i = 0, count = m_items.GetCount(); i < count; ++i) { \n "
" wxAuiToolBarItem& item = m_items.Item(i); \n "
" former_hover = &item; \n "
" } \n "
" if (former_hover != pitem) \n "
" dosth(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" wxAuiToolBarItem* former_hover = NULL; \n "
" for (i = 0, count = m_items.GetCount(); i < count; ++i) { \n "
" wxAuiToolBarItem item = m_items.Item(i); \n "
" former_hover = &item; \n "
" } \n "
" if (former_hover != pitem) \n "
" dosth(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:4] -> [test.cpp:7]: (error) Using pointer to local variable 'item' that is out of scope. \n " , errout . str ( ) ) ;
// #6575
check ( " void trp_deliver_signal() { \n "
" union { \n "
" Uint32 theData[25]; \n "
" EventReport repData; \n "
" }; \n "
" EventReport * rep = &repData; \n "
" rep->setEventType(NDB_LE_Connected); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #8785
check ( " int f(bool a, bool b) { \n "
" int *iPtr = 0; \n "
" if(b) { \n "
" int x = 42; \n "
" iPtr = &x; \n "
" } \n "
" if(b && a) \n "
" return *iPtr; \n "
" return 0; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-09-03 17:15:58 +02:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:4] -> [test.cpp:8]: (error) Using pointer to local variable 'x' that is out of scope. \n " , errout . str ( ) ) ;
}
2021-09-13 20:46:39 +02:00
void splitNamespaceAuto ( ) { // #10473
check ( " namespace ns \n "
" { \n "
" auto var{ 0 }; \n "
" } \n "
" namespace ns \n "
" { \n "
" int i; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-03-22 12:00:21 +01:00
} ;
REGISTER_TEST ( TestAutoVariables )