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());
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:13] -> [test.cpp:6:13]: (style) The if condition is the same as the previous if condition [duplicateCondition]\n", errout_str());
check("void f(double d) {\n" // #12712
" if (std::isfinite(d)) {}\n"
" if (std::isfinite(d)) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:2:22] -> [test.cpp:3:22]: (style) The if condition is the same as the previous if condition [duplicateCondition]\n", errout_str());
check("struct S { int x; };\n" // #12391
"int f(const struct S* a, const struct S* b) {\n"
" const struct S* p = b;\n"
" if (a->x < p->x) p++;\n"
" if (a->x < p->x) p++;\n"
" return p->x;\n"
"}\n");
ASSERT_EQUALS("", errout_str());
// 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"
"}");
ASSERT_EQUALS("", errout_str());
check("void foo() {\n" // #11202
" float f = 0x1.4p+3;\n"
" if (f > 10.0) {}\n"
" if (f < 10.0) {}\n"
"}\n");
ASSERT_EQUALS("", errout_str());
check("void f(char* s, const char* p) {\n" // #14070
" strcpy(s, p);\n"
"}\n"
"void g() {\n"
" char s1[10] = \"\";\n"
" char s2[10] = \"\";\n"
" f(s1, \"123\");\n"
" f(s2, \"1234\");\n"
" if (strlen(s1) > 0) {}\n"
" if (strlen(s2) > 0) {}\n"
"}\n");
ASSERT_EQUALS("", errout_str());
check("void g(int*);\n" // #14428
"int f(int* const p) {\n"
" int i = 0;\n"
" if (*p == 0)\n"
" g(p);\n"
" if (*p == 0)\n"
" i = 1;\n"
" return i;\n"
"}\n");
ASSERT_EQUALS("", errout_str());
check("void g(const int*);\n"
"int f(const int* const p) {\n"
" int i = 0;\n"
" if (*p == 0)\n"
" g(p);\n"
" if (*p == 0)\n"
" i = 1;\n"
" return i;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4:12] -> [test.cpp:6:12]: (style) The if condition is the same as the previous if condition [duplicateCondition]\n", errout_str());
}
void checkInvalidTestForOverflow() {
check("void f(char *p, unsigned int x) {\n"
" assert((p + x) < p);\n"
"}");
ASSERT_EQUALS("[test.cpp:2:20]: (warning) Invalid test for overflow '(p+x)= p);\n"
"}");
ASSERT_EQUALS("[test.cpp:2:20]: (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. [invalidTestForOverflow]\n", errout_str());
check("void f(char *p, unsigned int x) {\n"
" assert(p > (p + x));\n"
"}");
ASSERT_EQUALS("[test.cpp:2:14]: (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. [invalidTestForOverflow]\n", errout_str());
check("void f(char *p, unsigned int x) {\n"
" assert(p <= (p + x));\n"
"}");
ASSERT_EQUALS("[test.cpp:2:14]: (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. [invalidTestForOverflow]\n", errout_str());
check("void f(signed int x) {\n" // unsigned overflow => don't warn
" assert(x + 100U < x);\n"
"}");
ASSERT_EQUALS("", errout_str());
// x + c < x
#define MSG(EXPR, RESULT) "[test.cpp:1:30]: (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 ". [invalidTestForOverflow]\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; }");
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; }");
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-y0"), 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());
}
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:16]: (style) Condition 'g_flags&A' is always false [knownConditionTrueFalse]\n", errout_str());
check("void f() {\n"
" int a = 5;"
" if(a) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:2:22]: (style) Condition 'a' is always true [knownConditionTrueFalse]\n", errout_str());
check("void f() {\n"
" int a = 5;"
" while(a + 1) { a--; }\n"
"}");
ASSERT_EQUALS("", errout_str());
check("void f() {\n"
" int a = 5;"
" while(a + 1) { return; }\n"
"}");
ASSERT_EQUALS("[test.cpp:2:27]: (style) Condition 'a+1' is always true [knownConditionTrueFalse]\n", errout_str());
}
void alwaysTrueFalseInLogicalOperators() {
check("bool f();\n"
"void foo() { bool x = true; if(x||f()) {}}");
ASSERT_EQUALS("[test.cpp:2:32]: (style) Condition 'x' is always true [knownConditionTrueFalse]\n", errout_str());
check("void foo(bool b) { bool x = true; if(x||b) {}}");
ASSERT_EQUALS("[test.cpp:1:38]: (style) Condition 'x' is always true [knownConditionTrueFalse]\n", errout_str());
check("void foo(bool b) { if(true||b) {}}");
ASSERT_EQUALS("", errout_str());
check("bool f();\n"
"void foo() { bool x = false; if(x||f()) {}}");
ASSERT_EQUALS("[test.cpp:2:33]: (style) Condition 'x' is always false [knownConditionTrueFalse]\n", errout_str());
check("bool f();\n"
"void foo() { bool x = false; if(x&&f()) {}}");
ASSERT_EQUALS("[test.cpp:2:33]: (style) Condition 'x' is always false [knownConditionTrueFalse]\n", errout_str());
check("void foo(bool b) { bool x = false; if(x&&b) {}}");
ASSERT_EQUALS("[test.cpp:1:39]: (style) Condition 'x' is always false [knownConditionTrueFalse]\n", errout_str());
check("void foo(bool b) { if(false&&b) {}}");
ASSERT_EQUALS("", errout_str());
check("bool f();\n"
"void foo() { bool x = true; if(x&&f()) {}}");
ASSERT_EQUALS("[test.cpp:2:32]: (style) Condition 'x' is always true [knownConditionTrueFalse]\n", errout_str());
// #9578
check("bool f(const std::string &s) {\n"
" return s.size()>2U && s[0]=='4' && s[0]=='2';\n"
"}\n");
ASSERT_EQUALS("[test.cpp:2:35] -> [test.cpp:2:48]: (style) Return value 's[0]=='2'' is always false [knownConditionTrueFalse]\n", errout_str());
check("void f(int i) { if (i == 1 || 2) {} }\n"); // #12487
ASSERT_EQUALS("[test.cpp:1:28]: (style) Condition 'i==1||2' is always true [knownConditionTrueFalse]\n", errout_str());
check("enum E { E1 = 1, E2 = 2 };\n"
"void f(int i) { if (i == E1 || E2) {} }\n");
ASSERT_EQUALS("[test.cpp:2:29]: (style) Condition 'i==E1||E2' is always true [knownConditionTrueFalse]\n", errout_str());
}
void pointerAdditionResultNotNull() {
check("void f(char *ptr) {\n"
" if (ptr + 1 != 0);\n"
"}");
ASSERT_EQUALS("[test.cpp:2:15]: (warning) Comparison is wrong. Result of 'ptr+1' can't be 0 unless there is pointer overflow, and pointer overflow is undefined behaviour. [pointerAdditionResultNotNull]\n", errout_str());
}
void duplicateConditionalAssign() {
setMultiline();
check("void f(int& x, int y) {\n"
" if (x == y)\n"
" x = y;\n"
"}");
ASSERT_EQUALS("[test.cpp:3:11]: style: Assignment 'x=y' is redundant with condition 'x==y'. [duplicateConditionalAssign]\n"
"[test.cpp:2:11]: note: Condition 'x==y'\n"
"[test.cpp:3:11]: note: Assignment 'x=y' is redundant\n", errout_str());
check("void f(int& x, int y) {\n"
" if (x != y)\n"
" x = y;\n"
"}");
ASSERT_EQUALS("[test.cpp:2:11]: style: The statement 'if (x!=y) x=y' is logically equivalent to 'x=y'. [duplicateConditionalAssign]\n"
"[test.cpp:3:11]: note: Assignment 'x=y'\n"
"[test.cpp:2:11]: note: Condition 'x!=y' is redundant\n", errout_str());
check("void f(int& x, int y) {\n"
" if (x == y)\n"
" x = y;\n"
" else\n"
" x = 1;\n"
"}");
ASSERT_EQUALS("[test.cpp:3:11]: style: Assignment 'x=y' is redundant with condition 'x==y'. [duplicateConditionalAssign]\n"
"[test.cpp:2:11]: note: Condition 'x==y'\n"
"[test.cpp:3:11]: note: Assignment 'x=y' is redundant\n", errout_str());
check("void f(int& x, int y) {\n"
" if (x != y)\n"
" x = y;\n"
" else\n"
" x = 1;\n"
"}");
ASSERT_EQUALS("", errout_str());
check("void f(int& x, int y) {\n"
" if (x == y)\n"
" x = y + 1;\n"
"}");
ASSERT_EQUALS("", errout_str());
check("void g();\n"
"void f(int& x, int y) {\n"
" if (x == y) {\n"
" x = y;\n"
" g();\n"
" }\n"
"}");
ASSERT_EQUALS("", errout_str());
check("bool f(bool b) {\n"
" if (b)\n"
" b = false;\n"
" else\n"
" g();\n"
" return b;\n"
"}\n");
ASSERT_EQUALS("", errout_str());
check("void f(int& i) {\n"
" if (!i)\n"
" i = 1; \n"
"}\n");
ASSERT_EQUALS("", errout_str());
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:13]: style: The statement 'if (b) b=true' is redundant. [duplicateConditionalAssign]\n"
"[test.cpp:4:18]: note: Assignment 'b=true'\n"
"[test.cpp:4:13]: note: Condition 'b' is redundant\n"
"[test.cpp:5:13]: style: The statement 'if (b) b=false' is logically equivalent to 'b=false'. [duplicateConditionalAssign]\n"
"[test.cpp:5:18]: note: Assignment 'b=false'\n"
"[test.cpp:5:13]: note: Condition 'b' is redundant\n"
"[test.cpp:6:13]: style: The statement 'if (!b) b=true' is logically equivalent to 'b=true'. [duplicateConditionalAssign]\n"
"[test.cpp:6:19]: note: Assignment 'b=true'\n"
"[test.cpp:6:13]: note: Condition '!b' is redundant\n"
"[test.cpp:7:13]: style: The statement 'if (!b) b=false' is redundant. [duplicateConditionalAssign]\n"
"[test.cpp:7:19]: note: Assignment 'b=false'\n"
"[test.cpp:7:13]: note: Condition '!b' is redundant\n",
errout_str());
}
void checkAssignmentInCondition() {
check("void f(std::string s) {\n"
" if (s=\"123\"){}\n"
"}");
ASSERT_EQUALS("[test.cpp:2:10]: (style) Suspicious assignment in condition. Condition 's=\"123\"' is always true. [assignmentInCondition]\n", errout_str());
check("void f(std::string *p) {\n"
" if (p=foo()){}\n"
"}");
ASSERT_EQUALS("", errout_str());
check("void f(uint32_t u) {\n" // #2490
" if ((u = 0x00000000) || (u = 0xffffffff)) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:2:12]: (style) Condition 'u=0x00000000' is always false [knownConditionTrueFalse]\n"
"[test.cpp:2:32]: (style) Condition 'u=0xffffffff' is always true [knownConditionTrueFalse]\n",
errout_str());
}
void compareOutOfTypeRange() {
const Settings settingsUnix64 = settingsBuilder().severity(Severity::style).platform(Platform::Type::Unix64).build();
check("void f(unsigned char c) {\n"
" if (c == 256) {}\n"
"}", settingsUnix64);
ASSERT_EQUALS("[test.cpp:2:12]: (style) Comparing expression of type 'unsigned char' against value 256. Condition is always false. [compareValueOutOfTypeRangeError]\n", errout_str());
check("void f(unsigned char* b, int i) {\n" // #6372
" if (b[i] == 256) {}\n"
"}", settingsUnix64);
ASSERT_EQUALS("[test.cpp:2:15]: (style) Comparing expression of type 'unsigned char' against value 256. Condition is always false. [compareValueOutOfTypeRangeError]\n", errout_str());
check("void f(unsigned char c) {\n"
" if (c == 255) {}\n"
"}", settingsUnix64);
ASSERT_EQUALS("", errout_str());
check("void f(bool b) {\n"
" if (b == true) {}\n"
"}", settingsUnix64);
ASSERT_EQUALS("", errout_str());
// #10372
check("void f(signed char x) {\n"
" if (x == 0xff) {}\n"
"}", settingsUnix64);
ASSERT_EQUALS("[test.cpp:2:12]: (style) Comparing expression of type 'signed char' against value 255. Condition is always false. [compareValueOutOfTypeRangeError]\n", errout_str());
check("void f(short x) {\n"
" if (x == 0xffff) {}\n"
"}", settingsUnix64);
ASSERT_EQUALS("[test.cpp:2:12]: (style) Comparing expression of type 'signed short' against value 65535. Condition is always false. [compareValueOutOfTypeRangeError]\n", errout_str());
check("void f(int x) {\n"
" if (x == 0xffffffff) {}\n"
"}", settingsUnix64);
ASSERT_EQUALS("", errout_str());
check("void f(long x) {\n"
" if (x == ~0L) {}\n"
"}", settingsUnix64);
ASSERT_EQUALS("", errout_str());
check("void f(long long x) {\n"
" if (x == ~0LL) {}\n"
"}", settingsUnix64);
ASSERT_EQUALS("", errout_str());
check("int f(int x) {\n"
" const int i = 0xFFFFFFFF;\n"
" if (x == i) {}\n"
"}", settingsUnix64);
ASSERT_EQUALS("", errout_str());
check("void f() {\n"
" char c;\n"
" if ((c = foo()) != -1) {}\n"
"}", settingsUnix64);
ASSERT_EQUALS("", errout_str());
check("void f(int x) {\n"
" if (x < 3000000000) {}\n"
"}", settingsUnix64);
ASSERT_EQUALS("[test.cpp:2:11]: (style) Comparing expression of type 'signed int' against value 3000000000. Condition is always true. [compareValueOutOfTypeRangeError]\n", errout_str());
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"
"}\n", settingsUnix64);
ASSERT_EQUALS("[test.cpp:2:15]: (style) Comparing expression of type 'const signed char' against value -129. Condition is always true. [compareValueOutOfTypeRangeError]\n"
"[test.cpp:3:15]: (style) Comparing expression of type 'const signed char' against value -128. Condition is always true. [compareValueOutOfTypeRangeError]\n"
"[test.cpp:5:15]: (style) Comparing expression of type 'const signed char' against value 128. Condition is always true. [compareValueOutOfTypeRangeError]\n"
"[test.cpp:6:15]: (style) Comparing expression of type 'const signed char' against value 127. Condition is always true. [compareValueOutOfTypeRangeError]\n",
errout_str());
check("void f(const unsigned char u) {\n"
" if (u > 0) {}\n"
" if (u < 0) {}\n"
" if (u >= 0) {}\n"
" 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"
" if (0 <= u) {}\n"
" if (0 >= u) {}\n"
" if (255 < u) {}\n" // warn
" if (255 > u) {}\n"
" if (255 <= u) {}\n"
" if (255 >= u) {}\n" // warn
"}\n", settingsUnix64);
ASSERT_EQUALS("[test.cpp:6:14]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always false. [compareValueOutOfTypeRangeError]\n"
"[test.cpp:9:14]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always true. [compareValueOutOfTypeRangeError]\n"
"[test.cpp:14:9]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always false. [compareValueOutOfTypeRangeError]\n"
"[test.cpp:17:9]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always true. [compareValueOutOfTypeRangeError]\n",
errout_str());
check("void f(bool b) {\n" // #14037
" if (b != 2) {}\n"
"}\n", settingsUnix64);
ASSERT_EQUALS("[test.cpp:2:14]: (style) Comparing expression of type 'bool' against value 2. Condition is always true. [compareValueOutOfTypeRangeError]\n",
errout_str());
check("void f(const std::uint32_t& u) {\n" // #9078
" if (u >= UINT32_MAX) {}\n"
" if (u <= UINT32_MAX) {}\n"
" if (u > UINT32_MAX) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:14]: (style) Comparing expression of type 'const unsigned int &' against value 4294967295. Condition is always true. [compareValueOutOfTypeRangeError]\n"
"[test.cpp:4:13]: (style) Comparing expression of type 'const unsigned int &' against value 4294967295. Condition is always false. [compareValueOutOfTypeRangeError]\n",
errout_str());
}
void knownConditionCast() {
check("void f(int i) {\n" // #9976
" if (i < 0 || (unsigned)i > 5) {}\n"
"}\n");
ASSERT_EQUALS("", errout_str());
check("struct B {\n" // #12941
" virtual void f();\n"
"};\n"
"struct One : public B {};\n"
"struct Two : public B {};\n"
"void g(const B& b) {\n"
" const Two* two = nullptr;\n"
" const One* one = dynamic_cast(&b);\n"
" if (one == nullptr)\n"
" two = dynamic_cast(&b);\n"
" if (two) {}\n"
"}\n");
ASSERT_EQUALS("", errout_str());
}
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());
}
void knownConditionAfterBailout() { // #12526
check(
"#include \n"
"int func()\n"
"{\n"
" return VALUE_1;"
"}\n"
"\n"
"struct S1 {\n"
" bool b{};\n"
"};\n"
"\n"
"struct S {\n"
" void f(const std::list& l) const\n"
" {\n"
" if (mS.b)\n"
" return;\n"
" for (int i : l)\n"
" {\n"
" (void)i;\n"
" if (mS.b)\n"
" continue;\n"
" }\n"
" }\n"
"\n"
" S1 mS;\n"
"};"
);
ASSERT_EQUALS("[test.cpp:13:11] -> [test.cpp:18:13]: (style) Condition 'mS.b' is always false [knownConditionTrueFalse]\n", errout_str());
}
void knownConditionIncDecOperator() {
check(
"void f() {\n"
" unsigned int d = 0;\n"
" for (int i = 0; i < 4; ++i) {\n"
" if (i < 3)\n"
" ++d;\n"
" else if (--d == 0)\n"
" ;\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout_str());
}
void knownConditionFloating() {
check("void foo() {\n" // #11199
" float f = 1.0;\n"
" if (f > 1.0f) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:11]: (style) Condition 'f>1.0f' is always false [knownConditionTrueFalse]\n", errout_str());
check("void foo() {\n" // #11199
" float f = 1.0;\n"
" if (f > 1.0L) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:11]: (style) Condition 'f>1.0L' is always false [knownConditionTrueFalse]\n", errout_str());
check("void foo() {\n" // #11199
" float f = 1.0f;\n"
" if (f > 1.0) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:11]: (style) Condition 'f>1.0' is always false [knownConditionTrueFalse]\n", errout_str());
check("void foo() {\n" // #11199
" float f = 1.0f;\n"
" if (f > 1.0L) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:11]: (style) Condition 'f>1.0L' is always false [knownConditionTrueFalse]\n", errout_str());
check("void foo() {\n" // #11199
" float f = 1.0L;\n"
" if (f > 1.0) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:11]: (style) Condition 'f>1.0' is always false [knownConditionTrueFalse]\n", errout_str());
check("void foo() {\n" // #11199
" float f = 1.0L;\n"
" if (f > 1.0f) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:11]: (style) Condition 'f>1.0f' is always false [knownConditionTrueFalse]\n", errout_str());
check("void foo() {\n" // #11201
" float f = 0x1.4p+3;\n" // hex fraction 1.4 (decimal 1.25) scaled by 2^3, that is 10.0
" if (f > 9.9) {}\n"
" if (f < 9.9) {}\n"
"}\n");
ASSERT_EQUALS(
"[test.cpp:3:11]: (style) Condition 'f>9.9' is always true [knownConditionTrueFalse]\n"
"[test.cpp:4:11]: (style) Condition 'f<9.9' is always false [knownConditionTrueFalse]\n",
errout_str());
check("void foo() {\n" // #12330
" double d = 1.0;\n"
" if (d < 0.0) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:11]: (style) Condition 'd<0.0' is always false [knownConditionTrueFalse]\n", errout_str());
check("void foo() {\n" // #12330
" long double ld = 1.0;\n"
" if (ld < 0.0) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:12]: (style) Condition 'ld<0.0' is always false [knownConditionTrueFalse]\n", errout_str());
check("void foo() {\n" // #12330
" float f = 1.0;\n"
" if (f < 0.0) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:11]: (style) Condition 'f<0.0' is always false [knownConditionTrueFalse]\n", errout_str());
check("void foo() {\n" // #12774
" float f = 1.0f;\n"
" if (f > 1.01f) {}\n"
"}\n");
ASSERT_EQUALS(
"[test.cpp:3:11]: (style) Condition 'f>1.01f' is always false [knownConditionTrueFalse]\n",
errout_str());
check("void foo() {\n" // #12774
" float f = 1.0;\n"
" if (f > 1.01) {}\n"
"}\n");
ASSERT_EQUALS(
"[test.cpp:3:11]: (style) Condition 'f>1.01' is always false [knownConditionTrueFalse]\n",
errout_str());
check("void foo() {\n"
" float f = 1.0f;\n"
" if (f > 1) {}\n"
"}\n");
ASSERT_EQUALS(
"[test.cpp:3:11]: (style) Condition 'f>1' is always false [knownConditionTrueFalse]\n",
errout_str());
check("void foo() {\n" // #13508
" float f = 1.0f;\n"
" if (f > 1.00f) {}\n"
"}\n");
TODO_ASSERT_EQUALS(
"[test.cpp:3]: (style) Condition 'f>1.00f' is always false\n",
"",
errout_str());
check("void foo() {\n"
" float f = 1.0;\n"
" if (f > 1) {}\n"
"}\n");
ASSERT_EQUALS(
"[test.cpp:3:11]: (style) Condition 'f>1' is always false [knownConditionTrueFalse]\n",
errout_str());
check("void foo() {\n"// #13508
" float f = 1.0;\n"
" if (f > 1.00) {}\n"
"}\n");
TODO_ASSERT_EQUALS(
"[test.cpp:3]: (style) Condition 'f>1.00' is always false\n",
"",
errout_str());
check("void foo() {\n" // #13506
" float nf = -1.0;\n"
" if (nf > +1.0) {}\n"
"}\n");
ASSERT_EQUALS(
"[test.cpp:3:12]: (style) Condition 'nf>+1.0' is always false [knownConditionTrueFalse]\n",
errout_str());
check("void foo() {\n" // #11200
" float f = 1.0;\n"
" if (f > -1.0) {}\n"
"}\n");
ASSERT_EQUALS(
"[test.cpp:3:11]: (style) Condition 'f>-1.0' is always true [knownConditionTrueFalse]\n",
errout_str());
check("void foo() {\n" // #13508
" float f = 1.0;\n"
" if (f > 1.0) {}\n"
"}\n");
TODO_ASSERT_EQUALS(
"[test.cpp:3]: (style) Condition 'f>1.0' is always true\n",
"",
errout_str());
check("void foo() {\n" // #11200
" float pf = +1.0;\n"
" if (pf > -1.0) {}\n"
"}\n");
ASSERT_EQUALS(
"[test.cpp:3:12]: (style) Condition 'pf>-1.0' is always true [knownConditionTrueFalse]\n",
errout_str());
check("void foo() {\n" // #13508
" float pf = +1.0;\n"
" if (pf > 1.0) {}\n"
"}\n");
TODO_ASSERT_EQUALS(
"[test.cpp:3]: (style) Condition 'pf>1.0' is always true\n",
"",
errout_str());
check("void foo() {\n" // #11200
" float nf = -1.0;\n"
" if (nf > 1.0) {}\n"
"}\n");
ASSERT_EQUALS(
"[test.cpp:3:12]: (style) Condition 'nf>1.0' is always false [knownConditionTrueFalse]\n",
errout_str());
check("void foo() {\n" // / #13508
" float nf = -1.0;\n"
" if (nf > -1.0) {}\n"
"}\n");
TODO_ASSERT_EQUALS(
"[test.cpp:3]: (style) Condition 'nf>-1.0' is always false\n",
"",
errout_str());
}
};
REGISTER_TEST(TestCondition)