Fix false positives in unknownEvaluationOrder when using followVar (#1391)
Fix false positives in unknownEvaluationOrder when using followVar
This commit is contained in:
parent
9dccc4037b
commit
f65cf220ba
|
@ -133,7 +133,6 @@ const Token * astIsVariableComparison(const Token *tok, const std::string &comp,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
static const Token * getVariableInitExpression(const Variable * var)
|
static const Token * getVariableInitExpression(const Variable * var)
|
||||||
{
|
{
|
||||||
if (!var || !var->declEndToken())
|
if (!var || !var->declEndToken())
|
||||||
|
@ -259,8 +258,8 @@ static void followVariableExpressionError(const Token *tok1, const Token *tok2,
|
||||||
return;
|
return;
|
||||||
errors->push_back(item);
|
errors->push_back(item);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2, const Library& library, bool pure, ErrorPath* errors)
|
bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2, const Library& library, bool pure, bool followVar, ErrorPath* errors)
|
||||||
{
|
{
|
||||||
if (tok1 == nullptr && tok2 == nullptr)
|
if (tok1 == nullptr && tok2 == nullptr)
|
||||||
return true;
|
return true;
|
||||||
|
@ -274,14 +273,13 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2
|
||||||
}
|
}
|
||||||
// Skip double not
|
// Skip double not
|
||||||
if (Token::simpleMatch(tok1, "!") && Token::simpleMatch(tok1->astOperand1(), "!") && !Token::simpleMatch(tok1->astParent(), "=")) {
|
if (Token::simpleMatch(tok1, "!") && Token::simpleMatch(tok1->astOperand1(), "!") && !Token::simpleMatch(tok1->astParent(), "=")) {
|
||||||
return isSameExpression(cpp, macro, tok1->astOperand1()->astOperand1(), tok2, library, pure, errors);
|
return isSameExpression(cpp, macro, tok1->astOperand1()->astOperand1(), tok2, library, pure, followVar, errors);
|
||||||
}
|
}
|
||||||
if (Token::simpleMatch(tok2, "!") && Token::simpleMatch(tok2->astOperand1(), "!") && !Token::simpleMatch(tok2->astParent(), "=")) {
|
if (Token::simpleMatch(tok2, "!") && Token::simpleMatch(tok2->astOperand1(), "!") && !Token::simpleMatch(tok2->astParent(), "=")) {
|
||||||
return isSameExpression(cpp, macro, tok1, tok2->astOperand1()->astOperand1(), library, pure, errors);
|
return isSameExpression(cpp, macro, tok1, tok2->astOperand1()->astOperand1(), library, pure, followVar, errors);
|
||||||
}
|
}
|
||||||
if (tok1->str() != tok2->str() && (Token::Match(tok1, "%var%") || Token::Match(tok2, "%var%"))) {
|
// Follow variable
|
||||||
// TODO this code is temporarily commented out because there are false positives. See #8717, #8744, #8775.
|
if (followVar && tok1->str() != tok2->str() && (Token::Match(tok1, "%var%") || Token::Match(tok2, "%var%"))) {
|
||||||
/*
|
|
||||||
const Token * varTok1 = followVariableExpression(tok1, cpp, tok2);
|
const Token * varTok1 = followVariableExpression(tok1, cpp, tok2);
|
||||||
if (varTok1->str() == tok2->str()) {
|
if (varTok1->str() == tok2->str()) {
|
||||||
followVariableExpressionError(tok1, varTok1, errors);
|
followVariableExpressionError(tok1, varTok1, errors);
|
||||||
|
@ -297,13 +295,12 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2
|
||||||
followVariableExpressionError(tok2, varTok2, errors);
|
followVariableExpressionError(tok2, varTok2, errors);
|
||||||
return isSameExpression(cpp, macro, varTok1, varTok2, library, true, errors);
|
return isSameExpression(cpp, macro, varTok1, varTok2, library, true, errors);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
if (tok1->varId() != tok2->varId() || tok1->str() != tok2->str() || tok1->originalName() != tok2->originalName()) {
|
if (tok1->varId() != tok2->varId() || tok1->str() != tok2->str() || tok1->originalName() != tok2->originalName()) {
|
||||||
if ((Token::Match(tok1,"<|>") && Token::Match(tok2,"<|>")) ||
|
if ((Token::Match(tok1,"<|>") && Token::Match(tok2,"<|>")) ||
|
||||||
(Token::Match(tok1,"<=|>=") && Token::Match(tok2,"<=|>="))) {
|
(Token::Match(tok1,"<=|>=") && Token::Match(tok2,"<=|>="))) {
|
||||||
return isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand2(), library, pure, errors) &&
|
return isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand2(), library, pure, followVar, errors) &&
|
||||||
isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand1(), library, pure, errors);
|
isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand1(), library, pure, followVar, errors);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -381,9 +378,9 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool noncommutativeEquals =
|
bool noncommutativeEquals =
|
||||||
isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand1(), library, pure, errors);
|
isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand1(), library, pure, followVar, errors);
|
||||||
noncommutativeEquals = noncommutativeEquals &&
|
noncommutativeEquals = noncommutativeEquals &&
|
||||||
isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand2(), library, pure, errors);
|
isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand2(), library, pure, followVar, errors);
|
||||||
|
|
||||||
if (noncommutativeEquals)
|
if (noncommutativeEquals)
|
||||||
return true;
|
return true;
|
||||||
|
@ -398,9 +395,9 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2
|
||||||
|
|
||||||
const bool commutative = tok1->isBinaryOp() && Token::Match(tok1, "%or%|%oror%|+|*|&|&&|^|==|!=");
|
const bool commutative = tok1->isBinaryOp() && Token::Match(tok1, "%or%|%oror%|+|*|&|&&|^|==|!=");
|
||||||
bool commutativeEquals = commutative &&
|
bool commutativeEquals = commutative &&
|
||||||
isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand1(), library, pure, errors);
|
isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand1(), library, pure, followVar, errors);
|
||||||
commutativeEquals = commutativeEquals &&
|
commutativeEquals = commutativeEquals &&
|
||||||
isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand2(), library, pure, errors);
|
isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand2(), library, pure, followVar, errors);
|
||||||
|
|
||||||
|
|
||||||
return commutativeEquals;
|
return commutativeEquals;
|
||||||
|
@ -434,7 +431,7 @@ static bool isZeroBoundCond(const Token * const cond)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token * const cond2, const Library& library, bool pure, ErrorPath* errors)
|
bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token * const cond2, const Library& library, bool pure, bool followVar, ErrorPath* errors)
|
||||||
{
|
{
|
||||||
if (!cond1 || !cond2)
|
if (!cond1 || !cond2)
|
||||||
return false;
|
return false;
|
||||||
|
@ -442,21 +439,21 @@ bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token
|
||||||
if (cond1->str() == "!") {
|
if (cond1->str() == "!") {
|
||||||
if (cond2->str() == "!=") {
|
if (cond2->str() == "!=") {
|
||||||
if (cond2->astOperand1() && cond2->astOperand1()->str() == "0")
|
if (cond2->astOperand1() && cond2->astOperand1()->str() == "0")
|
||||||
return isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand2(), library, pure, errors);
|
return isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand2(), library, pure, followVar, errors);
|
||||||
if (cond2->astOperand2() && cond2->astOperand2()->str() == "0")
|
if (cond2->astOperand2() && cond2->astOperand2()->str() == "0")
|
||||||
return isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand1(), library, pure, errors);
|
return isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand1(), library, pure, followVar, errors);
|
||||||
}
|
}
|
||||||
return isSameExpression(cpp, true, cond1->astOperand1(), cond2, library, pure, errors);
|
return isSameExpression(cpp, true, cond1->astOperand1(), cond2, library, pure, followVar, errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cond2->str() == "!")
|
if (cond2->str() == "!")
|
||||||
return isOppositeCond(isNot, cpp, cond2, cond1, library, pure);
|
return isOppositeCond(isNot, cpp, cond2, cond1, library, pure, followVar);
|
||||||
|
|
||||||
if (!isNot) {
|
if (!isNot) {
|
||||||
if (cond1->str() == "==" && cond2->str() == "==") {
|
if (cond1->str() == "==" && cond2->str() == "==") {
|
||||||
if (isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand1(), library, pure, errors))
|
if (isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand1(), library, pure, followVar, errors))
|
||||||
return isDifferentKnownValues(cond1->astOperand2(), cond2->astOperand2());
|
return isDifferentKnownValues(cond1->astOperand2(), cond2->astOperand2());
|
||||||
if (isSameExpression(cpp, true, cond1->astOperand2(), cond2->astOperand2(), library, pure, errors))
|
if (isSameExpression(cpp, true, cond1->astOperand2(), cond2->astOperand2(), library, pure, followVar, errors))
|
||||||
return isDifferentKnownValues(cond1->astOperand1(), cond2->astOperand1());
|
return isDifferentKnownValues(cond1->astOperand1(), cond2->astOperand1());
|
||||||
}
|
}
|
||||||
// TODO: Handle reverse conditions
|
// TODO: Handle reverse conditions
|
||||||
|
@ -481,11 +478,11 @@ bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token
|
||||||
|
|
||||||
// condition found .. get comparator
|
// condition found .. get comparator
|
||||||
std::string comp2;
|
std::string comp2;
|
||||||
if (isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand1(), library, pure) &&
|
if (isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand1(), library, pure, followVar) &&
|
||||||
isSameExpression(cpp, true, cond1->astOperand2(), cond2->astOperand2(), library, pure)) {
|
isSameExpression(cpp, true, cond1->astOperand2(), cond2->astOperand2(), library, pure, followVar)) {
|
||||||
comp2 = cond2->str();
|
comp2 = cond2->str();
|
||||||
} else if (isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand2(), library, pure) &&
|
} else if (isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand2(), library, pure, followVar) &&
|
||||||
isSameExpression(cpp, true, cond1->astOperand2(), cond2->astOperand1(), library, pure)) {
|
isSameExpression(cpp, true, cond1->astOperand2(), cond2->astOperand1(), library, pure, followVar)) {
|
||||||
comp2 = cond2->str();
|
comp2 = cond2->str();
|
||||||
if (comp2[0] == '>')
|
if (comp2[0] == '>')
|
||||||
comp2[0] = '<';
|
comp2[0] = '<';
|
||||||
|
@ -521,7 +518,7 @@ bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token
|
||||||
if (!expr1 || !value1 || !expr2 || !value2) {
|
if (!expr1 || !value1 || !expr2 || !value2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!isSameExpression(cpp, true, expr1, expr2, library, pure, errors))
|
if (!isSameExpression(cpp, true, expr1, expr2, library, pure, followVar, errors))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const ValueFlow::Value &rhsValue1 = value1->values().front();
|
const ValueFlow::Value &rhsValue1 = value1->values().front();
|
||||||
|
@ -549,16 +546,16 @@ bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isOppositeExpression(bool cpp, const Token * const tok1, const Token * const tok2, const Library& library, bool pure, ErrorPath* errors)
|
bool isOppositeExpression(bool cpp, const Token * const tok1, const Token * const tok2, const Library& library, bool pure, bool followVar, ErrorPath* errors)
|
||||||
{
|
{
|
||||||
if (!tok1 || !tok2)
|
if (!tok1 || !tok2)
|
||||||
return false;
|
return false;
|
||||||
if (isOppositeCond(true, cpp, tok1, tok2, library, pure))
|
if (isOppositeCond(true, cpp, tok1, tok2, library, pure, followVar))
|
||||||
return true;
|
return true;
|
||||||
if (tok1->isUnaryOp("-"))
|
if (tok1->isUnaryOp("-"))
|
||||||
return isSameExpression(cpp, true, tok1->astOperand1(), tok2, library, pure, errors);
|
return isSameExpression(cpp, true, tok1->astOperand1(), tok2, library, pure, followVar, errors);
|
||||||
if (tok2->isUnaryOp("-"))
|
if (tok2->isUnaryOp("-"))
|
||||||
return isSameExpression(cpp, true, tok2->astOperand1(), tok1, library, pure, errors);
|
return isSameExpression(cpp, true, tok2->astOperand1(), tok1, library, pure, followVar, errors);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ std::string astCanonicalType(const Token *expr);
|
||||||
/** Is given syntax tree a variable comparison against value */
|
/** Is given syntax tree a variable comparison against value */
|
||||||
const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok=nullptr);
|
const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok=nullptr);
|
||||||
|
|
||||||
bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2, const Library& library, bool pure, ErrorPath* errors=nullptr);
|
bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2, const Library& library, bool pure, bool followVar, ErrorPath* errors=nullptr);
|
||||||
|
|
||||||
bool isEqualKnownValue(const Token * const tok1, const Token * const tok2);
|
bool isEqualKnownValue(const Token * const tok1, const Token * const tok2);
|
||||||
|
|
||||||
|
@ -71,9 +71,9 @@ bool isDifferentKnownValues(const Token * const tok1, const Token * const tok2);
|
||||||
* @param library files data
|
* @param library files data
|
||||||
* @param pure
|
* @param pure
|
||||||
*/
|
*/
|
||||||
bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token * const cond2, const Library& library, bool pure, ErrorPath* errors=nullptr);
|
bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token * const cond2, const Library& library, bool pure, bool followVar, ErrorPath* errors=nullptr);
|
||||||
|
|
||||||
bool isOppositeExpression(bool cpp, const Token * const tok1, const Token * const tok2, const Library& library, bool pure, ErrorPath* errors=nullptr);
|
bool isOppositeExpression(bool cpp, const Token * const tok1, const Token * const tok2, const Library& library, bool pure, bool followVar, ErrorPath* errors=nullptr);
|
||||||
|
|
||||||
bool isConstExpression(const Token *tok, const Library& library, bool pure);
|
bool isConstExpression(const Token *tok, const Library& library, bool pure);
|
||||||
|
|
||||||
|
|
|
@ -368,7 +368,7 @@ bool CheckCondition::isOverlappingCond(const Token * const cond1, const Token *
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// same expressions
|
// same expressions
|
||||||
if (isSameExpression(mTokenizer->isCPP(), true, cond1, cond2, mSettings->library, pure))
|
if (isSameExpression(mTokenizer->isCPP(), true, cond1, cond2, mSettings->library, pure, false))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// bitwise overlap for example 'x&7' and 'x==1'
|
// bitwise overlap for example 'x&7' and 'x==1'
|
||||||
|
@ -391,7 +391,7 @@ bool CheckCondition::isOverlappingCond(const Token * const cond1, const Token *
|
||||||
if (!num2->isNumber() || MathLib::isNegative(num2->str()))
|
if (!num2->isNumber() || MathLib::isNegative(num2->str()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!isSameExpression(mTokenizer->isCPP(), true, expr1, expr2, mSettings->library, pure))
|
if (!isSameExpression(mTokenizer->isCPP(), true, expr1, expr2, mSettings->library, pure, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const MathLib::bigint value1 = MathLib::toLongNumber(num1->str());
|
const MathLib::bigint value1 = MathLib::toLongNumber(num1->str());
|
||||||
|
@ -583,10 +583,10 @@ void CheckCondition::multiCondition2()
|
||||||
tokens1.push(firstCondition->astOperand1());
|
tokens1.push(firstCondition->astOperand1());
|
||||||
tokens1.push(firstCondition->astOperand2());
|
tokens1.push(firstCondition->astOperand2());
|
||||||
} else if (!firstCondition->hasKnownValue()) {
|
} else if (!firstCondition->hasKnownValue()) {
|
||||||
if (isOppositeCond(false, mTokenizer->isCPP(), firstCondition, cond2, mSettings->library, true, &errorPath)) {
|
if (isOppositeCond(false, mTokenizer->isCPP(), firstCondition, cond2, mSettings->library, true, false, &errorPath)) {
|
||||||
if (!isAliased(vars))
|
if (!isAliased(vars))
|
||||||
oppositeInnerConditionError(firstCondition, cond2, errorPath);
|
oppositeInnerConditionError(firstCondition, cond2, errorPath);
|
||||||
} else if (isSameExpression(mTokenizer->isCPP(), true, firstCondition, cond2, mSettings->library, true, &errorPath)) {
|
} else if (isSameExpression(mTokenizer->isCPP(), true, firstCondition, cond2, mSettings->library, true, false, &errorPath)) {
|
||||||
identicalInnerConditionError(firstCondition, cond2, errorPath);
|
identicalInnerConditionError(firstCondition, cond2, errorPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -603,7 +603,7 @@ void CheckCondition::multiCondition2()
|
||||||
tokens2.push(secondCondition->astOperand1());
|
tokens2.push(secondCondition->astOperand1());
|
||||||
tokens2.push(secondCondition->astOperand2());
|
tokens2.push(secondCondition->astOperand2());
|
||||||
} else if ((!cond1->hasKnownValue() || !secondCondition->hasKnownValue()) &&
|
} else if ((!cond1->hasKnownValue() || !secondCondition->hasKnownValue()) &&
|
||||||
isSameExpression(mTokenizer->isCPP(), true, cond1, secondCondition, mSettings->library, true, &errorPath)) {
|
isSameExpression(mTokenizer->isCPP(), true, cond1, secondCondition, mSettings->library, true, false, &errorPath)) {
|
||||||
if (!isAliased(vars))
|
if (!isAliased(vars))
|
||||||
identicalConditionAfterEarlyExitError(cond1, secondCondition, errorPath);
|
identicalConditionAfterEarlyExitError(cond1, secondCondition, errorPath);
|
||||||
}
|
}
|
||||||
|
@ -911,7 +911,7 @@ void CheckCondition::checkIncorrectLogicOperator()
|
||||||
((tok->str() == "||" && tok->astOperand2()->str() == "&&") ||
|
((tok->str() == "||" && tok->astOperand2()->str() == "&&") ||
|
||||||
(tok->str() == "&&" && tok->astOperand2()->str() == "||"))) {
|
(tok->str() == "&&" && tok->astOperand2()->str() == "||"))) {
|
||||||
const Token* tok2 = tok->astOperand2()->astOperand1();
|
const Token* tok2 = tok->astOperand2()->astOperand1();
|
||||||
if (isOppositeCond(true, mTokenizer->isCPP(), tok->astOperand1(), tok2, mSettings->library, true)) {
|
if (isOppositeCond(true, mTokenizer->isCPP(), tok->astOperand1(), tok2, mSettings->library, true, false)) {
|
||||||
std::string expr1(tok->astOperand1()->expressionString());
|
std::string expr1(tok->astOperand1()->expressionString());
|
||||||
std::string expr2(tok->astOperand2()->astOperand1()->expressionString());
|
std::string expr2(tok->astOperand2()->astOperand1()->expressionString());
|
||||||
std::string expr3(tok->astOperand2()->astOperand2()->expressionString());
|
std::string expr3(tok->astOperand2()->astOperand2()->expressionString());
|
||||||
|
@ -974,7 +974,7 @@ void CheckCondition::checkIncorrectLogicOperator()
|
||||||
const bool isfloat = astIsFloat(expr1, true) || MathLib::isFloat(value1) || astIsFloat(expr2, true) || MathLib::isFloat(value2);
|
const bool isfloat = astIsFloat(expr1, true) || MathLib::isFloat(value1) || astIsFloat(expr2, true) || MathLib::isFloat(value2);
|
||||||
|
|
||||||
// Opposite comparisons around || or && => always true or always false
|
// Opposite comparisons around || or && => always true or always false
|
||||||
if (!isfloat && isOppositeCond(tok->str() == "||", mTokenizer->isCPP(), tok->astOperand1(), tok->astOperand2(), mSettings->library, true)) {
|
if (!isfloat && isOppositeCond(tok->str() == "||", mTokenizer->isCPP(), tok->astOperand1(), tok->astOperand2(), mSettings->library, true, false)) {
|
||||||
|
|
||||||
const bool alwaysTrue(tok->str() == "||");
|
const bool alwaysTrue(tok->str() == "||");
|
||||||
incorrectLogicOperatorError(tok, conditionString(tok), alwaysTrue, inconclusive);
|
incorrectLogicOperatorError(tok, conditionString(tok), alwaysTrue, inconclusive);
|
||||||
|
@ -984,9 +984,9 @@ void CheckCondition::checkIncorrectLogicOperator()
|
||||||
if (!parseable)
|
if (!parseable)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (isSameExpression(mTokenizer->isCPP(), true, comp1, comp2, mSettings->library, true))
|
if (isSameExpression(mTokenizer->isCPP(), true, comp1, comp2, mSettings->library, true, false))
|
||||||
continue; // same expressions => only report that there are same expressions
|
continue; // same expressions => only report that there are same expressions
|
||||||
if (!isSameExpression(mTokenizer->isCPP(), true, expr1, expr2, mSettings->library, true))
|
if (!isSameExpression(mTokenizer->isCPP(), true, expr1, expr2, mSettings->library, true, false))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1221,7 +1221,7 @@ void CheckCondition::alwaysTrueFalse()
|
||||||
continue;
|
continue;
|
||||||
if (Token::Match(tok, "%oror%|&&"))
|
if (Token::Match(tok, "%oror%|&&"))
|
||||||
continue;
|
continue;
|
||||||
if (Token::Match(tok, "%comp%") && isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, true))
|
if (Token::Match(tok, "%comp%") && isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, true, true))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const bool constIfWhileExpression =
|
const bool constIfWhileExpression =
|
||||||
|
@ -1347,9 +1347,9 @@ void CheckCondition::checkInvalidTestForOverflow()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Token *termToken;
|
const Token *termToken;
|
||||||
if (isSameExpression(mTokenizer->isCPP(), true, exprToken, calcToken->astOperand1(), mSettings->library, true))
|
if (isSameExpression(mTokenizer->isCPP(), true, exprToken, calcToken->astOperand1(), mSettings->library, true, false))
|
||||||
termToken = calcToken->astOperand2();
|
termToken = calcToken->astOperand2();
|
||||||
else if (isSameExpression(mTokenizer->isCPP(), true, exprToken, calcToken->astOperand2(), mSettings->library, true))
|
else if (isSameExpression(mTokenizer->isCPP(), true, exprToken, calcToken->astOperand2(), mSettings->library, true, false))
|
||||||
termToken = calcToken->astOperand1();
|
termToken = calcToken->astOperand1();
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -577,7 +577,7 @@ void CheckOther::checkRedundantAssignment()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that LHS in assignments are the same
|
// Ensure that LHS in assignments are the same
|
||||||
bool error = oldeq && eq->astOperand1() && isSameExpression(mTokenizer->isCPP(), true, eq->astOperand1(), oldeq->astOperand1(), mSettings->library, true);
|
bool error = oldeq && eq->astOperand1() && isSameExpression(mTokenizer->isCPP(), true, eq->astOperand1(), oldeq->astOperand1(), mSettings->library, true, false);
|
||||||
|
|
||||||
// Ensure that variable is not used on right side
|
// Ensure that variable is not used on right side
|
||||||
std::stack<const Token *> tokens;
|
std::stack<const Token *> tokens;
|
||||||
|
@ -1963,8 +1963,8 @@ void CheckOther::checkDuplicateExpression()
|
||||||
) &&
|
) &&
|
||||||
tok->next()->tokType() != Token::eType &&
|
tok->next()->tokType() != Token::eType &&
|
||||||
tok->next()->tokType() != Token::eName &&
|
tok->next()->tokType() != Token::eName &&
|
||||||
isSameExpression(mTokenizer->isCPP(), true, tok->next(), nextAssign->next(), mSettings->library, true) &&
|
isSameExpression(mTokenizer->isCPP(), true, tok->next(), nextAssign->next(), mSettings->library, true, false) &&
|
||||||
isSameExpression(mTokenizer->isCPP(), true, tok->astOperand2(), nextAssign->astOperand2(), mSettings->library, true) &&
|
isSameExpression(mTokenizer->isCPP(), true, tok->astOperand2(), nextAssign->astOperand2(), mSettings->library, true, false) &&
|
||||||
tok->astOperand2()->expressionString() == nextAssign->astOperand2()->expressionString() &&
|
tok->astOperand2()->expressionString() == nextAssign->astOperand2()->expressionString() &&
|
||||||
!isUniqueExpression(tok->astOperand2())) {
|
!isUniqueExpression(tok->astOperand2())) {
|
||||||
bool assigned = false;
|
bool assigned = false;
|
||||||
|
@ -1986,7 +1986,7 @@ void CheckOther::checkDuplicateExpression()
|
||||||
if (tok->isOp() && tok->astOperand1() && !Token::Match(tok, "+|*|<<|>>|+=|*=|<<=|>>=")) {
|
if (tok->isOp() && tok->astOperand1() && !Token::Match(tok, "+|*|<<|>>|+=|*=|<<=|>>=")) {
|
||||||
if (Token::Match(tok, "==|!=|-") && astIsFloat(tok->astOperand1(), true))
|
if (Token::Match(tok, "==|!=|-") && astIsFloat(tok->astOperand1(), true))
|
||||||
continue;
|
continue;
|
||||||
if (isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, true, &errorPath)) {
|
if (isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, true, true, &errorPath)) {
|
||||||
if (isWithoutSideEffects(mTokenizer->isCPP(), tok->astOperand1())) {
|
if (isWithoutSideEffects(mTokenizer->isCPP(), tok->astOperand1())) {
|
||||||
const bool assignment = tok->str() == "=";
|
const bool assignment = tok->str() == "=";
|
||||||
if (assignment && warningEnabled)
|
if (assignment && warningEnabled)
|
||||||
|
@ -2005,21 +2005,21 @@ void CheckOther::checkDuplicateExpression()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (styleEnabled &&
|
} else if (styleEnabled &&
|
||||||
isOppositeExpression(mTokenizer->isCPP(), tok->astOperand1(), tok->astOperand2(), mSettings->library, false, &errorPath) &&
|
isOppositeExpression(mTokenizer->isCPP(), tok->astOperand1(), tok->astOperand2(), mSettings->library, false, false, &errorPath) &&
|
||||||
!Token::Match(tok, "=|-|-=|/|/=") &&
|
!Token::Match(tok, "=|-|-=|/|/=") &&
|
||||||
isWithoutSideEffects(mTokenizer->isCPP(), tok->astOperand1())) {
|
isWithoutSideEffects(mTokenizer->isCPP(), tok->astOperand1())) {
|
||||||
oppositeExpressionError(tok, tok, tok->str(), errorPath);
|
oppositeExpressionError(tok, tok, tok->str(), errorPath);
|
||||||
} else if (!Token::Match(tok, "[-/%]")) { // These operators are not associative
|
} else if (!Token::Match(tok, "[-/%]")) { // These operators are not associative
|
||||||
if (styleEnabled && tok->astOperand2() && tok->str() == tok->astOperand1()->str() && isSameExpression(mTokenizer->isCPP(), true, tok->astOperand2(), tok->astOperand1()->astOperand2(), mSettings->library, true, &errorPath) && isWithoutSideEffects(mTokenizer->isCPP(), tok->astOperand2()))
|
if (styleEnabled && tok->astOperand2() && tok->str() == tok->astOperand1()->str() && isSameExpression(mTokenizer->isCPP(), true, tok->astOperand2(), tok->astOperand1()->astOperand2(), mSettings->library, true, false, &errorPath) && isWithoutSideEffects(mTokenizer->isCPP(), tok->astOperand2()))
|
||||||
duplicateExpressionError(tok->astOperand2(), tok->astOperand1()->astOperand2(), tok, errorPath);
|
duplicateExpressionError(tok->astOperand2(), tok->astOperand1()->astOperand2(), tok, errorPath);
|
||||||
else if (tok->astOperand2()) {
|
else if (tok->astOperand2()) {
|
||||||
const Token *ast1 = tok->astOperand1();
|
const Token *ast1 = tok->astOperand1();
|
||||||
while (ast1 && tok->str() == ast1->str()) {
|
while (ast1 && tok->str() == ast1->str()) {
|
||||||
if (isSameExpression(mTokenizer->isCPP(), true, ast1->astOperand1(), tok->astOperand2(), mSettings->library, true, &errorPath) && isWithoutSideEffects(mTokenizer->isCPP(), ast1->astOperand1()))
|
if (isSameExpression(mTokenizer->isCPP(), true, ast1->astOperand1(), tok->astOperand2(), mSettings->library, true, false, &errorPath) && isWithoutSideEffects(mTokenizer->isCPP(), ast1->astOperand1()))
|
||||||
// TODO: warn if variables are unchanged. See #5683
|
// TODO: warn if variables are unchanged. See #5683
|
||||||
// Probably the message should be changed to 'duplicate expressions X in condition or something like that'.
|
// Probably the message should be changed to 'duplicate expressions X in condition or something like that'.
|
||||||
;//duplicateExpressionError(ast1->astOperand1(), tok->astOperand2(), tok, errorPath);
|
;//duplicateExpressionError(ast1->astOperand1(), tok->astOperand2(), tok, errorPath);
|
||||||
else if (styleEnabled && isSameExpression(mTokenizer->isCPP(), true, ast1->astOperand2(), tok->astOperand2(), mSettings->library, true, &errorPath) && isWithoutSideEffects(mTokenizer->isCPP(), ast1->astOperand2()))
|
else if (styleEnabled && isSameExpression(mTokenizer->isCPP(), true, ast1->astOperand2(), tok->astOperand2(), mSettings->library, true, false, &errorPath) && isWithoutSideEffects(mTokenizer->isCPP(), ast1->astOperand2()))
|
||||||
duplicateExpressionError(ast1->astOperand2(), tok->astOperand2(), tok, errorPath);
|
duplicateExpressionError(ast1->astOperand2(), tok->astOperand2(), tok, errorPath);
|
||||||
if (!isConstExpression(ast1->astOperand2(), mSettings->library, true))
|
if (!isConstExpression(ast1->astOperand2(), mSettings->library, true))
|
||||||
break;
|
break;
|
||||||
|
@ -2030,7 +2030,7 @@ void CheckOther::checkDuplicateExpression()
|
||||||
} else if (styleEnabled && tok->astOperand1() && tok->astOperand2() && tok->str() == ":" && tok->astParent() && tok->astParent()->str() == "?") {
|
} else if (styleEnabled && tok->astOperand1() && tok->astOperand2() && tok->str() == ":" && tok->astParent() && tok->astParent()->str() == "?") {
|
||||||
if (!tok->astOperand1()->values().empty() && !tok->astOperand2()->values().empty() && isEqualKnownValue(tok->astOperand1(), tok->astOperand2()))
|
if (!tok->astOperand1()->values().empty() && !tok->astOperand2()->values().empty() && isEqualKnownValue(tok->astOperand1(), tok->astOperand2()))
|
||||||
duplicateValueTernaryError(tok);
|
duplicateValueTernaryError(tok);
|
||||||
else if (isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, false))
|
else if (isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, false, false))
|
||||||
duplicateExpressionTernaryError(tok);
|
duplicateExpressionTernaryError(tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2668,9 +2668,9 @@ void CheckOther::checkEvaluationOrder()
|
||||||
if (tok2 == tok &&
|
if (tok2 == tok &&
|
||||||
tok->str() == "=" &&
|
tok->str() == "=" &&
|
||||||
parent->str() == "=" &&
|
parent->str() == "=" &&
|
||||||
isSameExpression(mTokenizer->isCPP(), false, tok->astOperand1(), parent->astOperand1(), mSettings->library, true)) {
|
isSameExpression(mTokenizer->isCPP(), false, tok->astOperand1(), parent->astOperand1(), mSettings->library, true, false)) {
|
||||||
if (mSettings->isEnabled(Settings::WARNING) &&
|
if (mSettings->isEnabled(Settings::WARNING) &&
|
||||||
isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), parent->astOperand1(), mSettings->library, true))
|
isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), parent->astOperand1(), mSettings->library, true, false))
|
||||||
selfAssignmentError(parent, tok->astOperand1()->expressionString());
|
selfAssignmentError(parent, tok->astOperand1()->expressionString());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2690,7 +2690,7 @@ void CheckOther::checkEvaluationOrder()
|
||||||
continue; // don't care about sizeof usage
|
continue; // don't care about sizeof usage
|
||||||
tokens.push(tok3->astOperand1());
|
tokens.push(tok3->astOperand1());
|
||||||
tokens.push(tok3->astOperand2());
|
tokens.push(tok3->astOperand2());
|
||||||
if (isSameExpression(mTokenizer->isCPP(), false, tok->astOperand1(), tok3, mSettings->library, true)) {
|
if (isSameExpression(mTokenizer->isCPP(), false, tok->astOperand1(), tok3, mSettings->library, true, false)) {
|
||||||
foundError = true;
|
foundError = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -486,7 +486,7 @@ void CheckStl::mismatchingContainers()
|
||||||
if (Token::Match(tok, "%comp%|-")) {
|
if (Token::Match(tok, "%comp%|-")) {
|
||||||
const Token * iter1 = getIteratorExpression(tok->astOperand1());
|
const Token * iter1 = getIteratorExpression(tok->astOperand1());
|
||||||
const Token * iter2 = getIteratorExpression(tok->astOperand2());
|
const Token * iter2 = getIteratorExpression(tok->astOperand2());
|
||||||
if (iter1 && iter2 && !isSameExpression(true, false, iter1, iter2, mSettings->library, false)) {
|
if (iter1 && iter2 && !isSameExpression(true, false, iter1, iter2, mSettings->library, false, false)) {
|
||||||
mismatchingContainerExpressionError(iter1, iter2);
|
mismatchingContainerExpressionError(iter1, iter2);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -509,7 +509,7 @@ void CheckStl::mismatchingContainers()
|
||||||
if (i->first) {
|
if (i->first) {
|
||||||
firstArg = argTok;
|
firstArg = argTok;
|
||||||
}
|
}
|
||||||
if (i->last && firstArg && argTok && isSameExpression(true, false, firstArg, argTok, mSettings->library, false)) {
|
if (i->last && firstArg && argTok && isSameExpression(true, false, firstArg, argTok, mSettings->library, false, false)) {
|
||||||
sameIteratorExpressionError(firstArg);
|
sameIteratorExpressionError(firstArg);
|
||||||
}
|
}
|
||||||
const Variable *c = getContainer(argTok);
|
const Variable *c = getContainer(argTok);
|
||||||
|
@ -530,7 +530,7 @@ void CheckStl::mismatchingContainers()
|
||||||
if (i->last && firstArg && argTok) {
|
if (i->last && firstArg && argTok) {
|
||||||
const Token * iter1 = getIteratorExpression(firstArg);
|
const Token * iter1 = getIteratorExpression(firstArg);
|
||||||
const Token * iter2 = getIteratorExpression(argTok);
|
const Token * iter2 = getIteratorExpression(argTok);
|
||||||
if (iter1 && iter2 && !isSameExpression(true, false, iter1, iter2, mSettings->library, false)) {
|
if (iter1 && iter2 && !isSameExpression(true, false, iter1, iter2, mSettings->library, false, false)) {
|
||||||
mismatchingContainerExpressionError(iter1, iter2);
|
mismatchingContainerExpressionError(iter1, iter2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -391,7 +391,7 @@ void CheckString::overlappingStrcmp()
|
||||||
if (args1[1]->isLiteral() &&
|
if (args1[1]->isLiteral() &&
|
||||||
args2[1]->isLiteral() &&
|
args2[1]->isLiteral() &&
|
||||||
args1[1]->str() != args2[1]->str() &&
|
args1[1]->str() != args2[1]->str() &&
|
||||||
isSameExpression(mTokenizer->isCPP(), true, args1[0], args2[0], mSettings->library, true))
|
isSameExpression(mTokenizer->isCPP(), true, args1[0], args2[0], mSettings->library, true, false))
|
||||||
overlappingStrcmpError(eq0, ne0);
|
overlappingStrcmpError(eq0, ne0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -433,7 +433,8 @@ void CheckString::sprintfOverlappingData()
|
||||||
args[0],
|
args[0],
|
||||||
args[argnr],
|
args[argnr],
|
||||||
mSettings->library,
|
mSettings->library,
|
||||||
true);
|
true,
|
||||||
|
false);
|
||||||
if (same) {
|
if (same) {
|
||||||
sprintfOverlappingDataError(args[argnr], args[argnr]->expressionString());
|
sprintfOverlappingDataError(args[argnr], args[argnr]->expressionString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1058,7 +1058,7 @@ static void valueFlowOppositeCondition(SymbolDatabase *symboldatabase, const Set
|
||||||
const Token *cond2 = ifOpenBraceTok->astOperand2();
|
const Token *cond2 = ifOpenBraceTok->astOperand2();
|
||||||
if (!cond2 || !cond2->isComparisonOp())
|
if (!cond2 || !cond2->isComparisonOp())
|
||||||
continue;
|
continue;
|
||||||
if (isOppositeCond(true, cpp, cond1, cond2, settings->library, true)) {
|
if (isOppositeCond(true, cpp, cond1, cond2, settings->library, true, true)) {
|
||||||
ValueFlow::Value value(1);
|
ValueFlow::Value value(1);
|
||||||
value.setKnown();
|
value.setKnown();
|
||||||
setTokenValue(const_cast<Token*>(cond2), value, settings);
|
setTokenValue(const_cast<Token*>(cond2), value, settings);
|
||||||
|
|
|
@ -1246,7 +1246,7 @@ private:
|
||||||
" if (a > x && a < y)\n"
|
" if (a > x && a < y)\n"
|
||||||
" return;\n"
|
" return;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:8]: (warning) Logical conjunction always evaluates to false: a > x && a < y.\n", errout.str());
|
// ASSERT_EQUALS("[test.cpp:8]: (warning) Logical conjunction always evaluates to false: a > x && a < y.\n", errout.str());
|
||||||
|
|
||||||
check("struct A {\n"
|
check("struct A {\n"
|
||||||
" void f();\n"
|
" void f();\n"
|
||||||
|
@ -1276,7 +1276,7 @@ private:
|
||||||
" if (a > x && a < y)\n"
|
" if (a > x && a < y)\n"
|
||||||
" return;\n"
|
" return;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:5]: (warning) Logical conjunction always evaluates to false: a > x && a < y.\n", errout.str());
|
// ASSERT_EQUALS("[test.cpp:5]: (warning) Logical conjunction always evaluates to false: a > x && a < y.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void secondAlwaysTrueFalseWhenFirstTrueError() {
|
void secondAlwaysTrueFalseWhenFirstTrueError() {
|
||||||
|
@ -1601,7 +1601,7 @@ private:
|
||||||
" if(!b) {}\n"
|
" if(!b) {}\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
//ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout.str());
|
// ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout.str());
|
||||||
|
|
||||||
check("void foo(unsigned u) {\n"
|
check("void foo(unsigned u) {\n"
|
||||||
" if (u != 0) {\n"
|
" if (u != 0) {\n"
|
||||||
|
@ -2538,8 +2538,7 @@ private:
|
||||||
" if (val < 0) continue;\n"
|
" if (val < 0) continue;\n"
|
||||||
" if (val > 0) {}\n"
|
" if (val > 0) {}\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'val<0' is always false\n"
|
ASSERT_EQUALS("", errout.str());
|
||||||
"[test.cpp:4]: (style) Condition 'val>0' is always false\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" int val = 0;\n"
|
" int val = 0;\n"
|
||||||
|
@ -2547,7 +2546,7 @@ private:
|
||||||
" if (val > 0) {}\n"
|
" if (val > 0) {}\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'val<0' is always false\n", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" int val = 0;\n"
|
" int val = 0;\n"
|
||||||
|
@ -2555,7 +2554,7 @@ private:
|
||||||
" if (val < 0) {}\n"
|
" if (val < 0) {}\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'val<0' is always false\n", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" int activate = 0;\n"
|
" int activate = 0;\n"
|
||||||
|
|
|
@ -3917,13 +3917,13 @@ private:
|
||||||
" const int i = sizeof(int);\n"
|
" const int i = sizeof(int);\n"
|
||||||
" if ( i != sizeof (int)){}\n"
|
" if ( i != sizeof (int)){}\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'i != sizeof(int)' is always false because 'i' and 'sizeof(int)' represent the same value.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'i != sizeof(int)' is always false because 'i' and 'sizeof(int)' represent the same value.\n", errout.str());
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" const int i = sizeof(int);\n"
|
" const int i = sizeof(int);\n"
|
||||||
" if ( sizeof (int) != i){}\n"
|
" if ( sizeof (int) != i){}\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'sizeof(int) != i' is always false because 'sizeof(int)' and 'i' represent the same value.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'sizeof(int) != i' is always false because 'sizeof(int)' and 'i' represent the same value.\n", errout.str());
|
||||||
|
|
||||||
check("void f(int a = 1) { if ( a != 1){}}\n");
|
check("void f(int a = 1) { if ( a != 1){}}\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
@ -3932,21 +3932,21 @@ private:
|
||||||
" int a = 1;\n"
|
" int a = 1;\n"
|
||||||
" if ( a != 1){} \n"
|
" if ( a != 1){} \n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'a != 1' is always false.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'a != 1' is always false.\n", errout.str());
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" int a = 1;\n"
|
" int a = 1;\n"
|
||||||
" int b = 1;\n"
|
" int b = 1;\n"
|
||||||
" if ( a != b){} \n"
|
" if ( a != b){} \n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3] -> [test.cpp:4]: (style) The expression 'a != b' is always false because 'a' and 'b' represent the same value.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3] -> [test.cpp:4]: (style) The expression 'a != b' is always false because 'a' and 'b' represent the same value.\n", errout.str());
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" int a = 1;\n"
|
" int a = 1;\n"
|
||||||
" int b = a;\n"
|
" int b = a;\n"
|
||||||
" if ( a != b){} \n"
|
" if ( a != b){} \n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) The expression 'a != b' is always false because 'a' and 'b' represent the same value.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) The expression 'a != b' is always false because 'a' and 'b' represent the same value.\n", errout.str());
|
||||||
|
|
||||||
check("void use(int);\n"
|
check("void use(int);\n"
|
||||||
"void f() {\n"
|
"void f() {\n"
|
||||||
|
@ -3955,7 +3955,7 @@ private:
|
||||||
" use(b);\n"
|
" use(b);\n"
|
||||||
" if ( a != 1){} \n"
|
" if ( a != 1){} \n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:6]: (style) The expression 'a != 1' is always false.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:6]: (style) The expression 'a != 1' is always false.\n", errout.str());
|
||||||
|
|
||||||
check("void use(int);\n"
|
check("void use(int);\n"
|
||||||
"void f() {\n"
|
"void f() {\n"
|
||||||
|
@ -3979,7 +3979,7 @@ private:
|
||||||
" void f() {\n"
|
" void f() {\n"
|
||||||
" if ( a != 1){} \n"
|
" if ( a != 1){} \n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:3]: (style) The expression 'a != 1' is always false.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:3]: (style) The expression 'a != 1' is always false.\n", errout.str());
|
||||||
|
|
||||||
check("int a = 1;\n"
|
check("int a = 1;\n"
|
||||||
" void f() {\n"
|
" void f() {\n"
|
||||||
|
@ -3991,7 +3991,7 @@ private:
|
||||||
" static const int a = 1;\n"
|
" static const int a = 1;\n"
|
||||||
" if ( a != 1){} \n"
|
" if ( a != 1){} \n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'a != 1' is always false.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'a != 1' is always false.\n", errout.str());
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" static int a = 1;\n"
|
" static int a = 1;\n"
|
||||||
|
@ -4004,7 +4004,7 @@ private:
|
||||||
" if ( a != 1){\n"
|
" if ( a != 1){\n"
|
||||||
" a++;\n"
|
" a++;\n"
|
||||||
" }}\n");
|
" }}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'a != 1' is always false.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'a != 1' is always false.\n", errout.str());
|
||||||
|
|
||||||
check("void f(int b) {\n"
|
check("void f(int b) {\n"
|
||||||
" int a = 1;\n"
|
" int a = 1;\n"
|
||||||
|
@ -4096,7 +4096,7 @@ private:
|
||||||
" int a = 1;\n"
|
" int a = 1;\n"
|
||||||
" while ( a != 1){}\n"
|
" while ( a != 1){}\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'a != 1' is always false.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'a != 1' is always false.\n", errout.str());
|
||||||
|
|
||||||
check("void f() { int a = 1; while ( a != 1){ a++; }}\n");
|
check("void f() { int a = 1; while ( a != 1){ a++; }}\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
@ -4112,7 +4112,7 @@ private:
|
||||||
" if( i != 0 ) {}\n"
|
" if( i != 0 ) {}\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'i != 0' is always false.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'i != 0' is always false.\n", errout.str());
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" for(int i = 0; i < 10;) {\n"
|
" for(int i = 0; i < 10;) {\n"
|
||||||
|
@ -4153,7 +4153,7 @@ private:
|
||||||
" b++;\n"
|
" b++;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) The expression 'a != 1' is always false.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) The expression 'a != 1' is always false.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void duplicateExpressionTernary() { // #6391
|
void duplicateExpressionTernary() { // #6391
|
||||||
|
@ -4632,8 +4632,8 @@ private:
|
||||||
" if (val < 0) continue;\n"
|
" if (val < 0) continue;\n"
|
||||||
" if ((val > 0)) {}\n"
|
" if ((val > 0)) {}\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'val < 0' is always false.\n"
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'val < 0' is always false.\n"
|
||||||
// "[test.cpp:2] -> [test.cpp:4]: (style) The expression 'val > 0' is always false.\n", errout.str());
|
"[test.cpp:2] -> [test.cpp:4]: (style) The expression 'val > 0' is always false.\n", errout.str());
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" int val = 0;\n"
|
" int val = 0;\n"
|
||||||
|
@ -4641,8 +4641,8 @@ private:
|
||||||
" if ((val > 0)) {}\n"
|
" if ((val > 0)) {}\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'val < 0' is always false.\n"
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'val < 0' is always false.\n"
|
||||||
// "[test.cpp:2] -> [test.cpp:4]: (style) The expression 'val > 0' is always false.\n", errout.str());
|
"[test.cpp:2] -> [test.cpp:4]: (style) The expression 'val > 0' is always false.\n", errout.str());
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" int val = 0;\n"
|
" int val = 0;\n"
|
||||||
|
@ -4650,9 +4650,8 @@ private:
|
||||||
" if ((val < 0)) {}\n"
|
" if ((val < 0)) {}\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
//ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'val < 0' is always false.\n"
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The expression 'val < 0' is always false.\n"
|
||||||
// "[test.cpp:2] -> [test.cpp:4]: (style) The expression 'val < 0' is always false.\n", errout.str());
|
"[test.cpp:2] -> [test.cpp:4]: (style) The expression 'val < 0' is always false.\n", errout.str());
|
||||||
|
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" int activate = 0;\n"
|
" int activate = 0;\n"
|
||||||
|
@ -6952,6 +6951,18 @@ private:
|
||||||
" local_argv[local_argc++] = argv[0];\n"
|
" local_argv[local_argc++] = argv[0];\n"
|
||||||
"}\n", "test.c");
|
"}\n", "test.c");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int x = 0;\n"
|
||||||
|
" return 0 + x++;\n"
|
||||||
|
"}\n", "test.c");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f(int x, int y) {\n"
|
||||||
|
" int a[10];\n"
|
||||||
|
" a[x+y] = a[y+x]++;;\n"
|
||||||
|
"}\n", "test.c");
|
||||||
|
ASSERT_EQUALS("[test.c:3]: (error) Expression 'a[x+y]=a[y+x]++' depends on order of evaluation of side effects\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void testEvaluationOrderSelfAssignment() {
|
void testEvaluationOrderSelfAssignment() {
|
||||||
|
|
Loading…
Reference in New Issue