2008-12-19 22:15:18 +01:00
/*
2009-01-21 21:04:20 +01:00
* Cppcheck - A tool for static C / C + + code analysis
2011-01-09 20:33:36 +01:00
* Copyright ( C ) 2007 - 2011 Daniel Marjamäki and Cppcheck team .
2008-12-19 22:15:18 +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/>.
2008-12-19 22:15:18 +01:00
*/
2011-02-19 09:33:29 +01:00
# include "preprocessor.h"
2009-10-25 12:49:06 +01:00
# include "tokenize.h"
# include "checkother.h"
2008-12-19 22:15:18 +01:00
# include "testsuite.h"
# include <sstream>
extern std : : ostringstream errout ;
class TestOther : public TestFixture
{
public :
TestOther ( ) : TestFixture ( " TestOther " )
{ }
private :
void run ( )
{
2009-03-28 07:49:47 +01:00
TEST_CASE ( zeroDiv1 ) ;
TEST_CASE ( zeroDiv2 ) ;
2009-08-23 05:34:19 +02:00
TEST_CASE ( zeroDiv3 ) ;
2009-08-30 21:02:09 +02:00
TEST_CASE ( zeroDiv4 ) ;
2009-03-28 07:49:47 +01:00
2009-01-15 17:57:51 +01:00
TEST_CASE ( sprintf1 ) ; // Dangerous usage of sprintf
2009-01-10 12:19:17 +01:00
TEST_CASE ( sprintf2 ) ;
2009-01-10 15:29:59 +01:00
TEST_CASE ( sprintf3 ) ;
2009-01-15 17:57:51 +01:00
TEST_CASE ( sprintf4 ) ; // struct member
2010-02-01 19:46:51 +01:00
TEST_CASE ( strPlusChar1 ) ; // "/usr" + '/'
TEST_CASE ( strPlusChar2 ) ; // "/usr" + ch
TEST_CASE ( strPlusChar3 ) ; // ok: path + "/sub" + '/'
2009-02-04 19:49:19 +01:00
2009-03-24 20:24:03 +01:00
TEST_CASE ( varScope1 ) ;
2009-03-24 20:59:56 +01:00
TEST_CASE ( varScope2 ) ;
2009-05-27 19:38:26 +02:00
TEST_CASE ( varScope3 ) ;
2009-06-12 16:17:51 +02:00
TEST_CASE ( varScope4 ) ;
2009-08-16 21:12:57 +02:00
TEST_CASE ( varScope5 ) ;
2009-09-17 21:05:12 +02:00
TEST_CASE ( varScope6 ) ;
2009-10-06 17:45:28 +02:00
TEST_CASE ( varScope7 ) ;
2010-01-21 18:50:56 +01:00
TEST_CASE ( varScope8 ) ;
2010-04-09 16:53:27 +02:00
TEST_CASE ( varScope9 ) ; // classes may have extra side-effects
2010-08-26 21:57:48 +02:00
TEST_CASE ( varScope10 ) ; // Undefined macro FOR
2011-01-17 20:51:15 +01:00
TEST_CASE ( varScope11 ) ; // #2475 - struct initialization is not inner scope
2009-03-27 17:19:34 +01:00
2009-06-18 22:26:21 +02:00
TEST_CASE ( oldStylePointerCast ) ;
2009-07-25 00:36:15 +02:00
2009-10-04 10:05:58 +02:00
TEST_CASE ( dangerousStrolUsage ) ;
TEST_CASE ( passedByValue ) ;
2010-04-02 02:19:38 +02:00
2010-04-02 07:32:03 +02:00
TEST_CASE ( mathfunctionCall1 ) ;
2010-04-13 19:30:25 +02:00
2010-05-04 08:14:45 +02:00
TEST_CASE ( fflushOnInputStreamTest ) ;
2010-05-15 14:06:45 +02:00
TEST_CASE ( sizeofsizeof ) ;
2010-08-06 22:57:10 +02:00
TEST_CASE ( sizeofCalculation ) ;
2010-06-15 08:45:46 +02:00
2010-06-30 09:10:30 +02:00
TEST_CASE ( switchRedundantAssignmentTest ) ;
2011-02-19 09:33:29 +01:00
TEST_CASE ( switchFallThroughCase ) ;
2010-08-14 15:15:12 +02:00
2010-08-15 06:28:22 +02:00
TEST_CASE ( selfAssignment ) ;
2010-08-14 15:15:12 +02:00
TEST_CASE ( testScanf1 ) ;
TEST_CASE ( testScanf2 ) ;
2010-10-01 17:23:22 +02:00
TEST_CASE ( trac1132 ) ;
TEST_CASE ( testMisusedScopeObjectDoesNotPickFunction ) ;
TEST_CASE ( testMisusedScopeObjectPicksClass ) ;
TEST_CASE ( testMisusedScopeObjectPicksStruct ) ;
TEST_CASE ( testMisusedScopeObjectDoesNotPickIf ) ;
TEST_CASE ( testMisusedScopeObjectDoesNotPickConstructorDeclaration ) ;
2010-10-02 10:43:12 +02:00
TEST_CASE ( testMisusedScopeObjectDoesNotPickFunctor ) ;
2010-10-02 14:59:04 +02:00
TEST_CASE ( testMisusedScopeObjectDoesNotPickLocalClassConstructors ) ;
2010-10-02 12:26:29 +02:00
TEST_CASE ( testMisusedScopeObjectDoesNotPickUsedObject ) ;
2010-12-25 08:43:52 +01:00
TEST_CASE ( testMisusedScopeObjectDoesNotPickPureC ) ;
2011-01-31 20:07:41 +01:00
TEST_CASE ( testMisusedScopeObjectDoesNotPickNestedClass ) ;
2010-10-03 23:16:11 +02:00
TEST_CASE ( trac2071 ) ;
2010-10-13 11:31:41 +02:00
TEST_CASE ( trac2084 ) ;
2010-10-10 22:05:06 +02:00
TEST_CASE ( assignmentInAssert ) ;
2010-10-25 03:14:21 +02:00
TEST_CASE ( incorrectLogicOperator ) ;
2010-12-31 12:01:38 +01:00
TEST_CASE ( catchExceptionByValue ) ;
2011-01-06 11:31:58 +01:00
TEST_CASE ( memsetZeroBytes ) ;
2011-01-22 19:21:56 +01:00
2011-01-24 19:04:56 +01:00
TEST_CASE ( sizeofForArrayParameter ) ;
2011-01-24 21:40:49 +01:00
TEST_CASE ( clarifyCalculation ) ;
2011-02-08 19:49:29 +01:00
TEST_CASE ( incorrectStringCompare ) ;
2011-02-11 23:38:23 +01:00
TEST_CASE ( incrementBoolean ) ;
2011-02-27 21:30:22 +01:00
TEST_CASE ( comparisonOfBoolWithInt ) ;
2008-12-19 22:15:18 +01:00
}
2010-12-25 08:43:52 +01:00
void check ( const char code [ ] , const char * filename = NULL )
2008-12-19 22:15:18 +01:00
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
settings . _checkCodingStyle = true ;
2008-12-19 22:15:18 +01:00
// Tokenize..
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , this ) ;
2008-12-19 22:15:18 +01:00
std : : istringstream istr ( code ) ;
2010-12-25 08:43:52 +01:00
tokenizer . tokenize ( istr , filename ? filename : " test.cpp " ) ;
2008-12-19 22:15:18 +01:00
2010-04-21 08:38:25 +02:00
// Check..
2009-03-20 18:16:21 +01:00
CheckOther checkOther ( & tokenizer , & settings , this ) ;
2010-05-15 14:06:45 +02:00
checkOther . sizeofsizeof ( ) ;
2010-08-06 22:57:10 +02:00
checkOther . sizeofCalculation ( ) ;
2010-06-30 09:10:30 +02:00
checkOther . checkRedundantAssignmentInSwitch ( ) ;
2010-10-10 22:05:06 +02:00
checkOther . checkAssignmentInAssert ( ) ;
2011-01-22 19:21:56 +01:00
checkOther . checkSizeofForArrayParameter ( ) ;
2010-05-15 14:06:45 +02:00
// Simplify token list..
tokenizer . simplifyTokenList ( ) ;
2009-07-05 22:16:43 +02:00
checkOther . checkZeroDivision ( ) ;
2010-04-02 07:32:03 +02:00
checkOther . checkMathFunctions ( ) ;
2010-05-04 08:14:45 +02:00
checkOther . checkFflushOnInputStream ( ) ;
2010-08-15 06:28:22 +02:00
checkOther . checkSelfAssignment ( ) ;
2010-08-14 15:15:12 +02:00
checkOther . invalidScanf ( ) ;
2010-10-01 17:23:22 +02:00
checkOther . checkMisusedScopedObject ( ) ;
2010-10-25 03:14:21 +02:00
checkOther . checkIncorrectLogicOperator ( ) ;
2010-12-31 12:01:38 +01:00
checkOther . checkCatchExceptionByValue ( ) ;
2011-01-06 11:31:58 +01:00
checkOther . checkMemsetZeroBytes ( ) ;
2011-01-24 21:40:49 +01:00
checkOther . clarifyCalculation ( ) ;
2011-02-08 19:49:29 +01:00
checkOther . checkIncorrectStringCompare ( ) ;
2011-02-11 23:38:23 +01:00
checkOther . checkIncrementBoolean ( ) ;
2011-02-27 21:30:22 +01:00
checkOther . checkComparisonOfBoolWithInt ( ) ;
2008-12-19 22:15:18 +01:00
}
2011-02-19 09:33:29 +01:00
class SimpleSuppressor : public ErrorLogger
{
public :
SimpleSuppressor ( Settings & settings , ErrorLogger * next )
: _settings ( settings ) , _next ( next )
{ }
virtual void reportOut ( const std : : string & outmsg )
{
_next - > reportOut ( outmsg ) ;
}
virtual void reportErr ( const ErrorLogger : : ErrorMessage & msg )
{
if ( ! msg . _callStack . empty ( ) & & ! _settings . nomsg . isSuppressed ( msg . _id , msg . _callStack . begin ( ) - > getfile ( ) , msg . _callStack . begin ( ) - > line ) )
_next - > reportErr ( msg ) ;
}
virtual void reportStatus ( unsigned int index , unsigned int max )
{
_next - > reportStatus ( index , max ) ;
}
private :
Settings & _settings ;
ErrorLogger * _next ;
} ;
void check_preprocess_suppress ( const char precode [ ] , const char * filename = NULL )
{
// Clear the error buffer..
errout . str ( " " ) ;
if ( filename = = NULL )
filename = " test.cpp " ;
Settings settings ;
settings . _checkCodingStyle = true ;
2011-03-06 01:06:30 +01:00
settings . inconclusive = true ;
2011-02-19 09:33:29 +01:00
// Preprocess file..
Preprocessor preprocessor ( & settings , this ) ;
std : : list < std : : string > configurations ;
std : : string filedata = " " ;
std : : istringstream fin ( precode ) ;
preprocessor . preprocess ( fin , filedata , configurations , filename , settings . _includePaths ) ;
SimpleSuppressor logger ( settings , this ) ;
const std : : string code = Preprocessor : : getcode ( filedata , " " , filename , & settings , & logger ) ;
// Tokenize..
Tokenizer tokenizer ( & settings , & logger ) ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , filename ) ;
2011-03-04 08:26:14 +01:00
tokenizer . simplifyGoto ( ) ;
2011-02-19 09:33:29 +01:00
// Check..
CheckOther checkOther ( & tokenizer , & settings , & logger ) ;
checkOther . checkSwitchCaseFallThrough ( ) ;
2011-02-19 20:02:28 +01:00
logger . reportUnmatchedSuppressions ( settings . nomsg . getUnmatchedLocalSuppressions ( filename ) ) ;
2011-02-19 09:33:29 +01:00
}
2009-03-27 17:19:34 +01:00
2009-03-28 07:49:47 +01:00
void zeroDiv1 ( )
{
check ( " void foo() \n "
" { \n "
" int a = 0; \n "
" double b = 1.; \n "
" cout<<b/a; \n "
" } " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Division by zero \n " , errout . str ( ) ) ;
2009-03-28 07:49:47 +01:00
}
void zeroDiv2 ( )
{
check ( " void foo() \n "
" { \n "
" int sum = 0; \n "
" int n = 100; \n "
" for(int i = 0; i < n; i ++) \n "
" { \n "
" sum += i; \n "
" } \n "
" cout<<b/sum; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-28 07:49:47 +01:00
2009-06-05 23:33:13 +02:00
check ( " void foo() \n "
" { \n "
" int a = 0 ? (2/0) : 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-03-28 07:49:47 +01:00
2009-08-23 05:34:19 +02:00
void zeroDiv3 ( )
{
check ( " void f() \n "
" { \n "
" div_t divresult = div (1,0); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Division by zero \n " , errout . str ( ) ) ;
}
2009-08-30 21:02:09 +02:00
void zeroDiv4 ( )
{
check ( " void f() \n "
" { \n "
" long a = b / 0x6; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" long a = b / 0x0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Division by zero \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" long a = b / 0L; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Division by zero \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" long a = b / 0ul; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Division by zero \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" div_t divresult = div (1,0L); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Division by zero \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" div_t divresult = div (1,0x5); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-01 16:00:26 +02:00
2009-09-01 21:06:46 +02:00
// Don't warn about floating points (gcc doesn't warn either)
// and floating points are handled differently than integers.
2009-09-01 16:00:26 +02:00
check ( " void f() \n "
" { \n "
" long a = b / 0.0; \n "
" } \n " ) ;
2009-09-01 21:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-01 16:00:26 +02:00
check ( " void f() \n "
" { \n "
" long a = b / 0.5; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-01 21:06:46 +02:00
// Don't warn about 0.0
2009-09-01 16:00:26 +02:00
check ( " void f() \n "
" { \n "
" div_t divresult = div (1,0.0); \n "
" } \n " ) ;
2009-09-01 21:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-01 16:00:26 +02:00
check ( " void f() \n "
" { \n "
" div_t divresult = div (1,0.5); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-08-30 21:02:09 +02:00
}
2009-01-08 22:08:14 +01:00
2009-01-08 07:24:08 +01:00
void sprintfUsage ( const char code [ ] )
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
2009-01-08 07:24:08 +01:00
// Tokenize..
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , this ) ;
2009-01-08 07:24:08 +01:00
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
tokenizer . setVarId ( ) ;
2009-01-11 11:03:21 +01:00
//tokenizer.tokens()->printOut( "tokens" );
2009-01-08 07:24:08 +01:00
// Check for redundant code..
2009-03-20 18:16:21 +01:00
CheckOther checkOther ( & tokenizer , & settings , this ) ;
2009-07-05 22:16:43 +02:00
checkOther . invalidFunctionUsage ( ) ;
2009-01-08 07:24:08 +01:00
}
2009-01-08 22:08:14 +01:00
2009-01-08 07:24:08 +01:00
void sprintf1 ( )
{
2009-01-08 22:08:14 +01:00
sprintfUsage ( " void foo() \n "
" { \n "
" char buf[100]; \n "
" sprintf(buf, \" %s \" ,buf); \n "
" } \n " ) ;
2010-12-26 20:40:58 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Undefined behavior: variable is used as parameter and destination in s[n]printf(). \n " , errout . str ( ) ) ;
2009-01-08 07:24:08 +01:00
}
2009-01-10 12:19:17 +01:00
void sprintf2 ( )
{
sprintfUsage ( " void foo() \n "
" { \n "
" char buf[100]; \n "
" sprintf(buf, \" %i \" ,sizeof(buf)); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-10 12:19:17 +01:00
}
2009-01-10 15:27:31 +01:00
2009-01-10 15:29:59 +01:00
void sprintf3 ( )
{
2009-01-10 15:27:31 +01:00
sprintfUsage ( " void foo() \n "
" { \n "
" char buf[100]; \n "
" sprintf(buf, \" %i \" ,sizeof(buf)); \n "
2009-01-10 15:29:59 +01:00
" if (buf[0]); \n "
2009-01-10 15:27:31 +01:00
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-10 15:29:59 +01:00
}
2009-01-10 15:27:31 +01:00
2009-01-11 11:03:21 +01:00
void sprintf4 ( )
{
sprintfUsage ( " struct A \n "
" { \n "
" char filename[128]; \n "
" }; \n "
" \n "
" void foo() \n "
" { \n "
" const char* filename = \" hello \" ; \n "
" struct A a; \n "
" snprintf(a.filename, 128, \" %s \" , filename); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-11 11:03:21 +01:00
}
2009-01-15 17:57:51 +01:00
void strPlusChar ( const char code [ ] )
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
2009-01-15 17:57:51 +01:00
// Tokenize..
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , this ) ;
2009-01-15 17:57:51 +01:00
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
tokenizer . setVarId ( ) ;
// Check for redundant code..
2009-03-20 18:16:21 +01:00
CheckOther checkOther ( & tokenizer , & settings , this ) ;
2009-01-15 17:57:51 +01:00
checkOther . strPlusChar ( ) ;
}
void strPlusChar1 ( )
{
// Strange looking pointer arithmetic..
strPlusChar ( " void foo() \n "
" { \n "
" const char *p = \" /usr \" + '/'; \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Unusual pointer arithmetic \n " , errout . str ( ) ) ;
2009-01-15 17:57:51 +01:00
}
2009-01-15 18:12:33 +01:00
void strPlusChar2 ( )
{
// Strange looking pointer arithmetic..
strPlusChar ( " void foo() \n "
" { \n "
2010-02-07 21:44:11 +01:00
" char ch = 1; \n "
" const char *p = ch + \" /usr \" ; \n "
2009-01-15 18:12:33 +01:00
" } \n " ) ;
2010-02-07 21:44:11 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-02-08 08:35:53 +01:00
// Strange looking pointer arithmetic..
2010-02-07 21:44:11 +01:00
strPlusChar ( " void foo() \n "
" { \n "
" int i = 1; \n "
2010-02-22 21:30:21 +01:00
" const char* psz = \" Bla \" ; \n "
2010-02-07 21:44:11 +01:00
" const std::string str = i + psz; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-02-08 08:35:53 +01:00
}
2009-01-15 18:12:33 +01:00
2009-01-18 18:42:41 +01:00
void strPlusChar3 ( )
{
// Strange looking pointer arithmetic..
strPlusChar ( " void foo() \n "
" { \n "
" std::string temp = \" /tmp \" ; \n "
" std::string path = temp + '/' + \" sub \" + '/'; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-18 18:42:41 +01:00
}
2009-02-04 19:49:19 +01:00
2009-03-24 20:24:03 +01:00
void varScope ( const char code [ ] )
{
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
2011-01-05 21:20:21 +01:00
settings . addEnabled ( " information " ) ;
2010-12-01 18:00:55 +01:00
// Tokenize..
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
// Check for redundant code..
2009-03-24 20:24:03 +01:00
CheckOther checkOther ( & tokenizer , & settings , this ) ;
2009-07-05 22:16:43 +02:00
checkOther . checkVariableScope ( ) ;
2009-03-24 20:24:03 +01:00
}
void varScope1 ( )
{
varScope ( " unsigned short foo() \n "
" { \n "
" test_client CClient; \n "
" try \n "
" { \n "
" if (CClient.Open()) \n "
" { \n "
" return 0; \n "
" } \n "
" } \n "
" catch (...) \n "
" { \n "
" return 2; \n "
" } \n "
" \n "
" try \n "
" { \n "
" CClient.Close(); \n "
" } \n "
" catch (...) \n "
" { \n "
" return 2; \n "
" } \n "
" \n "
" return 1; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-24 20:24:03 +01:00
}
2009-03-24 20:59:56 +01:00
void varScope2 ( )
{
varScope ( " int foo() \n "
" { \n "
" Error e; \n "
" e.SetValue(12); \n "
" throw e; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-24 20:59:56 +01:00
}
2009-03-27 17:19:34 +01:00
2009-05-27 19:38:26 +02:00
void varScope3 ( )
{
varScope ( " void foo() \n "
" { \n "
" int i; \n "
" int *p = 0; \n "
" if (abc) \n "
" { \n "
" p = &i; \n "
" } \n "
" *p = 1; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-27 19:38:26 +02:00
}
2009-06-12 16:17:51 +02:00
void varScope4 ( )
{
varScope ( " void foo() \n "
" { \n "
" int i; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-08-16 21:12:57 +02:00
void varScope5 ( )
{
2009-09-29 23:56:43 +02:00
varScope ( " void f(int x) \n "
" { \n "
" int i = 0; \n "
" if (x) { \n "
" for ( ; i < 10; ++i) ; \n "
" } \n "
" } \n " ) ;
2010-12-27 11:46:18 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (information) The scope of the variable i can be reduced \n " , errout . str ( ) ) ;
2009-09-29 23:56:43 +02:00
varScope ( " void f(int x) \n "
2009-08-16 21:12:57 +02:00
" { \n "
" int i = 0; \n "
2009-09-29 23:56:43 +02:00
" if (x) {b()} \n "
" else { \n "
2009-08-16 21:12:57 +02:00
" for ( ; i < 10; ++i) ; \n "
" } \n "
" } \n " ) ;
2010-12-27 11:46:18 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (information) The scope of the variable i can be reduced \n " , errout . str ( ) ) ;
2009-08-16 21:12:57 +02:00
}
2009-03-27 17:19:34 +01:00
2009-09-17 21:05:12 +02:00
void varScope6 ( )
{
varScope ( " void f(int x) \n "
" { \n "
" int i = x; \n "
" if (a) { \n "
" x++; \n "
" } \n "
" if (b) { \n "
" c(i); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-09-29 23:56:43 +02:00
varScope ( " void f() \n "
" { \n "
" int foo = 0; \n "
" std::vector<int> vec(10); \n "
" BOOST_FOREACH(int& i, vec) \n "
" { \n "
" foo += 1; \n "
" if(foo == 10) \n "
" { \n "
" return 0; \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-27 17:19:34 +01:00
2009-09-29 23:56:43 +02:00
varScope ( " void f(int &x) \n "
" { \n "
" int n = 1; \n "
" do \n "
" { \n "
" ++n; \n "
" ++x; \n "
" } while (x); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-03-27 17:19:34 +01:00
2009-10-06 17:45:28 +02:00
void varScope7 ( )
{
varScope ( " void f(int x) \n "
" { \n "
" int y = 0; \n "
" b(y); \n "
" if (x) { \n "
" y++; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-01-21 18:50:56 +01:00
void varScope8 ( )
{
varScope ( " void test() { \n "
" float edgeResistance=1; \n "
" std::vector<int> edges; \n "
" BOOST_FOREACH(int edge, edges) { \n "
" edgeResistance = (edge+1) / 2.0; \n "
" } \n "
" } \n " ) ;
2010-12-27 11:46:18 +01:00
ASSERT_EQUALS ( " [test.cpp:2]: (information) The scope of the variable edgeResistance can be reduced \n " , errout . str ( ) ) ;
2010-01-21 18:50:56 +01:00
}
2010-04-09 16:53:27 +02:00
void varScope9 ( )
{
// classes may have extra side effects
varScope ( " class fred { \n "
" public: \n "
" void x(); \n "
" }; \n "
" void test(int a) { \n "
" fred f; \n "
" if (a == 2) { \n "
" f.x(); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-08-26 21:57:48 +02:00
void varScope10 ( )
{
// classes may have extra side effects
varScope ( " int f() \n "
" { \n "
" int x = 0; \n "
" FOR { \n "
" foo(x++); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-01-17 20:51:15 +01:00
void varScope11 ( )
{
varScope ( " int f() { \n "
" int x = 0; \n "
" AB ab = { x, 0 }; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
varScope ( " int f() { \n "
" int x = 0; \n "
" if (a == 0) { ++x; } \n "
" AB ab = { x, 0 }; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
varScope ( " int f() { \n "
" int x = 0; \n "
" if (a == 0) { ++x; } \n "
" if (a == 1) { AB ab = { x, 0 }; } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-01-21 18:50:56 +01:00
2009-06-18 22:26:21 +02:00
void checkOldStylePointerCast ( const char code [ ] )
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
settings . _checkCodingStyle = true ;
2009-06-18 22:26:21 +02:00
// Tokenize..
2010-12-01 18:00:55 +01:00
Tokenizer tokenizerCpp ( & settings , this ) ;
2009-06-18 22:26:21 +02:00
std : : istringstream istr ( code ) ;
2010-04-24 16:46:09 +02:00
tokenizerCpp . tokenize ( istr , " test.cpp " ) ;
tokenizerCpp . setVarId ( ) ;
2010-12-01 18:00:55 +01:00
Tokenizer tokenizerC ( & settings , this ) ;
2010-04-24 16:46:09 +02:00
std : : istringstream istr2 ( code ) ;
tokenizerC . tokenize ( istr2 , " test.c " ) ;
tokenizerC . setVarId ( ) ;
2009-06-18 22:26:21 +02:00
2010-04-24 16:46:09 +02:00
CheckOther checkOtherCpp ( & tokenizerCpp , & settings , this ) ;
checkOtherCpp . warningOldStylePointerCast ( ) ;
CheckOther checkOtherC ( & tokenizerC , & settings , this ) ;
checkOtherC . warningOldStylePointerCast ( ) ;
2009-06-18 22:26:21 +02:00
}
void oldStylePointerCast ( )
{
2009-06-19 12:01:27 +02:00
checkOldStylePointerCast ( " class Base; \n "
" void foo() \n "
" { \n "
" Base * b = (Base *) derived; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) C-style pointer casting \n " , errout . str ( ) ) ;
2009-07-20 21:52:27 +02:00
checkOldStylePointerCast ( " class Base; \n "
" void foo() \n "
" { \n "
" Base * b = (const Base *) derived; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) C-style pointer casting \n " , errout . str ( ) ) ;
2009-06-19 12:01:27 +02:00
2009-09-24 22:46:08 +02:00
checkOldStylePointerCast ( " class Base; \n "
" void foo() \n "
" { \n "
" Base * b = (const Base *) ( new Derived() ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) C-style pointer casting \n " , errout . str ( ) ) ;
checkOldStylePointerCast ( " class Base; \n "
" void foo() \n "
" { \n "
" Base * b = (const Base *) new Derived(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) C-style pointer casting \n " , errout . str ( ) ) ;
checkOldStylePointerCast ( " class Base; \n "
" void foo() \n "
" { \n "
" Base * b = (const Base *) new short[10]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) C-style pointer casting \n " , errout . str ( ) ) ;
2009-06-18 22:26:21 +02:00
checkOldStylePointerCast ( " class B; \n "
" class A \n "
" { \n "
" virtual void abc(B *) const = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-20 21:52:27 +02:00
checkOldStylePointerCast ( " class B; \n "
" class A \n "
" { \n "
" virtual void abc(const B *) const = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-18 22:26:21 +02:00
}
2009-10-04 10:05:58 +02:00
void dangerousStrolUsage ( )
{
{
sprintfUsage ( " int f(const char *num) \n "
" { \n "
" return strtol(num, NULL, 1); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Invalid radix in call to strtol or strtoul. Must be 0 or 2-36 \n " , errout . str ( ) ) ;
}
{
sprintfUsage ( " int f(const char *num) \n "
" { \n "
" return strtol(num, NULL, 10); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
}
void testPassedByValue ( const char code [ ] )
{
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
2010-04-21 08:38:25 +02:00
settings . _checkCodingStyle = true ;
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
2009-10-04 10:05:58 +02:00
CheckOther checkOther ( & tokenizer , & settings , this ) ;
checkOther . checkConstantFunctionParameter ( ) ;
}
void passedByValue ( )
{
2009-10-06 23:04:54 +02:00
testPassedByValue ( " void f(const std::string str) {} " ) ;
2010-11-27 09:46:34 +01:00
ASSERT_EQUALS ( " [test.cpp:1]: (performance) Function parameter 'str' should be passed by reference. \n " , errout . str ( ) ) ;
2009-10-04 10:05:58 +02:00
2009-10-06 23:04:54 +02:00
testPassedByValue ( " class Foo; \n void f(const Foo foo) {} " ) ;
2010-11-27 09:46:34 +01:00
ASSERT_EQUALS ( " [test.cpp:2]: (performance) Function parameter 'foo' should be passed by reference. \n " , errout . str ( ) ) ;
2009-10-04 10:05:58 +02:00
2009-10-06 23:04:54 +02:00
testPassedByValue ( " void f(const std::string &str) {} " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-10-04 10:05:58 +02:00
2009-10-06 23:04:54 +02:00
testPassedByValue ( " void f(const std::vector<int> v) {} " ) ;
2010-11-27 09:46:34 +01:00
ASSERT_EQUALS ( " [test.cpp:1]: (performance) Function parameter 'v' should be passed by reference. \n " , errout . str ( ) ) ;
2009-10-04 10:05:58 +02:00
2009-10-06 23:04:54 +02:00
testPassedByValue ( " void f(const std::vector<std::string> v) {} " ) ;
2010-11-27 09:46:34 +01:00
ASSERT_EQUALS ( " [test.cpp:1]: (performance) Function parameter 'v' should be passed by reference. \n " , errout . str ( ) ) ;
2009-10-05 10:59:28 +02:00
2009-10-06 23:04:54 +02:00
testPassedByValue ( " void f(const std::vector<int> &v) {} " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-10-05 10:59:28 +02:00
2009-10-06 23:04:54 +02:00
testPassedByValue ( " void f(const std::map<int,int> &v) {} " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-10-05 10:59:28 +02:00
2009-10-06 23:04:54 +02:00
testPassedByValue ( " void f(const std::map<int,int> v) {} " ) ;
2010-11-27 09:46:34 +01:00
ASSERT_EQUALS ( " [test.cpp:1]: (performance) Function parameter 'v' should be passed by reference. \n " , errout . str ( ) ) ;
2009-10-05 10:59:28 +02:00
2009-10-06 23:04:54 +02:00
testPassedByValue ( " void f(const std::map<std::string,std::string> v) {} " ) ;
2010-11-27 09:46:34 +01:00
ASSERT_EQUALS ( " [test.cpp:1]: (performance) Function parameter 'v' should be passed by reference. \n " , errout . str ( ) ) ;
2009-10-05 10:59:28 +02:00
2009-10-06 23:04:54 +02:00
testPassedByValue ( " void f(const std::map<int,std::string> v) {} " ) ;
2010-11-27 09:46:34 +01:00
ASSERT_EQUALS ( " [test.cpp:1]: (performance) Function parameter 'v' should be passed by reference. \n " , errout . str ( ) ) ;
2009-10-05 10:59:28 +02:00
2009-10-06 23:04:54 +02:00
testPassedByValue ( " void f(const std::map<std::string,int> v) {} " ) ;
2010-11-27 09:46:34 +01:00
ASSERT_EQUALS ( " [test.cpp:1]: (performance) Function parameter 'v' should be passed by reference. \n " , errout . str ( ) ) ;
2009-10-04 10:05:58 +02:00
}
2010-04-02 07:32:03 +02:00
void mathfunctionCall1 ( )
{
2010-04-02 20:42:06 +02:00
// log|log10
2010-04-02 02:19:38 +02:00
check ( " void foo() \n "
" { \n "
" std::cout << log(-2) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Passing value -2 to log() leads to undefined result \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::cout << log(-1.) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Passing value -1. to log() leads to undefined result \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::cout << log(-1.0) << std::endl; \n "
" } " ) ;
2010-04-02 07:32:03 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Passing value -1.0 to log() leads to undefined result \n " , errout . str ( ) ) ;
2010-04-02 02:19:38 +02:00
check ( " void foo() \n "
" { \n "
" std::cout << log(-0.1) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Passing value -0.1 to log() leads to undefined result \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::cout << log(0) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Passing value 0 to log() leads to undefined result \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::cout << log(0.) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Passing value 0. to log() leads to undefined result \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::cout << log(0.0) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Passing value 0.0 to log() leads to undefined result \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::cout << log(1.0E+3) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::cout << log(1.0E-3) << std::endl; \n "
" } " ) ;
2010-04-04 08:01:05 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-04-02 02:19:38 +02:00
check ( " void foo() \n "
" { \n "
" std::cout << log(1E-3) << std::endl; \n "
" } " ) ;
2010-04-04 08:01:05 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-04-02 02:19:38 +02:00
2010-07-07 09:03:40 +02:00
check ( " void foo() \n "
" { \n "
" std::string *log(0); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-11-15 21:03:49 +01:00
check ( " void foo() \n "
" { \n "
" std::cout << log(2.0) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-07-07 09:03:40 +02:00
2010-04-02 20:42:06 +02:00
// acos
2010-04-02 20:23:37 +02:00
check ( " void foo() \n "
" { \n "
2010-04-04 08:01:05 +02:00
" std::cout << acos(1) << std::endl; \n "
" std::cout << acos(-1) << std::endl; \n "
" std::cout << acos(0.1) << std::endl; \n "
" std::cout << acos(0.0001) << std::endl; \n "
" std::cout << acos(0.01) << std::endl; \n "
" std::cout << acos(1.0E-1) << std::endl; \n "
2010-04-02 20:23:37 +02:00
" std::cout << acos(-1.0E-1) << std::endl; \n "
" std::cout << acos(+1.0E-1) << std::endl; \n "
" std::cout << acos(0.1E-1) << std::endl; \n "
" std::cout << acos(+0.1E-1) << std::endl; \n "
" std::cout << acos(-0.1E-1) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::cout << acos(1.1) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Passing value 1.1 to acos() leads to undefined result \n " , errout . str ( ) ) ;
2010-04-02 02:19:38 +02:00
2010-04-02 20:23:37 +02:00
check ( " void foo() \n "
" { \n "
" std::cout << acos(-1.1) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Passing value -1.1 to acos() leads to undefined result \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::cout << acos(-110) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Passing value -110 to acos() leads to undefined result \n " , errout . str ( ) ) ;
2010-04-05 19:35:56 +02:00
// atan2
check ( " void foo() \n "
" { \n "
" std::cout << atan2(1,1) << std::endl; \n "
" std::cout << atan2(-1,-1) << std::endl; \n "
" std::cout << atan2(0.1,1) << std::endl; \n "
" std::cout << atan2(0.0001,100) << std::endl; \n "
" std::cout << atan2(0.01m-1) << std::endl; \n "
" std::cout << atan2(1.0E-1,-3) << std::endl; \n "
" std::cout << atan2(-1.0E-1,+2) << std::endl; \n "
" std::cout << atan2(+1.0E-1,0) << std::endl; \n "
" std::cout << atan2(0.1E-1,3) << std::endl; \n "
" std::cout << atan2(+0.1E-1,1) << std::endl; \n "
" std::cout << atan2(-0.1E-1,8) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::cout << atan2(0,0) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Passing value 0 and 0 to atan2() leads to undefined result \n " , errout . str ( ) ) ;
2010-04-05 20:07:53 +02:00
// fmod
2010-04-05 19:45:33 +02:00
check ( " void foo() \n "
" { \n "
" std::cout << fmod(1.0,0) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Passing value 1.0 and 0 to fmod() leads to undefined result \n " , errout . str ( ) ) ;
2010-04-05 20:07:53 +02:00
check ( " void foo() \n "
" { \n "
" std::cout << fmod(1.0,1) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// pow
check ( " void foo() \n "
" { \n "
" std::cout << pow(0,-10) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Passing value 0 and -10 to pow() leads to undefined result \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::cout << pow(0,10) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-04-05 20:20:20 +02:00
// sqrt
check ( " void foo() \n "
" { \n "
" std::cout << sqrt(-1) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Passing value -1 to sqrt() leads to undefined result \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" std::cout << sqrt(1) << std::endl; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-04-05 19:35:56 +02:00
2010-04-02 20:23:37 +02:00
}
2010-04-13 19:30:25 +02:00
2010-05-04 08:14:45 +02:00
void fflushOnInputStreamTest ( )
{
check ( " void foo() \n "
" { \n "
" fflush(stdin); \n "
" } \n " ) ;
2010-05-07 08:08:10 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) fflush() called on input stream \" stdin \" may result in undefined behaviour \n " , errout . str ( ) ) ;
2010-05-04 08:14:45 +02:00
check ( " void foo() \n "
" { \n "
" fflush(stdout); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-05-15 14:06:45 +02:00
void sizeofsizeof ( )
{
check ( " void foo() \n "
" { \n "
" int i = sizeof sizeof char; \n "
" } \n " ) ;
2010-11-28 13:20:46 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Calling sizeof for 'sizeof'. \n " , errout . str ( ) ) ;
2011-02-02 17:56:02 +01:00
check ( " void foo() \n "
" { \n "
" int i = sizeof (sizeof long); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Calling sizeof for 'sizeof'. \n " , errout . str ( ) ) ;
check ( " void foo(long *p) \n "
" { \n "
" int i = sizeof (sizeof (p)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Calling sizeof for 'sizeof'. \n " , errout . str ( ) ) ;
2010-05-15 14:06:45 +02:00
}
2010-06-15 08:45:46 +02:00
2010-08-06 22:57:10 +02:00
void sizeofCalculation ( )
{
check ( " sizeof(a+b) " ) ;
2010-10-17 14:41:00 +02:00
ASSERT_EQUALS ( " [test.cpp:1]: (warning) Found calculation inside sizeof() \n " , errout . str ( ) ) ;
2010-08-07 10:12:39 +02:00
check ( " sizeof(-a) " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " sizeof(void * const) " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-08-06 22:57:10 +02:00
}
2010-06-30 09:10:30 +02:00
void switchRedundantAssignmentTest ( )
{
check ( " void foo() \n "
" { \n "
" int y = 1; \n "
" switch (a) \n "
" { \n "
" case 2: \n "
" y = 2; \n "
" case 3: \n "
" y = 3; \n "
" } \n "
" } \n " ) ;
2010-10-17 14:41:00 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (warning) Redundant assignment of \" y \" in switch \n " , errout . str ( ) ) ;
2010-06-30 09:10:30 +02:00
check ( " void foo() \n "
" { \n "
" int y = 1; \n "
" switch (a) \n "
" { \n "
" case 2: \n "
" { \n "
" y = 2; \n "
" } \n "
" case 3: \n "
" y = 3; \n "
" } \n "
" } \n " ) ;
2010-10-17 14:41:00 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (warning) Redundant assignment of \" y \" in switch \n " , errout . str ( ) ) ;
2010-06-30 09:10:30 +02:00
check ( " void foo() \n "
" { \n "
" int y = 1; \n "
" switch (a) \n "
" { \n "
" case 2: \n "
" y = 2; \n "
" case 3: \n "
" if (x) \n "
" { \n "
" y = 3; \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" int y = 1; \n "
" switch (a) \n "
" { \n "
" case 2: \n "
" { \n "
" y = 2; \n "
" if (y) \n "
" printf( \" %d \" , y); \n "
" } \n "
" case 3: \n "
" y = 3; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" int x = a; \n "
" int y = 1; \n "
" switch (x) \n "
" { \n "
" case 2: \n "
" x = 2; \n "
" case 3: \n "
" y = 3; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" int y = 1; \n "
" switch (x) \n "
" { \n "
" case 2: \n "
" { \n "
" int y = 2; \n "
" } \n "
" case 3: \n "
" y = 3; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" int y = 1; \n "
" switch (x) \n "
" { \n "
" case 2: \n "
" y = 2; \n "
" break; \n "
" case 3: \n "
" y = 3; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-09-04 14:24:45 +02:00
check ( " void foo() \n "
" { \n "
" int y = 1; \n "
" while(xyz()) { \n "
" switch (x) \n "
" { \n "
" case 2: \n "
" y = 2; \n "
" continue; \n "
" case 3: \n "
" y = 3; \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-06-30 09:10:30 +02:00
check ( " void foo() \n "
" { \n "
" int y = 1; \n "
" switch (x) \n "
" { \n "
" case 2: \n "
" y = 2; \n "
" printf( \" %d \" , y); \n "
" case 3: \n "
" y = 3; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" int y = 1; \n "
" switch (x) \n "
" { \n "
" case 2: \n "
" y = 2; \n "
" bar(); \n "
" case 3: \n "
" y = 3; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-08-14 15:15:12 +02:00
2011-02-19 09:33:29 +01:00
void switchFallThroughCase ( )
{
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" break; \n "
" case 2: \n "
" break; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-02-19 20:02:28 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 0: \n "
" case 1: \n "
" break; \n "
" case 2: \n "
" break; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-02-19 09:33:29 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" g(); \n "
" case 2: \n "
" break; \n "
" } \n "
" } \n " ) ;
2011-03-05 21:42:15 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (style) Switch falls through case without comment \n " , errout . str ( ) ) ;
2011-02-19 09:33:29 +01:00
2011-02-19 20:02:28 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" g(); \n "
" default: \n "
" break; \n "
" } \n "
" } \n " ) ;
2011-03-05 21:42:15 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (style) Switch falls through case without comment \n " , errout . str ( ) ) ;
2011-02-19 20:02:28 +01:00
2011-02-19 09:33:29 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" g(); \n "
" // fall through \n "
" case 2: \n "
" break; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-02-19 21:54:01 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" g(); \n "
" /* FALLTHRU */ \n "
" case 2: \n "
" break; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-02-19 09:33:29 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" g(); \n "
" break; \n "
" // fall through \n "
" case 2: \n "
" break; \n "
" } \n "
" } \n " ) ;
2011-02-19 20:02:28 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (information) Unmatched suppression: switchCaseFallThrough \n " , errout . str ( ) ) ;
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" { \n "
" break; \n "
" } \n "
" case 2: \n "
" break; \n "
" } \n "
" } \n " ) ;
2011-02-19 09:33:29 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-02-19 20:02:28 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" for (;;) { \n "
" break; \n "
" } \n "
" case 2: \n "
" break; \n "
" } \n "
" } \n " ) ;
2011-03-05 21:42:15 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (style) Switch falls through case without comment \n " , errout . str ( ) ) ;
2011-02-19 20:02:28 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" if (b) { \n "
" break; \n "
" } else { \n "
" break; \n "
" } \n "
" case 2: \n "
" break; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" if (b) { \n "
" break; \n "
" } else { \n "
" } \n "
" case 2: \n "
" break; \n "
" } \n "
" } \n " ) ;
2011-03-05 21:42:15 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (style) Switch falls through case without comment \n " , errout . str ( ) ) ;
2011-02-19 20:02:28 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" if (b) { \n "
" break; \n "
" } \n "
" case 2: \n "
" break; \n "
" } \n "
" } \n " ) ;
2011-03-05 21:42:15 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (style) Switch falls through case without comment \n " , errout . str ( ) ) ;
2011-02-19 20:02:28 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" if (b) { \n "
" } else { \n "
" break; \n "
" } \n "
" case 2: \n "
" break; \n "
" } \n "
" } \n " ) ;
2011-03-05 21:42:15 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (style) Switch falls through case without comment \n " , errout . str ( ) ) ;
2011-02-19 20:02:28 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" if (b) { \n "
" case 2: \n "
" } else { \n "
" break; \n "
" } \n "
" break; \n "
" } \n "
" } \n " ) ;
2011-03-05 21:42:15 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (style) Switch falls through case without comment \n " , errout . str ( ) ) ;
2011-02-23 10:45:21 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" int x; \n "
" case 1: \n "
" break; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-04 07:22:17 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" g(); \n "
" switch (b) { \n "
" case 1: \n "
" return; \n "
" default: \n "
" return; \n "
" } \n "
" case 2: \n "
" break; \n "
" } \n "
" } \n " ) ;
// This fails because the switch parsing code currently doesn't understand
// that all paths after g() actually return. It's a pretty unusual case
// (no pun intended).
TODO_ASSERT_EQUALS ( " " ,
2011-03-05 21:42:15 +01:00
" [test.cpp:11]: (style) Switch falls through case without comment \n " , errout . str ( ) ) ;
2011-03-04 07:26:48 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" #ifndef A \n "
" g(); \n "
" // fall through \n "
" #endif \n "
" case 2: \n "
" break; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-04 08:26:14 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" goto leave; \n "
" case 2: \n "
" break; \n "
" } \n "
" leave: \n "
" if (x) { \n "
" g(); \n "
" return; \n "
" } \n "
" } \n " ) ;
// This fails because Tokenizer::simplifyGoto() copies the "leave:" block
// into where the goto is, but because it contains a "return", it omits
// copying a final return after the block.
TODO_ASSERT_EQUALS ( " " ,
2011-03-05 21:42:15 +01:00
" [test.cpp:5]: (style) Switch falls through case without comment \n " , errout . str ( ) ) ;
2011-03-05 06:02:38 +01:00
check_preprocess_suppress (
" void foo() { \n "
" switch (a) { \n "
" case 1: \n "
" g(); \n "
" // fall through \n "
" case 2: \n "
" g(); \n "
" // falls through \n "
" case 3: \n "
" g(); \n "
" // fall-through \n "
" case 4: \n "
" g(); \n "
" // drop through \n "
" case 5: \n "
" g(); \n "
" // pass through \n "
" case 5: \n "
" g(); \n "
" // no break \n "
" case 5: \n "
" g(); \n "
" // fallthru \n "
" case 6: \n "
" g(); \n "
" /* fall */ \n "
" default: \n "
" break; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-06 00:14:10 +01:00
check_preprocess_suppress (
" void foo() { \n "
" // unrelated comment saying 'fall through' \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-02-19 09:33:29 +01:00
}
2010-08-15 06:28:22 +02:00
void selfAssignment ( )
{
check ( " void foo() \n "
" { \n "
" int x = 1; \n "
" x = x; \n "
" return 0; \n "
" } \n " ) ;
2010-10-17 14:41:00 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) Redundant assignment of \" x \" to itself \n " , errout . str ( ) ) ;
2010-08-15 06:28:22 +02:00
check ( " void foo() \n "
" { \n "
" int x = x; \n "
" } \n " ) ;
2010-10-17 14:41:00 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Redundant assignment of \" x \" to itself \n " , errout . str ( ) ) ;
2010-08-15 06:28:22 +02:00
check ( " void foo() \n "
" { \n "
" std::string var = var = \" test \" ; \n "
" } \n " ) ;
2011-02-04 21:08:42 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:3]: (warning) Redundant assignment of \" var \" to itself \n " , " " , errout . str ( ) ) ;
2010-08-15 06:28:22 +02:00
check ( " void foo() \n "
" { \n "
" int x = 1; \n "
" x = x + 1; \n "
" return 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-02-04 21:08:42 +01:00
check ( " void foo() \n "
" { \n "
" int *x = getx(); \n "
" *x = x; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-02-12 14:27:07 +01:00
// non-primitive type -> there might be some side effects
check ( " void foo() \n "
" { \n "
" Fred fred; fred = fred; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-08-15 06:28:22 +02:00
}
2010-08-14 15:15:12 +02:00
void testScanf1 ( )
{
check ( " #include <stdio.h> \n "
" int main(int argc, char **argv) \n "
" { \n "
" int a, b; \n "
" FILE *file = fopen( \" test \" , \" r \" ); \n "
" b = fscanf(file, \" aa %ds \" , &a); \n "
" c = scanf( \" aa %ds \" , &a); \n "
" b = fscanf(file, \" aa%%ds \" , &a); \n "
" fclose(file); \n "
" return b; \n "
" } \n " ) ;
2010-10-17 14:41:00 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (warning) scanf without field width limits can crash with huge input data \n "
" [test.cpp:7]: (warning) scanf without field width limits can crash with huge input data \n " , errout . str ( ) ) ;
2010-08-14 15:15:12 +02:00
}
void testScanf2 ( )
{
check ( " #include <stdio.h> \n "
" int main(int argc, char **argv) \n "
" { \n "
" int a, b; \n "
" FILE *file = fopen( \" test \" , \" r \" ); \n "
" b = fscanf(file, \" aa%%%ds \" , &a); \n "
" c = scanf( \" aa %%%ds \" , &a); \n "
" b = fscanf(file, \" aa%%ds \" , &a); \n "
" fclose(file); \n "
" return b; \n "
" } \n " ) ;
2010-10-17 14:41:00 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (warning) scanf without field width limits can crash with huge input data \n "
" [test.cpp:7]: (warning) scanf without field width limits can crash with huge input data \n " , errout . str ( ) ) ;
2010-08-14 15:15:12 +02:00
}
2010-10-01 17:23:22 +02:00
void trac1132 ( )
{
std : : istringstream code ( " #include <iostream> \n "
" class Lock \n "
" { \n "
" public: \n "
" Lock(int i) \n "
" { \n "
" std::cout << \" Lock \" << i << std::endl; \n "
" } \n "
" ~Lock() \n "
" { \n "
" std::cout << \" ~Lock \" << std::endl; \n "
" } \n "
" }; \n "
" int main() \n "
" { \n "
" Lock(123); \n "
" std::cout << \" hello \" << std::endl; \n "
" return 0; \n "
" } \n "
) ;
2010-12-01 18:00:55 +01:00
errout . str ( " " ) ;
2010-10-01 17:23:22 +02:00
Settings settings ;
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , this ) ;
tokenizer . tokenize ( code , " trac1132.cpp " ) ;
tokenizer . simplifyTokenList ( ) ;
2010-10-01 17:23:22 +02:00
CheckOther checkOther ( & tokenizer , & settings , this ) ;
checkOther . checkMisusedScopedObject ( ) ;
ASSERT_EQUALS ( " [trac1132.cpp:16]: (error) instance of \" Lock \" object destroyed immediately \n " , errout . str ( ) ) ;
}
void testMisusedScopeObjectDoesNotPickFunction ( )
{
check ( " int main ( ) \n "
" { \n "
" CouldBeFunction ( 123 ) ; \n "
" return 0 ; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void testMisusedScopeObjectPicksClass ( )
{
check ( " class NotAFunction ; \n "
" int function ( ) \n "
" { \n "
" NotAFunction ( 123 ); \n "
" return 0 ; \n "
" } \n "
) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) instance of \" NotAFunction \" object destroyed immediately \n " , errout . str ( ) ) ;
}
void testMisusedScopeObjectPicksStruct ( )
{
check ( " struct NotAClass; \n "
" bool func ( ) \n "
" { \n "
" NotAClass ( 123 ) ; \n "
" return true ; \n "
" } \n "
) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) instance of \" NotAClass \" object destroyed immediately \n " , errout . str ( ) ) ;
}
void testMisusedScopeObjectDoesNotPickIf ( )
{
check ( " bool func( int a , int b , int c ) \n "
" { \n "
" if ( a > b ) return c == a ; \n "
" return b == a ; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void testMisusedScopeObjectDoesNotPickConstructorDeclaration ( )
{
check ( " class Something : public SomthingElse \n "
" { \n "
" public: \n "
" ~Something ( ) ; \n "
" Something ( ) ; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-10-02 10:43:12 +02:00
void testMisusedScopeObjectDoesNotPickFunctor ( )
{
check ( " \n "
" #include <algorithm> \n "
" \n "
" class IncrementFunctor \n "
" { \n "
" public: \n "
" void operator()(int &i) \n "
" { \n "
" ++i; \n "
" } \n "
" }; \n "
" \n "
" int main() \n "
" { \n "
2010-10-02 13:16:50 +02:00
" int a = 1; \n "
" IncrementFunctor()(a); \n "
" return a; \n "
2010-10-02 10:43:12 +02:00
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-10-02 12:12:52 +02:00
2010-10-02 14:59:04 +02:00
void testMisusedScopeObjectDoesNotPickLocalClassConstructors ( )
2010-10-02 12:12:52 +02:00
{
check ( " void f() { \n "
" class Foo { \n "
" Foo() { } \n "
2010-10-02 14:59:04 +02:00
" Foo(int a) { } \n "
" Foo(int a, int b) { } \n "
2010-10-02 12:12:52 +02:00
" }; \n "
2010-10-02 14:59:04 +02:00
" Foo(); \n "
2010-10-02 12:12:52 +02:00
" } \n "
) ;
2010-10-02 14:59:04 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) instance of \" Foo \" object destroyed immediately \n " , errout . str ( ) ) ;
2010-10-02 12:12:52 +02:00
}
2010-10-02 12:26:29 +02:00
void testMisusedScopeObjectDoesNotPickUsedObject ( )
{
check ( " struct Foo { \n "
" void bar() { \n "
" } \n "
" }; \n "
" \n "
" void fn() { \n "
" Foo().bar(); \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-25 08:43:52 +01:00
}
void testMisusedScopeObjectDoesNotPickPureC ( )
{
// Ticket #2352
const char code [ ] = " struct cb_watch_bool { \n "
" int a; \n "
" }; \n "
" \n "
" void f() \n "
" { \n "
" cb_watch_bool(); \n "
" } \n " ;
check ( code , " test.cpp " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (error) instance of \" cb_watch_bool \" object destroyed immediately \n " , errout . str ( ) ) ;
check ( code , " test.c " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-31 20:07:41 +01:00
}
void testMisusedScopeObjectDoesNotPickNestedClass ( )
{
const char code [ ] = " class ios_base { \n "
" public: \n "
" class Init { \n "
" public: \n "
" }; \n "
" }; \n "
" class foo { \n "
" public: \n "
" foo(); \n "
" void Init(int); \n "
" }; \n "
" foo::foo() { \n "
" Init(0); \n "
" } \n " ;
check ( code , " test.cpp " ) ;
2011-02-01 09:55:02 +01:00
TODO_ASSERT_EQUALS ( " " , " [test.cpp:13]: (error) instance of \" Init \" object destroyed immediately \n " , errout . str ( ) ) ;
2010-10-02 12:26:29 +02:00
}
2010-10-03 23:16:11 +02:00
2010-10-13 11:31:41 +02:00
void trac2084 ( )
{
check ( " #include <signal.h> \n "
" \n "
" void f() \n "
" { \n "
" struct sigaction sa; \n "
" \n "
" { sigaction(SIGHUP, &sa, 0); }; \n "
" { sigaction(SIGINT, &sa, 0); }; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-10-03 23:16:11 +02:00
void trac2071 ( )
{
check ( " void f() { \n "
2010-10-05 20:54:13 +02:00
" struct AB { \n "
" AB(int a) { } \n "
" }; \n "
" \n "
" const AB ab[3] = { AB(0), AB(1), AB(2) }; \n "
" } \n "
) ;
2010-10-03 23:16:11 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-10-10 22:05:06 +02:00
void assignmentInAssert ( )
{
check ( " void f() { \n "
" int a = 0; \n "
" assert(a = 2); \n "
" return a; \n "
" } \n "
) ;
2010-11-29 19:12:21 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Assert statement modifies 'a'. \n " , errout . str ( ) ) ;
2010-10-10 22:05:06 +02:00
check ( " void f() { \n "
" int a = 0; \n "
" assert(a == 2); \n "
" return a; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int a = 0; \n "
" int b = 0; \n "
" assert(a == 2 && b = 1); \n "
" return a; \n "
" } \n "
) ;
2010-11-29 19:12:21 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) Assert statement modifies 'b'. \n " , errout . str ( ) ) ;
2010-10-10 22:05:06 +02:00
check ( " void f() { \n "
" int a = 0; \n "
" assert(a += 2); \n "
" return a; \n "
" } \n "
) ;
2010-11-29 19:12:21 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Assert statement modifies 'a'. \n " , errout . str ( ) ) ;
2010-10-10 22:05:06 +02:00
check ( " void f() { \n "
" int a = 0; \n "
" assert(a *= 2); \n "
" return a; \n "
" } \n "
) ;
2010-11-29 19:12:21 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Assert statement modifies 'a'. \n " , errout . str ( ) ) ;
2010-10-10 22:05:06 +02:00
check ( " void f() { \n "
" int a = 0; \n "
" assert(a -= 2); \n "
" return a; \n "
" } \n "
) ;
2010-11-29 19:12:21 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Assert statement modifies 'a'. \n " , errout . str ( ) ) ;
2010-10-10 22:05:06 +02:00
check ( " void f() { \n "
" int a = 0; \n "
" assert(a --); \n "
" return a; \n "
" } \n "
) ;
2010-11-29 19:12:21 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Assert statement modifies 'a'. \n " , errout . str ( ) ) ;
2010-10-10 22:05:06 +02:00
}
2010-10-25 03:14:21 +02:00
void incorrectLogicOperator ( )
{
2010-11-04 08:10:25 +01:00
check ( " void f(int x) { \n "
2010-10-25 03:14:21 +02:00
" if ((x != 1) || (x != 3)) \n "
" a++; \n "
" } \n "
) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Mutual exclusion over || always evaluates to true. Did you intend to use && instead? \n " , errout . str ( ) ) ;
2010-11-04 08:10:25 +01:00
check ( " void f(int x) { \n "
2010-10-25 03:14:21 +02:00
" if (x != 1 || x != 3) \n "
" a++; \n "
" } \n "
) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Mutual exclusion over || always evaluates to true. Did you intend to use && instead? \n " , errout . str ( ) ) ;
2010-11-04 08:10:25 +01:00
check ( " void f(int x) { \n "
2010-10-25 03:14:21 +02:00
" if (1 != x || 3 != x) \n "
" a++; \n "
" } \n "
) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Mutual exclusion over || always evaluates to true. Did you intend to use && instead? \n " , errout . str ( ) ) ;
2010-11-04 08:10:25 +01:00
check ( " void f(int x, int y) { \n "
2010-10-25 03:14:21 +02:00
" if (x != 1 || y != 1) \n "
" a++; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-11-04 08:10:25 +01:00
check ( " void f(int x, int y) { \n "
2010-10-25 03:14:21 +02:00
" if ((y == 1) && (x != 1) || (x != 3)) \n "
" a++; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-11-04 08:10:25 +01:00
check ( " void f(int x, int y) { \n "
2010-10-25 03:14:21 +02:00
" if ((x != 1) || (x != 3) && (y == 1)) \n "
" a++; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-11-04 08:10:25 +01:00
check ( " void f(int x) { \n "
2010-10-25 03:14:21 +02:00
" if ((x != 1) && (x != 3)) \n "
" a++; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-11-04 08:10:25 +01:00
check ( " void f(int x) { \n "
2010-10-25 03:14:21 +02:00
" if ((x == 1) || (x == 3)) \n "
" a++; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-11-04 08:10:25 +01:00
check ( " void f(int x, int y) { \n "
2010-10-25 03:14:21 +02:00
" if ((x != 1) || (y != 3)) \n "
" a++; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-11-04 08:10:25 +01:00
check ( " void f(int x, int y) { \n "
" if ((x != hotdog) || (y != hotdog)) \n "
" a++; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x, int y) { \n "
" if ((x != 5) || (y != 5)) \n "
" a++; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" const int ERR1 = 5; \n "
" const int ERR2 = 6; \n "
" if ((x != ERR1) || (x != ERR2)) \n "
" a++; \n "
" } \n "
) ;
ASSERT_EQUALS ( " [test.cpp:4]: (warning) Mutual exclusion over || always evaluates to true. Did you intend to use && instead? \n " , errout . str ( ) ) ;
check ( " void f(int x, int y) { \n "
" const int ERR1 = 5; \n "
" if ((x != ERR1) || (y != ERR1)) \n "
" a++; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-11-21 09:06:43 +01:00
check ( " void f(unsigned int a, unsigned int b, unsigned int c) { \n "
" if((a != b) || (c != b) || (c != a)) \n "
" { \n "
" return true; \n "
" } \n "
" return false; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-25 03:14:21 +02:00
}
2010-12-31 12:01:38 +01:00
void catchExceptionByValue ( )
{
check ( " void f() { \n "
" try \n "
" { \n "
" foo(); \n "
" } \n "
" catch( ::std::exception err) \n "
" { \n "
" throw err; \n "
" } \n "
" } \n "
) ;
ASSERT_EQUALS ( " [test.cpp:6]: (style) Exception should be caught by reference. \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" try \n "
" { \n "
" foo(); \n "
" } \n "
" catch(const exception err) \n "
" { \n "
" throw err; \n "
" } \n "
" } \n "
) ;
ASSERT_EQUALS ( " [test.cpp:6]: (style) Exception should be caught by reference. \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" try \n "
" { \n "
" foo(); \n "
" } \n "
" catch( ::std::exception& err) \n "
" { \n "
" throw err; \n "
" } \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" try \n "
" { \n "
" foo(); \n "
" } \n "
" catch(exception* err) \n "
" { \n "
" throw err; \n "
" } \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" try \n "
" { \n "
" foo(); \n "
" } \n "
" catch(const exception& err) \n "
" { \n "
" throw err; \n "
" } \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" try \n "
" { \n "
" foo(); \n "
" } \n "
" catch(int err) \n "
" { \n "
" throw err; \n "
" } \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" try \n "
" { \n "
" foo(); \n "
" } \n "
" catch(exception* const err) \n "
" { \n "
" throw err; \n "
" } \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-01-06 11:31:58 +01:00
void memsetZeroBytes ( )
{
check ( " void f() { \n "
" memset(p, 10, 0) \n "
" } \n "
) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) memset() called to fill 0 "
2011-01-06 16:27:22 +01:00
" bytes of \' p \' \n " , errout . str ( ) ) ;
2011-01-06 11:31:58 +01:00
check ( " void f() { \n "
" memset(p, sizeof(p), 0) \n "
" } \n "
) ;
TODO_ASSERT_EQUALS ( " [test.cpp:2]: (warning) memset() called to fill 0 "
2011-01-30 12:54:19 +01:00
" bytes of \" p \" . Second and third arguments might be inverted. \n " ,
" " , errout . str ( ) ) ;
2011-01-06 11:31:58 +01:00
}
2011-01-22 19:21:56 +01:00
2011-01-24 19:04:56 +01:00
void sizeofForArrayParameter ( )
2011-01-22 19:21:56 +01:00
{
check ( " void f() { \n "
" int a[10]; \n "
" std::cout << sizeof(a) / sizeof(int) << std::endl; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" unsigned int a = 2; \n "
" unsigned int b = 2; \n "
" int c[(a+b)]; \n "
" std::cout << sizeof(c) / sizeof(int) << std::endl; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" unsigned int a = { 2 }; \n "
" unsigned int b[] = { 0 }; \n "
" int c[a[b[0]]]; \n "
" std::cout << sizeof(c) / sizeof(int) << std::endl; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" unsigned int a[] = { 1 }; \n "
" unsigned int b = 2; \n "
" int c[(a[0]+b)]; \n "
" std::cout << sizeof(c) / sizeof(int) << std::endl; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int a[] = { 1, 2, 3 }; \n "
" std::cout << sizeof(a) / sizeof(int) << std::endl; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int a[3] = { 1, 2, 3 }; \n "
" std::cout << sizeof(a) / sizeof(int) << std::endl; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f( int a[]) { \n "
" std::cout << sizeof(a) / sizeof(int) << std::endl; \n "
" } \n "
) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Using sizeof for array given as "
" function argument returns the size of pointer. \n " , errout . str ( ) ) ;
check ( " void f( int a[]) { \n "
" std::cout << sizeof a / sizeof(int) << std::endl; \n "
" } \n "
) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Using sizeof for array given as "
" function argument returns the size of pointer. \n " , errout . str ( ) ) ;
check ( " void f( int a[3] ) { \n "
" std::cout << sizeof(a) / sizeof(int) << std::endl; \n "
" } \n "
) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Using sizeof for array given as "
" function argument returns the size of pointer. \n " , errout . str ( ) ) ;
check ( " void f(int *p) { \n "
" p[0] = 0; \n "
" sizeof(p); \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-24 19:04:56 +01:00
check ( " void f() { \n "
" char p[] = \" test \" ; \n "
" sizeof(p); \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-25 09:57:58 +01:00
// ticket 2495
check ( " void f() { \n "
" static float col[][3]={ \n "
" {1,0,0}, \n "
" {0,0,1}, \n "
" {0,1,0}, \n "
" {1,0,1}, \n "
" {1,0,1}, \n "
" {1,0,1}, \n "
" }; \n "
" const int COL_MAX=sizeof(col)/sizeof(col[0]); \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-25 10:05:03 +01:00
// ticket 155
check ( " void f() { \n "
" char buff1[1024*64],buff2[sizeof(buff1)*2]; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-26 20:08:06 +01:00
// ticket 2510
check ( " void f( int a[], int b) { \n "
" std::cout << sizeof(a) / sizeof(int) << std::endl; \n "
" } \n "
) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Using sizeof for array given as "
" function argument returns the size of pointer. \n " , errout . str ( ) ) ;
// ticket 2510
check ( " void f( int a[3] , int b[2] ) { \n "
" std::cout << sizeof(a) / sizeof(int) << std::endl; \n "
" } \n "
) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Using sizeof for array given as "
" function argument returns the size of pointer. \n " , errout . str ( ) ) ;
// ticket 2510
check ( " void f() { \n "
" char buff1[1024*64],buff2[sizeof(buff1)*(2+1)]; \n "
" } \n "
) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-24 21:40:49 +01:00
}
2011-01-25 09:57:58 +01:00
2011-01-24 21:40:49 +01:00
void clarifyCalculation ( )
{
check ( " int f(char c) { \n "
" return 10 * (c == 0) ? 1 : 2; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (information) Please clarify precedence: 'a*b?..' \n " , errout . str ( ) ) ;
2011-01-24 19:04:56 +01:00
2011-01-24 21:40:49 +01:00
check ( " void f(char c) { \n "
" printf( \" %i \" , 10 * (c == 0) ? 1 : 2); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (information) Please clarify precedence: 'a*b?..' \n " , errout . str ( ) ) ;
2011-02-17 21:30:59 +01:00
// Ticket #2585 - segmentation fault for invalid code
check ( " abcdef? " " ?< "
" 123456? " " ?> "
" +? " " ?= " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-22 19:21:56 +01:00
}
2011-02-08 19:49:29 +01:00
void incorrectStringCompare ( )
{
check ( " int f() { \n "
" return test.substr( 0 , 4 ) == \" Hello \" ? : 0 : 1 ; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) String literal \" Hello \" doesn't match length argument for substr(4). \n " , errout . str ( ) ) ;
check ( " int f() { \n "
" return test.substr( 0 , 5 ) == \" Hello \" ? : 0 : 1 ; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f() { \n "
" return \" Hello \" == test.substr( 0 , 4 ) ? : 0 : 1 ; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) String literal \" Hello \" doesn't match length argument for substr(4). \n " , errout . str ( ) ) ;
check ( " int f() { \n "
" return \" Hello \" == test.substr( 0 , 5 ) ? : 0 : 1 ; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f() { \n "
" return strncmp( \" test \" , \" test \" , 2) ; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) String literal \" test \" doesn't match length argument for strncmp(2). \n " , errout . str ( ) ) ;
check ( " int f() { \n "
" return strncmp( \" test \" , \" test \" , 4) ; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-02-11 23:38:23 +01:00
void incrementBoolean ( )
{
check ( " bool bValue = true; \n "
" bValue++; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) The use of a variable of type bool with the ++ postfix operator is always true and deprecated by the C++ Standard. \n " , errout . str ( ) ) ;
check ( " void f(bool test){ \n "
" test++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) The use of a variable of type bool with the ++ postfix operator is always true and deprecated by the C++ Standard. \n " , errout . str ( ) ) ;
check ( " void f(int test){ \n "
" test++; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-02-27 21:30:22 +01:00
void comparisonOfBoolWithInt ( )
{
check ( " void f(int x) { \n "
" if (!x == 10) { \n "
" printf( \" x not equal to 10 \" ); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Comparison of a boolean with a non-zero integer \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (!x != 10) { \n "
" printf( \" x not equal to 10 \" ); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Comparison of a boolean with a non-zero integer \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x != 10) { \n "
" printf( \" x not equal to 10 \" ); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (10 == !x) { \n "
" printf( \" x not equal to 10 \" ); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Comparison of a boolean with a non-zero integer \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (10 != !x) { \n "
" printf( \" x not equal to 10 \" ); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Comparison of a boolean with a non-zero integer \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (10 != x) { \n "
" printf( \" x not equal to 10 \" ); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2008-12-19 22:15:18 +01:00
} ;
2009-01-05 16:49:57 +01:00
REGISTER_TEST ( TestOther )
2010-10-01 12:52:16 +02:00