Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions lib/astutils.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -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)
Expand DownExpand Up@@ -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);
Expand DownExpand Up@@ -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;
Expand DownExpand Up@@ -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;

Expand DownExpand Up@@ -1271,6 +1272,7 @@ static SmallVector<ReferenceToken> followAllReferencesInternal(const Token* tok,
if (!tok)
return {};
if (depth < 0) {
// TODO: add bailout message
SmallVector<ReferenceToken> refs_result;
refs_result.emplace_back(tok, std::move(errors));
return refs_result;
Expand DownExpand Up@@ -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())
Expand DownExpand Up@@ -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);
});
Expand DownExpand Up@@ -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;
Expand Down
2 changes: 1 addition & 1 deletion lib/checkstl.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -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()) {
Expand Down
3 changes: 2 additions & 1 deletion lib/forwardanalyzer.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -46,6 +46,7 @@
namespace {
struct ForwardTraversal {
enum class Progress : std::uint8_t { Continue, Break, Skip };
// TODO: analyzer is copied
ForwardTraversal(const ValuePtr<Analyzer>& analyzer, const TokenList& tokenList, ErrorLogger& errorLogger, const Settings& settings)
: analyzer(analyzer), tokenList(tokenList), errorLogger(errorLogger), settings(settings)
{}
Expand DownExpand Up@@ -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;
Expand Down
7 changes: 4 additions & 3 deletions lib/programmemory.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -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<const Token*> conditions1 = flattenConditions(expr);
if (conditions1.empty())
return unknown();
Expand All@@ -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();
Expand DownExpand Up@@ -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) {
Expand DownExpand Up@@ -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;
Expand Down
61 changes: 30 additions & 31 deletions lib/valueflow.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -284,13 +284,12 @@ static void parseCompareEachInt(
return;
if (tok->isComparisonOp()) {
std::vector<ValueFlow::Value> value1 = evaluate(tok->astOperand1());
std::vector<ValueFlow::Value> value2 = evaluate(tok->astOperand2());
if (!value1.empty() && !value2.empty()) {
if (tok->astOperand1()->hasKnownIntValue())
value2.clear();
if (tok->astOperand2()->hasKnownIntValue())
value1.clear();
std::vector<ValueFlow::Value> 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;
Expand DownExpand Up@@ -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;
Expand DownExpand Up@@ -1027,7 +1026,7 @@ static std::vector<MathLib::bigint> 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()) {
Expand DownExpand Up@@ -1531,7 +1530,7 @@ static std::vector<ValueFlow::LifetimeToken> 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();
Expand DownExpand Up@@ -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<ValueFlow::Value> values = parent->astOperand2()->values();
values.remove_if(&isNotLifetimeValue);
Expand All@@ -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
Expand DownExpand Up@@ -2329,7 +2326,7 @@ struct LifetimeStore {
static bool hasBorrowingVariables(const std::list<Variable>& vars, const std::vector<const Token*>& 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 &&
Expand DownExpand Up@@ -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)
Expand DownExpand Up@@ -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();
Expand All@@ -3762,6 +3759,7 @@ struct SymbolicInferModel : InferModel {
result.setKnown();
return result;
}
const Token* expr;
};

static void valueFlowSymbolicInfer(const SymbolDatabase& symboldatabase, const Settings& settings)
Expand DownExpand Up@@ -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;
Expand DownExpand Up@@ -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,
Expand Down
4 changes: 2 additions & 2 deletions lib/vf_analyzers.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -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;
Expand DownExpand Up@@ -826,7 +826,7 @@ static bool bifurcateVariableChanged(const Variable* var,
static bool bifurcate(const Token* tok, const std::set<nonneg int>& varids, const Settings& settings, int depth)
{
if (depth < 0)
return false;
return false; // TODO: add bailout message
if (!tok)
return true;
if (tok->hasKnownIntValue())
Expand Down