diff --git a/cfg/windows.cfg b/cfg/windows.cfg
index 48c1e9f2f84..105ee469b56 100644
--- a/cfg/windows.cfg
+++ b/cfg/windows.cfg
@@ -3699,7 +3699,7 @@ HFONT CreateFont(
false
-
+
@@ -3746,7 +3746,7 @@ HFONT CreateFont(
false
-
+
diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp
index b6f4dde5b41..93fbb3a4bb3 100644
--- a/lib/checkmemoryleak.cpp
+++ b/lib/checkmemoryleak.cpp
@@ -968,11 +968,13 @@ void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope)
if (Token::simpleMatch(tok->next()->astParent(), "(")) // passed to another function
continue;
- if (!tok->isKeyword() && (mSettings->library.isNotLibraryFunction(tok) || !mSettings->library.isLeakIgnore(functionName)))
+ if (!tok->isKeyword() && !tok->function() && !mSettings->library.isLeakIgnore(functionName))
continue;
const std::vector args = getArguments(tok);
+ int argnr = -1;
for (const Token* arg : args) {
+ ++argnr;
if (arg->isOp() && !(tok->isKeyword() && arg->str() == "*")) // e.g. switch (*new int)
continue;
while (arg->astOperand1()) {
@@ -983,10 +985,28 @@ void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope)
const AllocType alloc = getAllocationType(arg, 0);
if (alloc == No)
continue;
- if ((alloc == New || alloc == NewArray) && arg->next() && !(arg->next()->isStandardType() || mSettings->library.detectContainerOrIterator(arg)))
- continue;
+ if (alloc == New || alloc == NewArray) {
+ 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))
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);
}
diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp
index beedd57b232..131116f5198 100644
--- a/test/testmemleak.cpp
+++ b/test/testmemleak.cpp
@@ -2456,6 +2456,43 @@ class TestMemleakNoVar : public TestFixture {
" s->p = s->p ? strcpy(new char[N], s->p) : nullptr;\n"
"};\n");
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());\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() {