2014-08-29 17:06:46 +02:00
/*
* Cppcheck - A tool for static C / C + + code analysis
2023-01-28 10:16:34 +01:00
* Copyright ( C ) 2007 - 2023 Cppcheck team .
2014-08-29 17:06:46 +02: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/>.
*/
# include "checkcondition.h"
2022-01-27 19:03:20 +01:00
# include "errortypes.h"
2023-10-08 11:29:52 +02:00
# include "helpers.h"
2022-01-27 19:03:20 +01:00
# include "platform.h"
2020-07-01 07:48:32 +02:00
# include "preprocessor.h"
2017-05-27 04:33:47 +02:00
# include "settings.h"
2023-01-27 08:18:32 +01:00
# include "fixture.h"
2017-05-27 04:33:47 +02:00
# include "tokenize.h"
2023-10-09 10:07:20 +02:00
# include <limits>
2022-09-16 07:15:49 +02:00
# include <sstream> // IWYU pragma: keep
2022-01-27 19:03:20 +01:00
# include <string>
2017-05-27 04:33:47 +02:00
# include <vector>
2014-08-29 17:06:46 +02:00
class TestCondition : public TestFixture {
public :
2021-08-07 20:51:18 +02:00
TestCondition ( ) : TestFixture ( " TestCondition " ) { }
2014-08-29 17:06:46 +02:00
private :
2023-09-11 11:08:23 +02:00
const Settings settings0 = settingsBuilder ( ) . library ( " qt.cfg " ) . library ( " std.cfg " ) . severity ( Severity : : style ) . severity ( Severity : : warning ) . build ( ) ;
Settings settings1 = settingsBuilder ( ) . severity ( Severity : : style ) . severity ( Severity : : warning ) . build ( ) ;
2014-08-29 17:06:46 +02:00
2022-02-10 23:02:24 +01:00
void run ( ) override {
2015-10-07 18:33:57 +02:00
const char cfg [ ] = " <?xml version= \" 1.0 \" ?> \n "
2021-08-07 20:51:18 +02:00
" <def> \n "
" <function name= \" bar \" > <pure/> </function> \n "
" </def> " ;
2023-09-25 13:37:24 +02:00
settings1 = settingsBuilder ( settings1 ) . libraryxml ( cfg , sizeof ( cfg ) ) . build ( ) ;
2015-10-07 18:33:57 +02:00
2014-08-29 17:06:46 +02:00
TEST_CASE ( assignAndCompare ) ; // assignment and comparison don't match
TEST_CASE ( mismatchingBitAnd ) ; // overlapping bitmasks
2016-07-31 22:09:47 +02:00
TEST_CASE ( comparison ) ; // CheckCondition::comparison test cases
2014-08-29 17:06:46 +02:00
TEST_CASE ( multicompare ) ; // mismatching comparisons
2019-06-30 23:26:49 +02:00
TEST_CASE ( overlappingElseIfCondition ) ; // overlapping conditions in if and else-if
TEST_CASE ( oppositeElseIfCondition ) ; // opposite conditions in if and else-if
2015-02-22 13:09:39 +01:00
TEST_CASE ( checkBadBitmaskCheck ) ;
2014-08-29 17:06:46 +02:00
TEST_CASE ( incorrectLogicOperator1 ) ;
TEST_CASE ( incorrectLogicOperator2 ) ;
TEST_CASE ( incorrectLogicOperator3 ) ;
TEST_CASE ( incorrectLogicOperator4 ) ;
TEST_CASE ( incorrectLogicOperator5 ) ; // complex expressions
TEST_CASE ( incorrectLogicOperator6 ) ; // char literals
TEST_CASE ( incorrectLogicOperator7 ) ; // opposite expressions: (expr || !expr)
2015-07-13 20:53:49 +02:00
TEST_CASE ( incorrectLogicOperator8 ) ; // !
2015-07-30 10:30:30 +02:00
TEST_CASE ( incorrectLogicOperator9 ) ;
2017-03-23 18:57:48 +01:00
TEST_CASE ( incorrectLogicOperator10 ) ; // enum
2018-08-05 22:39:40 +02:00
TEST_CASE ( incorrectLogicOperator11 ) ;
2018-08-27 11:09:09 +02:00
TEST_CASE ( incorrectLogicOperator12 ) ;
2019-01-25 07:48:18 +01:00
TEST_CASE ( incorrectLogicOperator13 ) ;
2019-07-24 09:59:01 +02:00
TEST_CASE ( incorrectLogicOperator14 ) ;
2021-01-29 10:26:57 +01:00
TEST_CASE ( incorrectLogicOperator15 ) ;
2021-05-04 13:46:46 +02:00
TEST_CASE ( incorrectLogicOperator16 ) ; // #10070
2014-08-29 17:06:46 +02:00
TEST_CASE ( secondAlwaysTrueFalseWhenFirstTrueError ) ;
TEST_CASE ( incorrectLogicOp_condSwapping ) ;
2015-06-13 18:08:13 +02:00
TEST_CASE ( testBug5895 ) ;
2015-06-20 12:18:24 +02:00
TEST_CASE ( testBug5309 ) ;
2014-08-29 17:06:46 +02:00
TEST_CASE ( modulo ) ;
TEST_CASE ( oppositeInnerCondition ) ;
2017-09-04 22:11:53 +02:00
TEST_CASE ( oppositeInnerConditionPointers ) ;
TEST_CASE ( oppositeInnerConditionClass ) ;
TEST_CASE ( oppositeInnerConditionUndeclaredVariable ) ;
2017-09-04 09:34:03 +02:00
TEST_CASE ( oppositeInnerConditionAlias ) ;
2017-08-31 22:53:21 +02:00
TEST_CASE ( oppositeInnerCondition2 ) ;
2018-03-24 07:58:37 +01:00
TEST_CASE ( oppositeInnerCondition3 ) ;
2017-09-01 23:24:15 +02:00
TEST_CASE ( oppositeInnerConditionAnd ) ;
2022-09-08 22:08:38 +02:00
TEST_CASE ( oppositeInnerConditionOr ) ;
2018-03-24 07:58:37 +01:00
TEST_CASE ( oppositeInnerConditionEmpty ) ;
2018-10-07 18:30:29 +02:00
TEST_CASE ( oppositeInnerConditionFollowVar ) ;
2014-08-29 17:06:46 +02:00
2018-04-08 08:13:44 +02:00
TEST_CASE ( identicalInnerCondition ) ;
2017-09-10 22:59:39 +02:00
TEST_CASE ( identicalConditionAfterEarlyExit ) ;
2018-04-28 18:56:13 +02:00
TEST_CASE ( innerConditionModified ) ;
2017-09-03 10:34:34 +02:00
2014-08-29 17:06:46 +02:00
TEST_CASE ( clarifyCondition1 ) ; // if (a = b() < 0)
TEST_CASE ( clarifyCondition2 ) ; // if (a & b == c)
TEST_CASE ( clarifyCondition3 ) ; // if (! a & b)
TEST_CASE ( clarifyCondition4 ) ; // ticket #3110
TEST_CASE ( clarifyCondition5 ) ; // #3609 CWinTraits<WS_CHILD|WS_VISIBLE>..
TEST_CASE ( clarifyCondition6 ) ; // #3818
2016-05-06 17:39:41 +02:00
TEST_CASE ( clarifyCondition7 ) ;
2016-07-29 17:24:22 +02:00
TEST_CASE ( clarifyCondition8 ) ;
2015-07-17 15:30:23 +02:00
TEST_CASE ( alwaysTrue ) ;
2021-08-04 21:07:31 +02:00
TEST_CASE ( alwaysTrueSymbolic ) ;
2019-12-26 15:47:53 +01:00
TEST_CASE ( alwaysTrueInfer ) ;
2021-08-27 05:46:57 +02:00
TEST_CASE ( alwaysTrueContainer ) ;
TEST_CASE ( alwaysTrueLoop ) ;
2021-09-03 23:07:08 +02:00
TEST_CASE ( alwaysTrueTryCatch ) ;
2018-09-06 06:55:36 +02:00
TEST_CASE ( multiConditionAlwaysTrue ) ;
2019-01-09 20:41:01 +01:00
TEST_CASE ( duplicateCondition ) ;
2015-11-30 08:51:15 +01:00
TEST_CASE ( checkInvalidTestForOverflow ) ;
2017-09-08 14:30:42 +02:00
TEST_CASE ( checkConditionIsAlwaysTrueOrFalseInsideIfWhile ) ;
2018-07-23 08:51:59 +02:00
TEST_CASE ( alwaysTrueFalseInLogicalOperators ) ;
2017-10-22 14:32:54 +02:00
TEST_CASE ( pointerAdditionResultNotNull ) ;
2019-04-18 20:20:24 +02:00
TEST_CASE ( duplicateConditionalAssign ) ;
2021-04-07 17:21:34 +02:00
TEST_CASE ( checkAssignmentInCondition ) ;
2021-07-15 09:43:38 +02:00
TEST_CASE ( compareOutOfTypeRange ) ;
2021-07-27 22:26:19 +02:00
TEST_CASE ( knownConditionCast ) ; // #9976
2021-08-02 06:53:54 +02:00
TEST_CASE ( knownConditionIncrementLoop ) ; // #9808
2014-08-29 17:06:46 +02:00
}
2023-10-08 11:29:52 +02:00
# define check(...) check_(__FILE__, __LINE__, __VA_ARGS__)
void check_ ( const char * file , int line , const char code [ ] , const Settings & settings , const char * filename = " test.cpp " ) {
2014-08-29 17:06:46 +02:00
// Clear the error buffer..
errout . str ( " " ) ;
2023-05-02 15:54:19 +02:00
Preprocessor preprocessor ( settings ) ;
2023-10-08 11:29:52 +02:00
std : : vector < std : : string > files ( 1 , filename ) ;
Tokenizer tokenizer ( & settings , this , & preprocessor ) ;
PreprocessorHelper : : preprocess ( preprocessor , code , files , tokenizer ) ;
2020-07-01 07:48:32 +02:00
2017-05-18 21:52:31 +02:00
// Tokenizer..
2023-10-08 11:29:52 +02:00
ASSERT_LOC ( tokenizer . simplifyTokens1 ( " " ) , file , line ) ;
2017-05-18 21:52:31 +02:00
// Run checks..
2023-08-18 12:03:50 +02:00
runChecks < CheckCondition > ( tokenizer , this ) ;
2021-07-15 09:43:38 +02:00
}
2023-10-08 11:29:52 +02:00
void check_ ( const char * file , int line , const char code [ ] , const char * filename = " test.cpp " , bool inconclusive = false ) {
2023-08-09 12:43:55 +02:00
const Settings settings = settingsBuilder ( settings0 ) . certainty ( Certainty : : inconclusive , inconclusive ) . build ( ) ;
2023-10-08 11:29:52 +02:00
check_ ( file , line , code , settings , filename ) ;
2014-08-29 17:06:46 +02:00
}
2014-11-20 14:20:09 +01:00
void assignAndCompare ( ) {
2014-08-29 17:06:46 +02:00
// &
check ( " void foo(int x) \n "
" { \n "
" int y = x & 4; \n "
" if (y == 3); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (style) Mismatching assignment and comparison, comparison 'y==3' is always false. \n " , errout . str ( ) ) ;
check ( " void foo(int x) \n "
" { \n "
" int y = x & 4; \n "
" if (y != 3); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (style) Mismatching assignment and comparison, comparison 'y!=3' is always true. \n " , errout . str ( ) ) ;
// |
check ( " void foo(int x) { \n "
" int y = x | 0x14; \n "
" if (y == 0x710); \n "
" } " ) ;
2020-02-19 07:51:39 +01:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (style) Mismatching assignment and comparison, comparison 'y==0x710' is always false. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void foo(int x) { \n "
" int y = x | 0x14; \n "
" if (y == 0x71f); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// various simple assignments
check ( " void foo(int x) { \n "
" int y = (x+1) | 1; \n "
" if (y == 2); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (style) Mismatching assignment and comparison, comparison 'y==2' is always false. \n " , errout . str ( ) ) ;
check ( " void foo() { \n "
" int y = 1 | x(); \n "
" if (y == 2); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (style) Mismatching assignment and comparison, comparison 'y==2' is always false. \n " , errout . str ( ) ) ;
// multiple conditions
check ( " void foo(int x) { \n "
" int y = x & 4; \n "
" if ((y == 3) && (z == 1)); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (style) Mismatching assignment and comparison, comparison 'y==3' is always false. \n " , errout . str ( ) ) ;
check ( " void foo(int x) { \n "
" int y = x & 4; \n "
" if ((x==123) || ((y == 3) && (z == 1))); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (style) Mismatching assignment and comparison, comparison 'y==3' is always false. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" int y = x & 7; \n "
" if (setvalue(&y) && y != 8); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// recursive checking into scopes
check ( " void f(int x) { \n "
" int y = x & 7; \n "
" if (z) y=0; \n "
" else { if (y==8); } \n " // always false
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (style) Mismatching assignment and comparison, comparison 'y==8' is always false. \n " , errout . str ( ) ) ;
// while
check ( " void f(int x) { \n "
" int y = x & 7; \n "
" while (y==8); \n " // local variable => always false
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (style) Mismatching assignment and comparison, comparison 'y==8' is always false. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" extern int y; y = x & 7; \n "
" while (y==8); \n " // non-local variable => no error
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-11-11 13:45:28 +01:00
check ( " void f(int x) { \n "
" int a = 100; \n "
" while (x) { \n "
" int y = 16 | a; \n "
" while (y != 0) y--; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-10-23 13:54:44 +02:00
check ( " void g(int x); \n "
" void f(int x) { \n "
" int a = 100; \n "
" while (x) { \n "
" int y = 16 | a; \n "
" while (y != 0) g(y); \n "
" } \n "
" } " ) ;
2019-09-20 15:06:37 +02:00
ASSERT_EQUALS (
" [test.cpp:5] -> [test.cpp:6]: (style) Mismatching assignment and comparison, comparison 'y!=0' is always true. \n " ,
errout . str ( ) ) ;
2016-10-23 13:54:44 +02:00
check ( " void g(int &x); \n "
" void f(int x) { \n "
" int a = 100; \n "
" while (x) { \n "
" int y = 16 | a; \n "
" while (y != 0) g(y); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
// calling function
check ( " void f(int x) { \n "
" int y = x & 7; \n "
" do_something(); \n "
" if (y==8); \n " // local variable => always false
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (style) Mismatching assignment and comparison, comparison 'y==8' is always false. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" int y = x & 7; \n "
" do_something(&y); \n " // passing variable => no error
" if (y==8); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void do_something(int); \n "
" void f(int x) { \n "
" int y = x & 7; \n "
" do_something(y); \n "
" if (y==8); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:5]: (style) Mismatching assignment and comparison, comparison 'y==8' is always false. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" extern int y; y = x & 7; \n "
" do_something(); \n "
" if (y==8); \n " // non-local variable => no error
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #4434 : false positive: ?:
check ( " void f(int x) { \n "
" x = x & 1; \n "
" x = x & 1 ? 1 : -1; \n "
" if(x != -1) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #4735
check ( " void f() { \n "
" int x = *(char*)&0x12345678; \n "
" if (x==18) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// bailout: no variable info
check ( " void foo(int x) { \n "
" y = 2 | x; \n " // y not declared => no error
" if(y == 1) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// bailout: negative number
check ( " void foo(int x) { \n "
" int y = -2 | x; \n " // negative number => no error
" if (y==1) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// bailout: pass variable to function
check ( " void foo(int x) { \n "
" int y = 2 | x; \n "
" bar(&y); \n " // pass variable to function => no error
" if (y==1) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// no crash on unary operator& (#5643)
2023-03-12 19:57:11 +01:00
// #11610
2014-08-29 17:06:46 +02:00
check ( " SdrObject* ApplyGraphicToObject() { \n "
" if (&rHitObject) {} \n "
" else if (rHitObject.IsClosedObj() && !&rHitObject) { } \n "
" } " ) ;
2023-03-12 19:57:11 +01:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Condition '&rHitObject' is always true \n "
" [test.cpp:3]: (style) Condition '!&rHitObject' is always false \n " ,
errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
// #5695: increment
check ( " void f(int a0, int n) { \n "
" int c = a0 & 3; \n "
" for (int a = 0; a < n; a++) { \n "
" c++; \n "
" if (c == 4) \n "
" c = 0; \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-06-20 16:23:16 +02:00
check ( " void f(int a) { \n " // #6662
" int x = a & 1; \n "
" while (x <= 4) { \n "
" if (x != 5) {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2015-06-20 16:23:16 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (style) Mismatching assignment and comparison, comparison 'x!=5' is always true. \n " , errout . str ( ) ) ;
check ( " void f(int a) { \n " // #6662
" int x = a & 1; \n "
" while ((x += 4) < 10) { \n "
" if (x != 5) {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2015-06-20 16:23:16 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-10-23 13:54:44 +02:00
check ( " void f() { \n "
" int x = 100; \n "
" while (x) { \n "
" g(x); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void g(int x); \n "
" void f() { \n "
" int x = 100; \n "
" while (x) { \n "
" g(x); \n "
" } \n "
" } " ) ;
2017-09-08 14:30:42 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Condition 'x' is always true \n " , errout . str ( ) ) ;
2016-10-23 13:54:44 +02:00
check ( " void g(int & x); \n "
" void f() { \n "
" int x = 100; \n "
" while (x) { \n "
" g(x); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
}
2014-11-20 14:20:09 +01:00
void mismatchingBitAnd ( ) {
2014-08-29 17:06:46 +02:00
check ( " void f(int a) { \n "
" int b = a & 0xf0; \n "
" b &= 1; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (style) Mismatching bitmasks. Result is always 0 (X = Y & 0xf0; Z = X & 0x1; => Z=0). \n " , errout . str ( ) ) ;
check ( " void f(int a) { \n "
" int b = a & 0xf0; \n "
" int c = b & 1; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (style) Mismatching bitmasks. Result is always 0 (X = Y & 0xf0; Z = X & 0x1; => Z=0). \n " , errout . str ( ) ) ;
check ( " void f(int a) { \n "
" int b = a; "
" switch (x) { \n "
" case 1: b &= 1; break; \n "
" case 2: b &= 2; break; \n "
" }; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2016-07-31 22:09:47 +02:00
void comparison ( ) {
// CheckCondition::comparison test cases
// '=='
check ( " void f(int a) { \n assert( (a & 0x07) == 8U ); \n } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Expression '(X & 0x7) == 0x8' is always false. \n " , errout . str ( ) ) ;
check ( " void f(int a) { \n assert( (a & b & 4 & c ) == 3 ); \n } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Expression '(X & 0x4) == 0x3' is always false. \n " , errout . str ( ) ) ;
check ( " void f(int a) { \n assert( (a | 0x07) == 8U ); \n } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Expression '(X | 0x7) == 0x8' is always false. \n " , errout . str ( ) ) ;
check ( " void f(int a) { \n assert( (a & 0x07) == 7U ); \n } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int a) { \n assert( (a | 0x01) == -15 ); \n } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// '!='
check ( " void f(int a) { \n assert( (a & 0x07) != 8U ); \n } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Expression '(X & 0x7) != 0x8' is always true. \n " , errout . str ( ) ) ;
check ( " void f(int a) { \n assert( (a | 0x07) != 8U ); \n } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Expression '(X | 0x7) != 0x8' is always true. \n " , errout . str ( ) ) ;
check ( " void f(int a) { \n assert( (a & 0x07) != 7U ); \n } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int a) { \n assert( (a | 0x07) != 7U ); \n } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// '>='
check ( " void f(int a) { \n assert( (a & 0x07) >= 8U ); \n } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Expression '(X & 0x7) >= 0x8' is always false. \n " , errout . str ( ) ) ;
check ( " void f(unsigned int a) { \n assert( (a | 0x7) >= 7U ); \n } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Expression '(X | 0x7) >= 0x7' is always true. \n " , errout . str ( ) ) ;
check ( " void f(int a) { \n assert( (a & 0x07) >= 7U ); \n } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int a) { \n assert( (a | 0x07) >= 8U ); \n } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ; //correct for negative 'a'
// '>'
check ( " void f(int a) { \n assert( (a & 0x07) > 7U ); \n } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Expression '(X & 0x7) > 0x7' is always false. \n " , errout . str ( ) ) ;
check ( " void f(unsigned int a) { \n assert( (a | 0x7) > 6U ); \n } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Expression '(X | 0x7) > 0x6' is always true. \n " , errout . str ( ) ) ;
check ( " void f(int a) { \n assert( (a & 0x07) > 6U ); \n } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int a) { \n assert( (a | 0x07) > 7U ); \n } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ; //correct for negative 'a'
// '<='
check ( " void f(int a) { \n assert( (a & 0x07) <= 7U ); \n } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Expression '(X & 0x7) <= 0x7' is always true. \n " , errout . str ( ) ) ;
check ( " void f(unsigned int a) { \n assert( (a | 0x08) <= 7U ); \n } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Expression '(X | 0x8) <= 0x7' is always false. \n " , errout . str ( ) ) ;
check ( " void f(int a) { \n assert( (a & 0x07) <= 6U ); \n } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int a) { \n assert( (a | 0x08) <= 7U ); \n } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ; //correct for negative 'a'
// '<'
check ( " void f(int a) { \n assert( (a & 0x07) < 8U ); \n } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Expression '(X & 0x7) < 0x8' is always true. \n " , errout . str ( ) ) ;
check ( " void f(unsigned int a) { \n assert( (a | 0x07) < 7U ); \n } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Expression '(X | 0x7) < 0x7' is always false. \n " , errout . str ( ) ) ;
check ( " void f(int a) { \n assert( (a & 0x07) < 3U ); \n } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int a) { \n assert( (a | 0x07) < 7U ); \n } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ; //correct for negative 'a'
2024-01-04 20:58:39 +01:00
check ( " void f(int i) { \n " // #11998
" if ((i & 0x100) == 0x200) {} \n "
" if (0x200 == (i & 0x100)) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (style) The if condition is the same as the previous if condition \n "
" [test.cpp:2]: (style) Expression '(X & 0x100) == 0x200' is always false. \n "
" [test.cpp:3]: (style) Expression '(X & 0x100) == 0x200' is always false. \n " ,
errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
}
2021-11-29 07:34:39 +01:00
# define checkPureFunction(code) checkPureFunction_(code, __FILE__, __LINE__)
2014-11-20 14:20:09 +01:00
void multicompare ( ) {
2014-08-29 17:06:46 +02:00
check ( " void foo(int x) \n "
" { \n "
" if (x & 7); \n "
" else { if (x == 1); } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Expression is always false because 'else if' condition matches previous condition at line 3. \n " , errout . str ( ) ) ;
check ( " void foo(int x) \n "
" { \n "
" if (x & 7); \n "
" else { if (x & 1); } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Expression is always false because 'else if' condition matches previous condition at line 3. \n " , errout . str ( ) ) ;
2015-01-10 12:21:55 +01:00
check ( " extern int bar() __attribute__((pure)); \n "
" void foo(int x) \n "
" { \n "
" if ( bar() >1 && b) {} \n "
" else if (bar() >1 && b) {} \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (style) Expression is always false because 'else if' condition matches previous condition at line 4. \n " , errout . str ( ) ) ;
checkPureFunction ( " extern int bar(); \n "
" void foo(int x) \n "
" { \n "
" if ( bar() >1 && b) {} \n "
" else if (bar() >1 && b) {} \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (style) Expression is always false because 'else if' condition matches previous condition at line 4. \n " , errout . str ( ) ) ;
2019-01-23 09:09:03 +01:00
// 7284
check ( " void foo() { \n "
" if (a) {} \n "
" else if (!!a) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-23 09:09:03 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2. \n " , errout . str ( ) ) ;
2022-05-11 20:01:13 +02:00
// #11059
check ( " int f(); \n "
" void g() { \n "
" int i = f(); \n "
" if (i == 3) {} \n "
" else if ((i = f()) == 5) {} \n "
" else if (i == 3) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f(); \n "
" void g() { \n "
" int i = f(); \n "
" if (i == 3) {} \n "
" else if ((i = f()) == 5) {} \n "
" else if (i != 3) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
}
2021-11-29 07:34:39 +01:00
void checkPureFunction_ ( const char code [ ] , const char * file , int line ) {
2015-01-10 12:21:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
// Tokenize..
2015-10-07 18:33:57 +02:00
Tokenizer tokenizer ( & settings1 , this ) ;
2015-01-10 12:21:55 +01:00
std : : istringstream istr ( code ) ;
2021-11-29 07:34:39 +01:00
ASSERT_LOC ( tokenizer . tokenize ( istr , " test.cpp " ) , file , line ) ;
2015-01-10 12:21:55 +01:00
2023-08-18 12:03:50 +02:00
runChecks < CheckCondition > ( tokenizer , this ) ;
2015-01-10 12:21:55 +01:00
}
2015-10-08 11:35:51 +02:00
2019-06-30 23:26:49 +02:00
void overlappingElseIfCondition ( ) {
2014-08-29 17:06:46 +02:00
check ( " void f(int a, int &b) { \n "
" if (a) { b = 1; } \n "
" else { if (a) { b = 2; } } \n "
" } " ) ;
2021-01-23 08:47:39 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int a, int &b) { \n "
" if (a) { b = 1; } \n "
" else { if (a) { b = 2; } } \n "
" } " ) ;
2021-01-23 08:47:39 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int a, int &b) { \n "
" if (a == 1) { b = 1; } \n "
" else { if (a == 2) { b = 2; } \n "
" else { if (a == 1) { b = 3; } } } \n "
" } " ) ;
2021-01-23 08:47:39 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Expression is always false because 'else if' condition matches previous condition at line 2. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int a, int &b) { \n "
" if (a == 1) { b = 1; } \n "
" else { if (a == 2) { b = 2; } \n "
" else { if (a == 2) { b = 3; } } } \n "
" } " ) ;
2021-01-23 08:47:39 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Expression is always false because 'else if' condition matches previous condition at line 3. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int a, int &b) { \n "
" if (a++) { b = 1; } \n "
" else { if (a++) { b = 2; } \n "
" else { if (a++) { b = 3; } } } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int a, int &b) { \n "
" if (!strtok(NULL, \" \" )) { b = 1; } \n "
" else { if (!strtok(NULL, \" \" )) { b = 2; } } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-07-08 15:58:04 +02:00
{
2018-07-10 22:56:01 +02:00
check ( " void f(Class &c) { \n "
" if (c.dostuff() == 3) {} \n "
" else { if (c.dostuff() == 3) {} } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(const Class &c) { \n "
" if (c.dostuff() == 3) {} \n "
" else { if (c.dostuff() == 3) {} } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2. \n " , errout . str ( ) ) ;
2018-07-08 15:58:04 +02:00
}
2014-08-29 17:06:46 +02:00
check ( " void f(int a, int &b) { \n "
" x = x / 2; \n "
" if (x < 100) { b = 1; } \n "
" else { x = x / 2; if (x < 100) { b = 2; } } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int i) { \n "
" if(i == 0x02e2000000 || i == 0xa0c6000000) \n "
" foo(i); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// ticket 3689 ( avoid false positive )
check ( " int fitInt(long long int nValue){ \n "
" if( nValue < 0x7fffffffLL ) \n "
" { \n "
" return 32; \n "
" } \n "
" if( nValue < 0x7fffffffffffLL ) \n "
" { \n "
" return 48; \n "
" } \n "
" else { \n "
" if( nValue < 0x7fffffffffffffffLL ) \n "
" { \n "
" return 64; \n "
" } else \n "
" { \n "
" return -1; \n "
" } \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(WIDGET *widget) { \n "
" if (dynamic_cast<BUTTON*>(widget)){} \n "
" else if (dynamic_cast<LABEL*>(widget)){} \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-01 12:58:06 +01:00
2022-07-20 20:48:17 +02:00
check ( " class B { virtual void v() {} }; \n " // #11037
" class D1 : public B {}; \n "
" class D2 : public B {}; \n "
" void f(const std::shared_ptr<B>&p) { \n "
" const auto d1 = dynamic_cast<D1*>(p.get()); \n "
" const auto d2 = dynamic_cast<D2*>(p.get()); \n "
" if (d1) {} \n "
" else if (d2) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-01 12:58:06 +01:00
check ( " void f(int x) { \n " // #6482
" if (x & 1) {} \n "
" else if (x == 0) {} \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2015-02-01 12:58:06 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-01 13:03:38 +01:00
check ( " void f(int x) { \n "
" if (x & 15) {} \n "
" else if (x == 40) {} \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2015-02-01 13:03:38 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2. \n " , errout . str ( ) ) ;
2017-02-22 21:13:36 +01:00
check ( " void f(int x) { \n "
" if (x == sizeof(double)) {} \n "
" else { if (x == sizeof(long double)) {} } "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-03-15 19:37:14 +01:00
check ( " void f(int x) { \n "
" if (x & 0x08) {} \n "
" else if (x & 0xF8) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x & 0xF8) {} \n "
" else if (x & 0x08) {} \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2. \n " , errout . str ( ) ) ;
2018-07-15 11:30:02 +02:00
check ( " void f(bool a, bool b) { \n "
" if(a && b){} \n "
" else if( !!b && !!a){} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-07-15 11:30:02 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2. \n " , errout . str ( ) ) ;
check ( " void f(bool a, bool b) { \n "
" if(a && b){} \n "
" else if( !!b && a){} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-07-15 11:30:02 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2. \n " , errout . str ( ) ) ;
check ( " void f(bool a, bool b) { \n "
" if(a && b){} \n "
" else if( b && !!a){} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-07-15 11:30:02 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2. \n " , errout . str ( ) ) ;
check ( " void f(bool a, bool b) { \n "
" if(a && b){} \n "
" else if( b && !(!a)){} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-07-15 11:30:02 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2. \n " , errout . str ( ) ) ;
check ( " void f(bool a, bool b) { \n "
" if(a && b){} \n "
" else if( !!b && !(!a)){} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-07-15 11:30:02 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Expression is always false because 'else if' condition matches previous condition at line 2. \n " , errout . str ( ) ) ;
check ( " void f(bool a, bool b) { \n "
" if(a && b){} \n "
" else if( !!(b) && !!(a+b)){} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-07-15 11:30:02 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-01-11 14:11:48 +01:00
// #8168
check ( " enum MaskValues \n "
" { \n "
" Value1 = 0x00000001, \n "
" Value2 = 0x00000002 \n "
" }; \n "
" void TestFunction(int value) { \n "
" if ( value & (int)Value1 ) {} \n "
" else if ( value & (int)Value2 ) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-11 14:11:48 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-11-11 08:01:11 +01:00
check ( " void f(size_t x) { \n "
" if (x == sizeof(int)) {} \n "
" else { if (x == sizeof(long))} {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(size_t x) { \n "
" if (x == sizeof(long)) {} \n "
" else { if (x == sizeof(long long))} {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
}
2019-06-30 23:26:49 +02:00
void oppositeElseIfCondition ( ) {
setMultiline ( ) ;
check ( " void f(int x) { \n "
" if (x) {} \n "
" else if (!x) {} \n "
" } " ) ;
2021-01-23 08:47:39 +01:00
ASSERT_EQUALS ( " test.cpp:3:style:Expression is always true because 'else if' condition is opposite to previous condition at line 2. \n "
" test.cpp:2:note:first condition \n "
" test.cpp:3:note:else if condition is opposite to first condition \n " , errout . str ( ) ) ;
2019-06-30 23:26:49 +02:00
check ( " void f(int x) { \n "
" int y = x; \n "
" if (x) {} \n "
" else if (!y) {} \n "
" } " ) ;
ASSERT_EQUALS ( " test.cpp:4:style:Expression is always true because 'else if' condition is opposite to previous condition at line 3. \n "
" test.cpp:2:note:'y' is assigned value 'x' here. \n "
" test.cpp:3:note:first condition \n "
" test.cpp:4:note:else if condition is opposite to first condition \n " , errout . str ( ) ) ;
}
2015-02-22 13:09:39 +01:00
void checkBadBitmaskCheck ( ) {
check ( " bool f(int x) { \n "
" bool b = x | 0x02; \n "
" return b; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'? \n " , errout . str ( ) ) ;
check ( " bool f(int x) { \n "
" bool b = 0x02 | x; \n "
" return b; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'? \n " , errout . str ( ) ) ;
check ( " int f(int x) { \n "
" int b = x | 0x02; \n "
" return b; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool f(int x) { \n "
" bool b = x & 0x02; \n "
" return b; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool f(int x) { \n "
" if(x | 0x02) \n "
" return b; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'? \n " , errout . str ( ) ) ;
check ( " bool f(int x) { \n "
" int y = 0x1; \n "
" if(b) y = 0; \n "
" if(x | y) \n "
" return b; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool f(int x) { \n "
" foo(a && (x | 0x02)); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'? \n " , errout . str ( ) ) ;
check ( " int f(int x) { \n "
" return (x | 0x02) ? 0 : 5; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'? \n " , errout . str ( ) ) ;
check ( " int f(int x) { \n "
" return x ? (x | 0x02) : 5; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool f(int x) { \n "
" return x | 0x02; \n "
" } " ) ;
2015-09-02 23:00:29 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'? \n " , errout . str ( ) ) ;
check ( " bool f(int x) { \n "
" if (x) { \n "
" return x | 0x02; \n "
" } \n "
" return 0; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'? \n " , errout . str ( ) ) ;
check ( " const bool f(int x) { \n "
" return x | 0x02; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'? \n " , errout . str ( ) ) ;
check ( " struct F { \n "
" static const bool f(int x) { \n "
" return x | 0x02; \n "
" } \n "
" }; " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'? \n " , errout . str ( ) ) ;
check ( " struct F { \n "
" typedef bool b_t; \n "
" }; \n "
" F::b_t f(int x) { \n "
" return x | 0x02; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'? \n " , errout . str ( ) ) ;
2015-02-22 13:09:39 +01:00
check ( " int f(int x) { \n "
" return x | 0x02; \n "
" } " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-23 22:06:55 +01:00
check ( " void create_rop_masks_4( rop_mask_bits *bits) { \n "
" DWORD mask_offset; \n "
" BYTE *and_bits = bits->and; \n "
" rop_mask *rop_mask; \n "
" and_bits[mask_offset] |= (rop_mask->and & 0x0f); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-01-24 13:45:44 +01:00
check ( " void f(unsigned a, unsigned b) { \n "
" unsigned cmd1 = b & 0x0F; \n "
" if (cmd1 | a) { \n "
" if (b == 0x0C) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-06-04 17:25:10 +02:00
check ( " void f(int i) { \n " // #11082
" int j = 0; \n "
" if (i | j) {} \n "
" } \n " ) ;
2022-07-28 21:56:05 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Operator '|' with one operand equal to zero is redundant. \n " , errout . str ( ) ) ;
2022-06-06 11:17:36 +02:00
check ( " #define EIGHTTOIS(x) (((x) << 8) | (x)) \n "
" int f() { \n "
" return EIGHTTOIS(0); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-06-07 21:13:31 +02:00
check ( " #define O_RDONLY 0 \n "
" void f(const char* s, int* pFd) { \n "
" *pFd = open(s, O_RDONLY | O_BINARY, 0); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-07-28 21:56:05 +02:00
check ( " const int FEATURE_BITS = x | \n "
" #if FOO_ENABLED \n "
" FEATURE_FOO | \n "
" #endif \n "
" #if BAR_ENABLED \n "
" FEATURE_BAR | \n "
" #endif \n "
" 0; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2023-06-26 10:43:20 +02:00
check ( " enum precedence { PC0, UNARY }; \n "
" int x = PC0 | UNARY; \n "
" int y = UNARY | PC0; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2023-08-11 23:06:24 +02:00
check ( " #define MASK 0 \n "
" #define SHIFT 1 \n "
" int x = 1 | (MASK << SHIFT); \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
}
2014-11-20 14:20:09 +01:00
void incorrectLogicOperator1 ( ) {
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n "
" if ((x != 1) || (x != 3)) \n "
" a++; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-08-31 08:46:56 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical disjunction always evaluates to true: x != 1 || x != 3. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n "
" if (1 != x || 3 != x) \n "
" a++; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-08-31 08:46:56 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical disjunction always evaluates to true: x != 1 || x != 3. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
2015-07-21 22:26:22 +02:00
check ( " void f(int x) { \n "
" if (x<0 && !x) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2015-07-21 22:26:22 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 0 && !x. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x==0 && x) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-08-31 08:46:56 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x == 0 && x. \n " , errout . str ( ) ) ;
2015-07-21 22:26:22 +02:00
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n " // ast..
" if (y == 1 && x == 1 && x == 7) { } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-08-31 08:46:56 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x == 1 && x == 7. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int x, int y) { \n "
" if (x != 1 || y != 1) \n "
" a++; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x, int y) { \n "
" if ((y == 1) && (x != 1) || (x != 3)) \n "
" a++; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x, int y) { \n "
" if ((x != 1) || (x != 3) && (y == 1)) \n "
" a++; \n "
2021-02-20 12:58:42 +01:00
" } "
2021-08-07 20:51:18 +02:00
) ;
2020-06-28 22:28:08 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:2]: (style) Condition 'x!=3' is always true \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n "
" if ((x != 1) && (x != 3)) \n "
" a++; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if ((x == 1) || (x == 3)) \n "
" a++; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x, int y) { \n "
" if ((x != 1) || (y != 3)) \n "
" a++; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x, int y) { \n "
" if ((x != hotdog) || (y != hotdog)) \n "
" a++; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x, int y) { \n "
" if ((x != 5) || (y != 5)) \n "
" a++; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if ((x != 5) || (x != 6)) \n "
" a++; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-08-31 08:46:56 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical disjunction always evaluates to true: x != 5 || x != 6. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02: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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2021-10-09 16:19:06 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:2]: (style) Condition 'c!=a' is always false \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
}
2014-11-20 14:20:09 +01:00
void incorrectLogicOperator2 ( ) {
2014-08-29 17:06:46 +02:00
check ( " void f(float x) { \n "
" if ((x == 1) && (x == 1.0)) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if ((x == 1) && (x == 0x00000001)) \n "
" a++; \n "
" } " ) ;
2020-06-28 22:28:08 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:2]: (style) Condition 'x==0x00000001' is always true \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n "
" if (x == 1 && x == 3) \n "
" a++; \n "
" } " ) ;
2020-08-31 08:46:56 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x == 1 && x == 3. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n "
" if (x == 1.0 && x == 3.0) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ; // float comparisons with == and != are not checked right now - such comparison is a bad idea
check ( " void f(float x) { \n "
" if (x == 1 && x == 1.0) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void bar(float f) { \n " // #5246
" if ((f > 0) && (f < 1)) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x < 1 && x > 1) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 1. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x < 1.0 && x > 1.0) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1.0 && x > 1.0. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x < 1 && x > 1.0) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 1.0. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x >= 1.0 && x <= 1.001) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x < 1 && x > 3) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 3. \n " , errout . str ( ) ) ;
check ( " void f(float x) { \n "
" if (x < 1.0 && x > 3.0) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1.0 && x > 3.0. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (1 > x && 3 < x) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 3. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x < 3 && x > 1) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x > 3 || x < 10) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical disjunction always evaluates to true: x > 3 || x < 10. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x >= 3 || x <= 10) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical disjunction always evaluates to true: x >= 3 || x <= 10. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x >= 3 || x < 10) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical disjunction always evaluates to true: x >= 3 || x < 10. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x > 3 || x <= 10) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical disjunction always evaluates to true: x > 3 || x <= 10. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x > 3 || x < 3) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x >= 3 || x <= 3) \n "
" a++; \n "
" } "
2021-08-07 20:51:18 +02:00
) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical disjunction always evaluates to true: x >= 3 || x <= 3. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x >= 3 || x < 3) \n "
" a++; \n "
" } "
2021-08-07 20:51:18 +02:00
) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical disjunction always evaluates to true: x >= 3 || x < 3. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x > 3 || x <= 3) \n "
" a++; \n "
" } "
2021-08-07 20:51:18 +02:00
) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical disjunction always evaluates to true: x > 3 || x <= 3. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if((x==3) && (x!=4)) \n "
" a++; \n "
" } " ) ;
2022-08-02 18:31:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: The condition 'x != 4' is redundant since 'x == 3' is sufficient. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
2021-08-24 14:36:13 +02:00
check ( " void f(const std::string &s) { \n " // #8860
" const std::size_t p = s.find( \" 42 \" ); \n "
" const std::size_t * const ptr = &p; \n "
" if(p != std::string::npos && p == 0 && *ptr != 1){;} \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:4]: (style) Condition '*ptr!=1' is always true \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n "
" if ((x!=4) && (x==3)) \n "
" a++; \n "
" } " ) ;
2022-08-02 18:31:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: The condition 'x != 4' is redundant since 'x == 3' is sufficient. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n "
" if ((x==3) || (x!=4)) \n "
" a++; \n "
" } " ) ;
2022-08-02 18:31:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: The condition 'x == 3' is redundant since 'x != 4' is sufficient. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n "
" if ((x!=4) || (x==3)) \n "
" a++; \n "
" } " ) ;
2022-08-02 18:31:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: The condition 'x == 3' is redundant since 'x != 4' is sufficient. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n "
" if ((x==3) && (x!=3)) \n "
" a++; \n "
" } " ) ;
2020-08-31 08:46:56 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x == 3 && x != 3. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n "
" if ((x==6) || (x!=6)) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical disjunction always evaluates to true: x == 6 || x != 6. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x > 10 || x < 3) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x > 5 && x == 1) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x > 5 && x == 1. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x > 5 && x == 6) \n "
" a++; \n "
" } " ) ;
2022-08-02 18:31:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: The condition 'x > 5' is redundant since 'x == 6' is sufficient. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
// #3419
check ( " void f() { \n "
" if ( &q != &a && &q != &b ) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #3676
check ( " void f(int m_x2, int w, int x) { \n "
" if (x + w - 1 > m_x2 || m_x2 < 0 ) \n "
" m_x2 = x + w - 1; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(float x) { \n " // x+1 => x
" if (x <= 1.0e20 && x >= -1.0e20) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(float x) { \n " // x+1 => x
" if (x >= 1.0e20 && x <= 1.0e21) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(float x) { \n " // x+1 => x
" if (x <= -1.0e20 && x >= -1.0e21) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void incorrectLogicOperator3 ( ) {
2014-08-29 17:06:46 +02:00
check ( " void f(int x, bool& b) { \n "
" b = x > 5 && x == 1; \n "
" c = x < 1 && x == 3; \n "
" d = x >= 5 && x == 1; \n "
" e = x <= 1 && x == 3; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x > 5 && x == 1. \n "
" [test.cpp:3]: (warning) Logical conjunction always evaluates to false: x < 1 && x == 3. \n "
" [test.cpp:4]: (warning) Logical conjunction always evaluates to false: x >= 5 && x == 1. \n "
" [test.cpp:5]: (warning) Logical conjunction always evaluates to false: x <= 1 && x == 3. \n " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void incorrectLogicOperator4 ( ) {
2017-05-18 21:52:31 +02:00
check ( " #define ZERO 0 \n "
" void f(int x) { \n "
" if (x && x != ZERO) {} \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-04-09 14:09:10 +02:00
check ( " void f(int N) { \n " // #9789
" T a[20] = { 0 }; \n "
" for (int i = 0; i < N; ++i) { \n "
" if (0 < a[i] && a[i] < 1) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
}
2014-11-20 14:20:09 +01:00
void incorrectLogicOperator5 ( ) { // complex expressions
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n "
" if (x+3 > 2 || x+3 < 10) {} \n "
" } " ) ;
2022-08-02 18:31:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical disjunction always evaluates to true: x+3 > 2 || x+3 < 10. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
}
2014-11-20 14:20:09 +01:00
void incorrectLogicOperator6 ( ) { // char literals
2014-08-29 17:06:46 +02:00
check ( " void f(char x) { \n "
" if (x == '1' || x == '2') {} \n "
2016-05-24 15:08:07 +02:00
" } " , " test.cpp " , true ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(char x) { \n "
" if (x == '1' && x == '2') {} \n "
2016-05-24 15:08:07 +02:00
" } " , " test.cpp " , true ) ;
2020-08-31 08:46:56 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x == '1' && x == '2'. \n " , errout . str ( ) ) ;
2016-05-24 15:08:07 +02:00
check ( " int f(char c) { \n "
" return (c >= 'a' && c <= 'z'); \n "
" } " , " test.cpp " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f(char c) { \n "
" return (c <= 'a' && c >= 'z'); \n "
" } " , " test.cpp " , true ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning, inconclusive) Logical conjunction always evaluates to false: c <= 'a' && c >= 'z'. \n " , errout . str ( ) ) ;
check ( " int f(char c) { \n "
" return (c <= 'a' && c >= 'z'); \n "
" } " , " test.cpp " , false ) ;
2022-10-10 13:45:30 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:2]: (style) Return value 'c>='z'' is always false \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
}
2014-11-20 14:20:09 +01:00
void incorrectLogicOperator7 ( ) { // opposite expressions
2014-08-29 17:06:46 +02:00
check ( " void f(int i) { \n "
" if (i || !i) {} \n "
" } " ) ;
2018-08-05 22:39:40 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical disjunction always evaluates to true: i || !(i). \n " , errout . str ( ) ) ;
2015-06-19 19:49:05 +02:00
check ( " void f(int a, int b) { \n "
" if (a>b || a<=b) {} \n "
" } " ) ;
2018-08-05 22:39:40 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical disjunction always evaluates to true: a > b || a <= b. \n " , errout . str ( ) ) ;
2015-06-19 19:49:05 +02:00
check ( " void f(int a, int b) { \n "
" if (a>b || a<b) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-11-07 11:17:44 +01:00
// #6064 False positive incorrectLogicOperator - invalid assumption about template type?
check ( " template<typename T> T icdf( const T uniform ) { \n "
" if ((0<uniform) && (uniform<1)) \n "
" {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #6081 False positive: incorrectLogicOperator, with close negative comparisons
check ( " double neg = -1.0 - 1.0e-13; \n "
" void foo() { \n "
" if ((neg < -1.0) && (neg > -1.0 - 1.0e-12)) \n "
" return; \n "
" else \n "
" return; \n "
" } " ) ;
2018-10-20 10:51:50 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
}
2015-07-13 20:53:49 +02:00
void incorrectLogicOperator8 ( ) { // opposite expressions
check ( " void f(int i) { \n "
" if (!(i!=10) && !(i!=20)) {} \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: !(i != 10) && !(i != 20). \n " , errout . str ( ) ) ;
}
2015-07-30 10:30:30 +02:00
void incorrectLogicOperator9 ( ) { // #6069 "False positive incorrectLogicOperator due to dynamic_cast"
check ( " class MyType; \n "
2015-07-30 13:30:16 +02:00
" class OtherType; \n "
2021-02-20 12:58:42 +01:00
" void foo (OtherType* obj) { \n "
2015-07-30 13:30:16 +02:00
" assert((!obj) || dynamic_cast<MyType*>(obj)); \n "
" } " ) ;
2015-07-30 10:30:30 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2017-03-23 18:57:48 +01:00
void incorrectLogicOperator10 ( ) { // #7794 - enum
check ( " typedef enum { A, B } Type_t; \n "
" void f(Type_t t) { \n "
" if ((t == A) && (t == B)) \n "
" {} \n "
" } " ) ;
2020-08-31 08:46:56 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Logical conjunction always evaluates to false: t == 0 && t == 1. \n " , errout . str ( ) ) ;
2017-03-23 18:57:48 +01:00
}
2018-08-05 22:39:40 +02:00
void incorrectLogicOperator11 ( ) {
check ( " void foo(int i, const int n) { if ( i < n && i == n ) {} } " ) ;
ASSERT_EQUALS ( " [test.cpp:1]: (warning) Logical conjunction always evaluates to false: i < n && i == n. \n " , errout . str ( ) ) ;
2018-08-05 22:40:21 +02:00
2018-08-05 22:39:40 +02:00
check ( " void foo(int i, const int n) { if ( i > n && i == n ) {} } " ) ;
ASSERT_EQUALS ( " [test.cpp:1]: (warning) Logical conjunction always evaluates to false: i > n && i == n. \n " , errout . str ( ) ) ;
2018-08-05 22:40:21 +02:00
2018-08-05 22:39:40 +02:00
check ( " void foo(int i, const int n) { if ( i == n && i > n ) {} } " ) ;
ASSERT_EQUALS ( " [test.cpp:1]: (warning) Logical conjunction always evaluates to false: i == n && i > n. \n " , errout . str ( ) ) ;
2018-08-05 22:40:21 +02:00
2018-08-05 22:39:40 +02:00
check ( " void foo(int i, const int n) { if ( i == n && i < n ) {} } " ) ;
ASSERT_EQUALS ( " [test.cpp:1]: (warning) Logical conjunction always evaluates to false: i == n && i < n. \n " , errout . str ( ) ) ;
}
2018-08-27 11:09:09 +02:00
void incorrectLogicOperator12 ( ) { // #8696
2022-09-08 22:08:38 +02:00
check ( " struct A { \n "
" void f() const; \n "
" }; \n "
" void foo(A a, A b) { \n "
" A x = b; \n "
" A y = b; \n "
" y.f(); \n "
" if (a > x && a < y) \n "
" return; \n "
" } " ) ;
ASSERT_EQUALS (
" [test.cpp:5] -> [test.cpp:6] -> [test.cpp:8]: (warning) Logical conjunction always evaluates to false: a > x && a < y. \n " ,
errout . str ( ) ) ;
check ( " struct A { \n "
" void f(); \n "
" }; \n "
" void foo(A a, A b) { \n "
" A x = b; \n "
" A y = b; \n "
" y.f(); \n "
" if (a > x && a < y) \n "
" return; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(A a, A b) { \n "
" A x = b; \n "
" A y = b; \n "
" y.f(); \n "
" if (a > x && a < y) \n "
" return; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(A a, A b) { \n "
" const A x = b; \n "
" const A y = b; \n "
" y.f(); \n "
" if (a > x && a < y) \n "
" return; \n "
" } " ) ;
ASSERT_EQUALS (
" [test.cpp:2] -> [test.cpp:3] -> [test.cpp:5]: (warning) Logical conjunction always evaluates to false: a > x && a < y. \n " ,
errout . str ( ) ) ;
2018-08-27 11:09:09 +02:00
check ( " struct A { \n "
" void f() const; \n "
" }; \n "
" void foo(A a) { \n "
" A x = a; \n "
" A y = a; \n "
" y.f(); \n "
" if (a > x && a < y) \n "
" return; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2022-09-08 22:08:38 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (style) Condition 'a>x' is always false \n "
" [test.cpp:8]: (style) Condition 'a<y' is always false \n " ,
errout . str ( ) ) ;
2018-08-27 11:09:09 +02:00
check ( " struct A { \n "
" void f(); \n "
" }; \n "
" void foo(A a) { \n "
" A x = a; \n "
" A y = a; \n "
" y.f(); \n "
" if (a > x && a < y) \n "
" return; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2022-09-08 22:08:38 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (style) Condition 'a>x' is always false \n " , errout . str ( ) ) ;
2018-08-27 11:09:09 +02:00
check ( " void foo(A a) { \n "
" A x = a; \n "
" A y = a; \n "
" y.f(); \n "
" if (a > x && a < y) \n "
" return; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2022-09-08 22:08:38 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (style) Condition 'a>x' is always false \n " , errout . str ( ) ) ;
2018-08-27 11:09:09 +02:00
check ( " void foo(A a) { \n "
" const A x = a; \n "
" const A y = a; \n "
" y.f(); \n "
" if (a > x && a < y) \n "
" return; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2022-09-08 22:08:38 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (style) Condition 'a>x' is always false \n "
" [test.cpp:5]: (style) Condition 'a<y' is always false \n " ,
errout . str ( ) ) ;
2018-08-27 11:09:09 +02:00
}
2019-01-25 07:48:18 +01:00
void incorrectLogicOperator13 ( ) {
// 8780
check ( " void f(const int &v) { \n "
" const int x=v; \n "
" if ((v == 1) && (x == 2)) {;} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-25 07:48:18 +01:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Logical conjunction always evaluates to false: v == 1 && x == 2. \n " , errout . str ( ) ) ;
check ( " void f2(const int *v) { \n "
" const int *x=v; \n "
" if ((*v == 1) && (*x == 2)) {;} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-25 07:48:18 +01:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Logical conjunction always evaluates to false: *(v) == 1 && *(x) == 2. \n " , errout . str ( ) ) ;
}
2019-07-24 09:59:01 +02:00
void incorrectLogicOperator14 ( ) {
check ( " static const std ::string h; \n "
" class i { \n "
" public: \n "
" struct j { \n "
" std ::string k; \n "
" std ::string l; \n "
" }; \n "
" struct a { \n "
" enum { m = 1 }; \n "
" }; \n "
" } b; \n "
" namespace n { \n "
" class c; \n "
" } \n "
" struct o { \n "
" enum { p, d, q, r }; \n "
" enum { e, f }; \n "
" \n "
" public: \n "
" class j { \n "
" public: \n "
" class s { \n "
" std ::string a; \n "
" }; \n "
" }; \n "
" }; \n "
" namespace n { \n "
" class b; \n "
" } \n "
" namespace aa { \n "
" class d { \n "
" public: \n "
" char t; \n "
" enum {} u; \n "
" }; \n "
" } // namespace aa \n "
" namespace aa { \n "
" struct e {}; \n "
" } // namespace aa \n "
" class a; \n "
" class w { \n "
" public: \n "
" enum { x }; \n "
" struct { \n "
" } y; \n "
" std ::string z; \n "
" }; \n "
" class ab { \n "
" friend class c; \n "
" \n "
" public: \n "
" class ac { \n "
" void e(const ac &v) const; \n "
" }; \n "
" }; \n "
" class f; \n "
" class ad { \n "
" friend class e; \n "
" enum { e, ae, ag, ah, ai, aj, ak, a, b }; \n "
" class c {}; \n "
" class d { \n "
" enum am { f, an, ao, ap, aq, ar, b, as, at, c, au }; \n "
" enum av { aw, ax, ay, az, e, ba, bb, bc, bd, a }; \n "
" struct b { \n "
" am action; \n "
" av c; \n "
" }; \n "
" }; \n "
" class e { \n "
" public: \n "
" std ::string e; \n "
" class f { \n "
" } f; \n "
" class be { \n "
" public: \n "
" }; \n "
" std ::vector<be> bf; \n "
" enum { bg, b } c; \n "
" }; \n "
" struct bh { \n "
" std ::map<int, d> b; \n "
" }; \n "
" std ::map<std ::string, bh> bi; \n "
" struct { \n "
" int b; \n "
" char bj; \n "
" } bk; \n "
" class a { \n "
" public: \n "
" std ::set<std ::string> b; \n "
" }; \n "
" }; \n "
" class bl; \n "
" class al; \n "
" class bm; \n "
" class f; \n "
" class b; \n "
" class bn; \n "
" namespace bo { \n "
" class bp { \n "
" public: \n "
" typedef std ::pair<const f *, std ::string> bq; \n "
" typedef std ::list<bq> br; \n "
" }; \n "
" const bo ::bp *dg(const f *a, const al *b); \n "
" } // namespace bo \n "
" const bn *dh(const f *d, bo ::bp ::br &bs); \n "
" class f { \n "
" public: \n "
" struct bt {}; \n "
" std ::vector<a> f; \n "
" }; \n "
" class bu; \n "
" class a; \n "
" class c; \n "
" struct bv {}; \n "
" class af { \n "
" private: \n "
" public: \n "
" enum { b, d, e, f, c, bw }; \n "
" void a(int c); \n "
" af *bx() const; \n "
" }; \n "
" namespace by { \n "
" class b; \n "
" } \n "
" class b { \n "
" public: \n "
" bool d, c; \n "
" }; \n "
" class bz; \n "
" class f; \n "
" class ca { \n "
" friend class b; \n "
" \n "
" public: \n "
" const bm *cb() const { return cc; } \n "
" f *d(f *e, bool f) const; \n "
" int e() { return ++cd; } \n "
" bl *const c; \n "
" bm *cc; \n "
" std ::map<std ::string, int> ce; \n "
" int cd; \n "
" bz *a; \n "
" }; \n "
" namespace n { \n "
" class c; \n "
" class d; \n "
" } // namespace n \n "
" class cf { \n "
" public: \n "
" explicit cf(const std ::string &aname); \n "
" cf(const std ::string &aname, const ca *cg, const al *ch, bl *ci) \n "
" : cj(cg), ck(ch), cl(ci), cn(aname) {} \n "
" \n "
" protected: \n "
" const ca *const cj; \n "
" const al *const ck; \n "
" bl *const cl; \n "
" const std ::string cn; \n "
" }; \n "
" class cm : public cf { \n "
" public: \n "
" void cp(); \n "
" std ::string d() const; \n "
" }; \n "
" struct co { \n "
" co(); \n "
" const bu *a; \n "
" enum f {}; \n "
" enum { \n "
" b = (1 << 0), \n "
" c = (1 << 1), \n "
" }; \n "
" void d(bool e); \n "
" }; \n "
" class bu { \n "
" friend class e; \n "
" \n "
" public: \n "
" struct f {}; \n "
" enum { d, cr, cq, ct, cs, e, a, b, c, dd, cu, cv, cw, cx, cy, cz, da }; \n "
" const f *db; \n "
" const af *dc; \n "
" } f{}; \n "
" class bm { \n "
" public: \n "
" std ::list<bu> df; \n "
" std ::vector<const bu *> de; \n "
" mutable std ::set<std ::string> f; \n "
" }; \n "
" void cm ::cp() { \n "
" const bm *a = cj->cb(); \n "
" for (const bu *b : a->de) \n "
" for (af *c = b->dc->bx();;) { \n "
" af *d = c; \n "
" af *e = c; \n "
" bool f(d); \n "
" bool g(e); \n "
" if (f && g) \n "
" ; \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2021-10-06 08:39:58 +02:00
ASSERT_EQUALS ( " [test.cpp:200] -> [test.cpp:200]: (style) Condition 'g' is always true \n " , errout . str ( ) ) ;
2019-07-24 09:59:01 +02:00
}
2021-01-29 10:27:32 +01:00
void incorrectLogicOperator15 ( ) {
2021-01-29 10:26:57 +01:00
// 10022
check ( " struct PipeRoute { \n "
" std::deque<int> points; \n "
" std::deque<int> estimates; \n "
" }; \n "
" void CleanPipeRoutes(std::map<int, PipeRoute*>& pipeRoutes) { \n "
" for (auto it = pipeRoutes.begin(); it != pipeRoutes.end(); ) { \n "
" PipeRoute* curRoute = it->second; \n "
" if (curRoute->points.empty() && curRoute->estimates.size() != 2) \n "
" { \n "
" delete curRoute; \n "
" it = pipeRoutes.erase(it); \n "
" } \n "
" else \n "
" { \n "
" ++it; \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2021-05-04 13:46:46 +02:00
void incorrectLogicOperator16 ( ) { // #10070
check ( " void foo(void* p) { \n "
" if (!p || p == -1) { } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void secondAlwaysTrueFalseWhenFirstTrueError ( ) {
2022-05-24 09:21:21 +02:00
check ( " void f(void) { \n " // #8892
" const char c[1] = { \' x \' }; \n "
" if(c[0] == \' x \' ){;} \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition 'c[0]=='x'' is always true \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n "
" if (x > 5 && x != 1) \n "
" a++; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2022-08-02 18:31:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: The condition 'x != 1' is redundant since 'x > 5' is sufficient. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n "
" if (x > 5 && x != 6) \n "
" a++; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if ((x > 5) && (x != 1)) \n "
" a++; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2022-08-02 18:31:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: The condition 'x != 1' is redundant since 'x > 5' is sufficient. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n "
" if ((x > 5) && (x != 6)) \n "
" a++; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x, bool& b) { \n "
" b = x > 3 || x == 4; \n "
" c = x < 5 || x == 4; \n "
" d = x >= 3 || x == 4; \n "
" e = x <= 5 || x == 4; \n "
" } " ) ;
2022-08-02 18:31:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: The condition 'x == 4' is redundant since 'x > 3' is sufficient. \n "
" [test.cpp:3]: (style) Redundant condition: The condition 'x == 4' is redundant since 'x < 5' is sufficient. \n "
" [test.cpp:4]: (style) Redundant condition: The condition 'x == 4' is redundant since 'x >= 3' is sufficient. \n "
" [test.cpp:5]: (style) Redundant condition: The condition 'x == 4' is redundant since 'x <= 5' is sufficient. \n " ,
errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int x, bool& b) { \n "
" b = x > 5 || x != 1; \n "
" c = x < 1 || x != 3; \n "
" d = x >= 5 || x != 1; \n "
" e = x <= 1 || x != 3; \n "
" } " ) ;
2022-08-02 18:31:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: The condition 'x > 5' is redundant since 'x != 1' is sufficient. \n "
" [test.cpp:3]: (style) Redundant condition: The condition 'x < 1' is redundant since 'x != 3' is sufficient. \n "
" [test.cpp:4]: (style) Redundant condition: The condition 'x >= 5' is redundant since 'x != 1' is sufficient. \n "
" [test.cpp:5]: (style) Redundant condition: The condition 'x <= 1' is redundant since 'x != 3' is sufficient. \n " ,
errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(int x, bool& b) { \n "
" b = x > 6 && x > 5; \n "
" c = x > 5 || x > 6; \n "
" d = x < 6 && x < 5; \n "
" e = x < 5 || x < 6; \n "
" } " ) ;
2022-08-02 18:31:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: The condition 'x > 5' is redundant since 'x > 6' is sufficient. \n "
" [test.cpp:3]: (style) Redundant condition: The condition 'x > 6' is redundant since 'x > 5' is sufficient. \n "
" [test.cpp:4]: (style) Redundant condition: The condition 'x < 6' is redundant since 'x < 5' is sufficient. \n "
" [test.cpp:5]: (style) Redundant condition: The condition 'x < 5' is redundant since 'x < 6' is sufficient. \n " ,
errout . str ( ) ) ;
2022-08-02 22:11:31 +02:00
check ( " void f(double x, bool& b) { \n "
" b = x > 6.5 && x > 5.5; \n "
" c = x > 5.5 || x > 6.5; \n "
" d = x < 6.5 && x < 5.5; \n "
" e = x < 5.5 || x < 6.5; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: The condition 'x > 5.5' is redundant since 'x > 6.5' is sufficient. \n "
" [test.cpp:3]: (style) Redundant condition: The condition 'x > 6.5' is redundant since 'x > 5.5' is sufficient. \n "
" [test.cpp:4]: (style) Redundant condition: The condition 'x < 6.5' is redundant since 'x < 5.5' is sufficient. \n "
" [test.cpp:5]: (style) Redundant condition: The condition 'x < 5.5' is redundant since 'x < 6.5' is sufficient. \n " ,
errout . str ( ) ) ;
2022-08-02 18:31:02 +02:00
check ( " void f(const char *p) { \n " // #10320
" if (!p || !*p || *p != 'x') {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: The condition '!*p' is redundant since '*p != 'x'' is sufficient. \n " ,
errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
}
2014-11-20 14:20:09 +01:00
void incorrectLogicOp_condSwapping ( ) {
2014-08-29 17:06:46 +02:00
check ( " void f(int x) { \n "
" if (x < 1 && x > 3) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 3. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (1 > x && x > 3) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 3. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x < 1 && 3 < x) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 3. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (1 > x && 3 < x) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 3. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x > 3 && x < 1) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x > 3 && x < 1. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (3 < x && x < 1) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x > 3 && x < 1. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x > 3 && 1 > x) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x > 3 && x < 1. \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (3 < x && 1 > x) \n "
" a++; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Logical conjunction always evaluates to false: x > 3 && x < 1. \n " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void modulo ( ) {
2014-08-29 17:06:46 +02:00
check ( " bool f(bool& b1, bool& b2, bool& b3) { \n "
" b1 = a % 5 == 4; \n "
" b2 = a % c == 100000; \n "
" b3 = a % 5 == c; \n "
" return a % 5 == 5-p; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool f(bool& b1, bool& b2, bool& b3, bool& b4, bool& b5) { \n "
" b1 = a % 5 < 5; \n "
" b2 = a % 5 <= 5; \n "
" b3 = a % 5 == 5; \n "
" b4 = a % 5 != 5; \n "
" b5 = a % 5 >= 5; \n "
" return a % 5 > 5; \n "
" } " ) ;
2021-03-30 14:02:28 +02:00
ASSERT_EQUALS (
" [test.cpp:2]: (warning) Comparison of modulo result is predetermined, because it is always less than 5. \n "
" [test.cpp:3]: (warning) Comparison of modulo result is predetermined, because it is always less than 5. \n "
" [test.cpp:4]: (warning) Comparison of modulo result is predetermined, because it is always less than 5. \n "
" [test.cpp:5]: (warning) Comparison of modulo result is predetermined, because it is always less than 5. \n "
" [test.cpp:6]: (warning) Comparison of modulo result is predetermined, because it is always less than 5. \n "
" [test.cpp:7]: (warning) Comparison of modulo result is predetermined, because it is always less than 5. \n " ,
errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(bool& b1, bool& b2) { \n "
" b1 = bar() % 5 < 889; \n "
" if(x[593] % 5 <= 5) \n "
" b2 = x.a % 5 == 5; \n "
" } " ) ;
2021-03-30 14:02:28 +02:00
ASSERT_EQUALS (
" [test.cpp:2]: (warning) Comparison of modulo result is predetermined, because it is always less than 5. \n "
" [test.cpp:3]: (warning) Comparison of modulo result is predetermined, because it is always less than 5. \n "
" [test.cpp:4]: (warning) Comparison of modulo result is predetermined, because it is always less than 5. \n " ,
errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f() { \n "
" if (a % 2 + b % 2 == 2) \n "
" foo(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void oppositeInnerCondition ( ) {
2014-08-29 17:06:46 +02:00
check ( " void foo(int a, int b) { \n "
" if(a==b) \n "
" if(a!=b) \n "
" cout << a; \n "
" } " ) ;
2017-09-01 13:33:47 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
2018-10-18 21:01:47 +02:00
check ( " bool foo(int a, int b) { \n "
" if(a==b) \n "
" return a!=b; \n "
" return false; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'return' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void foo(int a, int b) { \n "
" if(a==b) \n "
" if(b!=a) \n "
" cout << a; \n "
" } " ) ;
2017-09-01 13:33:47 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void foo(int a) { \n "
" if(a >= 50) { \n "
" if(a < 50) \n "
" cout << a; \n "
" else \n "
" cout << 100; \n "
" } \n "
" } " ) ;
2017-09-01 13:33:47 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
// #4186
check ( " void foo(int a) { \n "
" if(a >= 50) { \n "
" if(a > 50) \n "
" cout << a; \n "
" else \n "
" cout << 100; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// 4170
check ( " class foo { \n "
" void bar() { \n "
" if (tok == '(') { \n "
" next(); \n "
" if (tok == ',') { \n "
" next(); \n "
" if (tok != ',') { \n "
" op->reg2 = asm_parse_reg(); \n "
" } \n "
" skip(','); \n "
" } \n "
" } \n "
" } \n "
" void next(); \n "
" const char *tok; \n "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(int i) \n "
" { \n "
" if(i > 5) { \n "
" i = bar(); \n "
" if(i < 5) { \n "
" cout << a; \n "
" } \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(int& i) { \n "
" i=6; \n "
" } \n "
" void bar(int i) { \n "
" if(i>5) { \n "
" foo(i); \n "
" if(i<5) { \n "
" } \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(int& i); \n "
" void bar() { \n "
" int i; i = func(); \n "
" if(i>5) { \n "
" foo(i); \n "
" if(i<5) { \n "
" } \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(int i); \n "
" void bar(int i) { \n "
" if(i>5) { \n "
" foo(i); \n "
" if(i<5) { \n "
" } \n "
" } \n "
" } " ) ;
2019-06-22 21:57:19 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:5]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
2017-07-10 23:12:45 +02:00
check ( " void foo(const int &i); \n "
" void bar(int i) { \n "
" if(i>5) { \n "
" foo(i); \n "
" if(i<5) { \n "
" } \n "
" } \n "
" } " ) ;
2019-06-22 21:57:19 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:5]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2017-07-10 23:12:45 +02:00
2014-08-29 17:06:46 +02:00
check ( " void foo(int i); \n "
" void bar() { \n "
" int i; i = func(); \n "
" if(i>5) { \n "
" foo(i); \n "
" if(i<5) { \n "
" } \n "
" } \n "
" } " ) ;
2019-06-22 21:57:19 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:6]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
2017-07-10 23:12:45 +02:00
check ( " class C { void f(int &i) const; }; \n " // #7028 - variable is changed by const method
" void foo(C c, int i) { \n "
" if (i==5) { \n "
" c.f(i); \n "
" if (i != 5) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
// see linux revision 1f80c0cc
check ( " int generic_write_sync(int,int,int); \n "
" \n "
" void cifs_writev(int i) { \n "
" int rc = __generic_file_aio_write(); \n "
" if (rc > 0){ \n "
" err = generic_write_sync(file, iocb->ki_pos - rc, rc); \n "
" if(rc < 0) { \n " // <- condition is always false
" err = rc; \n "
" } \n "
" } \n "
" } " ) ;
2019-06-22 21:57:19 +02:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:7]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
2017-09-04 22:11:53 +02:00
// #5874 - array
check ( " void testOppositeConditions2() { \n "
" int array[2] = { 0, 0 }; \n "
" if (array[0] < 2) { \n "
" array[0] += 5; \n "
" if (array[0] > 2) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #6227 - FP caused by simplifications of casts and known variables
check ( " void foo(A *a) { \n "
" if(a) { \n "
" B *b = dynamic_cast<B*>(a); \n "
" if(!b) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(int a) { \n "
" if(a) { \n "
" int b = a; \n "
" if(!b) {} \n "
" } \n "
" } " ) ;
2018-10-04 21:17:47 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:2] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2017-09-04 22:11:53 +02:00
check ( " void foo(unsigned u) { \n "
" if (u != 0) { \n "
" for (int i=0; i<32; i++) { \n "
" if (u == 0) {} \n " // <- don't warn
" u = x; \n "
" } \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #8186
check ( " void f() { \n "
" for (int i=0;i<4;i++) { \n "
" if (i==5) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2020-01-04 11:38:56 +01:00
// #8938
check ( " void Delete(SS_CELLCOORD upperleft) { \n "
" if ((upperleft.Col == -1) && (upperleft.Row == -1)) { \n "
" GetActiveCell(&(upperleft.Col), &(upperleft.Row)); \n "
" if (upperleft.Row == -1) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-01-15 20:48:07 +01:00
// #9702
check ( " struct A { \n "
" void DoTest() { \n "
" if (!IsSet()) { \n "
" m_value = true; \n "
" if (IsSet()); \n "
" } \n "
" } \n "
" bool IsSet() const { return m_value; } \n "
" bool m_value = false; \n "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-09-04 22:11:53 +02:00
}
void oppositeInnerConditionPointers ( ) {
2014-08-29 17:06:46 +02:00
check ( " void f(struct ABC *abc) { \n "
" struct AB *ab = abc->ab; \n "
" if (ab->a == 123){ \n "
" do_something(abc); \n " // might change ab->a
" if (ab->a != 123) { \n "
" err = rc; \n "
" } \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-09-05 09:33:35 +02:00
check ( " void Fred::f() { \n " // daca: ace
" if (this->next_ == map_man_->table_) { \n "
" this->next_ = n; \n "
" if (this->next_ != map_man_->table_) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-09-05 22:03:29 +02:00
check ( " void test(float *f) { \n " // #7405
" if(*f>10) { \n "
" (*f) += 0.1f; \n "
" if(*f<10) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-10-31 09:47:48 +01:00
check ( " int * f(int * x, int * y) { \n "
" if(!x) return x; \n "
" return y; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-10-31 09:47:48 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-09-04 22:11:53 +02:00
}
void oppositeInnerConditionClass ( ) {
// #6095 - calling member function that might change the state
check ( " void f() { \n "
" const Fred fred; \n " // <- fred is const, warn
" if (fred.isValid()) { \n "
" fred.dostuff(); \n "
" if (!fred.isValid()) {} \n "
" } \n "
" } " ) ;
2019-06-22 21:57:19 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:5]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2017-09-04 22:11:53 +02:00
2017-09-06 22:26:00 +02:00
check ( " class Fred { public: bool isValid() const; void dostuff() const; }; \n "
2017-09-04 22:11:53 +02:00
" void f() { \n "
" Fred fred; \n "
" if (fred.isValid()) { \n "
" fred.dostuff(); \n " // <- dostuff() is const, warn
" if (!fred.isValid()) {} \n "
" } \n "
" } " ) ;
2019-06-22 21:57:19 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:6]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2017-09-04 22:11:53 +02:00
check ( " void f() { \n "
" Fred fred; \n "
" if (fred.isValid()) { \n "
" fred.dostuff(); \n "
" if (!fred.isValid()) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-09-04 15:58:22 +02:00
2017-09-04 22:11:53 +02:00
// #6385 "crash in Variable::getFlag()"
check ( " class TranslationHandler { \n "
" QTranslator *mTranslator; \n "
" void SetLanguage() { \n "
" if (mTranslator) { \n "
" qApp->removeTranslator(mTranslator); \n "
" } \n "
" } \n "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ; // just don't crash...
2017-09-04 22:25:20 +02:00
check ( " bool f(std::ofstream &CFileStream) { \n " // #8198
" if(!CFileStream.good()) { return; } \n "
" CFileStream << \" abc \" ; \n "
" if (!CFileStream.good()) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-09-04 22:11:53 +02:00
}
2014-12-31 15:14:22 +01:00
2017-09-04 22:11:53 +02:00
void oppositeInnerConditionUndeclaredVariable ( ) {
2014-08-29 17:06:46 +02:00
// #5731 - fp when undeclared variable is used
check ( " void f() { \n "
" if (x == -1){ \n "
" x = do_something(); \n "
" if (x != -1) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #5750 - another fp when undeclared variable is used
check ( " void f() { \n "
" if (r < w){ \n "
" r += 3; \n "
" if (r > w) {} \n "
2015-06-14 20:06:05 +02:00
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #6574 - another fp when undeclared variable is used
check ( " void foo() { \n "
" if(i) { \n "
" i++; \n "
" if(!i) {} \n "
2014-08-29 17:06:46 +02:00
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-09-03 14:46:37 +02:00
// undeclared array
check ( " void f(int x) { \n "
" if (a[x] > 0) { \n "
" a[x] -= dt; \n "
" if (a[x] < 0) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-11-27 11:40:42 +01:00
// #6313 - false positive: opposite conditions in nested if blocks when condition changed
2015-07-16 08:44:38 +02:00
check ( " void Foo::Bar() { \n "
" if(var){ \n "
" --var; \n "
" if(!var){} \n "
" else {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2015-07-16 08:44:38 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-09-10 22:30:41 +02:00
// daca hyphy
check ( " bool f() { \n "
" if (rec.lLength==0) { \n "
" rec.Delete(i); \n "
" if (rec.lLength!=0) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
}
2017-09-04 09:34:03 +02:00
void oppositeInnerConditionAlias ( ) {
check ( " void f() { \n "
" struct S s; \n "
" bool hasFailed = false; \n "
" s.status = &hasFailed; \n "
" \n "
" if (! hasFailed) { \n "
" doStuff(&s); \n "
" if (hasFailed) {} \n "
" } \n "
" } " ) ;
2020-02-13 16:27:06 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (style) Condition '!hasFailed' is always true \n " , errout . str ( ) ) ;
2017-09-04 09:34:03 +02:00
}
2017-08-31 22:53:21 +02:00
void oppositeInnerCondition2 ( ) {
// first comparison: <
check ( " void f(int x) { \n "
" \n "
" if (x<4) { \n "
" if (x==5) {} \n " // <- Warning
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " ,
errout . str ( ) ) ;
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x<4) { \n "
2019-09-20 15:06:37 +02:00
" if (x!=5) {} \n "
2017-08-31 22:53:21 +02:00
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
2019-09-20 15:06:37 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (style) Condition 'x!=5' is always true \n " , errout . str ( ) ) ;
2019-01-09 20:41:01 +01:00
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x<4) { \n "
" if (x>5) {} \n " // <- Warning
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " ,
errout . str ( ) ) ;
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x<4) { \n "
" if (x>=5) {} \n " // <- Warning
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " ,
errout . str ( ) ) ;
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x<4) { \n "
" if (x<5) {} \n "
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (style) Condition 'x<5' is always true \n " , errout . str ( ) ) ;
2019-01-09 20:41:01 +01:00
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x<4) { \n "
" if (x<=5) {} \n "
" } \n "
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (style) Condition 'x<=5' is always true \n " , errout . str ( ) ) ;
2017-08-31 22:53:21 +02:00
check ( " void f(int x) { \n "
" \n "
" if (x<5) { \n "
" if (x==4) {} \n "
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x<5) { \n "
" if (x!=4) {} \n "
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x<5) { \n "
2019-12-26 15:47:53 +01:00
" if (x!=6) {} \n "
2017-08-31 22:53:21 +02:00
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (style) Condition 'x!=6' is always true \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" \n "
" if (x<5) { \n "
" if (x>4) {} \n " // <- Warning
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (style) Condition 'x>4' is always false \n " , errout . str ( ) ) ;
2019-01-09 20:41:01 +01:00
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x<5) { \n "
" if (x>=4) {} \n "
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x<5) { \n "
" if (x<4) {} \n "
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x<5) { \n "
" if (x<=4) {} \n "
" } \n "
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (style) Condition 'x<=4' is always true \n " , errout . str ( ) ) ;
2017-08-31 22:53:21 +02:00
// first comparison: >
check ( " void f(int x) { \n "
" \n "
" if (x>4) { \n "
" if (x==5) {} \n "
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x>4) { \n "
" if (x>5) {} \n "
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x>4) { \n "
2019-12-26 15:47:53 +01:00
" if (x>=5) {} \n " // <- Warning
2017-08-31 22:53:21 +02:00
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (style) Condition 'x>=5' is always true \n " , errout . str ( ) ) ;
2019-01-09 20:41:01 +01:00
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x>4) { \n "
2019-12-26 15:47:53 +01:00
" if (x<5) {} \n " // <- Warning
2017-08-31 22:53:21 +02:00
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (style) Condition 'x<5' is always false \n " , errout . str ( ) ) ;
2019-01-09 20:41:01 +01:00
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x>4) { \n "
" if (x<=5) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" \n "
" if (x>5) { \n "
" if (x==4) {} \n " // <- Warning
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " ,
errout . str ( ) ) ;
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x>5) { \n "
2019-12-26 15:47:53 +01:00
" if (x>4) {} \n " // <- Warning
2017-08-31 22:53:21 +02:00
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (style) Condition 'x>4' is always true \n " , errout . str ( ) ) ;
2019-01-09 20:41:01 +01:00
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x>5) { \n "
2019-12-26 15:47:53 +01:00
" if (x>=4) {} \n " // <- Warning
2017-08-31 22:53:21 +02:00
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (style) Condition 'x>=4' is always true \n " , errout . str ( ) ) ;
2019-01-09 20:41:01 +01:00
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x>5) { \n "
" if (x<4) {} \n " // <- Warning
" } \n "
2019-01-09 20:41:01 +01:00
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " ,
errout . str ( ) ) ;
check ( " void f(int x) { \n "
2017-08-31 22:53:21 +02:00
" \n "
" if (x>5) { \n "
" if (x<=4) {} \n " // <- Warning
" } \n "
" } " ) ;
2019-01-09 20:41:01 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " ,
errout . str ( ) ) ;
2017-09-22 14:01:20 +02:00
check ( " void f(int x) { \n "
" if (x < 4) { \n "
" if (10 < x) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2017-08-31 22:53:21 +02:00
}
2018-03-24 07:58:37 +01:00
void oppositeInnerCondition3 ( ) {
2021-02-20 12:58:42 +01:00
check ( " void f3(char c) { if(c=='x') if(c=='y') {}} " ) ;
2018-11-07 06:49:07 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2018-03-24 07:58:37 +01:00
2021-02-20 12:58:42 +01:00
check ( " void f4(char *p) { if(*p=='x') if(*p=='y') {}} " ) ;
2018-03-24 07:58:37 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void f5(const char * const p) { if(*p=='x') if(*p=='y') {}} " ) ;
2018-03-24 07:58:37 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void f5(const char * const p) { if('x'==*p) if('y'==*p) {}} " ) ;
2018-03-24 07:58:37 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void f6(char * const p) { if(*p=='x') if(*p=='y') {}} " ) ;
2018-03-24 07:58:37 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void f7(const char * p) { if(*p=='x') if(*p=='y') {}} " ) ;
2018-03-24 07:58:37 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void f8(int i) { if(i==4) if(i==2) {}} " ) ;
2018-11-07 06:49:07 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2018-03-24 07:58:37 +01:00
2021-02-20 12:58:42 +01:00
check ( " void f9(int *p) { if (*p==4) if(*p==2) {}} " ) ;
2018-03-24 07:58:37 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void f10(int * const p) { if (*p==4) if(*p==2) {}} " ) ;
2018-03-24 07:58:37 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void f11(const int *p) { if (*p==4) if(*p==2) {}} " ) ;
2018-03-24 07:58:37 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
check ( " void f12(const int * const p) { if (*p==4) if(*p==2) {}} " ) ;
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
check ( " struct foo { \n "
" int a; \n "
" int b; \n "
" }; \n "
2021-02-20 12:58:42 +01:00
" void f(foo x) { if(x.a==4) if(x.b==2) {}} " ) ;
2018-03-24 07:58:37 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct foo { \n "
" int a; \n "
" int b; \n "
" }; \n "
2021-02-20 12:58:42 +01:00
" void f(foo x) { if(x.a==4) if(x.b==4) {}} " ) ;
2018-03-24 07:58:37 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void f3(char a, char b) { if(a==b) if(a==0) {}} " ) ;
2018-03-24 07:58:37 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { if (x == 1) if (x != 1) {} } " ) ;
2018-11-07 06:49:07 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2018-03-24 07:58:37 +01:00
}
2017-09-01 23:24:15 +02:00
void oppositeInnerConditionAnd ( ) {
check ( " void f(int x) { \n "
" if (a>3 && x > 100) { \n "
" if (x < 10) {} \n "
" } "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2020-09-07 07:53:41 +02:00
check ( " void f(bool x, const int a, const int b) { \n "
" if(x && a < b) \n "
" if( x && a > b){} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2022-09-08 22:08:38 +02:00
}
void oppositeInnerConditionOr ( )
{
check ( " void f(int x) { \n "
" if (x == 1 || x == 2) { \n "
" if (x == 3) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " ,
errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x == 1 || x == 2) { \n "
" if (x == 1) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x == 1 || x == 2) { \n "
" if (x == 2) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(std::string x) { \n "
" if (x == \" 1 \" || x == \" 2 \" ) { \n "
" if (x == \" 1 \" ) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x < 1 || x > 3) { \n "
" if (x == 3) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " ,
errout . str ( ) ) ;
2017-09-01 23:24:15 +02:00
}
2018-03-24 07:58:37 +01:00
void oppositeInnerConditionEmpty ( ) {
2021-02-20 12:58:42 +01:00
check ( " void f1(const std::string &s) { if(s.size() > 42) if(s.empty()) {}} " ) ;
2018-03-24 07:58:37 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void f1(const std::string &s) { if(s.size() > 0) if(s.empty()) {}} " ) ;
2018-05-11 10:22:06 +02:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2021-06-25 16:25:14 +02:00
check ( " void f1(const std::string &s) { if(s.size() < 0) if(s.empty()) {}} " ) ; // <- CheckOther reports: checking if unsigned expression is less than zero
2023-02-23 18:05:31 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (style) Condition 's.empty()' is always false \n " , errout . str ( ) ) ;
2018-05-11 10:22:06 +02:00
2021-02-20 12:58:42 +01:00
check ( " void f1(const std::string &s) { if(s.empty()) if(s.size() > 42) {}} " ) ;
2018-03-24 07:58:37 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " template<class T> void f1(const T &s) { if(s.size() > 42) if(s.empty()) {}} " ) ;
2020-09-03 18:44:44 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ; //We don't know the type of T so we don't know the relationship between size() and empty(). e.g. s might be a 50 tonne truck with nothing in it.
2019-05-16 21:11:04 +02:00
2021-02-20 12:58:42 +01:00
check ( " void f2(const std::wstring &s) { if(s.empty()) if(s.size() > 42) {}} " ) ;
2018-03-24 07:58:37 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void f1(QString s) { if(s.isEmpty()) if(s.length() > 42) {}} " ) ;
2018-11-07 06:49:07 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Opposite inner 'if' condition leads to a dead code block. \n " , errout . str ( ) ) ;
2018-03-24 07:58:37 +01:00
2021-02-20 12:58:42 +01:00
check ( " void f1(const std::string &s, bool b) { if(s.empty() || ((s.size() == 1) && b)) {}} " ) ;
2018-03-24 07:58:37 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-04-05 06:43:13 +02:00
2021-02-20 12:58:42 +01:00
check ( " void f1(const std::string &x, const std::string &y) { if(x.size() > 42) if(y.empty()) {}} " ) ;
2018-04-05 06:43:13 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void f1(const std::string &x, const std::string &y) { if(y.empty()) if(x.size() > 42) {}} " ) ;
2018-04-05 06:43:13 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void f1(const std::string v[10]) { if(v[0].size() > 42) if(v[1].empty()) {}} " ) ;
2018-04-05 06:43:13 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-05-11 10:22:06 +02:00
2021-02-20 12:58:42 +01:00
check ( " void f1(const std::string &s) { if(s.size() <= 1) if(s.empty()) {}} " ) ;
2018-05-11 10:22:06 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void f1(const std::string &s) { if(s.size() <= 2) if(s.empty()) {}} " ) ;
2018-05-11 10:22:06 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void f1(const std::string &s) { if(s.size() < 2) if(s.empty()) {}} " ) ;
2018-05-11 10:22:06 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-06-25 16:25:14 +02:00
check ( " void f1(const std::string &s) { if(s.size() >= 0) if(s.empty()) {}} " ) ; // CheckOther says: Unsigned expression 's.size()' can't be negative so it is unnecessary to test it. [unsignedPositive]
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-05-11 10:22:06 +02:00
// TODO: These are identical condition since size cannot be negative
2021-02-20 12:58:42 +01:00
check ( " void f1(const std::string &s) { if(s.size() <= 0) if(s.empty()) {}} " ) ;
2018-05-11 10:22:06 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// TODO: These are identical condition since size cannot be negative
2021-02-20 12:58:42 +01:00
check ( " void f1(const std::string &s) { if(s.size() < 1) if(s.empty()) {}} " ) ;
2018-05-11 10:22:06 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-10-07 18:30:29 +02:00
}
void oppositeInnerConditionFollowVar ( ) {
check ( " struct X { \n "
" void f() { \n "
" const int flag = get(); \n "
" if (flag) { \n "
" bar(); \n "
" if (!get()) {} \n "
" } \n "
" } \n "
" void bar(); \n "
" int get() const; \n "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-10-24 20:17:00 +02:00
2021-04-19 09:15:03 +02:00
check ( " struct CD { \n "
" bool state; \n "
" void foo() { \n "
" const bool flag = this->get(); \n "
" if (flag) { \n "
" this->bar(); \n "
" if (!this->get()) return; \n "
" } \n "
" } \n "
" bool get() const; \n "
" void bar(); \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-10-24 20:17:00 +02:00
check ( " class C { \n "
" public: \n "
" bool f() const { return x > 0; } \n "
" void g(); \n "
" int x = 0; \n "
" }; \n "
" \n "
" void C::g() { \n "
" bool b = f(); \n "
" x += 1; \n "
" if (!b && f()) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-04-07 10:42:57 +02:00
check ( " void f(double d) { \n "
" if (d != 0) { \n "
" int i = d; \n "
" if (i == 0) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-03-24 07:58:37 +01:00
}
2018-04-08 09:25:59 +02:00
2018-04-08 08:13:44 +02:00
void identicalInnerCondition ( ) {
check ( " void f1(int a, int b) { if(a==b) if(a==b) {}} " ) ;
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Identical inner 'if' condition is always true. \n " , errout . str ( ) ) ;
check ( " void f2(int a, int b) { if(a!=b) if(a!=b) {}} " ) ;
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (warning) Identical inner 'if' condition is always true. \n " , errout . str ( ) ) ;
2018-07-03 08:25:37 +02:00
// #6645 false negative: condition is always false
check ( " void f(bool a, bool b) { \n "
" if(a && b) { \n "
" if(a) {} \n "
" else {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-07-03 08:25:37 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Identical inner 'if' condition is always true. \n " , errout . str ( ) ) ;
2018-09-07 20:16:38 +02:00
2018-10-31 09:47:48 +01:00
check ( " bool f(int a, int b) { \n "
" if(a == b) { return a == b; } \n "
" return false; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-10-31 09:47:48 +01:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:2]: (warning) Identical inner 'return' condition is always true. \n " , errout . str ( ) ) ;
2018-10-18 21:01:47 +02:00
check ( " bool f(bool a) { \n "
" if(a) { return a; } \n "
" return false; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-10-31 09:47:48 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-10-18 21:01:47 +02:00
check ( " int* f(int* a, int * b) { \n "
" if(a) { return a; } \n "
" return b; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-10-18 21:01:47 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-10-31 09:47:48 +01:00
check ( " int* f(std::shared_ptr<int> a, std::shared_ptr<int> b) { \n "
" if(a.get()) { return a.get(); } \n "
" return b.get(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-10-31 09:47:48 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-10-18 21:01:47 +02:00
check ( " struct A { int * x; }; \n "
" int* f(A a, int * b) { \n "
" if(a.x) { return a.x; } \n "
" return b; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-10-18 21:01:47 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-09-07 20:16:38 +02:00
check ( " void f() { \n "
" uint32_t value; \n "
" get_value(&value); \n "
" int opt_function_capable = (value >> 28) & 1; \n "
" if (opt_function_capable) { \n "
" value = 0; \n "
" get_value (&value); \n "
" if ((value >> 28) & 1) {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-09-07 20:16:38 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-04-08 08:13:44 +02:00
}
2018-03-24 07:58:37 +01:00
2017-09-10 22:59:39 +02:00
void identicalConditionAfterEarlyExit ( ) {
2021-08-25 21:14:19 +02:00
check ( " void f(int x) { \n " // #8137
2017-09-03 10:34:34 +02:00
" if (x > 100) { return; } \n "
" if (x > 100) {} \n "
" } " ) ;
2017-09-08 12:41:33 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Identical condition 'x>100', second condition is always false \n " , errout . str ( ) ) ;
2017-09-04 22:40:34 +02:00
2018-10-18 21:01:47 +02:00
check ( " bool f(int x) { \n "
" if (x > 100) { return false; } \n "
" return x > 100; \n "
" } " ) ;
2019-11-16 17:24:54 +01:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Identical condition and return expression 'x>100', return value is always false \n " , errout . str ( ) ) ;
2018-10-18 21:01:47 +02:00
2017-09-04 22:40:34 +02:00
check ( " void f(int x) { \n "
" if (x > 100) { return; } \n "
" if (x > 100 || y > 100) {} \n "
" } " ) ;
2017-09-08 12:41:33 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Identical condition 'x>100', second condition is always false \n " , errout . str ( ) ) ;
2017-09-03 10:44:22 +02:00
2017-09-05 22:45:28 +02:00
check ( " void f(int x) { \n "
" if (x > 100) { return; } \n "
" if (x > 100 && y > 100) {} \n "
" } " ) ;
2017-09-08 12:41:33 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Identical condition 'x>100', second condition is always false \n " , errout . str ( ) ) ;
2017-09-05 22:45:28 +02:00
2017-09-03 10:44:22 +02:00
check ( " void f(int x) { \n "
" if (x > 100) { return; } \n "
" if (abc) {} \n "
" if (x > 100) {} \n "
" } " ) ;
2019-06-22 21:57:19 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (warning) Identical condition 'x>100', second condition is always false \n " , errout . str ( ) ) ;
2017-09-03 11:03:01 +02:00
check ( " void f(int x) { \n "
" if (x > 100) { return; } \n "
" while (abc) { y = x; } \n "
" if (x > 100) {} \n "
" } " ) ;
2019-06-22 21:57:19 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (warning) Identical condition 'x>100', second condition is always false \n " , errout . str ( ) ) ;
2017-09-04 22:40:34 +02:00
2017-09-14 15:45:15 +02:00
check ( " void f(int x) { \n " // #8217 - crash for incomplete code
" if (x > 100) { return; } \n "
" X(do); \n "
" if (x > 100) {} \n "
" } " ) ;
2019-01-06 17:15:57 +01:00
// TODO: we should probably throw unknownMacro InternalError. Complain that the macro X must be defined. We can't check the code well without the definition.
2019-08-05 07:18:06 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (style) Condition 'x>100' is always false \n " , errout . str ( ) ) ;
2017-09-14 15:45:15 +02:00
2017-09-04 22:40:34 +02:00
check ( " void f(const int *i) { \n "
" if (!i) return; \n "
" if (!num1tok) { *num1 = *num2; } \n "
" if (!i) {} \n "
" } " ) ;
2019-06-22 21:57:19 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (warning) Identical condition '!i', second condition is always false \n " , errout . str ( ) ) ;
2017-09-06 22:26:00 +02:00
2017-09-07 22:05:01 +02:00
check ( " void C::f(Tree &coreTree) { \n " // daca
2017-09-06 22:26:00 +02:00
" if(!coreTree.build()) \n "
" return; \n "
" coreTree.dostuff(); \n "
" if(!coreTree.build()) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2017-09-06 22:26:00 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-09-06 22:53:36 +02:00
check ( " struct C { void f(const Tree &coreTree); }; \n "
" void C::f(const Tree &coreTree) { \n "
2017-09-06 22:26:00 +02:00
" if(!coreTree.build()) \n "
" return; \n "
" coreTree.dostuff(); \n "
" if(!coreTree.build()) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-06-22 21:57:19 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:6]: (warning) Identical condition '!coreTree.build()', second condition is always false \n " , errout . str ( ) ) ;
2017-09-07 22:05:01 +02:00
check ( " void f(int x) { \n " // daca: labplot
" switch(type) { \n "
" case 1: \n "
" if (x == 0) return 1; \n "
" else return 2; \n "
" case 2: \n "
" if (x == 0) return 3; \n "
" else return 4; \n "
" } \n "
" return 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-09-08 15:44:56 +02:00
check ( " static int failed = 0; \n "
" void f() { \n "
" if (failed) return; \n "
" checkBuffer(); \n "
" if (failed) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-09-10 22:58:05 +02:00
// daca icu
check ( " void f(const uint32_t *section, int32_t start) { \n "
" if(10<=section[start]) { return; } \n "
" if(++start<100 && 10<=section[start]) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-09-13 22:46:36 +02:00
// daca iqtree
check ( " void readNCBITree(std::istream &in) { \n "
" char ch; \n "
" in >> ch; \n "
" if (ch != '|') return; \n "
" in >> ch; \n "
" if (ch != '|') {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2017-09-13 22:46:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-08-05 07:18:06 +02:00
// #8924
check ( " struct A { \n "
" void f() { \n "
" if (this->FileIndex >= 0) return; \n "
" this->FileIndex = 1 ; \n "
" if (this->FileIndex < 0) return; \n "
" } \n "
2021-02-20 12:58:42 +01:00
" int FileIndex; \n "
" }; " ) ;
2022-04-28 10:48:37 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (style) Condition 'this->FileIndex<0' is always false \n " , errout . str ( ) ) ;
2020-07-01 07:48:32 +02:00
// #8858 - #if
check ( " short Do() { \n "
" short ret = bar1(); \n "
" if ( ret ) \n "
" return ret; \n "
" #ifdef FEATURE \n "
" ret = bar2(); \n "
" #endif \n "
" return ret; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-09-04 19:05:41 +02:00
// #10456
check ( " int f() { \n "
" int i = 0; \n "
" auto f = [&](bool b) { if (b) ++i; }; \n "
" if (i) return i; \n "
" f(true); \n "
" if (i) return i; \n "
" return 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2023-01-07 22:10:07 +01:00
// #11478
check ( " struct S { \n "
" void run(); \n "
" bool b = false; \n "
" const std::function<void(S&)> f; \n "
" }; \n "
" void S::run() { \n "
" while (true) { \n "
" if (b) \n "
" return; \n "
" f(*this); \n "
" if (b) \n "
" return; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-09-03 10:34:34 +02:00
}
2018-04-28 18:56:13 +02:00
void innerConditionModified ( ) {
check ( " void f(int x, int y) { \n "
" if (x == 0) { \n "
" x += y; \n "
" if (x == 0) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x == 0) { \n "
" x += y; \n "
" if (x == 1) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int * x, int * y) { \n "
" if (x[*y] == 0) { \n "
" (*y)++; \n "
" if (x[*y] == 0) {} \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2015-07-16 08:44:38 +02:00
// clarify conditions with = and comparison
2014-11-20 14:20:09 +01:00
void clarifyCondition1 ( ) {
2014-08-29 17:06:46 +02:00
check ( " void f() { \n "
" if (x = b() < 0) {} \n " // don't simplify and verify this code
2015-07-25 14:17:55 +02:00
" } " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Suspicious condition (assignment + comparison); Clarify expression with parentheses. \n " , errout . str ( ) ) ;
check ( " void f(int i) { \n "
" for (i = 0; i < 10; i++) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" x = a<int>(); if (x) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-02-05 20:17:30 +01:00
check ( " void f() { \n "
" if (x = b < 0 ? 1 : 2) {} \n " // don't simplify and verify this code
2015-07-25 14:17:55 +02:00
" } " ) ;
2015-02-05 20:17:30 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-06-10 18:53:55 +02:00
check ( " void f() { \n "
" int y = rand(), z = rand(); \n "
" if (y || (!y && z)); \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2015-08-05 11:15:54 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Redundant condition: !y. 'y || (!y && z)' is equivalent to 'y || z' \n " , errout . str ( ) ) ;
2015-06-10 18:53:55 +02:00
check ( " void f() { \n "
" int y = rand(), z = rand(); \n "
" if (y || !y && z); \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2015-08-05 11:15:54 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Redundant condition: !y. 'y || (!y && z)' is equivalent to 'y || z' \n " , errout . str ( ) ) ;
2015-06-10 18:53:55 +02:00
check ( " void f() { \n "
" if (!a || a && b) {} \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2015-08-05 11:15:54 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: a. '!a || (a && b)' is equivalent to '!a || b' \n " , errout . str ( ) ) ;
2015-06-10 18:53:55 +02:00
2018-07-08 15:58:04 +02:00
check ( " void f(const Token *tok) { \n "
2021-02-20 12:58:42 +01:00
" if (!tok->next()->function() || \n "
2015-06-10 18:53:55 +02:00
" (tok->next()->function() && tok->next()->function()->isConstructor())); \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2017-04-30 14:22:18 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: tok->next()->function(). '!A || (A && B)' is equivalent to '!A || B' \n " , errout . str ( ) ) ;
2015-06-10 18:53:55 +02:00
check ( " void f() { \n "
2021-02-20 12:58:42 +01:00
" if (!tok->next()->function() || \n "
2015-06-10 18:53:55 +02:00
" (!tok->next()->function() && tok->next()->function()->isConstructor())); \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2015-06-10 18:53:55 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
2021-02-20 12:58:42 +01:00
" if (!tok->next()->function() || \n "
2015-06-10 18:53:55 +02:00
" (!tok2->next()->function() && tok->next()->function()->isConstructor())); \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2015-06-10 18:53:55 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-07-08 15:58:04 +02:00
check ( " void f(const Token *tok) { \n "
2021-02-20 12:58:42 +01:00
" if (!tok->next(1)->function(1) || \n "
2015-06-10 18:53:55 +02:00
" (tok->next(1)->function(1) && tok->next(1)->function(1)->isConstructor())); \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2017-04-30 14:22:18 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: tok->next(1)->function(1). '!A || (A && B)' is equivalent to '!A || B' \n " , errout . str ( ) ) ;
2015-06-10 18:53:55 +02:00
check ( " void f() { \n "
2021-02-20 12:58:42 +01:00
" if (!tok->next()->function(1) || \n "
2015-06-10 18:53:55 +02:00
" (tok->next()->function(2) && tok->next()->function()->isConstructor())); \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2015-06-10 18:53:55 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int y = rand(), z = rand(); \n "
" if (y==0 || y!=0 && z); \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2015-08-05 11:15:54 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Redundant condition: y!=0. 'y==0 || (y!=0 && z)' is equivalent to 'y==0 || z' \n " , errout . str ( ) ) ;
2015-06-19 19:49:05 +02:00
check ( " void f() { \n "
" if (x>0 || (x<0 && y)) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-08-12 10:55:25 +02:00
// Test Token::expressionString, TODO move this test
check ( " void f() { \n "
" if (!dead || (dead && (*it).ticks > 0)) {} \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: dead. '!dead || (dead && (*it).ticks>0)' is equivalent to '!dead || (*it).ticks>0' \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" if (!x || (x && (2>(y-1)))) {} \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: x. '!x || (x && 2>(y-1))' is equivalent to '!x || 2>(y-1)' \n " , errout . str ( ) ) ;
2020-04-07 07:15:15 +02:00
check ( " void f(bool a, bool b) { \n "
" if (a || (a && b)) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-04-07 07:15:15 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: a. 'a || (a && b)' is equivalent to 'a' \n " , errout . str ( ) ) ;
check ( " void f(bool a, bool b) { \n "
" if (a && (a || b)) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-04-07 07:15:15 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Redundant condition: a. 'a && (a || b)' is equivalent to 'a' \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
}
2016-08-29 04:26:27 +02:00
// clarify conditions with bitwise operator and comparison
2014-11-20 14:20:09 +01:00
void clarifyCondition2 ( ) {
2014-08-29 17:06:46 +02:00
check ( " void f() { \n "
" if (x & 3 == 2) {} \n "
" } " ) ;
2016-10-08 01:57:09 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Suspicious condition (bitwise operator + comparison); Clarify expression with parentheses. \n "
2018-04-17 22:14:17 +02:00
" [test.cpp:2]: (style) Boolean result is used in bitwise operation. Clarify expression with parentheses. \n "
2019-10-31 08:32:39 +01:00
" [test.cpp:2]: (style) Condition 'x&3==2' is always false \n " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f() { \n "
" if (a & fred1.x == fred2.y) {} \n "
" } " ) ;
2018-04-17 22:14:17 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Suspicious condition (bitwise operator + comparison); Clarify expression with parentheses. \n "
" [test.cpp:2]: (style) Boolean result is used in bitwise operation. Clarify expression with parentheses. \n "
, errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
}
2016-07-29 17:24:22 +02:00
// clarify condition that uses ! operator and then bitwise operator
2014-11-20 14:20:09 +01:00
void clarifyCondition3 ( ) {
2014-08-29 17:06:46 +02:00
check ( " void f(int w) { \n "
" if(!w & 0x8000) {} \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Boolean result is used in bitwise operation. Clarify expression with parentheses. \n " , errout . str ( ) ) ;
2016-07-29 18:46:43 +02:00
check ( " void f(int w) { \n "
" if((!w) & 0x8000) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f() { \n "
" if (x == foo() & 2) {} \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Boolean result is used in bitwise operation. Clarify expression with parentheses. \n " , errout . str ( ) ) ;
2016-07-29 18:46:43 +02:00
check ( " void f() { \n "
" if (2 & x == foo()) {} \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Boolean result is used in bitwise operation. Clarify expression with parentheses. \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" if (2 & (x == foo())) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
check ( " void f(std::list<int> &ints) { } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { A<x &> a; } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-07-25 14:17:55 +02:00
check ( " void f() { a(x<y|z,0); } " , " test.c " ) ; // filename is c => there are never templates
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " [test.c:1]: (style) Boolean result is used in bitwise operation. Clarify expression with parentheses. \n " , errout . str ( ) ) ;
2015-07-25 14:17:55 +02:00
check ( " class A<B&,C>; " , " test.cpp " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" if (result != (char *)&inline_result) { } \n " // don't simplify and verify cast
2015-07-25 14:17:55 +02:00
" } " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-04-17 22:14:17 +02:00
// #8495
check ( " void f(bool a, bool b) { \n "
" C & a & b; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-08-29 17:06:46 +02:00
}
2014-11-20 14:20:09 +01:00
void clarifyCondition4 ( ) { // ticket #3110
2014-08-29 17:06:46 +02:00
check ( " typedef double SomeType; \n "
" typedef std::pair<std::string,SomeType> PairType; \n "
" struct S \n "
" { \n "
" bool operator() \n "
" ( PairType const & left \n "
" , PairType const & right) const \n "
" { \n "
" return left.first < right.first; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void clarifyCondition5 ( ) { // ticket #3609 (using | in template instantiation)
2018-09-08 21:10:34 +02:00
check ( " template<bool B> struct CWinTraits; \n "
" CWinTraits<WS_CHILD|WS_VISIBLE>::GetWndStyle(0); " ) ;
2014-08-29 17:06:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void clarifyCondition6 ( ) {
2014-08-29 17:06:46 +02:00
check ( " template<class Y> \n "
" SharedPtr& operator=( SharedPtr<Y> const & r ) { \n "
" px = r.px; \n "
" return *this; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2015-06-13 18:08:13 +02:00
2016-05-06 17:39:41 +02:00
void clarifyCondition7 ( ) {
// Ensure that binary and unary &, and & in declarations are distinguished properly
check ( " void f(bool error) { \n "
" bool & withoutSideEffects=found.first->second; \n " // Declaring a reference to a boolean; & is no operator at all
" execute(secondExpression, &programMemory, &result, &error); \n " // Unary &
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2016-07-29 17:24:22 +02:00
void clarifyCondition8 ( ) {
// don't warn when boolean result comes from function call, array index, etc
// the operator precedence is not unknown then
check ( " bool a(); \n "
" bool f(bool b) { \n "
" return (a() & b); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool f(bool *a, bool b) { \n "
" return (a[10] & b); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { bool a; }; \n "
" bool f(struct A a, bool b) { \n "
" return (a.a & b); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { bool a; }; \n "
" bool f(struct A a, bool b) { \n "
" return (A::a & b); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2015-06-13 18:08:13 +02:00
void testBug5895 ( ) {
check ( " void png_parse(uint64_t init, int buf_size) { \n "
" if (init == 0x89504e470d0a1a0a || init == 0x8a4d4e470d0a1a0a) \n "
" ; \n "
" } " ) ;
2015-07-01 07:50:13 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-06-13 18:08:13 +02:00
}
2015-06-20 12:18:24 +02:00
void testBug5309 ( ) {
check ( " extern uint64_t value; \n "
" void foo() { \n "
" if( ( value >= 0x7ff0000000000001ULL ) \n "
" && ( value <= 0x7fffffffffffffffULL ) ); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2015-07-17 15:30:23 +02:00
void alwaysTrue ( ) {
2021-08-01 12:32:01 +02:00
2021-08-05 08:07:03 +02:00
check ( " void f(const struct S *s) { \n " //#8196
" int x1 = s->x; \n "
" int x2 = s->x; \n "
" if (x1 == 10 && x2 == 10) {} \n " // <<
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:4]: (style) Condition 'x2==10' is always true \n " , errout . str ( ) ) ;
2021-08-01 12:32:01 +02:00
check ( " void f () \n " // #8220
" { \n "
" int a; \n "
" int b = 0; \n "
" int ret; \n "
" \n "
" a = rand(); \n "
" while (((0 < a) && (a < 2)) && ((8 < a) && (a < 10))) \n "
" { \n "
" b += a; \n "
" a ++; \n "
" } \n "
" ret = b; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:8] -> [test.cpp:8]: (style) Condition '8<a' is always false \n " , errout . str ( ) ) ;
2015-07-17 15:30:23 +02:00
check ( " void f() { \n " // #4842
" int x = 0; \n "
" if (a) { return; } \n " // <- this is just here to fool simplifyKnownVariabels
" if (!x) {} \n "
" } " ) ;
2015-07-30 16:13:10 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Condition '!x' is always true \n " , errout . str ( ) ) ;
2015-07-29 12:51:00 +02:00
2019-11-03 08:45:07 +01:00
check ( " bool f(int x) { \n "
2021-02-20 12:58:42 +01:00
" if(x == 0) { x++; return x == 0; } \n "
2019-11-03 08:45:07 +01:00
" return false; \n "
" } " ) ;
2022-10-10 13:45:30 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:2]: (style) Return value 'x==0' is always false \n " , errout . str ( ) ) ;
2019-11-03 08:45:07 +01:00
check ( " void f() { \n " // #6898 (Token::expressionString)
" int x = 0; \n "
" A(x++ == 1); \n "
" A(x++ == 2); \n "
" } " ) ;
2023-08-20 22:32:41 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition 'x++==1' is always false \n "
" [test.cpp:4]: (style) Condition 'x++==2' is always false \n " ,
errout . str ( ) ) ;
2019-11-03 08:45:07 +01:00
2019-11-03 08:49:39 +01:00
check ( " bool foo(int bar) { \n "
" bool ret = false; \n "
" if (bar == 1) \n "
" return ret; \n " // <- #9326 - FP condition is always false
" if (bar == 2) \n "
" ret = true; \n "
" return ret; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void f1(const std::string &s) { if(s.empty()) if(s.size() == 0) {}} " ) ;
2018-11-27 06:39:29 +01:00
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (style) Condition 's.size()==0' is always true \n " , errout . str ( ) ) ;
2018-12-17 06:07:34 +01:00
check ( " void f() { \n "
" int buf[42]; \n "
" if( buf != 0) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-21 20:05:35 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition 'buf!=0' is always true \n " , errout . str ( ) ) ; // #8924
check ( " void f() { \n "
" int buf[42]; \n "
" if( !buf ) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-21 20:05:35 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition '!buf' is always false \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" int buf[42]; \n "
" bool b = buf; \n "
" if( b ) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-21 20:05:35 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Condition 'b' is always true \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" int buf[42]; \n "
" bool b = buf; \n "
" if( !b ) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-21 20:05:35 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Condition '!b' is always false \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" int buf[42]; \n "
" int * p = nullptr; \n "
" if( buf == p ) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-21 20:05:35 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Condition 'buf==p' is always false \n " , errout . str ( ) ) ;
check ( " void f(bool x) { \n "
" int buf[42]; \n "
" if( buf || x ) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-21 20:05:35 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition 'buf' is always true \n " , errout . str ( ) ) ;
check ( " void f(int * p) { \n "
" int buf[42]; \n "
" if( buf == p ) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-21 20:05:35 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int buf[42]; \n "
" int p[42]; \n "
" if( buf == p ) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-21 20:05:35 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int buf[42]; \n "
" if( buf == 1) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-21 20:05:35 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-12-17 06:07:34 +01:00
2015-07-29 12:51:00 +02:00
// Avoid FP when condition comes from macro
2017-05-18 21:52:31 +02:00
check ( " #define NOT ! \n "
" void f() { \n "
2015-07-29 12:51:00 +02:00
" int x = 0; \n "
" if (a) { return; } \n " // <- this is just here to fool simplifyKnownVariabels
2017-05-18 21:52:31 +02:00
" if (NOT x) {} \n "
2015-07-29 12:51:00 +02:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-07-30 13:30:16 +02:00
2017-05-18 21:52:31 +02:00
check ( " #define M x != 0 \n "
" void f() { \n "
2015-07-30 13:30:16 +02:00
" int x = 0; \n "
" if (a) { return; } \n " // <- this is just here to fool simplifyKnownVariabels
2017-05-18 21:52:31 +02:00
" if (M) {} \n "
2015-07-30 13:30:16 +02:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-02-06 14:37:44 +01:00
2017-05-18 21:52:31 +02:00
check ( " #define IF(X) if (X && x()) \n "
" void f() { \n "
" IF(1) {} \n "
2017-03-03 19:53:16 +01:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-05-13 19:07:24 +02:00
// Avoid FP for sizeof condition
check ( " void f() { \n "
" if (sizeof(char) != 123) {} \n "
2020-07-10 23:33:43 +02:00
" if (123 != sizeof(char)) {} \n "
2017-05-13 19:07:24 +02:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int x = 123; \n "
" if (sizeof(char) != x) {} \n "
2020-07-10 23:33:43 +02:00
" if (x != sizeof(char)) {} \n "
2017-05-13 19:07:24 +02:00
" } " ) ;
2020-11-11 08:01:11 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition 'sizeof(char)!=x' is always true \n "
" [test.cpp:4]: (style) Condition 'x!=sizeof(char)' is always true \n " , " " , errout . str ( ) ) ;
2017-05-13 19:07:24 +02:00
2016-02-06 14:37:44 +01:00
// Don't warn in assertions. Condition is often 'always true' by intention.
// If platform,defines,etc cause an 'always false' assertion then that is not very dangerous neither
check ( " void f() { \n "
" int x = 0; \n "
" assert(x == 0); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-10-08 01:57:09 +02:00
2019-10-31 08:32:39 +01:00
// #9363 - do not warn about value passed to function
check ( " void f(bool b) { \n "
" if (b) { \n "
" if (bar(!b)) {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-10-31 08:32:39 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-11-23 19:59:00 +01:00
// #7783 FP knownConditionTrueFalse on assert(0 && "message")
check ( " void foo(int x) { \n "
" if (x<0) \n "
" { \n "
" assert(0 && \" bla \" ); \n "
" ASSERT(0 && \" bla \" ); \n "
" assert_foo(0 && \" bla \" ); \n "
" ASSERT_FOO(0 && \" bla \" ); \n "
" assert((int)(0==0)); \n "
" assert((int)(0==0) && \" bla \" ); \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2016-11-23 19:59:00 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-07-21 18:40:06 +02:00
// #7750 char literals in boolean expressions
2016-10-08 01:57:09 +02:00
check ( " void f() { \n "
" if('a'){} \n "
" if(L'b'){} \n "
" if(1 && 'c'){} \n "
" int x = 'd' ? 1 : 2; \n "
" } " ) ;
2018-07-21 18:40:06 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-07-12 23:06:47 +02:00
2021-04-09 08:53:01 +02:00
// #8206 - knownCondition always false
check ( " void f(int i) \n "
2021-04-09 08:53:32 +02:00
" { \n "
" if(i > 4) \n "
" for( int x = 0; i < 3; ++x){} \n " // <<
" } " ) ;
2021-04-09 08:53:01 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (style) Condition 'i<3' is always false \n " , errout . str ( ) ) ;
2018-07-12 23:06:47 +02:00
// Skip literals
check ( " void f() { if(true) {} } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { if(false) {} } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { if(!true) {} } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { if(!false) {} } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { if(0) {} } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { if(1) {} } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-08-10 18:05:23 +02:00
check ( " void f(int i) { \n "
" bool b = false; \n "
" if (i == 0) b = true; \n "
" else if (!b && i == 1) {} \n "
" if (b) \n "
" {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-08-10 18:05:23 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Condition '!b' is always true \n " , errout . str ( ) ) ;
2018-10-18 21:01:47 +02:00
check ( " bool f() { return nullptr; } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " enum E { A }; \n "
2021-02-20 12:58:42 +01:00
" bool f() { return A; } " ) ;
2018-10-18 21:01:47 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " bool f() { \n "
2018-10-18 21:01:47 +02:00
" const int x = 0; \n "
2021-02-20 12:58:42 +01:00
" return x; \n "
" } " ) ;
2018-10-18 21:01:47 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-10-31 09:47:48 +01:00
check ( " int f(void){return 1/abs(10);} " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " bool f() { \n "
2018-10-18 21:01:47 +02:00
" int x = 0; \n "
2021-02-20 12:58:42 +01:00
" return x; \n "
" } " ) ;
2018-10-18 21:01:47 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-10-31 09:47:48 +01:00
check ( " bool f() { \n "
2018-10-21 08:04:00 +02:00
" const int a = 50; \n "
" const int b = 52; \n "
" return a+b; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2022-10-10 13:45:30 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Return value 'a+b' is always true \n " , errout . str ( ) ) ;
2018-10-21 08:04:00 +02:00
2018-10-31 09:47:48 +01:00
check ( " int f() { \n "
" int a = 50; \n "
" int b = 52; \n "
" a++; \n "
" b++; \n "
" return a+b; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-10-31 09:47:48 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-10-18 21:01:47 +02:00
check ( " bool& g(); \n "
" bool f() { \n "
" bool & b = g(); \n "
" b = false; \n "
" return b; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-10-18 21:01:47 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { \n "
" bool b; \n "
" bool f() { \n "
" b = false; \n "
" return b; \n "
" } \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2018-10-18 21:01:47 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-07 06:49:07 +01:00
check ( " bool f(long maxtime) { \n "
" if (std::time(0) > maxtime) \n "
" return std::time(0) > maxtime; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-07 06:49:07 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-09 06:09:51 +01:00
check ( " void foo(double param) { \n "
" while(bar()) { \n "
" if (param<0.) \n "
" return; \n "
" } \n "
" if (param<0.) \n "
" return; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-09 06:09:51 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-11 08:04:01 +01:00
check ( " void foo(int i) { \n "
" if (i==42) \n "
" { \n "
" bar(); \n "
" } \n "
" if (cond && (42==i)) \n "
" return; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-11 08:04:01 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-14 06:23:45 +01:00
// 8842 crash
check ( " class a { \n "
" int b; \n "
" c(b); \n "
" void f() { \n "
" if (b) return; \n "
" } \n "
2021-02-20 12:58:42 +01:00
" }; " ) ;
2018-11-14 06:23:45 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-11-27 06:39:29 +01:00
check ( " void f(const char* x, const char* t) { \n "
" if (!(strcmp(x, y) == 0)) { return; } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-11-27 06:39:29 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-12-18 08:16:43 +01:00
check ( " void f(const int a[]){ if (a == 0){} } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-01-11 08:39:23 +01:00
check ( " struct S { \n "
" bool operator<(const S&); \n "
" }; \n "
" int main() { \n "
" S s; \n "
" bool c = s<s; \n "
" if (c) return 0; \n "
" else return 42; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-11 08:39:23 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-02-20 15:28:31 +01:00
check ( " long X::g(bool unknown, int& result) { \n "
" long ret = 0; \n "
" bool f = false; \n "
" f = f || unknown; \n "
" f ? result = 42 : ret = -1; \n "
" return ret; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-02-20 15:28:31 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-08-08 07:46:47 +02:00
check ( " int f(void *handle) { \n "
" if (!handle) return 0; \n "
" if (handle) return 1; \n "
" else return 0; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-08-08 07:46:47 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (style) Condition 'handle' is always true \n " , errout . str ( ) ) ;
check ( " int f(void *handle) { \n "
" if (handle == 0) return 0; \n "
" if (handle) return 1; \n "
" else return 0; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2021-10-09 16:19:06 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition 'handle' is always true \n " , errout . str ( ) ) ;
2019-08-08 07:46:47 +02:00
check ( " int f(void *handle) { \n "
" if (handle != 0) return 0; \n "
" if (handle) return 1; \n "
" else return 0; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-08-31 08:48:48 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Identical condition 'handle!=0', second condition is always false \n " , errout . str ( ) ) ;
2019-08-08 07:46:47 +02:00
2023-08-24 10:36:01 +02:00
check ( " int f(void *handle) { \n "
" if (handle != nullptr) return 0; \n "
" if (handle) return 1; \n "
" else return 0; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Identical condition 'handle!=nullptr', second condition is always false \n " , errout . str ( ) ) ;
2019-08-08 07:46:47 +02:00
check ( " void f(void* x, void* y) { \n "
" if (x == nullptr && y == nullptr) \n "
" return; \n "
" if (x == nullptr || y == nullptr) \n "
" return; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-08-08 07:46:47 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void* g(); \n "
" void f(void* a, void* b) { \n "
" while (a) { \n "
" a = g(); \n "
" if (a == b) \n "
" break; \n "
" } \n "
" if (a) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-08-08 07:46:47 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void* g(); \n "
" void f(void* a, void* b) { \n "
" while (a) { \n "
" a = g(); \n "
" } \n "
" if (a) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-08-08 07:46:47 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:6]: (style) Condition 'a' is always false \n " , errout . str ( ) ) ;
check ( " void f(int * x, bool b) { \n "
" if (!x && b) {} \n "
" else if (x) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-08-08 07:46:47 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-08-12 11:04:01 +02:00
2019-08-12 20:24:16 +02:00
check ( " void f() { \n "
" const std::string x= \" xyz \" ; \n "
" if(!x.empty()){} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-08-12 20:24:16 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition '!x.empty()' is always true \n " , errout . str ( ) ) ;
check ( " std::string g(); \n "
" void f() { \n "
" const std::string msg = g(); \n "
" if(!msg.empty()){} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-08-12 20:24:16 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-08-12 11:04:01 +02:00
check ( " void f(int *array, int size ) { \n "
" for(int i = 0; i < size; ++i) { \n "
" if(array == 0) \n "
" continue; \n "
" if(array){} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2021-10-09 16:19:06 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (style) Condition 'array' is always true \n " , errout . str ( ) ) ;
2019-08-17 07:36:41 +02:00
2019-08-14 06:34:27 +02:00
check ( " void f(int *array, int size ) { \n "
" for(int i = 0; i < size; ++i) { \n "
" if(array == 0) \n "
" continue; \n "
" else if(array){} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2021-10-09 16:19:06 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (style) Condition 'array' is always true \n " , errout . str ( ) ) ;
2019-08-17 07:36:41 +02:00
2019-08-16 07:56:39 +02:00
// #9277
check ( " int f() { \n "
" constexpr bool x = true; \n "
" if constexpr (x) \n "
" return 0; \n "
" else \n "
" return 1; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-08-16 07:56:39 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-09-05 19:36:45 +02:00
2022-04-11 20:42:54 +02:00
// #9954
check ( " void f() { \n "
" const size_t a(8 * sizeof(short)); \n "
" const size_t b(8 * sizeof(int)); \n "
" if constexpr (a == 16 && b == 16) {} \n "
" else if constexpr (a == 16 && b == 32) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-09-05 19:36:45 +02:00
// #9319
check ( " struct S { \n "
" int a; \n "
" int b; \n "
" }; \n "
" void g(S s, bool& x); \n "
" void f() { \n "
" bool x = false; \n "
" g({0, 1}, x); \n "
" if (x) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-09-05 19:36:45 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-09-20 15:06:37 +02:00
// #9318
check ( " class A {}; \n "
" class B : public A {}; \n "
" void f(A* x) { \n "
" if (!x) \n "
" return; \n "
" auto b = dynamic_cast<B*>(x); \n "
" if (b) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-09-20 15:06:37 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-04 07:06:26 +02:00
check ( " int foo() { \n "
2020-09-04 18:43:17 +02:00
" auto x = getX(); \n "
" if (x == nullptr) \n "
" return 1; \n "
" auto y = dynamic_cast<Y*>(x) \n "
" if (y == nullptr) \n "
" return 2; \n "
" return 3; \n "
" } \n " ) ;
2020-09-04 07:06:26 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-09-20 15:06:37 +02:00
// handleKnownValuesInLoop
check ( " bool g(); \n "
" void f(bool x) { \n "
" if (x) while(x) x = g(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-09-20 15:06:37 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// isLikelyStream
check ( " void f(std::istringstream& iss) { \n "
" std::string x; \n "
" while (iss) { \n "
" iss >> x; \n "
" if (!iss) break; \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-09-20 15:06:37 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #9332
check ( " struct A { void* g(); }; \n "
" void f() { \n "
" A a; \n "
" void* b = a.g(); \n "
" if (!b) return; \n "
" void* c = a.g(); \n "
" if (!c) return; \n "
" bool compare = c == b; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-09-20 15:06:37 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-09-21 08:19:54 +02:00
// #9361
check ( " void f(char c) { \n "
" if (c == '.') {} \n "
" else if (isdigit(c) != 0) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-09-21 08:19:54 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-09-21 19:53:54 +02:00
2019-09-23 08:49:04 +02:00
// #9351
check ( " int f(int x) { \n "
" const bool b = x < 42; \n "
" if(b) return b?0:-1; \n "
" return 42; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-09-23 08:49:04 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3]: (style) Condition 'b' is always true \n " , errout . str ( ) ) ;
2019-09-21 19:53:54 +02:00
// #9362
check ( " uint8_t g(); \n "
" void f() { \n "
" const uint8_t v = g(); \n "
" if((v != 0x00)) { \n "
" if( (v & 0x01) == 0x00) {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-09-21 19:53:54 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-09-24 08:15:03 +02:00
// #9367
check ( " void f(long x) { \n "
" if (x <= 0L) \n "
" return; \n "
" if (x % 360L == 0) \n "
" return; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-09-24 08:15:03 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-01-03 19:35:28 +01:00
check ( " int f(int a, int b) { \n "
" static const int x = 10; \n "
" return x == 1 ? a : b; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-01-03 19:35:28 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " const bool x = false; \n "
" void f() { \n "
" if (x) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-01-03 19:35:28 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " const bool x = false; \n "
" void f() { \n "
" if (!x) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-01-03 19:35:28 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-05-14 14:10:32 +02:00
// #9709
check ( " void f(int a) { \n "
" bool ok = false; \n "
" const char * r = nullptr; \n "
" do_something(&r); \n "
" if (r != nullptr) \n "
" ok = a != 0; \n "
" if (ok) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-05-14 14:10:32 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-07-24 08:12:36 +02:00
// #9816
check ( " bool g(); \n "
" void f() { \n "
" bool b = false; \n "
" do { \n "
" do { \n "
" if (g()) \n "
" break; \n "
" b = true; \n "
" } while(false); \n "
" } while(!b); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-01 11:22:38 +02:00
// #9865
check ( " void f(const std::string &s) { \n "
" for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) { \n "
" const unsigned char c = static_cast<unsigned char>(*it); \n "
" if (c == '0') {} \n "
" else if ((c == 'a' || c == 'A') \n "
" || (c == 'b' || c == 'B')) {} \n "
" else {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-09-20 14:27:09 +02:00
// #9711
check ( " int main(int argc, char* argv[]) { \n "
" int foo = 0; \n "
" struct option options[] = { \n "
" { \" foo \" , no_argument, &foo, \' f \' }, \n "
" {NULL, 0, NULL, 0}, \n "
" }; \n "
" getopt_long(argc, argv, \" f \" , options, NULL); \n "
" if (foo) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2023-03-12 19:57:11 +01:00
// TODO: if (!v) is a known condition as well
2020-11-10 16:00:55 +01:00
check ( " struct a { \n "
" int *b(); \n "
" }; \n "
" bool g(a c, a* d) { \n "
" a *v, *e = v = &c; \n "
" if (!v) \n "
" return true; \n "
" int *f = v->b(); \n "
" if (f) \n "
" v = nullptr; \n "
" if (v == nullptr && e) {} \n "
" return d; \n "
" } \n " ) ;
2023-03-12 19:57:11 +01:00
ASSERT_EQUALS ( " [test.cpp:11]: (style) Condition 'e' is always true \n " , errout . str ( ) ) ;
2020-12-19 08:29:37 +01:00
// #10037
check ( " struct a { \n "
" int* p; \n "
" }; \n "
" void g(a*); \n "
" void f() { \n "
" struct a b; \n "
" uint32_t p = (uint32_t) -1; \n "
" b.p = (void *) &p; \n "
" int r = g(&b); \n "
" if (r == 0) \n "
" if (p != (uint32_t) -1) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-01-05 16:49:08 +01:00
// #9890
check ( " int g(int); \n "
" bool h(int*); \n "
" int f(int *x) { \n "
" int y = g(0); \n "
" if (!y) { \n "
" if (h(x)) { \n "
" y = g(1); \n "
" if (y) {} \n "
" return 0; \n "
" } \n "
" if (!y) {} \n "
" } \n "
" return 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:11]: (style) Condition '!y' is always true \n " , errout . str ( ) ) ;
2021-01-28 12:37:56 +01:00
// #10134
check ( " bool foo(bool b); \n "
" bool thud(const std::vector<std::wstring>& Arr, const std::wstring& Str) { \n "
" if (Arr.empty() && Str.empty()) \n "
" return false; \n "
" bool OldFormat = Arr.empty() && !Str.empty(); \n "
" if (OldFormat) \n "
" return foo(OldFormat); \n "
" return false; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-04-18 21:42:27 +02:00
// #10208
check ( " bool GetFirst(std::string &first); \n "
" bool GetNext(std::string &next); \n "
" void g(const std::string& name); \n "
" void f() { \n "
" for (std::string name; name.empty() ? GetFirst(name) : GetNext(name);) \n "
" g(name); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool GetFirst(std::string &first); \n "
" bool GetNext(std::string &next); \n "
" void g(const std::string& name); \n "
" void f() { \n "
" for (std::string name{}; name.empty() ? GetFirst(name) : GetNext(name);) \n "
" g(name); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool GetFirst(std::string &first); \n "
" bool GetNext(std::string &next); \n "
" void g(const std::string& name); \n "
" void f() { \n "
" for (std::string name{'a', 'b'}; name.empty() ? GetFirst(name) : GetNext(name);) \n "
" g(name); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool GetFirst(const std::string &first); \n "
" bool GetNext(const std::string &next); \n "
" void g(const std::string& name); \n "
" void f() { \n "
" for (std::string name; name.empty() ? GetFirst(name) : GetNext(name);) \n "
" g(name); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (style) Condition 'name.empty()' is always true \n " , errout . str ( ) ) ;
2021-05-18 07:28:45 +02:00
// #10278
check ( " void foo(unsigned int x) { \n "
" if ((100 - x) > 0) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-06-04 17:17:41 +02:00
// #10298
check ( " void foo(unsigned int x) { \n "
" if (x == -1) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-06-25 16:25:14 +02:00
2021-08-01 10:10:11 +02:00
// #10121
check ( " struct AB { \n "
" int a; \n "
" }; \n "
" struct ABC { \n "
" AB* ab; \n "
" }; \n "
" void g(ABC*); \n "
" int f(struct ABC *abc) { \n "
" int err = 0; \n "
" AB *ab = abc->ab; \n "
" if (ab->a == 123){ \n "
" g(abc); \n "
" if (ab->a != 123) { \n "
" err = 1; \n "
" } \n "
" } \n "
" return err; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-06-26 09:16:45 +02:00
// #10323
check ( " void foo(int x) { \n "
" if(x) \n "
" if(x == 1) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(int x) { \n "
" if(x) {} \n "
" else \n "
" if(x == 1) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (style) Condition 'x==1' is always false \n " , errout . str ( ) ) ;
2021-06-25 16:25:14 +02:00
// do not report both unsignedLessThanZero and knownConditionTrueFalse
check ( " void foo(unsigned int max) { \n "
" unsigned int num = max - 1; \n "
" if (num < 0) {} \n " // <- do not report knownConditionTrueFalse
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-06-26 09:16:04 +02:00
// #10297
check ( " void foo(size_t len, int start) { \n "
" if (start < 0) { \n "
" start = len+start; \n "
" if (start < 0) {} \n "
" } \n "
" } \n " ) ;
2021-07-26 22:21:56 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #10362
check ( " int tok; \n "
" void next(); \n "
" void parse_attribute() { \n "
" if (tok == '(') { \n "
" int parenthesis = 0; \n "
" do { \n "
" if (tok == '(') \n "
" parenthesis++; \n "
" else if (tok == ')') \n "
" parenthesis--; \n "
" next(); \n "
" } while (parenthesis && tok != -1); \n "
" } \n "
" } \n " ) ;
2021-06-26 09:16:04 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-08-02 10:51:34 +02:00
2021-08-03 06:31:28 +02:00
// #7843
check ( " void f(int i) { \n "
" if(abs(i) == -1) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Condition 'abs(i)==-1' is always false \n " , errout . str ( ) ) ;
// #7844
check ( " void f(int i) { \n "
" if(i > 0 && abs(i) == i) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Condition 'abs(i)==i' is always true \n " , errout . str ( ) ) ;
check ( " void f(int i) { \n "
" if(i < 0 && abs(i) == i) {} \n "
" } \n " ) ;
2021-10-09 16:19:06 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:2]: (style) Condition 'abs(i)==i' is always false \n " , errout . str ( ) ) ;
2021-08-03 06:31:28 +02:00
check ( " void f(int i) { \n "
" if(i > -3 && abs(i) == i) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-08-02 10:51:34 +02:00
// #9948
check ( " bool f(bool a, bool b) { \n "
" return a || ! b || ! a; \n "
" } \n " ) ;
2022-10-10 13:45:30 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:2]: (style) Return value '!a' is always true \n " , errout . str ( ) ) ;
2021-08-28 09:28:29 +02:00
// #10148
check ( " void f(int i) { \n "
" if (i >= 64) {} \n "
" else if (i >= 32) { \n "
" i &= 31; \n "
" if (i == 0) {} \n "
" else {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-10-15 10:59:01 +02:00
// #10548
check ( " void f() { \n "
" int i = 0; \n "
" do {} while (i++ == 0); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-07 06:51:51 +01:00
// #10582
check ( " static void fun(message_t *message) { \n "
" if (message->length >= 1) { \n "
" switch (data[0]) {} \n "
" } \n "
" uint8_t d0 = message->length > 0 ? data[0] : 0xff; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-12-18 22:52:54 +01:00
// #8266
check ( " void f(bool b) { \n "
" if (b) \n "
" return; \n "
" if (g(&b) || b) \n "
" return; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #9720
check ( " bool bar(int &); \n "
" void f(int a, int b) { \n "
" if (a + b == 3) \n "
" return; \n "
" if (bar(a) && (a + b == 3)) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-12-20 07:28:40 +01:00
// #10437
check ( " void f() { \n "
" Obj* PObj = nullptr; \n "
" bool b = false; \n "
" if (GetObj(PObj) && PObj != nullptr) \n "
" b = true; \n "
" if (b) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-01-01 23:15:14 +01:00
// #10223
check ( " static volatile sig_atomic_t is_running; \n "
" static void handler(int signum) { \n "
" is_running = 0; \n "
" } \n "
" void f() { \n "
" signal(SIGINT, &handler); \n "
" is_running = 1; \n "
" while (is_running) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-01-02 08:14:50 +01:00
// #10659
check ( " auto func(const std::tuple<int, int>& t) { \n "
" auto& [foo, bar] = t; \n "
" std::cout << foo << bar << std::endl; \n "
" return foo < bar; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-01-20 16:15:38 +01:00
2022-02-02 22:30:49 +01:00
// #10484
check ( " void f() { \n "
" static bool init = true; \n "
" if (init) \n "
" init = false; \n "
" } \n " ) ;
2022-09-20 07:30:12 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3]: (style) The statement 'if (init) init=false' is logically equivalent to 'init=false'. \n " , errout . str ( ) ) ;
2022-02-02 22:30:49 +01:00
check ( " void f() { \n "
" static bool init(true); \n "
" if (init) \n "
" init = false; \n "
" } \n " ) ;
2022-09-20 07:30:12 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3]: (style) The statement 'if (init) init=false' is logically equivalent to 'init=false'. \n " , errout . str ( ) ) ;
2022-02-02 22:30:49 +01:00
check ( " void f() { \n "
" static bool init{ true }; \n "
" if (init) \n "
" init = false; \n "
" } \n " ) ;
2022-09-20 07:30:12 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3]: (style) The statement 'if (init) init=false' is logically equivalent to 'init=false'. \n " , errout . str ( ) ) ;
2022-02-02 22:30:49 +01:00
// #10248
check ( " void f() { \n "
" static int var(1); \n "
" if (var == 1) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" static int var{ 1 }; \n "
" if (var == 1) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void Fun(); \n "
" using Fn = void (*)(); \n "
" void f() { \n "
" static Fn logger = nullptr; \n "
" if (logger == nullptr) \n "
" logger = Fun; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void Fun(); \n "
" using Fn = void (*)(); \n "
" void f() { \n "
" static Fn logger(nullptr); \n "
" if (logger == nullptr) \n "
" logger = Fun; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void Fun(); \n "
" using Fn = void (*)(); \n "
" void f() { \n "
" static Fn logger{ nullptr }; \n "
" if (logger == nullptr) \n "
" logger = Fun; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void Fun(); \n "
" typedef void (*Fn)(); \n "
" void f() { \n "
" static Fn logger = nullptr; \n "
" if (logger == nullptr) \n "
" logger = Fun; \n "
" } \n " ) ;
2022-03-22 07:24:40 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-02-02 22:30:49 +01:00
check ( " void Fun(); \n "
" typedef void (*Fn)(); \n "
" void f() { \n "
" static Fn logger(nullptr); \n "
" if (logger == nullptr) \n "
" logger = Fun; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void Fun(); \n "
" typedef void (*Fn)(); \n "
" void f() { \n "
" static Fn logger{ nullptr }; \n "
" if (logger == nullptr) \n "
" logger = Fun; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-01-20 16:15:38 +01:00
// #9256
check ( " bool f() { \n "
" bool b = false; \n "
" b = true; \n "
" return b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-02-28 18:54:55 +01:00
// #10702
check ( " struct Object { \n "
" int _count=0; \n "
" void increment() { ++_count;} \n "
" auto get() const { return _count; } \n "
" }; \n "
" struct Modifier { \n "
" Object & _object; \n "
" explicit Modifier(Object & object) : _object(object) {} \n "
" void do_something() { _object.increment(); } \n "
" }; \n "
" struct Foo { \n "
" Object _object; \n "
" void foo() { \n "
" Modifier mod(_object); \n "
" if (_object.get()>0) \n "
" return; \n "
" mod.do_something(); \n "
" if (_object.get()>0) \n "
" return; \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct Object { \n "
" int _count=0; \n "
" auto get() const; \n "
" }; \n "
" struct Modifier { \n "
" Object & _object; \n "
" explicit Modifier(Object & object); \n "
" void do_something(); \n "
" }; \n "
" struct Foo { \n "
" Object _object; \n "
" void foo() { \n "
" Modifier mod(_object); \n "
" if (_object.get()>0) \n "
" return; \n "
" mod.do_something(); \n "
" if (_object.get()>0) \n "
" return; \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-04-03 20:04:05 +02:00
check ( " void f(const uint32_t u) { \n "
" const uint32_t v = u < 4; \n "
" if (v) { \n "
" const uint32_t w = v < 2; \n "
" if (w) {} \n "
" } \n "
" } \n " ) ;
2023-08-20 22:32:41 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Condition 'v<2' is always true \n "
" [test.cpp:5]: (style) Condition 'w' is always true \n " ,
errout . str ( ) ) ;
2022-04-06 06:35:38 +02:00
2022-04-07 10:42:57 +02:00
check ( " void f(double d) { \n " // #10792
" if (d != 0) { \n "
" int i = (int)d; \n "
" if (i == 0) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(double d) { \n "
" if (0 != d) { \n "
" int i = (int)d; \n "
" if (i == 0) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { double d; } \n "
" void f(A a) { \n "
" if (a.d != 0) { \n "
" int i = a.d; \n "
" if (i == 0) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-04-06 06:35:38 +02:00
check ( " void f() { \n "
" if(strlen( \" abc \" ) == 3) {;} \n "
" if(strlen( \" abc \" ) == 1) {;} \n "
" if(wcslen(L \" abc \" ) == 3) {;} \n "
" if(wcslen(L \" abc \" ) == 1) {;} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Condition 'strlen( \" abc \" )==3' is always true \n "
" [test.cpp:3]: (style) Condition 'strlen( \" abc \" )==1' is always false \n "
" [test.cpp:4]: (style) Condition 'wcslen(L \" abc \" )==3' is always true \n "
" [test.cpp:5]: (style) Condition 'wcslen(L \" abc \" )==1' is always false \n " ,
errout . str ( ) ) ;
2022-04-07 06:48:13 +02:00
check ( " int foo(bool a, bool b) { \n "
" if(!a && b && (!a == !b)) \n "
" return 1; \n "
" return 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:2]: (style) Condition '!a==!b' is always false \n " , errout . str ( ) ) ;
2022-04-13 12:25:53 +02:00
// #10454
check ( " struct S { \n "
" int f() const { return g() ? 0 : 1; } \n "
" bool g() const { return u == 18446744073709551615ULL; } \n "
" unsigned long long u{}; \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-04-30 09:35:51 +02:00
// #8358
check ( " void f(double d) { if ((d * 0) != 0) {} } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-05-09 14:52:31 +02:00
// #6870
check ( " struct S { \n "
" int* p; \n "
" void f() const; \n "
" int g(); \n "
" }; \n "
" void S::f() { \n "
" if ((p == NULL) || ((p) && (g() >= *p))) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (style) Condition 'p' is always true \n " , errout . str ( ) ) ;
// #10749
check ( " struct Interface { \n "
" virtual int method() = 0; \n "
" }; \n "
" struct Child : Interface { \n "
" int method() override { return 0; } \n "
" auto foo() { \n "
" if (method() == 0) \n "
" return true; \n "
" else \n "
" return false; \n "
" } \n "
" }; \n "
" struct GrandChild : Child { \n "
" int method() override { return 1; } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-05-10 18:25:01 +02:00
// #6855
check ( " struct S { int i; }; \n "
" void f(S& s) { \n "
" if (!(s.i > 0) && (s.i != 0)) \n "
" s.i = 0; \n "
" else if (s.i < 0) \n "
" s.s = 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:5]: (style) Condition 's.i<0' is always false \n " , errout . str ( ) ) ;
// #6857
check ( " int bar(int i) { return i; } \n "
" void foo() { \n "
" if (bar(1) == 0 && bar(1) > 0) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition 'bar(1)==0' is always false \n "
" [test.cpp:3]: (style) Condition 'bar(1)>0' is always true \n " ,
errout . str ( ) ) ;
check ( " struct S { int bar(int i) const; }; \n "
" void foo(const S& s) { \n "
" if (s.bar(1) == 0 && s.bar(1) > 0) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (warning) Logical conjunction always evaluates to false: s.bar(1) == 0 && s.bar(1) > 0. \n " ,
errout . str ( ) ) ;
2022-06-10 20:17:57 +02:00
check ( " struct B { \n " // #10618
" void Modify(); \n "
" static void Static(); \n "
" virtual void CalledByModify(); \n "
" }; \n "
" struct D : B { \n "
" int i{}; \n "
" void testV(); \n "
" void testS(); \n "
" void CalledByModify() override { i = 0; } \n "
" }; \n "
" void D::testV() { \n "
" i = 1; \n "
" B::Modify(); \n "
" if (i == 1) {} \n "
" } \n "
" void D::testS() { \n "
" i = 1; \n "
" B::Static(); \n "
" if (i == 1) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:20]: (style) Condition 'i==1' is always true \n " , errout . str ( ) ) ;
2022-07-18 18:03:08 +02:00
check ( " typedef struct { bool x; } s_t; \n " // #8446
" unsigned f(bool a, bool b) { \n "
" s_t s; \n "
" const unsigned col = a ? (s.x = false) : (b = true); \n "
" if (!s.x) {} \n "
" return col; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-08-02 18:18:46 +02:00
check ( " struct S { \n " // #11233
" static std::string m; \n "
" static void f() { m = \" abc \" ; } \n "
" static void g() { \n "
" m.clear(); \n "
" f(); \n "
" if (m.empty()) {} \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-08-07 19:06:19 +02:00
2022-09-08 19:59:02 +02:00
// #11203
check ( " void f() { \n "
" int i = 10; \n "
" if(i > 9.9){} \n "
" float f = 9.9f; \n "
" if(f < 10) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition 'i>9.9' is always true \n "
" [test.cpp:5]: (style) Condition 'f<10' is always true \n " ,
errout . str ( ) ) ;
2022-08-07 19:06:19 +02:00
check ( " constexpr int f() { \n " // #11238
" return 1; \n "
" } \n "
" constexpr bool g() { \n "
" return f() == 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-08-09 13:13:16 +02:00
check ( " int g() { return -1; } \n "
" void f() { \n "
" if (g() == 1 && g() == -1) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition 'g()==1' is always false \n "
" [test.cpp:3]: (style) Condition 'g()==-1' is always true \n " ,
errout . str ( ) ) ;
2022-08-20 19:23:55 +02:00
// #9817
check ( " void f(float x) { \n "
" if (x <= 0) {} \n "
" else if (x < 1) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-08-29 12:25:10 +02:00
// #10426
2022-08-30 18:08:24 +02:00
check ( " int f() { \n "
2022-08-29 12:25:10 +02:00
" std::string s; \n "
" for (; !s.empty();) {} \n "
" for (; s.empty();) {} \n "
" if (s.empty()) {} \n "
2022-08-30 18:08:24 +02:00
" if ((bool)0) {} \n "
" return s.empty(); "
2022-08-29 12:25:10 +02:00
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition '!s.empty()' is always false \n "
" [test.cpp:4]: (style) Condition 's.empty()' is always true \n "
2022-08-30 18:08:24 +02:00
" [test.cpp:5]: (style) Condition 's.empty()' is always true \n "
2022-09-04 10:24:45 +02:00
" [test.cpp:6]: (style) Condition '(bool)0' is always false \n "
2022-10-10 13:45:30 +02:00
" [test.cpp:7]: (style) Return value 's.empty()' is always true \n " ,
2022-08-30 18:08:24 +02:00
errout . str ( ) ) ;
check ( " int f(bool b) { \n "
" if (b) return static_cast<int>(1); \n "
" return (int)0; \n "
" } \n "
" bool g(bool b) { \n "
" if (b) return static_cast<int>(1); \n "
" return (int)0; \n "
" } \n " ) ;
2022-10-10 13:45:30 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (style) Return value 'static_cast<int>(1)' is always true \n "
" [test.cpp:7]: (style) Return value '(int)0' is always false \n " ,
2022-08-30 18:08:24 +02:00
errout . str ( ) ) ;
check ( " int f() { return 3; } \n "
" int g() { return f(); } \n "
" int h() { if (f()) {} } \n "
" int i() { return f() == 3; } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition 'f()' is always true \n "
2022-10-10 13:45:30 +02:00
" [test.cpp:4]: (style) Return value 'f()==3' is always true \n " ,
2022-08-29 12:25:10 +02:00
errout . str ( ) ) ;
2022-09-06 07:31:38 +02:00
check ( " int f() { \n "
" const char *n; \n "
" return((n=42) && \n "
" *n == 'A'); \n "
2022-10-25 19:41:48 +02:00
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(std::istringstream& i) { \n " // #9327
" std::string s; \n "
" if (!(i >> s)) \n "
" return; \n "
" if (!(i >> s)) \n "
" return; \n "
2022-09-06 07:31:38 +02:00
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-12-18 22:07:43 +01:00
// #11227
check ( " struct S { \n "
" int get(); \n "
" }; \n "
" void f(const S* s) { \n "
" if (!s) \n "
" return; \n "
" g(s ? s->get() : 0); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:7]: (style) Condition 's' is always true \n " , errout . str ( ) ) ;
2023-02-18 17:35:12 +01:00
check ( " void f(const char* o) { \n " // #11558
" if (!o || !o[0]) \n "
" return; \n "
" if (o[0] == '-' && o[1]) { \n "
" if (o[1] == '-') {} \n "
" if (o[1] == ' \\ 0') {} \n "
" } \n "
" } \n " ) ;
2023-10-07 23:04:57 +02:00
if ( std : : numeric_limits < char > : : is_signed ) {
ASSERT_EQUALS ( " [test.cpp:6]: (style) Condition 'o[1]==' \\ 0'' is always false \n " , errout . str ( ) ) ;
} else {
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:6]: (style) Condition 'o[1]==' \\ 0'' is always false \n " , errout . str ( ) ) ;
}
2023-03-02 21:45:15 +01:00
check ( " void f(int x) { \n " // #11449
" int i = x; \n "
" i = (std::min)(i, 1); \n "
" if (i == 1) {} \n "
" int j = x; \n "
" j = (::std::min)(j, 1); \n "
" if (j == 1) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2023-04-28 08:27:48 +02:00
check ( " void h(int); \n " // #11679
" bool g(int a) { h(a); return false; } \n "
" bool f(int i) { \n "
" return g(i); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(std::string a) { \n " // #11051
" a = \" x \" ; \n "
" if (a == \" x \" ) {} \n "
" return a; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition 'a== \" x \" ' is always true \n " , errout . str ( ) ) ;
2023-08-18 10:32:52 +02:00
check ( " void g(bool); \n "
" void f() { \n "
" int i = 5; \n "
" int* p = &i; \n "
" g(i == 7); \n "
" g(p == nullptr); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (style) Condition 'i==7' is always false \n "
2023-08-20 22:32:41 +02:00
" [test.cpp:6]: (style) Condition 'p==nullptr' is always false \n " ,
2023-08-18 10:32:52 +02:00
errout . str ( ) ) ;
2023-08-23 01:07:49 +02:00
check ( " enum E { E0, E1 }; \n "
" void f() { \n "
" static_assert(static_cast<int>(E::E1) == 1); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2023-12-10 19:42:35 +01:00
check ( " struct a { \n "
" bool g(); \n "
" int h(); \n "
" }; \n "
" void f(a c, int d, int e) { \n "
" if (c.g() && c.h()) {} \n "
" else { \n "
" bool u = false; \n "
" if (d && e) \n "
" u = true; \n "
" if (u) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2023-12-16 17:03:56 +01:00
check ( " int f(int i) { \n " // #11741
" i = -i - 1; \n "
" if (i < 0 || i >= 20) \n "
" return 0; \n "
" return 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-07-17 15:30:23 +02:00
}
2015-11-30 08:51:15 +01:00
2021-08-04 21:07:31 +02:00
void alwaysTrueSymbolic ( )
{
check ( " void f(const uint32_t x) { \n "
" uint32_t y[1]; \n "
" y[0]=x; \n "
" if(x > 0 || y[0] < 42){} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:4]: (style) Condition 'y[0]<42' is always true \n " , errout . str ( ) ) ;
2021-08-19 22:01:55 +02:00
check ( " void f(int x, int y) { \n "
" if(x < y && x < 42) { \n "
" --x; \n "
" if(x == y) {} \n "
" } \n "
" } \n " ) ;
2021-10-09 16:19:06 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (style) Condition 'x==y' is always false \n " , errout . str ( ) ) ;
2021-08-19 22:01:55 +02:00
check ( " void f(bool a, bool b) { if (a == b && a && !b){} } " ) ;
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (style) Condition '!b' is always false \n " , errout . str ( ) ) ;
check ( " bool f(bool a, bool b) { if(a && b && (!a)){} } " ) ;
ASSERT_EQUALS ( " [test.cpp:1] -> [test.cpp:1]: (style) Condition '!a' is always false \n " , errout . str ( ) ) ;
2021-08-21 21:17:05 +02:00
check ( " void f(int x, int y) { \n "
" if (x < y) { \n "
" auto z = y - x; \n "
" if (z < 1) {} \n "
" } \n "
" } \n " ) ;
2021-10-09 16:19:06 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (style) Condition 'z<1' is always false \n " , errout . str ( ) ) ;
2021-08-21 21:17:05 +02:00
2021-10-11 19:10:37 +02:00
check ( " bool f(int &index, const int s, const double * const array, double & x) { \n "
" if (index >= s) \n "
" return false; \n "
" else { \n "
" x = array[index]; \n "
" return (index++) >= s; \n "
" } \n "
" } \n " ) ;
2022-10-10 13:45:30 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:6]: (style) Return value '(index++)>=s' is always false \n " , errout . str ( ) ) ;
2021-10-11 19:10:37 +02:00
2021-08-04 21:07:31 +02:00
check ( " struct a { \n "
" a *b() const; \n "
" } c; \n "
" void d() { \n "
" a *e = nullptr; \n "
" e = c.b(); \n "
" if (e) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-08-09 07:45:41 +02:00
check ( " int g(int i) { \n "
" if (i < 256) \n "
" return 1; \n "
" const int N = 2 * i; \n "
" i -= 256; \n "
" if (i == 0) \n "
" return 0; \n "
" return N; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-08-19 22:01:55 +02:00
check ( " void f(int i, int j) { \n "
" if (i < j) { \n "
" i++; \n "
" if (i >= j) \n "
" return; \n "
" i++; \n "
" if (i >= j) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-10-09 16:20:04 +02:00
check ( " int get_delta() { \n "
" clock_t now_ms = (clock() / (CLOCKS_PER_SEC / 1000)); \n "
" static clock_t last_clock_ms = now_ms; \n "
" clock_t delta = now_ms - last_clock_ms; \n "
" last_clock_ms = now_ms; \n "
" if (delta > 50) \n "
" delta = 50; \n "
" return delta; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-12 20:05:43 +01:00
// #10555
check ( " struct C { \n "
" int GetI() const { return i; } \n "
" int i{}; \n "
" }; \n "
" struct B { \n "
" C *m_PC{}; \n "
" Modify(); \n "
" }; \n "
" struct D : B { \n "
" void test(); \n "
" }; \n "
" void D::test() { \n "
" const int I = m_PC->GetI(); \n "
" Modify(); \n "
" if (m_PC->GetI() != I) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-12-04 08:54:24 +01:00
// #10624
check ( " struct Data { \n "
" Base* PBase{}; \n "
" }; \n "
" void f(Data* BaseData) { \n "
" Base* PObj = BaseData->PBase; \n "
" if (PObj == nullptr) \n "
" return; \n "
" Derived* pD = dynamic_cast<Derived*>(PObj); \n "
" if (pD) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-12-14 07:30:57 +01:00
// #9549
check ( " void f(const uint32_t v) { \n "
" const uint32_t v16 = v >> 16; \n "
" if (v16) { \n "
" const uint32_t v8 = v16 >> 8; \n "
" if (v8) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-12-15 19:37:25 +01:00
// #10649
check ( " void foo(struct diag_msg *msg) { \n "
" msg = msg->next; \n "
" if (msg == NULL) \n "
" return CMD_OK; \n "
" msg = msg->next; \n "
" if (msg == NULL) \n "
" return CMD_OK; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-04-07 06:48:13 +02:00
check ( " int foo(bool a, bool b) { \n "
" if((!a == !b) && !a && b) \n "
" return 1; \n "
" return 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:2]: (style) Condition 'b' is always false \n " , errout . str ( ) ) ;
2022-06-11 11:02:04 +02:00
// #11124
check ( " struct Basket { \n "
" std::vector<int> getApples() const; \n "
" std::vector<int> getBananas() const; \n "
" }; \n "
" int getFruit(const Basket & b, bool preferApples) \n "
" { \n "
" std::vector<int> apples = b.getApples(); \n "
" int apple = apples.empty() ? -1 : apples.front(); \n "
" std::vector<int> bananas = b.getBananas(); \n "
" int banana = bananas.empty() ? -1 : bananas.front(); \n "
" int fruit = std::max(apple, banana); \n "
" if (fruit == -1) \n "
" return fruit; \n "
" if (std::min(apple, banana) != -1) \n "
" fruit = preferApples ? apple : banana; \n "
" return fruit; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(const std::string & s, int i) { \n "
" const char c = s[i]; \n "
" if (!std::isalnum(c)) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-12-08 10:40:55 +01:00
check ( " struct S { \n " // #11404
" int f() const; \n "
" void g(); \n "
" }; \n "
" void h(std::vector<S*>::iterator it) { \n "
" auto i = (*it)->f(); \n "
" (*it)->g(); \n "
" auto j = (*it)->f(); \n "
" if (i == j) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-12-09 07:15:15 +01:00
// #11384
check ( " bool f(const int* it, const int* end) { \n "
" return (it != end) && *it++ && \n "
" (it != end) && *it; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2023-10-29 00:11:03 +02:00
// #12116
check ( " void f(int n) { \n "
" for (int i = 0; i < N; ++i) { \n "
" if (i < n) {} \n "
" else if (i > n) {} \n "
" else {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-08-04 21:07:31 +02:00
}
2019-12-26 15:47:53 +01:00
void alwaysTrueInfer ( ) {
2019-12-26 15:48:17 +01:00
check ( " void f(int x) { \n "
2019-12-26 15:47:53 +01:00
" if (x > 5) { \n "
" x++; \n "
" if (x == 1) {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (style) Condition 'x==1' is always false \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if (x > 5) { \n "
" x++; \n "
" if (x != 1) {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (style) Condition 'x!=1' is always true \n " , errout . str ( ) ) ;
2019-12-26 15:48:17 +01:00
// #6890
2019-12-26 15:47:53 +01:00
check ( " void f(int i) { \n "
" int x = i; \n "
" if (x >= 1) {} \n "
" else { \n "
2021-02-20 12:58:42 +01:00
" x = 8 - x; \n "
2019-12-26 15:47:53 +01:00
" if (x == -1) {} \n "
" else {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:6]: (style) Condition 'x==-1' is always false \n " , errout . str ( ) ) ;
check ( " void f(int i) { \n "
" int x = i; \n "
" if (x >= 1) {} \n "
" else { \n "
2021-02-20 12:58:42 +01:00
" x = 8 - x; \n "
2019-12-26 15:47:53 +01:00
" if (x != -1) {} \n "
" else {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:6]: (style) Condition 'x!=-1' is always true \n " , errout . str ( ) ) ;
check ( " void f(int i) { \n "
" int x = i; \n "
" if (x >= 1) {} \n "
" else { \n "
2021-02-20 12:58:42 +01:00
" x = 8 - x; \n "
2019-12-26 15:47:53 +01:00
" if (x >= -1) {} \n "
" else {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:6]: (style) Condition 'x>=-1' is always true \n " , errout . str ( ) ) ;
check ( " void f(int i) { \n "
" int x = i; \n "
" if (x >= 1) {} \n "
" else { \n "
2021-02-20 12:58:42 +01:00
" x = 8 - x; \n "
2019-12-26 15:47:53 +01:00
" if (x > -1) {} \n "
" else {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:6]: (style) Condition 'x>-1' is always true \n " , errout . str ( ) ) ;
check ( " void f(int i) { \n "
" int x = i; \n "
" if (x >= 1) {} \n "
" else { \n "
2021-02-20 12:58:42 +01:00
" x = 8 - x; \n "
2019-12-26 15:47:53 +01:00
" if (x < -1) {} \n "
" else {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:6]: (style) Condition 'x<-1' is always false \n " , errout . str ( ) ) ;
check ( " void f(int i) { \n "
" int x = i; \n "
" if (x >= 1) {} \n "
" else { \n "
2021-02-20 12:58:42 +01:00
" x = 8 - x; \n "
2019-12-26 15:47:53 +01:00
" if (x <= -1) {} \n "
" else {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:6]: (style) Condition 'x<=-1' is always false \n " , errout . str ( ) ) ;
check ( " void f(int i) { \n "
" int x = i; \n "
" if (x >= 1) {} \n "
" else { \n "
2021-02-20 12:58:42 +01:00
" x = 8 - x; \n "
2019-12-26 15:47:53 +01:00
" if (x > 7) {} \n "
" else {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:6]: (style) Condition 'x>7' is always true \n " , errout . str ( ) ) ;
check ( " void f(int i) { \n "
" int x = i; \n "
" if (x >= 1) {} \n "
" else { \n "
2021-02-20 12:58:42 +01:00
" x = 8 - x; \n "
2019-12-26 15:47:53 +01:00
" if (x > 9) {} \n "
" else {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int i) { \n "
" int x = i; \n "
" if (x >= 1) {} \n "
" else { \n "
2021-02-20 12:58:42 +01:00
" x = 8 - x; \n "
2019-12-26 15:47:53 +01:00
" if (x > 10) {} \n "
" else {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-12-26 15:47:53 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-01-05 16:25:33 +01:00
2022-06-11 11:00:40 +02:00
// #11100
check ( " struct T { \n "
" bool m{}; \n "
" void f(bool b); \n "
" bool get() const { return m; } \n "
" void set(bool v) { m = v; } \n "
" }; \n "
" void T::f(bool b) { \n "
" bool tmp = get(); \n "
" set(b); \n "
" if (tmp != get()) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-01-05 16:25:33 +01:00
// #9541
check ( " int f(int pos, int a) { \n "
" if (pos <= 0) \n "
" pos = 0; \n "
" else if (pos < a) \n "
" if(pos > 0) \n "
" --pos; \n "
" return pos; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-01-05 16:25:33 +01:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:5]: (style) Condition 'pos>0' is always true \n " , errout . str ( ) ) ;
2020-05-23 07:15:13 +02:00
// #9721
check ( " void f(int x) { \n "
" if (x > 127) { \n "
" if ( (x>255) || (-128>x) ) \n "
" return; \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2020-05-23 07:15:13 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (style) Condition '-128>x' is always false \n " , errout . str ( ) ) ;
2021-08-16 09:19:07 +02:00
// #8778
check ( " void f() { \n "
" for(int i = 0; i < 19; ++i) \n "
" if(i<=18) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition 'i<=18' is always true \n " , errout . str ( ) ) ;
2021-10-09 16:19:06 +02:00
2021-10-12 08:25:08 +02:00
// #8209
check ( " void f() { \n "
" for(int x = 0; x < 3; ++x) \n "
" if(x == -5) {} \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition 'x==-5' is always false \n " , errout . str ( ) ) ;
2021-10-12 09:42:18 +02:00
// #8407
check ( " int f(void) { \n "
" for(int i = 0; i <1; ++i) \n "
" if(i == 0) return 1; \n " // <<
" else return 0; \n "
" return -1; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition 'i==0' is always true \n " , errout . str ( ) ) ;
2021-10-09 16:19:06 +02:00
check ( " void f(unsigned int u1, unsigned int u2) { \n "
" if (u1 <= 10 && u2 >= 20) { \n "
" if (u1 != u2) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (style) Condition 'u1!=u2' is always true \n " , errout . str ( ) ) ;
2021-10-14 16:47:15 +02:00
// #10544
check ( " void f(int N) { \n "
" if (N > 0) { \n "
" while (N) \n "
" N = test(); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-07-16 07:28:15 +02:00
// #11098
check ( " void f(unsigned int x) { if (x == -1u) {} } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-09-06 07:31:48 +02:00
check ( " bool f(const int *p, const int *q) { \n "
" return p != NULL && q != NULL && p == NULL; \n "
" } \n " ) ;
2022-10-10 13:45:30 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Return value 'p==NULL' is always false \n " , errout . str ( ) ) ;
2023-06-23 20:31:25 +02:00
check ( " struct S { \n " // #11789
" std::vector<int> v; \n "
" void f(int i) const; \n "
" }; \n "
" void S::f(int i) const { \n "
" int j = i - v.size(); \n "
" if (j >= 0) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2023-10-06 09:53:24 +02:00
check ( " void f(int i) { \n " // #12039
" if ((128 + i < 255 ? 128 + i : 255) > 0) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-12-26 15:47:53 +01:00
}
2019-09-05 16:42:26 +02:00
void alwaysTrueContainer ( ) {
// #9329
check ( " void c1(std::vector<double>&); \n "
" void c2(std::vector<double>&); \n "
" void foo(int flag) { \n "
" std::vector<double> g; \n "
" if (flag) \n "
" c1(g ); \n "
" else \n "
" c2(g ); \n "
" if ( !g.empty() ) \n "
" return; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-09-05 16:42:26 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(int flag) { \n "
" std::vector<double> g; \n "
" if (flag) \n "
" c1(g ); \n "
" else \n "
" c2(g ); \n "
" if ( !g.empty() ) \n "
" return; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-09-05 16:42:26 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-08-28 19:26:09 +02:00
check ( " struct A { \n "
" std::vector<int> v; \n "
" void g(); \n "
" void f(bool b) { \n "
" v.clear(); \n "
" g(); \n "
" return !v.empty(); \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-08-14 06:48:38 +02:00
// #10409
check ( " void foo(const std::string& s) { \n "
" if( s.size() < 2 ) return; \n "
" if( s == \" ab \" ) return; \n "
" if( s.size() < 3 ) return; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(const std::string& s) { \n "
" if( s.size() < 2 ) return; \n "
" if( s != \" ab \" ) \n "
" if( s.size() < 3 ) return; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-10-31 14:51:07 +01:00
// #10226
check ( " int f(std::vector<int>::iterator it, const std::vector<int>& vector) { \n "
" if (!(it != vector.end() && it != vector.begin())) \n "
" throw 0; \n "
" if (it != vector.end() && *it == 0) \n "
" return -1; \n "
" return *it; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Condition 'it!=vector.end()' is always true \n " , errout . str ( ) ) ;
2022-12-15 18:35:19 +01:00
// #11303
check ( " void f(int n) { \n "
" std::vector<char> buffer(n); \n "
" if(buffer.back() == 0 || \n "
" buffer.back() == ' \\ n' || \n "
" buffer.back() == ' \\ 0') {} \n "
" } \n " ) ;
2023-10-07 23:04:57 +02:00
if ( std : : numeric_limits < char > : : is_signed ) {
ASSERT_EQUALS ( " [test.cpp:5]: (style) Condition 'buffer.back()==' \\ 0'' is always false \n " , errout . str ( ) ) ;
} else {
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:5]: (style) Condition 'buffer.back()==' \\ 0'' is always false \n " , errout . str ( ) ) ;
}
2023-01-26 22:03:12 +01:00
// #9353
2023-11-09 07:48:33 +01:00
check ( " struct X { std::string s; }; \n "
2023-01-26 22:03:12 +01:00
" void f(const std::vector<X>&v) { \n "
" for (std::vector<X>::const_iterator it = v.begin(); it != v.end(); ++it) \n "
" if (!it->s.empty()) { \n "
" if (!it->s.empty()) {} \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:5]: (style) Condition '!it->s.empty()' is always true \n " , errout . str ( ) ) ;
2023-11-09 07:48:33 +01:00
check ( " struct X { std::string s; }; \n "
" void f(const std::vector<struct X>&v) { \n "
" for (std::vector<struct X>::const_iterator it = v.begin(); it != v.end(); ++it) \n "
" if (!it->s.empty()) { \n "
" if (!it->s.empty()) {} \n "
" } \n "
" } \n " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:5]: (style) Condition '!it->s.empty()' is always true \n " , " " , errout . str ( ) ) ;
2023-01-26 22:03:12 +01:00
// #10508
check ( " bool f(const std::string& a, const std::string& b) { \n "
" return a.empty() || (b.empty() && a.empty()); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:2]: (style) Return value 'a.empty()' is always false \n " , errout . str ( ) ) ;
2023-02-23 18:05:31 +01:00
check ( " struct A { \n "
" struct iterator; \n "
" iterator begin() const; \n "
" iterator end() const; \n "
" }; \n "
" A g(); \n "
" void f(bool b) { \n "
" std::set<int> s; \n "
" auto v = g(); \n "
" s.insert(v.begin(), v.end()); \n "
" if(!b && s.size() != 1) \n "
" return; \n "
" if(!s.empty()) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2023-08-09 20:33:44 +02:00
check ( " int f(std::string s) { \n "
" if (s.empty()) \n "
" return -1; \n "
" s += ' \\ n'; \n "
" if (s.empty()) \n "
" return -1; \n "
" return -1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (style) Condition 's.empty()' is always false \n " , errout . str ( ) ) ;
2023-08-13 22:31:38 +02:00
check ( " void f(std::string& p) { \n "
" const std::string d{ \" abc \" }; \n "
" p += d; \n "
" if(p.empty()) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Condition 'p.empty()' is always false \n " , errout . str ( ) ) ;
check ( " bool f(int i, FILE* fp) { \n "
" std::string s = \" abc \" ; \n "
" s += std::to_string(i); \n "
" s += \" \\ n \" ; \n "
" return fwrite(s.c_str(), 1, s.length(), fp) == s.length(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2023-12-07 19:24:51 +01:00
check ( " void f(const std::string& s) { \n " // #9148
" if (s.empty() || s.size() < 1) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:2]: (style) Condition 's.size()<1' is always false \n " , errout . str ( ) ) ;
2024-01-02 15:49:47 +01:00
check ( " void bar(std::vector<int>& vv) { \n " // #11464
" class F { \n "
" public: \n "
" F(int, std::vector<int>& lv) : mV(lv) { \n "
" mV.push_back(0); \n "
" } \n "
" private: \n "
" std::vector<int>& mV; \n "
" } fi(1, vv); \n "
" } \n "
" void g() { \n "
" std::vector<int> v; \n "
" bar(v); \n "
" if (v.empty()) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct F { \n "
" F(int, std::vector<int>&lv) : mV(lv) { \n "
" mV.push_back(0); \n "
" } \n "
" std::vector<int>& mV; \n "
" }; \n "
" void g(std::vector<int>& vv) { \n "
" F(1, vv); \n "
" } \n "
" void f() { \n "
" std::vector<int> v; \n "
" g(v); \n "
" if (v.empty()) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-09-05 16:42:26 +02:00
}
2021-08-27 05:46:57 +02:00
void alwaysTrueLoop ( )
{
check ( " long foo() { \n "
" bool bUpdated = false; \n "
" long Ret{}; \n "
" do { \n "
" Ret = bar(); \n "
" if (Ret == 0) { \n "
" if (bUpdated) \n "
" return 1; \n "
" bUpdated = true; \n "
" } \n "
" else \n "
" bUpdated = false; \n "
" } \n "
" while (bUpdated); \n "
" return Ret; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool foo() { \n "
" bool bFirst = true; \n "
" do { \n "
" if (bFirst) \n "
" bar(); \n "
" if (baz()) \n "
" break; \n "
" bFirst = false; \n "
" } while (true); \n "
" return bFirst; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-12-15 19:32:14 +01:00
check ( " void f() { \n "
" void * pool = NULL; \n "
" do { \n "
" pool = malloc(40); \n "
" if (dostuff()) \n "
" break; \n "
" pool = NULL; \n "
" } \n "
" while (0); \n "
" if (pool) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-03-12 06:15:35 +01:00
2023-03-17 19:06:17 +01:00
// #8499
check ( " void f(void) \n "
" { \n "
" for (int i = 0; i < 2; ++i) \n "
" { \n "
" for (int j = 0; j < 8; ++j) \n "
" { \n "
" if ( (i==0|| i==1) \n " // << always true
" && (j==0) ) \n "
" {;} \n "
" } \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:7] -> [test.cpp:7]: (style) Condition 'i==1' is always true \n " , errout . str ( ) ) ;
2022-03-12 06:15:35 +01:00
// #10863
check ( " void f(const int A[], int Len) { \n "
" if (Len <= 0) \n "
" return; \n "
" int I = 0; \n "
" while (I < Len) { \n "
" int K = I + 1; \n "
" for (; K < Len; K++) { \n "
" if (A[I] != A[K]) \n "
" break; \n "
" } \n "
" I = K; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-12-15 14:31:02 +01:00
check ( " void f() { \n " // #11434
" const int N = 5; \n "
" bool a[N]; \n "
" for (int i = 0; i < N; a[i++] = false); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2023-12-23 11:31:27 +01:00
check ( " void f() { \n " // #8192
" for (int i = 0; i > 10; ++i) {} \n "
" } \n " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:2]: (style) Condition 'i>10' is always false \n " , " " , errout . str ( ) ) ;
check ( " void f() { \n "
" for (int i = 1000; i < 20; ++i) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Condition 'i<20' is always false \n " , errout . str ( ) ) ;
2021-08-27 05:46:57 +02:00
}
2021-09-03 23:07:08 +02:00
void alwaysTrueTryCatch ( )
{
check ( " void g(); \n "
" void f(int x) \n "
" { \n "
" if( x ) { \n "
" try { \n "
" g(); \n "
" } \n "
" catch(...) { \n "
" return; \n "
" } \n "
" } \n "
" g(); \n "
" if( x ) { \n "
" g(); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void g(); \n "
" void h(); \n "
" void f(int x) { \n "
" if( x ) { \n "
" try { \n "
" g(); \n "
" return; \n "
" } \n "
" catch( ... ) {} \n "
" } \n "
" h(); \n "
" if( x ) { \n "
" g(); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2023-12-13 19:22:54 +01:00
check ( " void f() { \n " // #10701
" std::string s; \n "
" try { \n "
" try { \n "
" s = g(); \n "
" } \n "
" catch (const Err& err) {} \n "
" } \n "
" catch (const std::exception& e) {} \n "
" if (s != \" abc \" ) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-09-03 23:07:08 +02:00
}
2018-09-06 06:55:36 +02:00
void multiConditionAlwaysTrue ( ) {
check ( " void f() { \n "
" int val = 0; \n "
" if (val < 0) continue; \n "
" if (val > 0) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-09-28 08:38:24 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-09-06 06:55:36 +02:00
check ( " void f() { \n "
" int val = 0; \n "
" if (val < 0) { \n "
" if (val > 0) {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-09-28 08:38:24 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-09-06 06:55:36 +02:00
check ( " void f() { \n "
" int val = 0; \n "
" if (val < 0) { \n "
" if (val < 0) {} \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-09-28 08:38:24 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-09-07 15:02:34 +02:00
check ( " void f() { \n "
" int activate = 0; \n "
" int foo = 0; \n "
" if (activate) {} \n "
" else if (foo) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-09-07 15:02:34 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Condition 'activate' is always false \n "
" [test.cpp:5]: (style) Condition 'foo' is always false \n " , errout . str ( ) ) ;
2019-01-20 10:05:09 +01:00
// #6904
check ( " void f() { \n "
" const int b[2] = { 1,0 }; \n "
" if(b[1] == 2) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-20 10:05:09 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Condition 'b[1]==2' is always false \n " , errout . str ( ) ) ;
2020-09-09 15:39:36 +02:00
// #9878
check ( " void f(bool a, bool b) { \n "
" if (a && b){;} \n "
" else if (!a && b){;} \n "
" else if (!a && !b){;} \n "
" else {;} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-09-06 06:55:36 +02:00
}
2019-01-09 20:41:01 +01:00
void duplicateCondition ( ) {
check ( " void f(bool x) { \n "
" if(x) {} \n "
" if(x) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-09 20:41:01 +01:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (style) The if condition is the same as the previous if condition \n " ,
errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if(x == 1) {} \n "
" if(x == 1) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-09 20:41:01 +01:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (style) The if condition is the same as the previous if condition \n " ,
errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if(x == 1) {} \n "
" if(x == 2) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-09 20:41:01 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if(x == 1) {} \n "
" if(x != 1) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-09 20:41:01 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(bool x) { \n "
" if(x) {} \n "
" g(); \n "
" if(x) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-09 20:41:01 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" if(x == 1) { x++; } \n "
" if(x == 1) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-01-09 20:41:01 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-03-19 06:25:10 +01:00
// #8996
check ( " void g(int** v); \n "
" void f() { \n "
" int a = 0; \n "
" int b = 0; \n "
" int* d[] = {&a, &b}; \n "
" g(d); \n "
" if (a) {} \n "
" if (b) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-03-19 06:25:10 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-05-14 08:57:36 +02:00
2019-09-10 19:41:35 +02:00
// #9311
check ( " struct c { \n "
" int* p; \n "
" }; \n "
" void g(struct c* v); \n "
" void f() { \n "
" int a = 0; \n "
" int b = 0; \n "
" struct c d[] = {{&a}, {&b}}; \n "
" g(d); \n "
" if (a) {} \n "
" if (b) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-09-10 19:41:35 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-05-14 08:57:36 +02:00
// #8993
check ( " void f(const std::string& x) { \n "
" auto y = x; \n "
" if (x.empty()) y = \" 1 \" ; \n "
" if (y.empty()) return; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-05-14 08:57:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-12-09 06:51:58 +01:00
// #9106
check ( " struct A {int b;}; \n "
" void f(A a, int c) { \n "
" if (a.b) a.b = c; \n "
" if (a.b) {} \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-12-09 06:51:58 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-07-13 19:40:01 +02:00
check ( " struct A { \n "
" int a; \n "
" void b() const { \n "
" return a == 1; \n "
" } \n "
" void c(); \n "
" void d() { \n "
" if(b()) { \n "
" c(); \n "
" } \n "
" if (b()) { \n "
" a = 3; \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { \n "
" int a; \n "
" void b() const { \n "
" return a == 1; \n "
" } \n "
" void d() { \n "
" if(b()) { \n "
" a = 2; \n "
" } \n "
" if (b()) { \n "
" a = 3; \n "
" } \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct A { \n "
" int a; \n "
" void b() const { \n "
" return a == 1; \n "
" } \n "
" void d() { \n "
" if(b()) { \n "
" } \n "
" if (b()) { \n "
" a = 3; \n "
" } \n "
" } \n "
" } \n " ) ;
2020-07-13 20:55:45 +02:00
ASSERT_EQUALS ( " [test.cpp:7] -> [test.cpp:9]: (style) The if condition is the same as the previous if condition \n " ,
errout . str ( ) ) ;
2020-09-18 07:44:26 +02:00
check ( " void f(bool a, bool b) { \n "
" auto g = [&] { b = !a; }; \n "
" if (b) \n "
" g(); \n "
" if (b) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void g(bool& a); \n "
" void f(bool b) { \n "
" auto h = std::bind(&g, std::ref(b)); \n "
" if (b) \n "
" h(); \n "
" if (b) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-10-20 07:56:41 +02:00
check ( " void f(int *i) { \n "
" if (*i == 0) { \n "
" *i = 1; \n "
" } \n "
" if (*i == 0) { \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2020-10-22 07:39:57 +02:00
2021-04-18 21:42:27 +02:00
check ( " void g(std::function<void()>); \n "
" void f(std::vector<int> v) { \n "
" auto x = [&v] { v.push_back(1); }; \n "
" if(v.empty()) { \n "
" g(x); \n "
" } \n "
" if(v.empty()) \n "
" return; \n "
" return; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-05-03 19:57:30 +02:00
check ( " struct S { int i; }; \n "
" int f(const S& s) { \n "
" int a = 0, b = 0; \n "
" if (s.i == 0) \n "
" a = 1; \n "
" if (s.i == 0) \n "
" b = 1; \n "
" return a + b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:6]: (style) The if condition is the same as the previous if condition \n " , errout . str ( ) ) ;
2020-10-22 07:39:57 +02:00
// do not crash
check ( " void assign(const MMA& other) { \n "
" if (mPA.cols != other.mPA.cols || mPA.rows != other.mPA.rows) \n "
" ; \n "
" if (other.mPA.cols > 0 && other.mPA.rows > 0) \n "
" ; \n "
" } " ) ;
2019-01-09 20:41:01 +01:00
}
2015-11-30 08:51:15 +01:00
void checkInvalidTestForOverflow ( ) {
check ( " void f(char *p, unsigned int x) { \n "
" assert((p + x) < p); \n "
" } " ) ;
2021-01-05 11:38:19 +01:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Invalid test for overflow '(p+x)<p'; pointer overflow is undefined behavior. Some mainstream compilers remove such overflow tests when optimising the code and assume it's always false. \n " , errout . str ( ) ) ;
2015-11-30 08:51:15 +01:00
2015-11-30 11:12:51 +01:00
check ( " void f(char *p, unsigned int x) { \n "
" assert((p + x) >= p); \n "
" } " ) ;
2021-01-05 11:38:19 +01:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Invalid test for overflow '(p+x)>=p'; pointer overflow is undefined behavior. Some mainstream compilers remove such overflow tests when optimising the code and assume it's always true. \n " , errout . str ( ) ) ;
2015-11-30 11:12:51 +01:00
check ( " void f(char *p, unsigned int x) { \n "
" assert(p > (p + x)); \n "
" } " ) ;
2021-01-05 11:38:19 +01:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Invalid test for overflow 'p>(p+x)'; pointer overflow is undefined behavior. Some mainstream compilers remove such overflow tests when optimising the code and assume it's always false. \n " , errout . str ( ) ) ;
2015-11-30 11:12:51 +01:00
check ( " void f(char *p, unsigned int x) { \n "
" assert(p <= (p + x)); \n "
" } " ) ;
2021-01-05 11:38:19 +01:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Invalid test for overflow 'p<=(p+x)'; pointer overflow is undefined behavior. Some mainstream compilers remove such overflow tests when optimising the code and assume it's always true. \n " , errout . str ( ) ) ;
2015-11-30 08:51:15 +01:00
2016-11-27 11:40:42 +01:00
check ( " void f(signed int x) { \n " // unsigned overflow => don't warn
2015-11-30 08:51:15 +01:00
" assert(x + 100U < x); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-01-05 11:38:19 +01:00
// x + c < x
# define MSG(EXPR, RESULT) "[test.cpp:1]: (warning) Invalid test for overflow '" EXPR "'; signed integer overflow is undefined behavior. Some mainstream compilers remove such overflow tests when optimising the code and assume it's always " RESULT ".\n"
check ( " int f(int x) { return x + 10 > x; } " ) ;
ASSERT_EQUALS ( MSG ( " x+10>x " , " true " ) , errout . str ( ) ) ;
check ( " int f(int x) { return x + 10 >= x; } " ) ;
ASSERT_EQUALS ( MSG ( " x+10>=x " , " true " ) , errout . str ( ) ) ;
check ( " int f(int x) { return x + 10 < x; } " ) ;
ASSERT_EQUALS ( MSG ( " x+10<x " , " false " ) , errout . str ( ) ) ;
check ( " int f(int x) { return x + 10 <= x; } " ) ;
ASSERT_EQUALS ( MSG ( " x+10<=x " , " false " ) , errout . str ( ) ) ;
check ( " int f(int x) { return x - 10 > x; } " ) ;
ASSERT_EQUALS ( MSG ( " x-10>x " , " false " ) , errout . str ( ) ) ;
check ( " int f(int x) { return x - 10 >= x; } " ) ;
ASSERT_EQUALS ( MSG ( " x-10>=x " , " false " ) , errout . str ( ) ) ;
check ( " int f(int x) { return x - 10 < x; } " ) ;
ASSERT_EQUALS ( MSG ( " x-10<x " , " true " ) , errout . str ( ) ) ;
check ( " int f(int x) { return x - 10 <= x; } " ) ;
ASSERT_EQUALS ( MSG ( " x-10<=x " , " true " ) , errout . str ( ) ) ;
// x + y < x
# undef MSG
# define MSG(EXPR, RESULT) "[test.cpp:1]: (warning) Invalid test for overflow '" EXPR "'; signed integer overflow is undefined behavior. Some mainstream compilers removes handling of overflows when optimising the code and change the code to '" RESULT "'.\n"
check ( " int f(int x, int y) { return x + y < x; } " ) ;
ASSERT_EQUALS ( MSG ( " x+y<x " , " y<0 " ) , errout . str ( ) ) ;
check ( " int f(int x, int y) { return x + y <= x; } " ) ;
ASSERT_EQUALS ( MSG ( " x+y<=x " , " y<=0 " ) , errout . str ( ) ) ;
check ( " int f(int x, int y) { return x + y > x; } " ) ;
ASSERT_EQUALS ( MSG ( " x+y>x " , " y>0 " ) , errout . str ( ) ) ;
check ( " int f(int x, int y) { return x + y >= x; } " ) ;
ASSERT_EQUALS ( MSG ( " x+y>=x " , " y>=0 " ) , errout . str ( ) ) ;
// x - y < x
check ( " int f(int x, int y) { return x - y < x; } " ) ;
ASSERT_EQUALS ( MSG ( " x-y<x " , " y>0 " ) , errout . str ( ) ) ;
check ( " int f(int x, int y) { return x - y <= x; } " ) ;
ASSERT_EQUALS ( MSG ( " x-y<=x " , " y>=0 " ) , errout . str ( ) ) ;
check ( " int f(int x, int y) { return x - y > x; } " ) ;
ASSERT_EQUALS ( MSG ( " x-y>x " , " y<0 " ) , errout . str ( ) ) ;
check ( " int f(int x, int y) { return x - y >= x; } " ) ;
ASSERT_EQUALS ( MSG ( " x-y>=x " , " y<=0 " ) , errout . str ( ) ) ;
2015-11-30 08:51:15 +01:00
}
2017-09-08 14:30:42 +02:00
void checkConditionIsAlwaysTrueOrFalseInsideIfWhile ( ) {
check ( " void f() { \n "
" enum states {A,B,C}; \n "
" const unsigned g_flags = B|C; \n "
" if(g_flags & A) {} \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (style) Condition 'g_flags&A' is always false \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" int a = 5; "
" if(a) {} \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Condition 'a' is always true \n " , errout . str ( ) ) ;
check ( " void f() { \n "
2017-09-08 15:41:14 +02:00
" int a = 5; "
" while(a + 1) { a--; } \n "
" } " ) ;
2017-09-08 14:30:42 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int a = 5; "
" while(a + 1) { return; } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Condition 'a+1' is always true \n " , errout . str ( ) ) ;
}
2017-10-22 14:32:54 +02:00
2018-07-23 08:51:59 +02:00
void alwaysTrueFalseInLogicalOperators ( ) {
check ( " bool f(); \n "
2021-02-20 12:58:42 +01:00
" void foo() { bool x = true; if(x||f()) {}} " ) ;
2018-07-23 08:51:59 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Condition 'x' is always true \n " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void foo(bool b) { bool x = true; if(x||b) {}} " ) ;
2018-07-23 08:51:59 +02:00
ASSERT_EQUALS ( " [test.cpp:1]: (style) Condition 'x' is always true \n " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void foo(bool b) { if(true||b) {}} " ) ;
2018-07-23 08:51:59 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool f(); \n "
2021-02-20 12:58:42 +01:00
" void foo() { bool x = false; if(x||f()) {}} " ) ;
2018-07-23 08:51:59 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Condition 'x' is always false \n " , errout . str ( ) ) ;
check ( " bool f(); \n "
2021-02-20 12:58:42 +01:00
" void foo() { bool x = false; if(x&&f()) {}} " ) ;
2018-07-23 08:51:59 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Condition 'x' is always false \n " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void foo(bool b) { bool x = false; if(x&&b) {}} " ) ;
2018-07-23 08:51:59 +02:00
ASSERT_EQUALS ( " [test.cpp:1]: (style) Condition 'x' is always false \n " , errout . str ( ) ) ;
2021-02-20 12:58:42 +01:00
check ( " void foo(bool b) { if(false&&b) {}} " ) ;
2018-07-23 08:51:59 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool f(); \n "
2021-02-20 12:58:42 +01:00
" void foo() { bool x = true; if(x&&f()) {}} " ) ;
2018-07-23 08:51:59 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Condition 'x' is always true \n " , errout . str ( ) ) ;
2020-06-28 22:28:08 +02:00
// #9578
check ( " bool f(const std::string &s) { \n "
" return s.size()>2U && s[0]=='4' && s[0]=='2'; \n "
" } \n " ) ;
2022-10-10 13:45:30 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:2]: (style) Return value 's[0]=='2'' is always false \n " , errout . str ( ) ) ;
2018-07-23 08:51:59 +02:00
}
2017-10-22 14:32:54 +02:00
void pointerAdditionResultNotNull ( ) {
check ( " void f(char *ptr) { \n "
" if (ptr + 1 != 0); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Comparison is wrong. Result of 'ptr+1' can't be 0 unless there is pointer overflow, and pointer overflow is undefined behaviour. \n " , errout . str ( ) ) ;
}
2019-04-18 20:20:24 +02:00
2019-04-18 20:21:00 +02:00
void duplicateConditionalAssign ( ) {
2019-04-28 07:48:38 +02:00
setMultiline ( ) ;
2019-04-18 20:20:24 +02:00
check ( " void f(int& x, int y) { \n "
" if (x == y) \n "
" x = y; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-04-28 07:48:38 +02:00
ASSERT_EQUALS ( " test.cpp:3:style:Assignment 'x=y' is redundant with condition 'x==y'. \n "
" test.cpp:2:note:Condition 'x==y' \n "
" test.cpp:3:note:Assignment 'x=y' is redundant \n " , errout . str ( ) ) ;
2019-04-18 20:20:24 +02:00
check ( " void f(int& x, int y) { \n "
" if (x != y) \n "
" x = y; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-04-28 07:48:38 +02:00
ASSERT_EQUALS ( " test.cpp:2:style:The statement 'if (x!=y) x=y' is logically equivalent to 'x=y'. \n "
" test.cpp:3:note:Assignment 'x=y' \n "
" test.cpp:2:note:Condition 'x!=y' is redundant \n " , errout . str ( ) ) ;
2019-04-18 20:20:24 +02:00
check ( " void f(int& x, int y) { \n "
" if (x == y) \n "
" x = y; \n "
" else \n "
" x = 1; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-04-28 07:48:38 +02:00
ASSERT_EQUALS ( " test.cpp:3:style:Assignment 'x=y' is redundant with condition 'x==y'. \n "
" test.cpp:2:note:Condition 'x==y' \n "
" test.cpp:3:note:Assignment 'x=y' is redundant \n " , errout . str ( ) ) ;
2019-04-18 20:20:24 +02:00
check ( " void f(int& x, int y) { \n "
" if (x != y) \n "
" x = y; \n "
" else \n "
" x = 1; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-04-18 20:20:24 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int& x, int y) { \n "
" if (x == y) \n "
" x = y + 1; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-04-18 20:20:24 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-04-26 12:30:41 +02:00
check ( " void g(); \n "
" void f(int& x, int y) { \n "
" if (x == y) { \n "
" x = y; \n "
" g(); \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-04-26 12:30:41 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-09-20 07:30:12 +02:00
check ( " bool f(bool b) { \n "
" if (b) \n "
" b = false; \n "
" else \n "
" g(); \n "
" return b; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-09-20 21:57:27 +02:00
check ( " void f(int& i) { \n "
" if (!i) \n "
" i = 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-09-20 07:30:12 +02:00
check ( " struct S { \n " // #9406
" S() : b(false) {} \n "
" void f() { \n "
" if (b) b = true; \n "
" if (b) b = false; \n "
" if (!b) b = true; \n "
" if (!b) b = false; \n "
" } \n "
" bool b; \n "
" }; \n " ) ;
ASSERT_EQUALS ( " test.cpp:4:style:The statement 'if (b) b=true' is redundant. \n "
" test.cpp:4:note:Assignment 'b=true' \n "
" test.cpp:4:note:Condition 'b' is redundant \n "
" test.cpp:5:style:The statement 'if (b) b=false' is logically equivalent to 'b=false'. \n "
" test.cpp:5:note:Assignment 'b=false' \n "
" test.cpp:5:note:Condition 'b' is redundant \n "
" test.cpp:6:style:The statement 'if (!b) b=true' is logically equivalent to 'b=true'. \n "
" test.cpp:6:note:Assignment 'b=true' \n "
" test.cpp:6:note:Condition '!b' is redundant \n "
" test.cpp:7:style:The statement 'if (!b) b=false' is redundant. \n "
" test.cpp:7:note:Assignment 'b=false' \n "
" test.cpp:7:note:Condition '!b' is redundant \n " ,
errout . str ( ) ) ;
2019-04-18 20:20:24 +02:00
}
2021-04-07 17:21:34 +02:00
void checkAssignmentInCondition ( ) {
check ( " void f(std::string s) { \n "
" if (s= \" 123 \" ){} \n "
" } " ) ;
2021-04-07 19:46:00 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Suspicious assignment in condition. Condition 's= \" 123 \" ' is always true. \n " , errout . str ( ) ) ;
check ( " void f(std::string *p) { \n "
" if (p=foo()){} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-10-14 11:55:45 +02:00
check ( " void f(uint32_t u) { \n " // #2490
" if ((u = 0x00000000) || (u = 0xffffffff)) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (style) Condition 'u=0x00000000' is always false \n "
" [test.cpp:2]: (style) Condition 'u=0xffffffff' is always true \n " ,
errout . str ( ) ) ;
2021-04-07 17:21:34 +02:00
}
2021-07-15 09:43:38 +02:00
void compareOutOfTypeRange ( ) {
2023-10-13 16:02:04 +02:00
const Settings settingsUnix64 = settingsBuilder ( ) . severity ( Severity : : style ) . platform ( Platform : : Type : : Unix64 ) . build ( ) ;
2021-07-15 09:43:38 +02:00
check ( " void f(unsigned char c) { \n "
2021-07-16 19:08:08 +02:00
" if (c == 256) {} \n "
2023-05-02 15:54:19 +02:00
" } " , settingsUnix64 ) ;
2021-09-12 15:08:14 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Comparing expression of type 'unsigned char' against value 256. Condition is always false. \n " , errout . str ( ) ) ;
2021-07-16 19:08:08 +02:00
2022-05-09 20:26:15 +02:00
check ( " void f(unsigned char* b, int i) { \n " // #6372
" if (b[i] == 256) {} \n "
2023-05-02 15:54:19 +02:00
" } " , settingsUnix64 ) ;
2022-05-09 20:26:15 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Comparing expression of type 'unsigned char' against value 256. Condition is always false. \n " , errout . str ( ) ) ;
2021-07-16 19:08:08 +02:00
check ( " void f(unsigned char c) { \n "
" if (c == 255) {} \n "
2023-05-02 15:54:19 +02:00
" } " , settingsUnix64 ) ;
2021-07-16 19:08:08 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(bool b) { \n "
" if (b == true) {} \n "
2023-05-02 15:54:19 +02:00
" } " , settingsUnix64 ) ;
2021-07-16 19:08:08 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-08-10 09:38:28 +02:00
// #10372
check ( " void f(signed char x) { \n "
" if (x == 0xff) {} \n "
2023-05-02 15:54:19 +02:00
" } " , settingsUnix64 ) ;
2021-09-12 15:08:14 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Comparing expression of type 'signed char' against value 255. Condition is always false. \n " , errout . str ( ) ) ;
2021-08-10 09:38:28 +02:00
check ( " void f(short x) { \n "
" if (x == 0xffff) {} \n "
2023-05-02 15:54:19 +02:00
" } " , settingsUnix64 ) ;
2021-09-12 15:08:14 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Comparing expression of type 'signed short' against value 65535. Condition is always false. \n " , errout . str ( ) ) ;
2021-08-10 09:38:28 +02:00
check ( " void f(int x) { \n "
" if (x == 0xffffffff) {} \n "
2023-05-02 15:54:19 +02:00
" } " , settingsUnix64 ) ;
2021-08-10 09:38:28 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(long x) { \n "
" if (x == ~0L) {} \n "
2023-05-02 15:54:19 +02:00
" } " , settingsUnix64 ) ;
2021-08-10 09:38:28 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(long long x) { \n "
" if (x == ~0LL) {} \n "
2023-05-02 15:54:19 +02:00
" } " , settingsUnix64 ) ;
2021-08-10 09:38:28 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-08-29 16:03:45 +02:00
2022-07-01 10:48:32 +02:00
check ( " int f(int x) { \n "
" const int i = 0xFFFFFFFF; \n "
" if (x == i) {} \n "
2023-05-02 15:54:19 +02:00
" } " , settingsUnix64 ) ;
2022-07-01 10:48:32 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-08-29 16:03:45 +02:00
check ( " void f() { \n "
" char c; \n "
" if ((c = foo()) != -1) {} \n "
2023-05-02 15:54:19 +02:00
" } " , settingsUnix64 ) ;
2021-08-29 16:03:45 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-09-12 15:08:14 +02:00
check ( " void f(int x) { \n "
" if (x < 3000000000) {} \n "
2023-05-02 15:54:19 +02:00
" } " , settingsUnix64 ) ;
2021-09-12 15:08:14 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Comparing expression of type 'signed int' against value 3000000000. Condition is always true. \n " , errout . str ( ) ) ;
2022-05-21 08:33:42 +02:00
check ( " void f(const signed char i) { \n " // #8545
" if (i > -129) {} \n " // warn
" if (i >= -128) {} \n " // warn
" if (i >= -127) {} \n "
" if (i < +128) {} \n " // warn
" if (i <= +127) {} \n " // warn
" if (i <= +126) {} \n "
2023-05-02 15:54:19 +02:00
" } \n " , settingsUnix64 ) ;
2022-05-21 08:33:42 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (style) Comparing expression of type 'const signed char' against value -129. Condition is always true. \n "
" [test.cpp:3]: (style) Comparing expression of type 'const signed char' against value -128. Condition is always true. \n "
" [test.cpp:5]: (style) Comparing expression of type 'const signed char' against value 128. Condition is always true. \n "
" [test.cpp:6]: (style) Comparing expression of type 'const signed char' against value 127. Condition is always true. \n " ,
errout . str ( ) ) ;
check ( " void f(const unsigned char u) { \n "
" if (u > 0) {} \n "
" if (u < 0) {} \n " // warn
" if (u >= 0) {} \n " // warn
" if (u <= 0) {} \n "
" if (u > 255) {} \n " // warn
" if (u < 255) {} \n "
" if (u >= 255) {} \n "
" if (u <= 255) {} \n " // warn
" if (0 < u) {} \n "
" if (0 > u) {} \n " // warn
" if (0 <= u) {} \n " // warn
" if (0 >= u) {} \n "
" if (255 < u) {} \n " // warn
" if (255 > u) {} \n "
" if (255 <= u) {} \n "
" if (255 >= u) {} \n " // warn
2023-05-02 15:54:19 +02:00
" } \n " , settingsUnix64 ) ;
2022-05-21 08:33:42 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always false. \n "
" [test.cpp:4]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always true. \n "
" [test.cpp:6]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always false. \n "
" [test.cpp:9]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always true. \n "
" [test.cpp:11]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always false. \n "
" [test.cpp:12]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always true. \n "
" [test.cpp:14]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always false. \n "
" [test.cpp:17]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always true. \n " ,
errout . str ( ) ) ;
2021-08-01 12:32:01 +02:00
}
2021-07-27 22:26:19 +02:00
void knownConditionCast ( ) { // #9976
check ( " void f(int i) { \n "
" if (i < 0 || (unsigned)i > 5) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-07-15 09:43:38 +02:00
}
2021-08-02 06:53:54 +02:00
void knownConditionIncrementLoop ( ) { // #9808
check ( " void f() { \n "
" int a = 0; \n "
" while (++a < 5) {} \n "
" if (a == 1) {} \n "
" std::cout << a; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-08-29 17:06:46 +02:00
} ;
REGISTER_TEST ( TestCondition )