diff --git a/lib/astutils.cpp b/lib/astutils.cpp index f16144310ac..1152a556d28 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -68,7 +68,9 @@ const Token* findExpression(const nonneg int exprid, static int findArgumentPosRecursive(const Token* tok, const Token* tokToFind, bool &found, nonneg int depth=0) { ++depth; - if (!tok || depth >= 100) + if (depth >= 100) + return -1; // TODO: add bailout message + if (!tok) return -1; if (tok->str() == ",") { int res = findArgumentPosRecursive(tok->astOperand1(), tokToFind, found, depth); @@ -111,8 +113,10 @@ templatestr().c_str(), op) == 0) { astFlattenCopy(tok->astOperand1(), op, out, depth); astFlattenCopy(tok->astOperand2(), op, out, depth); @@ -139,8 +143,10 @@ std::vector astFlatten(Token* tok, const char* op) nonneg int astCount(const Token* tok, const char* op, int depth) { --depth; - if (!tok || depth < 0) + if (!tok || depth < 0) { + // TODO: add bailout message return 0; + } if (strcmp(tok->str().c_str(), op) == 0) return astCount(tok->astOperand1(), op, depth) + astCount(tok->astOperand2(), op, depth); return 1; @@ -1130,6 +1136,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; @@ -1274,6 +1281,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; @@ -2917,7 +2925,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()) @@ -2975,8 +2983,10 @@ Token* findVariableChanged(Token *start, const Token *end, int indirect, const n { if (!precedes(start, end)) return nullptr; - if (depth < 0) + if (depth < 0) { + // TODO: add bailout message return start; + } auto getExprTok = utils::memoize([&] { return findExpression(start, exprid); }); @@ -3074,8 +3084,10 @@ static const Token* findExpressionChangedImpl(const Token* expr, int depth, Find find) { - if (depth < 0) + if (depth < 0) { + // TODO: add bailout message return start; + } if (!precedes(start, end)) return nullptr; const Token* result = nullptr; diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index 882f4588eeb..b5381fc62d9 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 83f183643e6..ba4783a8c40 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; @@ -1032,7 +1031,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()) { @@ -1536,7 +1535,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(); @@ -1984,11 +1983,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); @@ -2001,21 +1998,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 @@ -2334,7 +2331,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 && @@ -3615,7 +3612,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) @@ -3735,10 +3732,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(); @@ -3751,6 +3748,7 @@ struct SymbolicInferModel : InferModel { result.setKnown(); return result; } + const Token* expr; }; static void valueFlowSymbolicInfer(const SymbolDatabase& symboldatabase, const Settings& settings) @@ -5747,7 +5745,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; @@ -6108,6 +6106,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 58fbe0b6d61..640a9c9cb78 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())