Skip to content

Commit 11387cb

Browse files
authored
Fix 10768: performance regression (#3788)
1 parent 4af8734 commit 11387cb

1 file changed

Lines changed: 55 additions & 1 deletion

File tree

lib/valueflow.cpp

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3388,6 +3388,60 @@ static void valueFlowLifetimeConstructor(Token *tok,
33883388
ErrorLogger *errorLogger,
33893389
const Settings *settings);
33903390

3391+
static const Token* getEndOfVarScope(const Variable* var)
3392+
{
3393+
if (!var)
3394+
return nullptr;
3395+
const Scope* innerScope = var->scope();
3396+
const Scope* outerScope = innerScope;
3397+
if (var->typeStartToken() && var->typeStartToken()->scope())
3398+
outerScope = var->typeStartToken()->scope();
3399+
if (!innerScope && outerScope)
3400+
innerScope = outerScope;
3401+
if (!innerScope || !outerScope)
3402+
return nullptr;
3403+
if (!innerScope->isExecutable())
3404+
return nullptr;
3405+
// If the variable is defined in a for/while initializer then we want to
3406+
// pick one token after the end so forward analysis can analyze the exit
3407+
// conditions
3408+
if (innerScope != outerScope && outerScope->isExecutable() && innerScope->isLocal())
3409+
return innerScope->bodyEnd->next();
3410+
return innerScope->bodyEnd;
3411+
}
3412+
3413+
static const Token* getEndOfExprScope(const Token* tok, const Scope* defaultScope = nullptr)
3414+
{
3415+
const Token* end = nullptr;
3416+
bool local = false;
3417+
visitAstNodes(tok, [&](const Token* child) {
3418+
if (const Variable* var = child->variable()) {
3419+
local |= var->isLocal();
3420+
if (var->isLocal() || var->isArgument()) {
3421+
const Token* varEnd = getEndOfVarScope(var);
3422+
if (!end || precedes(varEnd, end))
3423+
end = varEnd;
3424+
}
3425+
}
3426+
return ChildrenToVisit::op1_and_op2;
3427+
});
3428+
if (!end && defaultScope)
3429+
end = defaultScope->bodyEnd;
3430+
if (!end) {
3431+
const Scope* scope = tok->scope();
3432+
if (scope)
3433+
end = scope->bodyEnd;
3434+
// If there is no local variables then pick the function scope
3435+
if (!local) {
3436+
while (scope && scope->isLocal())
3437+
scope = scope->nestedIn;
3438+
if (scope && scope->isExecutable())
3439+
end = scope->bodyEnd;
3440+
}
3441+
}
3442+
return end;
3443+
}
3444+
33913445
static const Token* getEndOfVarScope(const Token* tok, const std::vector<const Variable*>& vars)
33923446
{
33933447
const Token* endOfVarScope = nullptr;
@@ -5627,7 +5681,7 @@ struct ConditionHandler {
56275681
}
56285682
if (values.empty())
56295683
return;
5630-
forward(after, scope->bodyEnd, cond.vartok, values, tokenlist, settings);
5684+
forward(after, getEndOfExprScope(cond.vartok, scope), cond.vartok, values, tokenlist, settings);
56315685
}
56325686
});
56335687
}

0 commit comments

Comments
 (0)