Improvement: Support member variables in CheckOther::checkIncompleteArrayFill() (#4205)

Merged from LCppC.
This commit is contained in:
PKEuS 2022-07-12 19:43:48 +02:00 committed by GitHub
parent 1d9b6e1aac
commit f3565e1056
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 4 deletions

View File

@ -2838,8 +2838,16 @@ void CheckOther::checkIncompleteArrayFill()
for (const Scope * scope : symbolDatabase->functionScopes) {
for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
if (Token::Match(tok, "memset|memcpy|memmove ( %var% ,") && Token::Match(tok->linkAt(1)->tokAt(-2), ", %num% )")) {
const Variable *var = tok->tokAt(2)->variable();
if (Token::Match(tok, "memset|memcpy|memmove (") && Token::Match(tok->linkAt(1)->tokAt(-2), ", %num% )")) {
const Token* tok2 = tok->tokAt(2);
if (tok2->str() == "::")
tok2 = tok2->next();
while (Token::Match(tok2, "%name% ::|."))
tok2 = tok2->tokAt(2);
if (!Token::Match(tok2, "%var% ,"))
continue;
const Variable *var = tok2->variable();
if (!var || !var->isArray() || var->dimensions().empty() || !var->dimension(0))
continue;
@ -2849,11 +2857,12 @@ void CheckOther::checkIncompleteArrayFill()
size = mSettings->sizeof_pointer;
else if (size == 0 && var->type())
size = estimateSize(var->type(), mSettings, symbolDatabase);
const Token* tok3 = tok->next()->astOperand2()->astOperand1()->astOperand1();
if ((size != 1 && size != 100 && size != 0) || var->isPointer()) {
if (printWarning)
incompleteArrayFillError(tok, var->name(), tok->str(), false);
incompleteArrayFillError(tok, tok3->expressionString(), tok->str(), false);
} else if (var->valueType()->type == ValueType::Type::BOOL && printPortability) // sizeof(bool) is not 1 on all platforms
incompleteArrayFillError(tok, var->name(), tok->str(), true);
incompleteArrayFillError(tok, tok3->expressionString(), tok->str(), true);
}
}
}

View File

@ -7714,6 +7714,16 @@ private:
"[test.cpp:4]: (warning, inconclusive) Array 'a' is filled incompletely. Did you forget to multiply the size given to 'memcpy()' with 'sizeof(*a)'?\n"
"[test.cpp:5]: (warning, inconclusive) Array 'a' is filled incompletely. Did you forget to multiply the size given to 'memmove()' with 'sizeof(*a)'?\n", errout.str());
check("int a[5];\n"
"namespace Z { struct B { int a[5]; } b; }\n"
"void f() {\n"
" memset(::a, 123, 5);\n"
" memset(Z::b.a, 123, 5);\n"
"}");
TODO_ASSERT_EQUALS("[test.cpp:4]: (warning, inconclusive) Array '::a' is filled incompletely. Did you forget to multiply the size given to 'memset()' with 'sizeof(*::a)'?\n"
"[test.cpp:5]: (warning, inconclusive) Array 'Z::b.a' is filled incompletely. Did you forget to multiply the size given to 'memset()' with 'sizeof(*Z::b.a)'?\n",
"[test.cpp:4]: (warning, inconclusive) Array '::a' is filled incompletely. Did you forget to multiply the size given to 'memset()' with 'sizeof(*::a)'?\n", errout.str());
check("void f() {\n"
" Foo* a[5];\n"
" memset(a, 'a', 5);\n"