Skip to content

Commit 85e6ad9

Browse files
committed
fix #13915
1 parent b6a1915 commit 85e6ad9

1 file changed

Lines changed: 46 additions & 21 deletions

File tree

lib/checkclass.cpp

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -413,30 +413,47 @@ void CheckClass::copyconstructors()
413413

414414
for (const Scope * scope : mSymbolDatabase->classAndStructScopes) {
415415
std::map<int, const Token*> allocatedVars;
416+
std::map<int, const Token*> deallocatedVars;
416417

417418
for (const Function &func : scope->functionList) {
418-
if (func.type != FunctionType::eConstructor || !func.functionScope)
419-
continue;
420-
const Token* tok = func.token->linkAt(1);
421-
for (const Token* const end = func.functionScope->bodyStart; tok != end; tok = tok->next()) {
422-
if (Token::Match(tok, "%var% ( new") ||
423-
(Token::Match(tok, "%var% ( %name% (") && mSettings->library.getAllocFuncInfo(tok->tokAt(2)))) {
424-
const Variable* var = tok->variable();
425-
if (var && var->isPointer() && var->scope() == scope)
426-
allocatedVars[tok->varId()] = tok;
419+
if (func.type == FunctionType::eConstructor && func.functionScope) {
420+
// Allocations in constructors
421+
const Token* tok = func.token->linkAt(1);
422+
for (const Token* const end = func.functionScope->bodyStart; tok != end; tok = tok->next()) {
423+
if (Token::Match(tok, "%var% ( new") ||
424+
(Token::Match(tok, "%var% ( %name% (") && mSettings->library.getAllocFuncInfo(tok->tokAt(2)))) {
425+
const Variable* var = tok->variable();
426+
if (var && var->isPointer() && var->scope() == scope)
427+
allocatedVars[tok->varId()] = tok;
428+
}
427429
}
428-
}
429-
for (const Token* const end = func.functionScope->bodyEnd; tok != end; tok = tok->next()) {
430-
if (Token::Match(tok, "%var% = new") ||
431-
(Token::Match(tok, "%var% = %name% (") && mSettings->library.getAllocFuncInfo(tok->tokAt(2)))) {
432-
const Variable* var = tok->variable();
433-
if (var && var->isPointer() && var->scope() == scope && !var->isStatic())
434-
allocatedVars[tok->varId()] = tok;
430+
for (const Token* const end = func.functionScope->bodyEnd; tok != end; tok = tok->next()) {
431+
if (Token::Match(tok, "%var% = new") ||
432+
(Token::Match(tok, "%var% = %name% (") && mSettings->library.getAllocFuncInfo(tok->tokAt(2)))) {
433+
const Variable* var = tok->variable();
434+
if (var && var->isPointer() && var->scope() == scope && !var->isStatic())
435+
allocatedVars[tok->varId()] = tok;
436+
}
437+
}
438+
} else if (func.type == FunctionType::eDestructor && func.functionScope) {
439+
// Deallocations in destructors
440+
const Token* tok = func.token->linkAt(1);
441+
for (const Token* const end = func.functionScope->bodyEnd; tok != end; tok = tok->next()) {
442+
if (Token::Match(tok, "delete %var%") ||
443+
(Token::Match(tok, "%name% ( %var%") && mSettings->library.getDeallocFuncInfo(tok))) {
444+
const Token *vartok = tok->str() == "delete" ? tok->next() : tok->tokAt(2);
445+
const Variable* var = vartok->variable();
446+
if (var && var->isPointer() && var->scope() == scope && !var->isStatic())
447+
deallocatedVars[vartok->varId()] = vartok;
448+
}
435449
}
436450
}
437451
}
438452

439-
if (!allocatedVars.empty()) {
453+
bool hasAllocatedVars = !allocatedVars.empty();
454+
bool hasDeallocatedVars = !deallocatedVars.empty();
455+
456+
if (hasAllocatedVars || hasDeallocatedVars) {
440457
const Function *funcCopyCtor = nullptr;
441458
const Function *funcOperatorEq = nullptr;
442459
const Function *funcDestructor = nullptr;
@@ -450,13 +467,21 @@ void CheckClass::copyconstructors()
450467
}
451468
if (!funcCopyCtor || funcCopyCtor->isDefault()) {
452469
bool unknown = false;
453-
if (!hasNonCopyableBase(scope, &unknown) && !unknown)
454-
noCopyConstructorError(scope, funcCopyCtor, allocatedVars.cbegin()->second, unknown);
470+
if (!hasNonCopyableBase(scope, &unknown) && !unknown) {
471+
if (hasAllocatedVars)
472+
noCopyConstructorError(scope, funcCopyCtor, allocatedVars.cbegin()->second, unknown);
473+
else
474+
noCopyConstructorError(scope, funcCopyCtor, deallocatedVars.cbegin()->second, unknown);
475+
}
455476
}
456477
if (!funcOperatorEq || funcOperatorEq->isDefault()) {
457478
bool unknown = false;
458-
if (!hasNonCopyableBase(scope, &unknown) && !unknown)
459-
noOperatorEqError(scope, funcOperatorEq, allocatedVars.cbegin()->second, unknown);
479+
if (!hasNonCopyableBase(scope, &unknown) && !unknown) {
480+
if (hasAllocatedVars)
481+
noOperatorEqError(scope, funcOperatorEq, allocatedVars.cbegin()->second, unknown);
482+
else
483+
noOperatorEqError(scope, funcOperatorEq, deallocatedVars.cbegin()->second, unknown);
484+
}
460485
}
461486
if (!funcDestructor || funcDestructor->isDefault()) {
462487
const Token * mustDealloc = nullptr;

0 commit comments

Comments
 (0)