Fix 11296: FN: knownConditionTrueFalse ( a !=0 && b != 0 && a == 0) (#4444)
This commit is contained in:
parent
016793f258
commit
2d37a77281
|
@ -1984,9 +1984,12 @@ static bool isConditionKnown(const Token* tok, bool then)
|
||||||
if (then)
|
if (then)
|
||||||
op = "&&";
|
op = "&&";
|
||||||
const Token* parent = tok->astParent();
|
const Token* parent = tok->astParent();
|
||||||
while (parent && (parent->str() == op || parent->str() == "!"))
|
while (parent && (parent->str() == op || parent->str() == "!" || parent->isCast()))
|
||||||
parent = parent->astParent();
|
parent = parent->astParent();
|
||||||
return Token::Match(parent, "(|;");
|
const Token* top = tok->astTop();
|
||||||
|
if (top && Token::Match(top->previous(), "if|while|for ("))
|
||||||
|
return parent == top || Token::simpleMatch(parent, ";");
|
||||||
|
return parent && parent->str() != op;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const std::string& invertAssign(const std::string& assign)
|
static const std::string& invertAssign(const std::string& assign)
|
||||||
|
@ -6353,12 +6356,16 @@ static bool isIntegralOnlyOperator(const Token* tok) {
|
||||||
return Token::Match(tok, "%|<<|>>|&|^|~|%or%");
|
return Token::Match(tok, "%|<<|>>|&|^|~|%or%");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isIntegral(const Token* tok)
|
static bool isIntegralOrPointer(const Token* tok)
|
||||||
{
|
{
|
||||||
if (!tok)
|
if (!tok)
|
||||||
return false;
|
return false;
|
||||||
if (astIsIntegral(tok, false))
|
if (astIsIntegral(tok, false))
|
||||||
return true;
|
return true;
|
||||||
|
if (astIsPointer(tok))
|
||||||
|
return true;
|
||||||
|
if (Token::Match(tok, "NULL|nullptr"))
|
||||||
|
return true;
|
||||||
if (tok->valueType())
|
if (tok->valueType())
|
||||||
return false;
|
return false;
|
||||||
// These operators only work on integers
|
// These operators only work on integers
|
||||||
|
@ -6367,7 +6374,7 @@ static bool isIntegral(const Token* tok)
|
||||||
if (isIntegralOnlyOperator(tok->astParent()))
|
if (isIntegralOnlyOperator(tok->astParent()))
|
||||||
return true;
|
return true;
|
||||||
if (Token::Match(tok, "+|-|*|/") && tok->isBinaryOp())
|
if (Token::Match(tok, "+|-|*|/") && tok->isBinaryOp())
|
||||||
return isIntegral(tok->astOperand1()) && isIntegral(tok->astOperand2());
|
return isIntegralOrPointer(tok->astOperand1()) && isIntegralOrPointer(tok->astOperand2());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6400,7 +6407,7 @@ static void valueFlowInferCondition(TokenList* tokenlist,
|
||||||
setTokenValue(tok, value, settings);
|
setTokenValue(tok, value, settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (isIntegral(tok->astOperand1()) && isIntegral(tok->astOperand2())) {
|
} else if (isIntegralOrPointer(tok->astOperand1()) && isIntegralOrPointer(tok->astOperand2())) {
|
||||||
std::vector<ValueFlow::Value> result =
|
std::vector<ValueFlow::Value> result =
|
||||||
infer(IntegralInferModel{}, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values());
|
infer(IntegralInferModel{}, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values());
|
||||||
for (const ValueFlow::Value& value : result) {
|
for (const ValueFlow::Value& value : result) {
|
||||||
|
|
|
@ -1309,7 +1309,7 @@ private:
|
||||||
check("int f(char c) {\n"
|
check("int f(char c) {\n"
|
||||||
" return (c <= 'a' && c >= 'z');\n"
|
" return (c <= 'a' && c >= 'z');\n"
|
||||||
"}", "test.cpp", false);
|
"}", "test.cpp", false);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Condition 'c>='z'' is always false\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void incorrectLogicOperator7() { // opposite expressions
|
void incorrectLogicOperator7() { // opposite expressions
|
||||||
|
@ -4714,6 +4714,11 @@ private:
|
||||||
// #11098
|
// #11098
|
||||||
check("void f(unsigned int x) { if (x == -1u) {} }\n");
|
check("void f(unsigned int x) { if (x == -1u) {} }\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("bool f(const int *p, const int *q) {\n"
|
||||||
|
" return p != NULL && q != NULL && p == NULL;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'p==NULL' is always false\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void alwaysTrueContainer() {
|
void alwaysTrueContainer() {
|
||||||
|
|
|
@ -5089,6 +5089,7 @@ private:
|
||||||
" return((n=42) && *n == 'A');\n"
|
" return((n=42) && *n == 'A');\n"
|
||||||
"}";
|
"}";
|
||||||
values = tokenValues(code, "n ==");
|
values = tokenValues(code, "n ==");
|
||||||
|
values.remove_if(&isNotUninitValue);
|
||||||
ASSERT_EQUALS(true, values.empty());
|
ASSERT_EQUALS(true, values.empty());
|
||||||
|
|
||||||
// #8233
|
// #8233
|
||||||
|
|
Loading…
Reference in New Issue