parent
fc6b79a5e6
commit
078a6d7804
|
@ -2768,35 +2768,37 @@ bool isCPPCast(const Token* tok)
|
||||||
return tok && Token::simpleMatch(tok->previous(), "> (") && tok->astOperand2() && tok->astOperand1() && isCPPCastKeyword(tok->astOperand1());
|
return tok && Token::simpleMatch(tok->previous(), "> (") && tok->astOperand2() && tok->astOperand1() && isCPPCastKeyword(tok->astOperand1());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isConstVarExpression(const Token *tok, const char* skipMatch)
|
bool isConstVarExpression(const Token *tok, std::function<bool(const Token*)> skipPredicate)
|
||||||
{
|
{
|
||||||
if (!tok)
|
if (!tok)
|
||||||
return false;
|
return false;
|
||||||
if (tok->str() == "?" && tok->astOperand2() && tok->astOperand2()->str() == ":") // ternary operator
|
if (tok->str() == "?" && tok->astOperand2() && tok->astOperand2()->str() == ":") // ternary operator
|
||||||
return isConstVarExpression(tok->astOperand2()->astOperand1()) && isConstVarExpression(tok->astOperand2()->astOperand2()); // left and right of ":"
|
return isConstVarExpression(tok->astOperand2()->astOperand1()) && isConstVarExpression(tok->astOperand2()->astOperand2()); // left and right of ":"
|
||||||
if (skipMatch && Token::Match(tok, skipMatch))
|
if (skipPredicate && skipPredicate(tok))
|
||||||
return false;
|
return false;
|
||||||
if (Token::simpleMatch(tok->previous(), "sizeof ("))
|
if (Token::simpleMatch(tok->previous(), "sizeof ("))
|
||||||
return true;
|
return true;
|
||||||
if (Token::Match(tok->previous(), "%name% (")) {
|
if (Token::Match(tok->previous(), "%name% (")) {
|
||||||
if (Token::simpleMatch(tok->astOperand1(), ".") && !isConstVarExpression(tok->astOperand1(), skipMatch))
|
if (Token::simpleMatch(tok->astOperand1(), ".") && !isConstVarExpression(tok->astOperand1(), skipPredicate))
|
||||||
return false;
|
return false;
|
||||||
std::vector<const Token *> args = getArguments(tok);
|
std::vector<const Token *> args = getArguments(tok);
|
||||||
|
if (args.empty() && tok->previous()->function() && tok->previous()->function()->isConstexpr())
|
||||||
|
return true;
|
||||||
return std::all_of(args.begin(), args.end(), [&](const Token* t) {
|
return std::all_of(args.begin(), args.end(), [&](const Token* t) {
|
||||||
return isConstVarExpression(t, skipMatch);
|
return isConstVarExpression(t, skipPredicate);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (isCPPCast(tok)) {
|
if (isCPPCast(tok)) {
|
||||||
return isConstVarExpression(tok->astOperand2(), skipMatch);
|
return isConstVarExpression(tok->astOperand2(), skipPredicate);
|
||||||
}
|
}
|
||||||
if (Token::Match(tok, "( %type%"))
|
if (Token::Match(tok, "( %type%"))
|
||||||
return isConstVarExpression(tok->astOperand1(), skipMatch);
|
return isConstVarExpression(tok->astOperand1(), skipPredicate);
|
||||||
if (tok->str() == "::" && tok->hasKnownValue())
|
if (tok->str() == "::" && tok->hasKnownValue())
|
||||||
return isConstVarExpression(tok->astOperand2(), skipMatch);
|
return isConstVarExpression(tok->astOperand2(), skipPredicate);
|
||||||
if (Token::Match(tok, "%cop%|[|.")) {
|
if (Token::Match(tok, "%cop%|[|.")) {
|
||||||
if (tok->astOperand1() && !isConstVarExpression(tok->astOperand1(), skipMatch))
|
if (tok->astOperand1() && !isConstVarExpression(tok->astOperand1(), skipPredicate))
|
||||||
return false;
|
return false;
|
||||||
if (tok->astOperand2() && !isConstVarExpression(tok->astOperand2(), skipMatch))
|
if (tok->astOperand2() && !isConstVarExpression(tok->astOperand2(), skipPredicate))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -383,7 +383,7 @@ bool isLikelyStreamRead(bool cpp, const Token *op);
|
||||||
|
|
||||||
bool isCPPCast(const Token* tok);
|
bool isCPPCast(const Token* tok);
|
||||||
|
|
||||||
bool isConstVarExpression(const Token *tok, const char * skipMatch = nullptr);
|
bool isConstVarExpression(const Token* tok, std::function<bool(const Token*)> skipPredicate = nullptr);
|
||||||
|
|
||||||
const Variable *getLHSVariable(const Token *tok);
|
const Variable *getLHSVariable(const Token *tok);
|
||||||
|
|
||||||
|
|
|
@ -1497,7 +1497,9 @@ void CheckCondition::alwaysTrueFalse()
|
||||||
continue;
|
continue;
|
||||||
if (tok->isComparisonOp() && isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, true, true))
|
if (tok->isComparisonOp() && isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, true, true))
|
||||||
continue;
|
continue;
|
||||||
if (isConstVarExpression(tok, "[|(|&|+|-|*|/|%|^|>>|<<"))
|
if (isConstVarExpression(tok, [](const Token* tok) {
|
||||||
|
return Token::Match(tok, "[|(|&|+|-|*|/|%|^|>>|<<") && !Token::simpleMatch(tok, "( )");
|
||||||
|
}))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// there are specific warnings about nonzero expressions (pointer/unsigned)
|
// there are specific warnings about nonzero expressions (pointer/unsigned)
|
||||||
|
|
|
@ -4281,6 +4281,14 @@ private:
|
||||||
" }\n"
|
" }\n"
|
||||||
"};\n");
|
"};\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("constexpr int f() {\n" // #11238
|
||||||
|
" return 1;\n"
|
||||||
|
"}\n"
|
||||||
|
"constexpr bool g() {\n"
|
||||||
|
" return f() == 1;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void alwaysTrueSymbolic()
|
void alwaysTrueSymbolic()
|
||||||
|
|
Loading…
Reference in New Issue