Skip to content

Commit 0f259a5

Browse files
committed
Fixed #10222 (regression: arrayIndexOutOfBounds)
1 parent d3f0aa5 commit 0f259a5

2 files changed

Lines changed: 43 additions & 3 deletions

File tree

lib/valueflow.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3394,10 +3394,22 @@ static const Token* getEndOfVarScope(const Token* tok, const std::vector<const V
33943394
{
33953395
const Token* endOfVarScope = nullptr;
33963396
for (const Variable* var : vars) {
3397+
const Scope *varScope = nullptr;
33973398
if (var && (var->isLocal() || var->isArgument()) && var->typeStartToken()->scope()->type != Scope::eNamespace)
3398-
endOfVarScope = var->typeStartToken()->scope()->bodyEnd;
3399-
else if (!endOfVarScope)
3400-
endOfVarScope = tok->scope()->bodyEnd;
3399+
varScope = var->typeStartToken()->scope();
3400+
else if (!endOfVarScope) {
3401+
varScope = tok->scope();
3402+
// A "local member" will be a expression like foo.x where foo is a local variable.
3403+
// A "global member" will be a member that belongs to a global object.
3404+
const bool globalMember = vars.size() == 1; // <- could check if it's a member here also but it seems redundant
3405+
if (var && (var->isGlobal() || var->isNamespace() || globalMember)) {
3406+
// Global variable => end of function
3407+
while (varScope->isLocal())
3408+
varScope = varScope->nestedIn;
3409+
}
3410+
}
3411+
if (varScope && (!endOfVarScope || precedes(varScope->bodyEnd, endOfVarScope)))
3412+
endOfVarScope = varScope->bodyEnd;
34013413
}
34023414
return endOfVarScope;
34033415
}

test/testvalueflow.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2475,6 +2475,34 @@ class TestValueFlow : public TestFixture {
24752475
" }\n"
24762476
"};\n";
24772477
ASSERT_EQUALS(true, testValueOfXKnown(code, 7U, 1));
2478+
2479+
// global variable
2480+
code = "int x;\n"
2481+
"int foo(int y) {\n"
2482+
" if (y)\n"
2483+
" x = 10;\n"
2484+
" return x;\n"
2485+
"}";
2486+
ASSERT_EQUALS(true, testValueOfX(code, 5U, 10));
2487+
2488+
code = "namespace A { int x; }\n"
2489+
"int foo(int y) {\n"
2490+
" if (y)\n"
2491+
" A::x = 10;\n"
2492+
" return A::x;\n"
2493+
"}";
2494+
ASSERT_EQUALS(true, testValueOfX(code, 5U, 10));
2495+
2496+
// member variable
2497+
code = "struct Fred {\n"
2498+
" int x;\n"
2499+
" int foo(int y) {\n"
2500+
" if (y)\n"
2501+
" x = 10;\n"
2502+
" return x;\n"
2503+
" }\n"
2504+
"};";
2505+
ASSERT_EQUALS(true, testValueOfX(code, 6U, 10));
24782506
}
24792507

24802508
void valueFlowAfterSwap()

0 commit comments

Comments
 (0)