diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index c06a07741..1ce306a39 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3388,6 +3388,60 @@ static void valueFlowLifetimeConstructor(Token *tok, ErrorLogger *errorLogger, const Settings *settings); +static const Token* getEndOfVarScope(const Variable* var) +{ + if (!var) + return nullptr; + const Scope* innerScope = var->scope(); + const Scope* outerScope = innerScope; + if (var->typeStartToken() && var->typeStartToken()->scope()) + outerScope = var->typeStartToken()->scope(); + if (!innerScope && outerScope) + innerScope = outerScope; + if (!innerScope || !outerScope) + return nullptr; + if (!innerScope->isExecutable()) + return nullptr; + // If the variable is defined in a for/while initializer then we want to + // pick one token after the end so forward analysis can analyze the exit + // conditions + if (innerScope != outerScope && outerScope->isExecutable() && innerScope->isLocal()) + return innerScope->bodyEnd->next(); + return innerScope->bodyEnd; +} + +static const Token* getEndOfExprScope(const Token* tok, const Scope* defaultScope = nullptr) +{ + const Token* end = nullptr; + bool local = false; + visitAstNodes(tok, [&](const Token* child) { + if (const Variable* var = child->variable()) { + local |= var->isLocal(); + if (var->isLocal() || var->isArgument()) { + const Token* varEnd = getEndOfVarScope(var); + if (!end || precedes(varEnd, end)) + end = varEnd; + } + } + return ChildrenToVisit::op1_and_op2; + }); + if (!end && defaultScope) + end = defaultScope->bodyEnd; + if (!end) { + const Scope* scope = tok->scope(); + if (scope) + end = scope->bodyEnd; + // If there is no local variables then pick the function scope + if (!local) { + while (scope && scope->isLocal()) + scope = scope->nestedIn; + if (scope && scope->isExecutable()) + end = scope->bodyEnd; + } + } + return end; +} + static const Token* getEndOfVarScope(const Token* tok, const std::vector& vars) { const Token* endOfVarScope = nullptr; @@ -5627,7 +5681,7 @@ struct ConditionHandler { } if (values.empty()) return; - forward(after, scope->bodyEnd, cond.vartok, values, tokenlist, settings); + forward(after, getEndOfExprScope(cond.vartok, scope), cond.vartok, values, tokenlist, settings); } }); }