Skip to content

Commit 04af809

Browse files
authored
Fix #13685 FP uninitvar with nested compound statement scopes (danmar#8300)
PR danmar#6714 introduced a regression in which variables initialized in nested compound statements are incorrectly flagged as uninitialized by uninitvar. Such scopes could be present due to usage of GNU compound statements.
1 parent 929f95c commit 04af809

File tree

3 files changed

+40
-5
lines changed

3 files changed

+40
-5
lines changed

lib/symboldatabase.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
160160
};
161161

162162
std::stack<const Token*> inIfCondition;
163+
std::stack<Scope*> pendingIfScopes;
163164

164165
auto addLambda = [this, &scope](const Token* tok, const Token* lambdaEndToken) -> const Token* {
165166
const Token* lambdaStartToken = lambdaEndToken->link();
@@ -766,13 +767,14 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
766767
scopeList.emplace_back(*this, tok, scope, ScopeType::eSwitch, scopeStartTok);
767768

768769
scope->nestedList.push_back(&scopeList.back());
769-
scope = &scopeList.back();
770-
if (scope->type == ScopeType::eFor)
771-
scope->checkVariable(tok->tokAt(2), AccessControl::Local); // check for variable declaration and add it to new scope if found
772-
else if (scope->type == ScopeType::eCatch)
773-
scope->checkVariable(tok->tokAt(2), AccessControl::Throw); // check for variable declaration and add it to new scope if found
770+
Scope* newScope = &scopeList.back();
771+
if (newScope->type == ScopeType::eFor)
772+
newScope->checkVariable(tok->tokAt(2), AccessControl::Local); // check for variable declaration and add it to new scope if found
773+
else if (newScope->type == ScopeType::eCatch)
774+
newScope->checkVariable(tok->tokAt(2), AccessControl::Throw); // check for variable declaration and add it to new scope if found
774775
tok = tok->next();
775776
inIfCondition.push(scopeStartTok);
777+
pendingIfScopes.push(newScope);
776778
} else if (Token::Match(tok, "%var% {")) {
777779
endInitList.emplace(tok->linkAt(1), scope);
778780
tok = tok->next();
@@ -783,6 +785,8 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
783785
endInitList.emplace(tok->link(), scope);
784786
} else if (!inIfCondition.empty() && tok == inIfCondition.top()) {
785787
inIfCondition.pop();
788+
scope = pendingIfScopes.top();
789+
pendingIfScopes.pop();
786790
} else if (isExecutableScope(tok)) {
787791
scopeList.emplace_back(*this, tok, scope, ScopeType::eUnconditional, tok);
788792
scope->nestedList.push_back(&scopeList.back());

test/testsymboldatabase.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ class TestSymbolDatabase : public TestFixture {
441441
TEST_CASE(createSymbolDatabaseFindAllScopes8); // #12761
442442
TEST_CASE(createSymbolDatabaseFindAllScopes9);
443443
TEST_CASE(createSymbolDatabaseFindAllScopes10);
444+
TEST_CASE(createSymbolDatabaseFindAllScopes11);
444445

445446
TEST_CASE(createSymbolDatabaseIncompleteVars);
446447

@@ -6110,6 +6111,24 @@ class TestSymbolDatabase : public TestFixture {
61106111
}
61116112
}
61126113

6114+
void createSymbolDatabaseFindAllScopes11() // #13685
6115+
{
6116+
GET_SYMBOL_DB("int f() {\n"
6117+
" int x;\n"
6118+
" if (!({ int *p = &x; *p = 1; 1; }))\n"
6119+
" return 0;\n"
6120+
" return x;\n"
6121+
"}\n");
6122+
ASSERT(db && db->scopeList.size() == 4);
6123+
6124+
auto it = db->scopeList.begin();
6125+
std::advance(it, 3);
6126+
const Scope& compoundScope = *it;
6127+
ASSERT_EQUALS_ENUM(ScopeType::eUnconditional, compoundScope.type);
6128+
ASSERT_EQUALS_ENUM(ScopeType::eFunction, compoundScope.nestedIn->type);
6129+
ASSERT_EQUALS("f", compoundScope.nestedIn->className);
6130+
}
6131+
61136132
void createSymbolDatabaseIncompleteVars()
61146133
{
61156134
{

test/testuninitvar.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class TestUninitVar : public TestFixture {
7676
TEST_CASE(uninitvar12); // #10218 - stream read
7777
TEST_CASE(uninitvar13); // #9772
7878
TEST_CASE(uninitvar14);
79+
TEST_CASE(uninitvar15); // #13685
7980
TEST_CASE(uninitvar_unconditionalTry);
8081
TEST_CASE(uninitvar_funcptr); // #6404
8182
TEST_CASE(uninitvar_operator); // #6680
@@ -3647,6 +3648,17 @@ class TestUninitVar : public TestFixture {
36473648
(checkuninitvar.valueFlowUninit)();
36483649
}
36493650

3651+
void uninitvar15() { // #13685
3652+
const char code[] = "int f() {\n"
3653+
" int x;\n"
3654+
" if (!({ int *p = &x; *p = 1; 1; }))\n"
3655+
" return 0;\n"
3656+
" return x;\n"
3657+
"}";
3658+
valueFlowUninit(code, false);
3659+
ASSERT_EQUALS("", errout_str());
3660+
}
3661+
36503662
void valueFlowUninit2_value()
36513663
{
36523664
valueFlowUninit("void f() {\n"

0 commit comments

Comments
 (0)