diff --git a/lib/astutils.cpp b/lib/astutils.cpp index fa2c9c3890b..3be688978fd 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -69,7 +69,7 @@ static int findArgumentPosRecursive(const Token* tok, const Token* tokToFind, b { ++depth; if (!tok || depth >= 100) - return -1; + return -1; // TODO: add bailout message if (tok->str() == ",") { int res = findArgumentPosRecursive(tok->astOperand1(), tokToFind, found, depth); if (res == -1) @@ -112,7 +112,7 @@ static void astFlattenCopy(T* tok, const char* op, OuputIterator out, int depth { --depth; if (!tok || depth < 0) - return; + return; // TODO: add bailout message if (strcmp(tok->str().c_str(), op) == 0) { astFlattenCopy(tok->astOperand1(), op, out, depth); astFlattenCopy(tok->astOperand2(), op, out, depth); @@ -140,7 +140,7 @@ nonneg int astCount(const Token* tok, const char* op, int depth) { --depth; if (!tok || depth < 0) - return 0; + return 0; // TODO: add bailout message if (strcmp(tok->str().c_str(), op) == 0) return astCount(tok->astOperand1(), op, depth) + astCount(tok->astOperand2(), op, depth); return 1; @@ -1127,6 +1127,7 @@ bool exprDependsOnThis(const Token* expr, bool onVar, nonneg int depth) return true; if (depth >= 1000) // Abort recursion to avoid stack overflow + // TODO: add bailout message return true; ++depth; @@ -1271,6 +1272,7 @@ static SmallVector followAllReferencesInternal(const Token* tok, if (!tok) return {}; if (depth < 0) { + // TODO: add bailout message SmallVector refs_result; refs_result.emplace_back(tok, std::move(errors)); return refs_result; @@ -2929,7 +2931,7 @@ static bool isExpressionChangedAt(const F& getExprTok, int depth) { if (depth < 0) - return true; + return true; // TODO: add bailout message if (!tok) return false; if (!tok->isMutableExpr()) @@ -2988,7 +2990,7 @@ Token* findVariableChanged(Token *start, const Token *end, int indirect, const n if (!precedes(start, end)) return nullptr; if (depth < 0) - return start; + return start; // TODO: add bailout message auto getExprTok = utils::memoize([&] { return findExpression(start, exprid); }); @@ -3087,7 +3089,7 @@ static const Token* findExpressionChangedImpl(const Token* expr, Find find) { if (depth < 0) - return start; + return start; // TODO: add bailout message if (!precedes(start, end)) return nullptr; const Token* result = nullptr; diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index faa6f25911d..7c78d6ec842 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -1078,7 +1078,7 @@ static const ValueFlow::Value* getInnerLifetime(const Token* tok, int depth = 4) { if (depth < 0) - return nullptr; + return nullptr;// TODO: add bailout message if (!tok) return nullptr; for (const ValueFlow::Value& val : tok->values()) { diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index 5c97528372b..8c8972f6b2e 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -46,6 +46,7 @@ namespace { struct ForwardTraversal { enum class Progress : std::uint8_t { Continue, Break, Skip }; + // TODO: analyzer is copied ForwardTraversal(const ValuePtr& analyzer, const TokenList& tokenList, ErrorLogger& errorLogger, const Settings& settings) : analyzer(analyzer), tokenList(tokenList), errorLogger(errorLogger), settings(settings) {} @@ -580,7 +581,7 @@ namespace { */ Progress updateRange(Token* start, const Token* end, int depth = 20) { if (depth < 0) - return Break(Analyzer::Terminate::Bail); + return Break(Analyzer::Terminate::Bail); // TODO: add bailout message std::size_t i = 0; for (Token* tok = start; precedes(tok, end); tok = tok->next()) { Token* next = nullptr; diff --git a/lib/programmemory.cpp b/lib/programmemory.cpp index eb0b290ac6c..9fadafddd25 100644 --- a/lib/programmemory.cpp +++ b/lib/programmemory.cpp @@ -1388,7 +1388,7 @@ namespace { nonneg int n = astCount(expr, expr->str().c_str()); if (n > 50) - return unknown(); + return unknown(); // TODO: add bailout message std::vector conditions1 = flattenConditions(expr); if (conditions1.empty()) return unknown(); @@ -1405,7 +1405,7 @@ namespace { } if (condValues.size() == conditions1.size() && allNegated) return negatedValue; - if (n > 4) + if (n > 4) // TODO: add bailout message return unknown(); if (!sortConditions(conditions1)) return unknown(); @@ -1646,6 +1646,7 @@ namespace { return execute(tok); }); if (f) { + // TODO: add bailout message if (fdepth >= 0 && !f->isImplicitlyVirtual()) { ProgramMemory functionState; for (std::size_t i = 0; i < args.size(); ++i) { @@ -1734,7 +1735,7 @@ namespace { depth++; }}; if (depth < 0) - return unknown(); + return unknown(); // TODO: add bailout message ValueFlow::Value v = unknown(); if (updateValue(v, executeImpl(expr))) return v; diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index e22a93845a8..e2b6a848b90 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -284,13 +284,12 @@ static void parseCompareEachInt( return; if (tok->isComparisonOp()) { std::vector value1 = evaluate(tok->astOperand1()); - std::vector value2 = evaluate(tok->astOperand2()); - if (!value1.empty() && !value2.empty()) { - if (tok->astOperand1()->hasKnownIntValue()) - value2.clear(); - if (tok->astOperand2()->hasKnownIntValue()) - value1.clear(); + std::vector value2; + if (value1.empty() || !tok->astOperand1()->hasKnownIntValue()) { + value2 = evaluate(tok->astOperand2()); } + if (!value2.empty() && tok->astOperand2()->hasKnownIntValue()) + value1.clear(); for (const ValueFlow::Value& v1 : value1) { if (isSaturated(v1.intvalue) || astIsFloat(tok->astOperand2(), /*unknown*/ false)) continue; @@ -393,28 +392,28 @@ void ValueFlow::combineValueProperties(const ValueFlow::Value &value1, const Val result.tokvalue = value1.tokvalue; else if (value2.tokvalue) result.tokvalue = value2.tokvalue; - if (value1.isSymbolicValue()) { - result.valueType = value1.valueType; - result.tokvalue = value1.tokvalue; - } if (value2.isSymbolicValue()) { result.valueType = value2.valueType; result.tokvalue = value2.tokvalue; } - if (value1.isIteratorValue()) + else if (value1.isSymbolicValue()) { result.valueType = value1.valueType; + result.tokvalue = value1.tokvalue; + } if (value2.isIteratorValue()) result.valueType = value2.valueType; + else if (value1.isIteratorValue()) + result.valueType = value1.valueType; result.condition = value1.condition ? value1.condition : value2.condition; result.varId = (value1.varId != 0) ? value1.varId : value2.varId; result.varvalue = (result.varId == value1.varId) ? value1.varvalue : value2.varvalue; result.errorPath = (value1.errorPath.empty() ? value2 : value1).errorPath; result.safe = value1.safe || value2.safe; if (value1.bound == ValueFlow::Value::Bound::Point || value2.bound == ValueFlow::Value::Bound::Point) { - if (value1.bound == ValueFlow::Value::Bound::Upper || value2.bound == ValueFlow::Value::Bound::Upper) - result.bound = ValueFlow::Value::Bound::Upper; if (value1.bound == ValueFlow::Value::Bound::Lower || value2.bound == ValueFlow::Value::Bound::Lower) result.bound = ValueFlow::Value::Bound::Lower; + else if (value1.bound == ValueFlow::Value::Bound::Upper || value2.bound == ValueFlow::Value::Bound::Upper) + result.bound = ValueFlow::Value::Bound::Upper; } if (value1.path != value2.path) result.path = -1; @@ -1027,7 +1026,7 @@ static std::vector minUnsignedValue(const Token* tok, int depth if (!tok) return result; if (depth < 0) - return result; + return result; // TODO: add bailout message if (const ValueFlow::Value* v = tok->getKnownValue(ValueFlow::Value::ValueType::INT)) { result = {v->intvalue}; } else if (!Token::Match(tok, "-|%|&|^") && tok->isConstOp() && tok->astOperand1() && tok->astOperand2()) { @@ -1531,7 +1530,7 @@ static std::vector getLifetimeTokens(const Token* tok, if (pred(tok)) return {{tok, std::move(errorPath)}}; if (depth < 0) - return {{tok, std::move(errorPath)}}; + return {{tok, std::move(errorPath)}}; // TODO: add bailout message if (var && var->declarationId() == tok->varId()) { if (var->isReference() || var->isRValueReference()) { const Token * const varDeclEndToken = var->declEndToken(); @@ -1979,11 +1978,9 @@ static void valueFlowForwardLifetime(Token * tok, const TokenList &tokenlist, Er if (!expr) return; - if (expr->exprId() == 0) + if (expr->exprId() <= 0) return; - const Token* endOfVarScope = ValueFlow::getEndOfExprScope(expr); - // Only forward lifetime values std::list values = parent->astOperand2()->values(); values.remove_if(&isNotLifetimeValue); @@ -1996,21 +1993,21 @@ static void valueFlowForwardLifetime(Token * tok, const TokenList &tokenlist, Er // Skip RHS Token* nextExpression = nextAfterAstRightmostLeaf(parent); + const Token* endOfVarScope = ValueFlow::getEndOfExprScope(expr); - if (expr->exprId() > 0) { - valueFlowForward(nextExpression, endOfVarScope->next(), expr, values, tokenlist, errorLogger, settings); + valueFlowForward(nextExpression, endOfVarScope->next(), expr, values, tokenlist, errorLogger, settings); + // TODO: handle `[` + if (Token::simpleMatch(parent->astOperand1(), ".")) { for (ValueFlow::Value& val : values) { if (val.lifetimeKind == ValueFlow::Value::LifetimeKind::Address) val.lifetimeKind = ValueFlow::Value::LifetimeKind::SubObject; } - // TODO: handle `[` - if (Token::simpleMatch(parent->astOperand1(), ".")) { - const Token* parentLifetime = - getParentLifetime(parent->astOperand1()->astOperand2(), settings.library); - if (parentLifetime && parentLifetime->exprId() > 0) { - valueFlowForward(nextExpression, endOfVarScope, parentLifetime, std::move(values), tokenlist, errorLogger, settings); - } + + const Token* parentLifetime = + getParentLifetime(parent->astOperand1()->astOperand2(), settings.library); + if (parentLifetime && parentLifetime->exprId() > 0) { + valueFlowForward(nextExpression, endOfVarScope, parentLifetime, std::move(values), tokenlist, errorLogger, settings); } } // Constructor @@ -2329,7 +2326,7 @@ struct LifetimeStore { static bool hasBorrowingVariables(const std::list& vars, const std::vector& args, int depth = 10) { if (depth < 0) - return true; + return true; // TODO: add bailout message return std::any_of(vars.cbegin(), vars.cend(), [&](const Variable& var) { if (const ValueType* vt = var.valueType()) { if (vt->pointer > 0 && @@ -3626,7 +3623,7 @@ static void valueFlowSymbolic(const TokenList& tokenlist, const SymbolDatabase& static const Token* isStrlenOf(const Token* tok, const Token* expr, int depth = 10) { if (depth < 0) - return nullptr; + return nullptr; // TODO: add bailout message if (!tok) return nullptr; if (!expr) @@ -3746,10 +3743,10 @@ static void valueFlowSymbolicOperators(const SymbolDatabase& symboldatabase, con } struct SymbolicInferModel : InferModel { - const Token* expr; explicit SymbolicInferModel(const Token* tok) : expr(tok) { assert(expr->exprId() != 0); } +private: bool match(const ValueFlow::Value& value) const override { return value.isSymbolicValue() && value.tokvalue && value.tokvalue->exprId() == expr->exprId(); @@ -3762,6 +3759,7 @@ struct SymbolicInferModel : InferModel { result.setKnown(); return result; } + const Token* expr; }; static void valueFlowSymbolicInfer(const SymbolDatabase& symboldatabase, const Settings& settings) @@ -5761,7 +5759,7 @@ static const ValueFlow::Value* getKnownValueFromToken(const Token* tok) if (!tok) return nullptr; auto it = std::find_if(tok->values().begin(), tok->values().end(), [&](const ValueFlow::Value& v) { - return (v.isIntValue() || v.isContainerSizeValue() || v.isFloatValue()) && v.isKnown(); + return v.isKnown() && (v.isIntValue() || v.isContainerSizeValue() || v.isFloatValue()); }); if (it == tok->values().end()) return nullptr; @@ -6122,6 +6120,7 @@ static bool isContainerSizeChangedByFunction(const Token* tok, // Argument not used if (!arg->nameToken()) return false; + // TODO: add bailout message if (depth > 0) return isContainerSizeChanged(arg->nameToken(), scope->bodyStart, diff --git a/lib/vf_analyzers.cpp b/lib/vf_analyzers.cpp index 45d5e7c9547..81f328bead7 100644 --- a/lib/vf_analyzers.cpp +++ b/lib/vf_analyzers.cpp @@ -118,7 +118,7 @@ struct ValueFlowAnalyzer : Analyzer { if (!tok) return {}; if (depth < 0) - return {}; + return {}; // TODO: add bailout message depth--; if (analyze(tok, Direction::Forward).isRead()) { ConditionState result; @@ -826,7 +826,7 @@ static bool bifurcateVariableChanged(const Variable* var, static bool bifurcate(const Token* tok, const std::set& varids, const Settings& settings, int depth) { if (depth < 0) - return false; + return false; // TODO: add bailout message if (!tok) return true; if (tok->hasKnownIntValue())