incorrectLogicOperator: fixed FP when comparing char values. improved handling of float comparisons.
This commit is contained in:
parent
807f62520c
commit
4027848761
|
@ -1349,7 +1349,10 @@ void CheckOther::checkIncorrectLogicOperator()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MathLib::isInt(value1) != MathLib::isInt(value2))
|
// Only float and int values are currently handled
|
||||||
|
if (!MathLib::isInt(value1) && !MathLib::isFloat(value1))
|
||||||
|
continue;
|
||||||
|
if (!MathLib::isInt(value2) && !MathLib::isFloat(value2))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const std::set<std::string> constStandardFunctions;
|
const std::set<std::string> constStandardFunctions;
|
||||||
|
@ -1360,6 +1363,11 @@ void CheckOther::checkIncorrectLogicOperator()
|
||||||
|
|
||||||
const bool isfloat = MathLib::isFloat(value1) || MathLib::isFloat(value2);
|
const bool isfloat = MathLib::isFloat(value1) || MathLib::isFloat(value2);
|
||||||
|
|
||||||
|
// don't check floating point equality comparisons. that is bad
|
||||||
|
// and deserves different warnings.
|
||||||
|
if (isfloat && (op1=="==" || op1=="!=" || op2=="==" || op2=="!="))
|
||||||
|
continue;
|
||||||
|
|
||||||
// evaluate if expression is always true/false
|
// evaluate if expression is always true/false
|
||||||
bool alwaysTrue = true, alwaysFalse = true;
|
bool alwaysTrue = true, alwaysFalse = true;
|
||||||
bool firstTrue = true, secondTrue = true;
|
bool firstTrue = true, secondTrue = true;
|
||||||
|
@ -1367,7 +1375,28 @@ void CheckOther::checkIncorrectLogicOperator()
|
||||||
for (int selvalue = 1; selvalue <= 2; selvalue++) {
|
for (int selvalue = 1; selvalue <= 2; selvalue++) {
|
||||||
bool res1,res2;
|
bool res1,res2;
|
||||||
if (isfloat) {
|
if (isfloat) {
|
||||||
const double varvalue = MathLib::toDoubleNumber(selvalue==1 ? value1 : value2) + (double)offset;
|
const double d1 = MathLib::toDoubleNumber(value1);
|
||||||
|
const double d2 = MathLib::toDoubleNumber(value2);
|
||||||
|
double varvalue = (selvalue==1) ? d1 : d2;
|
||||||
|
switch (offset) {
|
||||||
|
case -3:
|
||||||
|
varvalue /= 2.0;
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
varvalue *= 2.0;
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
varvalue -= 1.0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
varvalue += 1.0;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
varvalue = (d1 + d2) / 2.0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
res1 = checkFloatRelation(op1, varvalue, MathLib::toDoubleNumber(value1));
|
res1 = checkFloatRelation(op1, varvalue, MathLib::toDoubleNumber(value1));
|
||||||
res2 = checkFloatRelation(op2, varvalue, MathLib::toDoubleNumber(value2));
|
res2 = checkFloatRelation(op2, varvalue, MathLib::toDoubleNumber(value2));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -129,6 +129,7 @@ private:
|
||||||
TEST_CASE(incorrectLogicOperator3);
|
TEST_CASE(incorrectLogicOperator3);
|
||||||
TEST_CASE(incorrectLogicOperator4);
|
TEST_CASE(incorrectLogicOperator4);
|
||||||
TEST_CASE(incorrectLogicOperator5);
|
TEST_CASE(incorrectLogicOperator5);
|
||||||
|
TEST_CASE(incorrectLogicOperator6);
|
||||||
TEST_CASE(secondAlwaysTrueFalseWhenFirstTrueError);
|
TEST_CASE(secondAlwaysTrueFalseWhenFirstTrueError);
|
||||||
TEST_CASE(incorrectLogicOp_condSwapping);
|
TEST_CASE(incorrectLogicOp_condSwapping);
|
||||||
TEST_CASE(sameExpression);
|
TEST_CASE(sameExpression);
|
||||||
|
@ -3835,7 +3836,8 @@ private:
|
||||||
" a++;\n"
|
" a++;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
);
|
);
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x == 1.0 && x == 3.0.\n", errout.str());
|
//ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x == 1.0 && x == 3.0.\n", errout.str());
|
||||||
|
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"
|
check("void f(float x) {\n"
|
||||||
" if (x == 1 && x == 1.0)\n"
|
" if (x == 1 && x == 1.0)\n"
|
||||||
|
@ -3863,6 +3865,13 @@ private:
|
||||||
" a++;\n"
|
" a++;\n"
|
||||||
"}\n"
|
"}\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"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void f(int x) {\n"
|
check("void f(int x) {\n"
|
||||||
|
@ -4047,13 +4056,25 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void incorrectLogicOperator5() {
|
void incorrectLogicOperator5() { // complex expressions
|
||||||
check("void f(int x) {\n"
|
check("void f(int x) {\n"
|
||||||
" if (x+3 > 2 || x+3 < 10) {}\n"
|
" if (x+3 > 2 || x+3 < 10) {}\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: EXPR > 2 || EXPR < 10.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: EXPR > 2 || EXPR < 10.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void incorrectLogicOperator6() { // char literals
|
||||||
|
check("void f(char x) {\n"
|
||||||
|
" if (x == '1' || x == '2') {}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f(char x) {\n"
|
||||||
|
" if (x == '1' && x == '2') {}\n"
|
||||||
|
"}");
|
||||||
|
TODO_ASSERT_EQUALS("error", "", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void secondAlwaysTrueFalseWhenFirstTrueError() {
|
void secondAlwaysTrueFalseWhenFirstTrueError() {
|
||||||
check("void f(int x) {\n"
|
check("void f(int x) {\n"
|
||||||
" if (x > 5 && x != 1)\n"
|
" if (x > 5 && x != 1)\n"
|
||||||
|
|
Loading…
Reference in New Issue