@@ -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