2008-12-18 22:28:57 +01:00
/*
2009-01-21 21:04:20 +01:00
* Cppcheck - A tool for static C / C + + code analysis
* Copyright ( C ) 2007 - 2009 Daniel Marjamäki , Reijo Tomperi , Nicolas Le Cam ,
2009-03-01 20:52:33 +01:00
* Leandro Penz , Kimmo Varis , Vesa Pikki
2008-12-18 22:28:57 +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
* along with this program . If not , see < http : //www.gnu.org/licenses/
*/
2009-01-06 15:18:36 +01:00
# include "../src/tokenize.h"
# include "../src/checkclass.h"
2008-12-18 22:28:57 +01:00
# include "testsuite.h"
# include <sstream>
extern std : : ostringstream errout ;
class TestConstructors : public TestFixture
{
public :
TestConstructors ( ) : TestFixture ( " TestConstructors " )
{ }
private :
2009-01-05 16:49:57 +01:00
void check ( const char code [ ] )
2008-12-18 22:28:57 +01:00
{
// Tokenize..
Tokenizer tokenizer ;
std : : istringstream istr ( code ) ;
2009-01-05 16:49:57 +01:00
tokenizer . tokenize ( istr , " test.cpp " ) ;
2008-12-18 22:28:57 +01:00
tokenizer . simplifyTokenList ( ) ;
// Clear the error buffer..
errout . str ( " " ) ;
// Check class constructors..
Settings settings ;
settings . _checkCodingStyle = true ;
2009-03-20 17:30:24 +01:00
CheckClass checkClass ( & tokenizer , & settings , this ) ;
2008-12-20 09:48:52 +01:00
checkClass . constructors ( ) ;
2008-12-18 22:28:57 +01:00
}
void run ( )
{
2009-01-05 16:49:57 +01:00
TEST_CASE ( simple1 ) ;
TEST_CASE ( simple2 ) ;
TEST_CASE ( simple3 ) ;
TEST_CASE ( simple4 ) ;
TEST_CASE ( initvar_with_this ) ; // BUG 2190300
TEST_CASE ( initvar_if ) ; // BUG 2190290
TEST_CASE ( initvar_operator_eq1 ) ; // BUG 2190376
TEST_CASE ( initvar_operator_eq2 ) ; // BUG 2190376
TEST_CASE ( initvar_operator_eq3 ) ;
TEST_CASE ( initvar_same_classname ) ; // BUG 2208157
TEST_CASE ( initvar_chained_assign ) ; // BUG 2270433
TEST_CASE ( initvar_2constructors ) ; // BUG 2270353
2009-03-12 21:33:10 +01:00
TEST_CASE ( initvar_constvar ) ;
2009-01-05 16:49:57 +01:00
TEST_CASE ( initvar_private_constructor ) ; // BUG 2354171 - private constructor
TEST_CASE ( initvar_destructor ) ; // No variables need to be initialized in a destructor
2009-04-28 20:50:10 +02:00
TEST_CASE ( operatorEqSTL ) ;
2008-12-18 22:28:57 +01:00
}
void simple1 ( )
{
2009-01-05 16:49:57 +01:00
check ( " class Fred \n "
" { \n "
" public: \n "
" int i; \n "
" }; \n " ) ;
std : : string actual ( errout . str ( ) ) ;
2009-01-31 09:33:31 +01:00
std : : string expected ( " [test.cpp:1]: (style) The class 'Fred' has no constructor \n " ) ;
2009-01-05 16:49:57 +01:00
ASSERT_EQUALS ( expected , actual ) ;
2008-12-18 22:28:57 +01:00
}
void simple2 ( )
{
2009-01-05 16:49:57 +01:00
check ( " class Fred \n "
" { \n "
" public: \n "
" Fred() { } \n "
" int i; \n "
" }; \n " ) ;
2009-02-14 09:52:03 +01:00
ASSERT_EQUALS ( std : : string ( " [test.cpp:4]: (style) Member variable not initialized in the constructor 'Fred::i' \n " ) , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void simple3 ( )
{
2009-01-05 16:49:57 +01:00
check ( " class Fred \n "
" { \n "
" public: \n "
" Fred(); \n "
" int i; \n "
" }; \n "
" Fred::Fred() \n "
" { } \n " ) ;
2009-02-14 09:52:03 +01:00
ASSERT_EQUALS ( std : : string ( " [test.cpp:7]: (style) Member variable not initialized in the constructor 'Fred::i' \n " ) , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void simple4 ( )
{
2009-01-05 16:49:57 +01:00
check ( " class Fred \n "
" { \n "
" public: \n "
" Fred(); \n "
" Fred(int _i); \n "
" int i; \n "
" }; \n "
" Fred::Fred() \n "
" { } \n "
" Fred::Fred(int _i) \n "
" { \n "
" i = _i; \n "
" } \n " ) ;
2009-02-14 09:52:03 +01:00
ASSERT_EQUALS ( std : : string ( " [test.cpp:8]: (style) Member variable not initialized in the constructor 'Fred::i' \n " ) , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void initvar_with_this ( )
{
2009-01-05 16:49:57 +01:00
check ( " class Fred \n "
" { \n "
" public: \n "
" Fred() \n "
" { this->i = 0; } \n "
" int i; \n "
" }; \n " ) ;
ASSERT_EQUALS ( std : : string ( " " ) , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void initvar_if ( )
{
2009-01-05 16:49:57 +01:00
check ( " class Fred \n "
" { \n "
" public: \n "
" Fred() \n "
" { \n "
" if (true) \n "
" i = 0; \n "
" else \n "
" i = 1; \n "
" } \n "
" int i; \n "
" }; \n " ) ;
ASSERT_EQUALS ( std : : string ( " " ) , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void initvar_operator_eq1 ( )
{
// Bug 2190376 - False positive, Uninitialized member variable with operator=
2009-01-05 16:49:57 +01:00
check ( " class Fred \n "
" { \n "
" private: \n "
" int i; \n "
" \n "
" public: \n "
" Fred() \n "
" { i = 0; } \n "
" \n "
" Fred(const Fred &fred) \n "
" { *this = fred; } \n "
" \n "
" const Fred & operator=(const Fred &fred) \n "
" { i = fred.i; return *this; } \n "
" }; \n " ) ;
std : : string err ( errout . str ( ) ) ;
ASSERT_EQUALS ( std : : string ( " " ) , err ) ;
2008-12-18 22:28:57 +01:00
}
void initvar_operator_eq2 ( )
{
2009-01-05 16:49:57 +01:00
check ( " class Fred \n "
" { \n "
" public: \n "
" Fred() { i = 0; } \n "
" void operator=() { } \n "
" int i; \n "
" }; \n " ) ;
2009-03-31 19:00:56 +02:00
ASSERT_EQUALS ( std : : string ( " [test.cpp:5]: (all style) Member variable 'Fred::i' is not assigned a value in 'Fred::operator=' \n " ) , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void initvar_operator_eq3 ( )
{
2009-01-05 16:49:57 +01:00
check ( " class Fred \n "
" { \n "
" public: \n "
" Fred() { Init(); } \n "
" void operator=() { Init(); } \n "
" private: \n "
" Init() { i = 0; } \n "
" int i; \n "
" }; \n " ) ;
ASSERT_EQUALS ( std : : string ( " " ) , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void initvar_same_classname ( )
{
// Bug 2208157 - False positive: Uninitialized variable, same class name
2009-01-05 16:49:57 +01:00
check ( " void func1() \n "
" { \n "
" class Fred \n "
" { \n "
" int a; \n "
" Fred() { a = 0; } \n "
" }; \n "
" } \n "
" \n "
" void func2() \n "
" { \n "
" class Fred \n "
" { \n "
" int b; \n "
" Fred() { b = 0; } \n "
" }; \n "
" } \n " ) ;
std : : string err ( errout . str ( ) ) ;
ASSERT_EQUALS ( std : : string ( " " ) , err ) ;
2008-12-18 22:28:57 +01:00
}
void initvar_chained_assign ( )
{
// Bug 2270433 - Uninitialized variable false positive on chained assigns
2009-01-05 16:49:57 +01:00
check ( " class c \n "
" { \n "
" c(); \n "
" \n "
" int m_iMyInt1; \n "
" int m_iMyInt2; \n "
" } \n "
" \n "
" c::c() \n "
" { \n "
" m_iMyInt1 = m_iMyInt2 = 0; \n "
" } \n " ) ;
std : : string err ( errout . str ( ) ) ;
ASSERT_EQUALS ( std : : string ( " " ) , err ) ;
2008-12-18 22:28:57 +01:00
}
void initvar_2constructors ( )
{
2009-01-05 16:49:57 +01:00
check ( " class c \n "
" { \n "
" c(); \n "
" c(bool b); "
" \n "
" void InitInt(); \n "
" \n "
" int m_iMyInt; \n "
" int m_bMyBool; \n "
" } \n "
" \n "
" c::c() \n "
" { \n "
" m_bMyBool = false; \n "
" InitInt(); "
" } \n "
" \n "
" c::c(bool b) \n "
" { \n "
" m_bMyBool = b; \n "
" InitInt(); \n "
" } \n "
" \n "
" void c::InitInt() \n "
" { \n "
" m_iMyInt = 0; \n "
" } \n " ) ;
std : : string err ( errout . str ( ) ) ;
ASSERT_EQUALS ( std : : string ( " " ) , err ) ;
2008-12-18 22:28:57 +01:00
}
2009-03-12 21:33:10 +01:00
void initvar_constvar ( )
{
check ( " class Fred \n "
" { \n "
" public: \n "
" const char *s; \n "
" Fred(); \n "
" }; \n "
" Fred::Fred() \n "
" { } " ) ;
ASSERT_EQUALS ( std : : string ( " [test.cpp:7]: (style) Member variable not initialized in the constructor 'Fred::s' \n " ) , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
void initvar_private_constructor ( )
{
2009-01-05 16:49:57 +01:00
check ( " class Fred \n "
" { \n "
" private: \n "
" int var; \n "
" Fred(); \n "
" }; \n "
" Fred::Fred() \n "
" { } " ) ;
ASSERT_EQUALS ( std : : string ( " " ) , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-01-05 16:49:57 +01:00
void initvar_destructor ( )
{
check ( " class Fred \n "
" { \n "
" private: \n "
" int var; \n "
" public: \n "
" Fred() : var(0) {} \n "
" ~Fred() {} \n "
" }; \n " ) ;
ASSERT_EQUALS ( std : : string ( " " ) , errout . str ( ) ) ;
}
2009-04-28 20:50:10 +02:00
void operatorEqSTL ( )
{
check ( " class Fred \n "
" { \n "
" private: \n "
" std::vector<int> ints; \n "
" public: \n "
" Fred(); \n "
" void operator=(const Fred &f); \n "
" }; \n "
" \n "
" Fred::Fred() \n "
" { } \n "
" \n "
" void Fred::operator=(const Fred &f) \n "
" { } " ) ;
2009-05-01 11:28:33 +02:00
TODO_ASSERT_EQUALS ( std : : string ( " [test.cpp:13]: (all style) Member variable 'Fred::ints' is not assigned a value in 'Fred::operator=' \n " ) , errout . str ( ) ) ;
2009-04-28 20:50:10 +02:00
}
2008-12-18 22:28:57 +01:00
} ;
2009-01-05 16:49:57 +01:00
REGISTER_TEST ( TestConstructors )