Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions lib/checkclass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,15 +473,15 @@ void CheckClassImpl::copyconstructors()
if (Token::Match(tok, "%var% ( new") ||
(Token::Match(tok, "%var% ( %name% (") && mSettings.library.getAllocFuncInfo(tok->tokAt(2)))) {
const Variable* var = tok->variable();
if (var && var->isPointer() && var->scope() == scope)
if (var && var->scope() == scope && !(var->valueType() && var->valueType()->type == ValueType::SMART_POINTER))
allocatedVars[tok->varId()] = tok;
}
}
for (const Token* const end = func.functionScope->bodyEnd; tok != end; tok = tok->next()) {
if (Token::Match(tok, "%var% = new") ||
(Token::Match(tok, "%var% = %name% (") && mSettings.library.getAllocFuncInfo(tok->tokAt(2)))) {
const Variable* var = tok->variable();
if (var && var->isPointer() && var->scope() == scope && !var->isStatic())
if (var && var->scope() == scope && !var->isStatic() && !(var->valueType() && var->valueType()->type == ValueType::SMART_POINTER))
allocatedVars[tok->varId()] = tok;
}
}
Expand All @@ -493,7 +493,7 @@ void CheckClassImpl::copyconstructors()
(Token::Match(tok, "%name% ( %var%") && mSettings.library.getDeallocFuncInfo(tok))) {
const Token *vartok = tok->str() == "delete" ? tok->next() : tok->tokAt(2);
const Variable* var = vartok->variable();
if (var && var->isPointer() && var->scope() == scope && !var->isStatic())
if (var && var->scope() == scope && !var->isStatic())
deallocatedVars[vartok->varId()] = vartok;
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/checkmemoryleak.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ void CheckMemoryLeakInClassImpl::check()
// only check classes and structures
for (const Scope * scope : symbolDatabase->classAndStructScopes) {
for (const Variable &var : scope->varlist) {
if (!var.isStatic() && (var.isPointer() || var.isPointerArray())) {
if (!var.isStatic()) {
// allocation but no deallocation of private variables in public function..
const Token *tok = var.typeStartToken();
// Either it is of standard type or a non-derived type
Expand Down
32 changes: 31 additions & 1 deletion test/testclass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class TestClass : public TestFixture {
const Settings settings0_i = settingsBuilder(settings0).certainty(Certainty::inconclusive).build();
const Settings settings1 = settingsBuilder().severity(Severity::warning).library("std.cfg").build();
const Settings settings2 = settingsBuilder().severity(Severity::style).library("std.cfg").certainty(Certainty::inconclusive).build();
const Settings settings3 = settingsBuilder().severity(Severity::style).library("std.cfg").severity(Severity::warning).build();
const Settings settings3 = settingsBuilder().severity(Severity::style).library("std.cfg").severity(Severity::warning).library("posix.cfg").build();
const Settings settings3_i = settingsBuilder(settings3).certainty(Certainty::inconclusive).build();
const Settings settings4 = settingsBuilder().severity(Severity::warning).severity(Severity::portability).library("std.cfg").library("posix.cfg").build();

Expand All @@ -62,6 +62,8 @@ class TestClass : public TestFixture {
TEST_CASE(copyConstructor4); // base class with private constructor
TEST_CASE(copyConstructor5); // multiple inheritance
TEST_CASE(copyConstructor6); // array of pointers
TEST_CASE(copyConstructor7);

@aadanen aadanen Jul 31, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the other copy constructor test cases have a reference to a ticket or a description. Should these be updated to match?

TEST_CASE(copyConstructor8);
TEST_CASE(deletedMemberPointer); // deleted member pointer in destructor
TEST_CASE(noOperatorEq); // class with memory management should have operator eq
TEST_CASE(noDestructor); // class with memory management should have destructor
Expand Down Expand Up @@ -1094,6 +1096,25 @@ class TestClass : public TestFixture {
errout_str());
}

void copyConstructor7() {
checkCopyConstructor("struct S {\n"
" explicit S(char *name) { m_fd = mkstemp(name); }\n"
" ~S() { /* close(m_fd); */ }\n"
" S &operator =(const S&);\n"
" int m_fd;\n"
"};\n");
ASSERT_EQUALS("[test.cpp:2:30]: (warning) Struct 'S' does not have a copy constructor which is recommended since it has dynamic memory/resource management. [noCopyConstructor]\n", errout_str());
}

void copyConstructor8() {
checkCopyConstructor("struct S {\n"
" S() : m_ptr(new int) {}\n"
" ~S();\n"
" std::unique_ptr<int> m_ptr;\n"
"};\n");
ASSERT_EQUALS("", errout_str());
}

void deletedMemberPointer() {

// delete ...
Expand Down Expand Up @@ -1158,6 +1179,15 @@ class TestClass : public TestFixture {
" ~F();\n"
"};");
ASSERT_EQUALS("", errout_str());

checkCopyConstructor("struct S {\n"
" explicit S(char *name) { m_fd = mkstemp(name); }\n"
" S(const S&);\n"
" ~S() { /* close(m_fd); */ }\n"
" int m_fd;\n"
"};\n");
ASSERT_EQUALS("[test.cpp:2:30]: (warning) Struct 'S' does not have a operator= which is recommended since it has dynamic memory/resource management. [noOperatorEq]\n", errout_str());

}

void noDestructor() {
Expand Down
12 changes: 11 additions & 1 deletion test/testmemleak.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ class TestMemleakInClass : public TestFixture {
TestMemleakInClass() : TestFixture("TestMemleakInClass") {}

private:
const Settings settings = settingsBuilder().severity(Severity::warning).severity(Severity::style).library("std.cfg").build();
const Settings settings = settingsBuilder().severity(Severity::warning).severity(Severity::style).library("std.cfg").library("posix.cfg").build();

/**
* Tokenize and execute leak check for given code
Expand Down Expand Up @@ -533,6 +533,7 @@ class TestMemleakInClass : public TestFixture {
TEST_CASE(class25); // ticket #4367 - false positive implementation for destructor is not seen
TEST_CASE(class26); // ticket #10789
TEST_CASE(class27); // ticket #8126
TEST_CASE(class28);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this should also reference ticket #14954


TEST_CASE(staticvar);

Expand Down Expand Up @@ -1484,6 +1485,15 @@ class TestMemleakInClass : public TestFixture {
ASSERT_EQUALS("[test.cpp:6:11]: (style) Class 'S' is unsafe, 'S::a' can leak by wrong usage. [unsafeClassCanLeak]\n", errout_str());
}

void class28() {
check("struct S {\n"
" explicit S(char *name) { m_fd = mkstemp(name); }\n"
" ~S() { /* close(m_fd); */ }\n"
" int m_fd;\n"
"};\n");
ASSERT_EQUALS("[test.cpp:4:9]: (style) Class 'S' is unsafe, 'S::m_fd' can leak by wrong usage. [unsafeClassCanLeak]\n", errout_str());
}

void staticvar() {
check("class A\n"
"{\n"
Expand Down
Loading