2009-03-22 12:00:21 +01:00
/*
* Cppcheck - A tool for static C / C + + code analysis
2015-01-03 12:14:58 +01:00
* Copyright ( C ) 2007 - 2015 Daniel Marjamäki and 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
*/
2009-10-25 12:49:06 +01:00
# include "tokenize.h"
# include "checkautovariables.h"
2009-03-22 12:00:21 +01:00
# include "testsuite.h"
2011-10-13 20:53:06 +02:00
class TestAutoVariables : public TestFixture {
2009-03-22 12:00:21 +01:00
public :
2014-11-20 14:20:09 +01:00
TestAutoVariables ( ) : TestFixture ( " TestAutoVariables " ) {
2013-08-07 16:27:37 +02:00
}
2009-03-22 12:00:21 +01:00
private :
2015-03-15 12:36:40 +01:00
void check ( const char code [ ] , bool inconclusive = false , bool runSimpleChecks = true , const char * filename = " test.cpp " ) {
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
2010-11-07 11:07:56 +01:00
Settings settings ;
2015-06-20 21:00:54 +02:00
LOAD_LIB_2 ( settings . library , " std.cfg " ) ;
2011-08-09 18:24:39 +02:00
settings . inconclusive = inconclusive ;
2013-02-02 15:08:05 +01:00
settings . addEnabled ( " warning " ) ;
2014-08-04 11:45:24 +02:00
settings . addEnabled ( " style " ) ;
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 ) ;
2015-03-15 12:36:40 +01:00
tokenizer . tokenize ( istr , filename ) ;
2011-02-12 15:39:26 +01:00
CheckAutoVariables checkAutoVariables ( & tokenizer , & settings , this ) ;
2012-03-01 18:38:20 +01:00
checkAutoVariables . returnReference ( ) ;
2013-10-06 16:07:27 +02:00
checkAutoVariables . assignFunctionArg ( ) ;
2011-02-12 15:39:26 +01:00
2013-04-13 18:38:15 +02:00
if ( runSimpleChecks ) {
2013-12-30 17:45:28 +01:00
tokenizer . simplifyTokenList2 ( ) ;
2013-04-13 18:38:15 +02:00
// Check auto variables
checkAutoVariables . autoVariables ( ) ;
checkAutoVariables . returnPointerToLocalArray ( ) ;
}
2009-03-22 12:00:21 +01:00
}
2014-11-20 14:20:09 +01:00
void run ( ) {
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
2011-02-08 01:26:34 +01:00
TEST_CASE ( testautovar_array1 ) ;
TEST_CASE ( testautovar_array2 ) ;
TEST_CASE ( testautovar_return1 ) ;
TEST_CASE ( testautovar_return2 ) ;
2011-08-10 18:16:31 +02:00
TEST_CASE ( testautovar_return3 ) ;
2011-08-20 21:08:30 +02:00
TEST_CASE ( testautovar_return4 ) ; // ticket #3030
2009-07-27 19:32:01 +02:00
TEST_CASE ( testautovar_extern ) ;
2009-08-09 15:43:00 +02:00
TEST_CASE ( testinvaliddealloc ) ;
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
TEST_CASE ( returnLocalVariable1 ) ;
TEST_CASE ( returnLocalVariable2 ) ;
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 ) ;
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 ) ;
2010-01-26 22:11:34 +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()
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 "
" } " ) ;
2012-07-07 20:31:18 +02: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 "
" } " ) ;
2012-07-07 20:31:18 +02: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 "
" } " ) ;
2012-07-07 20:31:18 +02: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 "
2011-08-09 18:24:39 +02:00
" } " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(struct AB *ab) \n "
" { \n "
" char a; \n "
" ab->a = &a; \n "
" } " , true ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error, inconclusive) 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 ) ;
2012-07-07 20:31:18 +02: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 ) ;
2012-07-07 20:31:18 +02: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 "
" p = &p_fp->i; \n "
" p = &fp.f->i; \n "
" } " , false ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Address of local auto-variable assigned to a function parameter. \n " , 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 "
" } " ) ;
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
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; "
" } " , false , false ) ;
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 ( ) ) ;
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 "
" char *data[10]; \n "
" }; \n "
" void foo(char** p) { \n "
" struct A a = bar(); \n "
" *p = &a.data[0]; \n "
" } " ) ;
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 "
" } " ) ;
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
// #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 "
" } " ) ;
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
2013-09-28 00:14:12 +02:00
check ( " void f(int* a) { a = } " ) ;
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 "
" }; \n " ) ;
}
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 "
" } " , false , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-10-21 16:21:33 +02:00
}
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 "
" } " ) ;
2012-07-07 20:31:18 +02: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 "
" } " ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Address of local auto-variable assigned to a function parameter. \n " , errout . str ( ) ) ;
2011-02-08 01:26:34 +01: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 # "
" } " ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Address of an auto-variable returned. \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 "
" int* func1() \n "
" } \n "
" int* Fred::func1() \n "
" { \n "
" int num=2; "
" return # "
" } " ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Address of an auto-variable returned. \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 ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void testautovar_return4 ( ) {
2011-08-20 21:08:30 +02:00
// #3030
check ( " char *foo() \n "
" { \n "
" char q[] = \" AAAAAAAAAAAA \" ; \n "
" return &q[1]; \n "
" } " ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Address of an auto-variable returned. \n " , errout . str ( ) ) ;
2011-08-20 22:41:12 +02:00
check ( " char *foo() \n "
" { \n "
" static char q[] = \" AAAAAAAAAAAA \" ; \n "
" return &q[1]; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-08-20 21:08:30 +02:00
}
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 ( ) ) ;
}
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
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
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 "
" } " ) ;
TODO_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 "
" } " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour. \n " , " " , errout . str ( ) ) ;
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 ( ) ) ;
2014-05-01 07:32:37 +02: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 "
" } \n " , false , true , " test.c " ) ;
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 ( ) ) ;
2010-10-22 21:12:28 +02:00
}
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
" } " ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Pointer to local array variable returned. \n " , errout . str ( ) ) ;
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
" } " ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Pointer to local array variable returned. \n " , 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
2014-11-20 14:20:09 +01:00
void returnReference1 ( ) {
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
" } " ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Reference to auto 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
" } " ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Reference to auto 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 ( ) ) ;
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 "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
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
" } " ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Reference to auto 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
" } " ) ;
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Reference to auto 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 "
2013-04-13 18:38:15 +02:00
" } " , false , 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
}
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 ( ) ) ;
}
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 ( ) ) ;
}
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 ( ) ) ;
}
2011-04-18 06:56:39 +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
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Address of function parameter 'y' returned. \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
2012-07-07 20:31:18 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Address of function parameter 'y' returned. \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 ( ) ) ;
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 "
" } " ) ;
}
2009-03-22 12:00:21 +01:00
} ;
REGISTER_TEST ( TestAutoVariables )