Refactor: Assert an expression has an id and fix assertion failures (#3377)
* Fix 10390: FP: knownConditionTrueFalse * Assert expression has an ID * Fix assertion errors * Format
This commit is contained in:
parent
7be9b217e6
commit
08041e3a0b
|
@ -162,7 +162,7 @@ struct ReverseTraversal {
|
||||||
Analyzer::Action lhsAction =
|
Analyzer::Action lhsAction =
|
||||||
analyzer->analyze(assignTok->astOperand1(), Analyzer::Direction::Reverse);
|
analyzer->analyze(assignTok->astOperand1(), Analyzer::Direction::Reverse);
|
||||||
// Assignment from
|
// Assignment from
|
||||||
if (rhsAction.isRead() && !lhsAction.isInvalid()) {
|
if (rhsAction.isRead() && !lhsAction.isInvalid() && assignTok->astOperand1()->exprId() > 0) {
|
||||||
const std::string info = "Assignment from '" + assignTok->expressionString() + "'";
|
const std::string info = "Assignment from '" + assignTok->expressionString() + "'";
|
||||||
ValuePtr<Analyzer> a = analyzer->reanalyze(assignTok->astOperand1(), info);
|
ValuePtr<Analyzer> a = analyzer->reanalyze(assignTok->astOperand1(), info);
|
||||||
if (a) {
|
if (a) {
|
||||||
|
@ -173,6 +173,7 @@ struct ReverseTraversal {
|
||||||
}
|
}
|
||||||
// Assignment to
|
// Assignment to
|
||||||
} else if (lhsAction.matches() && !assignTok->astOperand2()->hasKnownIntValue() &&
|
} else if (lhsAction.matches() && !assignTok->astOperand2()->hasKnownIntValue() &&
|
||||||
|
assignTok->astOperand2()->exprId() > 0 &&
|
||||||
isConstExpression(assignTok->astOperand2(), settings->library, true, true)) {
|
isConstExpression(assignTok->astOperand2(), settings->library, true, true)) {
|
||||||
const std::string info = "Assignment to '" + assignTok->expressionString() + "'";
|
const std::string info = "Assignment to '" + assignTok->expressionString() + "'";
|
||||||
ValuePtr<Analyzer> a = analyzer->reanalyze(assignTok->astOperand2(), info);
|
ValuePtr<Analyzer> a = analyzer->reanalyze(assignTok->astOperand2(), info);
|
||||||
|
|
|
@ -2412,6 +2412,7 @@ struct ExpressionAnalyzer : SingleValueFlowAnalyzer {
|
||||||
ExpressionAnalyzer(const Token* e, const ValueFlow::Value& val, const TokenList* t)
|
ExpressionAnalyzer(const Token* e, const ValueFlow::Value& val, const TokenList* t)
|
||||||
: SingleValueFlowAnalyzer(val, t), expr(e), local(true), unknown(false), dependOnThis(false) {
|
: SingleValueFlowAnalyzer(val, t), expr(e), local(true), unknown(false), dependOnThis(false) {
|
||||||
|
|
||||||
|
assert(e && e->exprId() != 0 && "Not a valid expression");
|
||||||
dependOnThis = exprDependsOnThis(expr);
|
dependOnThis = exprDependsOnThis(expr);
|
||||||
setupExprVarIds(expr);
|
setupExprVarIds(expr);
|
||||||
if (val.isSymbolicValue())
|
if (val.isSymbolicValue())
|
||||||
|
@ -2521,6 +2522,10 @@ static const Token* parseBinaryIntOp(const Token* expr, MathLib::bigint& known)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (!expr->astOperand1() || !expr->astOperand2())
|
if (!expr->astOperand1() || !expr->astOperand2())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
if (expr->astOperand1()->exprId() == 0 && !expr->astOperand1()->hasKnownIntValue())
|
||||||
|
return nullptr;
|
||||||
|
if (expr->astOperand2()->exprId() == 0 && !expr->astOperand2()->hasKnownIntValue())
|
||||||
|
return nullptr;
|
||||||
const Token* knownTok = nullptr;
|
const Token* knownTok = nullptr;
|
||||||
const Token* varTok = nullptr;
|
const Token* varTok = nullptr;
|
||||||
if (expr->astOperand1()->hasKnownIntValue() && !expr->astOperand2()->hasKnownIntValue()) {
|
if (expr->astOperand1()->hasKnownIntValue() && !expr->astOperand2()->hasKnownIntValue()) {
|
||||||
|
@ -3932,6 +3937,23 @@ static ValueFlow::Value makeConditionValue(long long val, const Token* condTok,
|
||||||
v.errorPath.emplace_back(condTok, "Assuming condition '" + condTok->expressionString() + "' is false");
|
v.errorPath.emplace_back(condTok, "Assuming condition '" + condTok->expressionString() + "' is false");
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::vector<const Token*> getConditions(const Token* tok, const char* op)
|
||||||
|
{
|
||||||
|
std::vector<const Token*> conds = {tok};
|
||||||
|
if (tok->str() == op) {
|
||||||
|
std::vector<const Token*> args = astFlatten(tok, op);
|
||||||
|
std::copy_if(args.begin(), args.end(), std::back_inserter(conds), [&](const Token* tok2) {
|
||||||
|
if (tok2->exprId() == 0)
|
||||||
|
return false;
|
||||||
|
if (tok2->hasKnownIntValue())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return conds;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
static void valueFlowConditionExpressions(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
|
static void valueFlowConditionExpressions(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
|
||||||
{
|
{
|
||||||
|
@ -3952,6 +3974,8 @@ static void valueFlowConditionExpressions(TokenList *tokenlist, SymbolDatabase*
|
||||||
continue;
|
continue;
|
||||||
Token * blockTok = parenTok->link()->tokAt(1);
|
Token * blockTok = parenTok->link()->tokAt(1);
|
||||||
const Token* condTok = parenTok->astOperand2();
|
const Token* condTok = parenTok->astOperand2();
|
||||||
|
if (condTok->exprId() == 0)
|
||||||
|
continue;
|
||||||
if (condTok->hasKnownIntValue())
|
if (condTok->hasKnownIntValue())
|
||||||
continue;
|
continue;
|
||||||
if (!isConstExpression(condTok, settings->library, true, tokenlist->isCPP()))
|
if (!isConstExpression(condTok, settings->library, true, tokenlist->isCPP()))
|
||||||
|
@ -3961,12 +3985,7 @@ static void valueFlowConditionExpressions(TokenList *tokenlist, SymbolDatabase*
|
||||||
Token* startTok = blockTok;
|
Token* startTok = blockTok;
|
||||||
// Inner condition
|
// Inner condition
|
||||||
{
|
{
|
||||||
std::vector<const Token*> conds = {condTok};
|
for (const Token* condTok2 : getConditions(condTok, "&&")) {
|
||||||
if (Token::simpleMatch(condTok, "&&")) {
|
|
||||||
std::vector<const Token*> args = astFlatten(condTok, "&&");
|
|
||||||
conds.insert(conds.end(), args.begin(), args.end());
|
|
||||||
}
|
|
||||||
for (const Token* condTok2:conds) {
|
|
||||||
if (is1) {
|
if (is1) {
|
||||||
ExpressionAnalyzer a1(condTok2, makeConditionValue(1, condTok2, true), tokenlist);
|
ExpressionAnalyzer a1(condTok2, makeConditionValue(1, condTok2, true), tokenlist);
|
||||||
valueFlowGenericForward(startTok, startTok->link(), a1, settings);
|
valueFlowGenericForward(startTok, startTok->link(), a1, settings);
|
||||||
|
@ -3977,11 +3996,7 @@ static void valueFlowConditionExpressions(TokenList *tokenlist, SymbolDatabase*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<const Token*> conds = {condTok};
|
std::vector<const Token*> conds = getConditions(condTok, "||");
|
||||||
if (Token::simpleMatch(condTok, "||")) {
|
|
||||||
std::vector<const Token*> args = astFlatten(condTok, "||");
|
|
||||||
conds.insert(conds.end(), args.begin(), args.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check else block
|
// Check else block
|
||||||
if (Token::simpleMatch(startTok->link(), "} else {")) {
|
if (Token::simpleMatch(startTok->link(), "} else {")) {
|
||||||
|
@ -4459,6 +4474,8 @@ struct ConditionHandler {
|
||||||
for (const Condition& cond : parse(tok, settings)) {
|
for (const Condition& cond : parse(tok, settings)) {
|
||||||
if (!cond.vartok)
|
if (!cond.vartok)
|
||||||
continue;
|
continue;
|
||||||
|
if (cond.vartok->exprId() == 0)
|
||||||
|
continue;
|
||||||
if (cond.vartok->hasKnownIntValue())
|
if (cond.vartok->hasKnownIntValue())
|
||||||
continue;
|
continue;
|
||||||
if (cond.true_values.empty() || cond.false_values.empty())
|
if (cond.true_values.empty() || cond.false_values.empty())
|
||||||
|
|
Loading…
Reference in New Issue