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}); ```
This commit is contained in:
parent
fb850a844b
commit
3d6c453058
|
@ -1123,6 +1123,10 @@ const Token* CheckUninitVar::isVariableUsage(bool cpp, const Token *vartok, cons
|
||||||
// (type &)x
|
// (type &)x
|
||||||
else if (valueExpr->astParent()->isCast() && valueExpr->astParent()->isUnaryOp("(") && Token::simpleMatch(valueExpr->astParent()->link()->previous(), "& )"))
|
else if (valueExpr->astParent()->isCast() && valueExpr->astParent()->isUnaryOp("(") && Token::simpleMatch(valueExpr->astParent()->link()->previous(), "& )"))
|
||||||
valueExpr = valueExpr->astParent();
|
valueExpr = valueExpr->astParent();
|
||||||
|
// designated initializers: {.x | { ... , .x
|
||||||
|
else if (Token::simpleMatch(valueExpr->astParent(), ".") &&
|
||||||
|
Token::Match(valueExpr->astParent()->previous(), ",|{"))
|
||||||
|
valueExpr = valueExpr->astParent();
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,7 @@ private:
|
||||||
TEST_CASE(uninitvar_ipa);
|
TEST_CASE(uninitvar_ipa);
|
||||||
TEST_CASE(uninitvar_memberfunction);
|
TEST_CASE(uninitvar_memberfunction);
|
||||||
TEST_CASE(uninitvar_nonmember); // crash in ycmd test
|
TEST_CASE(uninitvar_nonmember); // crash in ycmd test
|
||||||
|
TEST_CASE(uninitvarDesignatedInitializers);
|
||||||
|
|
||||||
TEST_CASE(isVariableUsageDeref); // *p
|
TEST_CASE(isVariableUsageDeref); // *p
|
||||||
TEST_CASE(isVariableUsageDerefValueflow); // *p
|
TEST_CASE(isVariableUsageDerefValueflow); // *p
|
||||||
|
@ -6955,6 +6956,24 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: foo\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: foo\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void uninitvarDesignatedInitializers() {
|
||||||
|
checkUninitVar("struct a { int b; };\n"
|
||||||
|
"int main() {\n"
|
||||||
|
" char *b;\n"
|
||||||
|
" extern int f(struct a *);\n"
|
||||||
|
" return f(&(struct a){.b = 0});\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
checkUninitVar("struct a { int b, c; };\n"
|
||||||
|
"int main() {\n"
|
||||||
|
" char *c;\n"
|
||||||
|
" extern int f(struct a *);\n"
|
||||||
|
" return f(&(struct a){.b = 0, .c = 0});\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void isVariableUsageDeref() {
|
void isVariableUsageDeref() {
|
||||||
// *p
|
// *p
|
||||||
checkUninitVar("void f() {\n"
|
checkUninitVar("void f() {\n"
|
||||||
|
|
Loading…
Reference in New Issue