Skip to content

Commit 3d6c453

Browse files
authored
Fix uninitvar false positive in designed initializers (#5079)
Stop interpreting struct fields in designed initializers as usage of local variables which can happen if they share the same name. ``` $ cat test.c struct a { int b; }; int main() { char *b; extern int foo(struct a *); return foo(&(struct a){.b = 0}); } $ cppcheck --quiet test.c test.c:5:27: error: Uninitialized variable: b [legacyUninitvar] return foo(&(struct a){.b = 0}); ```
1 parent fb850a8 commit 3d6c453

2 files changed

Lines changed: 23 additions & 0 deletions

File tree

lib/checkuninitvar.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,10 @@ const Token* CheckUninitVar::isVariableUsage(bool cpp, const Token *vartok, cons
11231123
// (type &)x
11241124
else if (valueExpr->astParent()->isCast() && valueExpr->astParent()->isUnaryOp("(") && Token::simpleMatch(valueExpr->astParent()->link()->previous(), "& )"))
11251125
valueExpr = valueExpr->astParent();
1126+
// designated initializers: {.x | { ... , .x
1127+
else if (Token::simpleMatch(valueExpr->astParent(), ".") &&
1128+
Token::Match(valueExpr->astParent()->previous(), ",|{"))
1129+
valueExpr = valueExpr->astParent();
11261130
else
11271131
break;
11281132
}

test/testuninitvar.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class TestUninitVar : public TestFixture {
9494
TEST_CASE(uninitvar_ipa);
9595
TEST_CASE(uninitvar_memberfunction);
9696
TEST_CASE(uninitvar_nonmember); // crash in ycmd test
97+
TEST_CASE(uninitvarDesignatedInitializers);
9798

9899
TEST_CASE(isVariableUsageDeref); // *p
99100
TEST_CASE(isVariableUsageDerefValueflow); // *p
@@ -6955,6 +6956,24 @@ class TestUninitVar : public TestFixture {
69556956
ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: foo\n", errout.str());
69566957
}
69576958

6959+
void uninitvarDesignatedInitializers() {
6960+
checkUninitVar("struct a { int b; };\n"
6961+
"int main() {\n"
6962+
" char *b;\n"
6963+
" extern int f(struct a *);\n"
6964+
" return f(&(struct a){.b = 0});\n"
6965+
"}");
6966+
ASSERT_EQUALS("", errout.str());
6967+
6968+
checkUninitVar("struct a { int b, c; };\n"
6969+
"int main() {\n"
6970+
" char *c;\n"
6971+
" extern int f(struct a *);\n"
6972+
" return f(&(struct a){.b = 0, .c = 0});\n"
6973+
"}");
6974+
ASSERT_EQUALS("", errout.str());
6975+
}
6976+
69586977
void isVariableUsageDeref() {
69596978
// *p
69606979
checkUninitVar("void f() {\n"

0 commit comments

Comments
 (0)