parent
de9795b07b
commit
23deadb370
|
@ -3699,7 +3699,7 @@ HFONT CreateFont(
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
<returnValue type="DWORD"/>
|
<returnValue type="DWORD"/>
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<arg nr="1" direction="in">
|
<arg nr="1">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
</arg>
|
</arg>
|
||||||
<arg nr="2" direction="in">
|
<arg nr="2" direction="in">
|
||||||
|
@ -3746,7 +3746,7 @@ HFONT CreateFont(
|
||||||
<use-retval/>
|
<use-retval/>
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
<returnValue type="HRSRC"/>
|
<returnValue type="HRSRC"/>
|
||||||
<arg nr="1" direction="in">
|
<arg nr="1">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
</arg>
|
</arg>
|
||||||
<arg nr="2" direction="in">
|
<arg nr="2" direction="in">
|
||||||
|
|
|
@ -968,11 +968,13 @@ void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope)
|
||||||
|
|
||||||
if (Token::simpleMatch(tok->next()->astParent(), "(")) // passed to another function
|
if (Token::simpleMatch(tok->next()->astParent(), "(")) // passed to another function
|
||||||
continue;
|
continue;
|
||||||
if (!tok->isKeyword() && (mSettings->library.isNotLibraryFunction(tok) || !mSettings->library.isLeakIgnore(functionName)))
|
if (!tok->isKeyword() && !tok->function() && !mSettings->library.isLeakIgnore(functionName))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const std::vector<const Token *> args = getArguments(tok);
|
const std::vector<const Token *> args = getArguments(tok);
|
||||||
|
int argnr = -1;
|
||||||
for (const Token* arg : args) {
|
for (const Token* arg : args) {
|
||||||
|
++argnr;
|
||||||
if (arg->isOp() && !(tok->isKeyword() && arg->str() == "*")) // e.g. switch (*new int)
|
if (arg->isOp() && !(tok->isKeyword() && arg->str() == "*")) // e.g. switch (*new int)
|
||||||
continue;
|
continue;
|
||||||
while (arg->astOperand1()) {
|
while (arg->astOperand1()) {
|
||||||
|
@ -983,10 +985,28 @@ void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope)
|
||||||
const AllocType alloc = getAllocationType(arg, 0);
|
const AllocType alloc = getAllocationType(arg, 0);
|
||||||
if (alloc == No)
|
if (alloc == No)
|
||||||
continue;
|
continue;
|
||||||
if ((alloc == New || alloc == NewArray) && arg->next() && !(arg->next()->isStandardType() || mSettings->library.detectContainerOrIterator(arg)))
|
if (alloc == New || alloc == NewArray) {
|
||||||
continue;
|
const Token* typeTok = arg->next();
|
||||||
|
bool bail = !typeTok->isStandardType() &&
|
||||||
|
!mSettings->library.detectContainerOrIterator(typeTok) &&
|
||||||
|
!mSettings->library.podtype(typeTok->expressionString());
|
||||||
|
if (bail && typeTok->type() && typeTok->type()->classScope &&
|
||||||
|
typeTok->type()->classScope->numConstructors == 0 &&
|
||||||
|
typeTok->type()->classScope->getDestructor() == nullptr) {
|
||||||
|
bail = false;
|
||||||
|
}
|
||||||
|
if (bail)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (isReopenStandardStream(arg))
|
if (isReopenStandardStream(arg))
|
||||||
continue;
|
continue;
|
||||||
|
if (tok->function()) {
|
||||||
|
const Variable* argvar = tok->function()->getArgumentVar(argnr);
|
||||||
|
if (!argvar || !argvar->valueType())
|
||||||
|
continue;
|
||||||
|
if (argvar->valueType()->typeSize(mSettings->platform, /*p*/ true) >= mSettings->platform.sizeof_pointer)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
functionCallLeak(arg, arg->str(), functionName);
|
functionCallLeak(arg, arg->str(), functionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2456,6 +2456,43 @@ private:
|
||||||
" s->p = s->p ? strcpy(new char[N], s->p) : nullptr;\n"
|
" s->p = s->p ? strcpy(new char[N], s->p) : nullptr;\n"
|
||||||
"};\n");
|
"};\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("struct S {};\n" // #11866
|
||||||
|
"void f(bool b);\n"
|
||||||
|
"void g() {\n"
|
||||||
|
" f(new int());\n"
|
||||||
|
" f(new std::vector<int>());\n"
|
||||||
|
" f(new S());\n"
|
||||||
|
" f(new tm());\n"
|
||||||
|
" f(malloc(sizeof(S)));\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (error) Allocation with new, f doesn't release it.\n"
|
||||||
|
"[test.cpp:5]: (error) Allocation with new, f doesn't release it.\n"
|
||||||
|
"[test.cpp:6]: (error) Allocation with new, f doesn't release it.\n"
|
||||||
|
"[test.cpp:7]: (error) Allocation with new, f doesn't release it.\n"
|
||||||
|
"[test.cpp:8]: (error) Allocation with malloc, f doesn't release it.\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
|
check("void f(uintptr_t u);\n"
|
||||||
|
"void g() {\n"
|
||||||
|
" f((uintptr_t)new int());\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f(uint8_t u);\n"
|
||||||
|
"void g() {\n"
|
||||||
|
" f((uint8_t)new int());\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Allocation with new, f doesn't release it.\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
|
check("void f(int i, T t);\n"
|
||||||
|
"void g(int i, U* u);\n"
|
||||||
|
"void h() {\n"
|
||||||
|
" f(1, new int());\n"
|
||||||
|
" g(1, new int());\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void missingAssignment() {
|
void missingAssignment() {
|
||||||
|
|
Loading…
Reference in New Issue