@@ -363,52 +363,40 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
363
363
while (Token::Match (ftok, " %name% :: %name%" ))
364
364
ftok = ftok->tokAt (2 );
365
365
366
- // memcpy / memmove
367
- if (Token::Match (varTok, " memcpy|memmove" )) {
368
- const std::vector<const Token*> args = getArguments (varTok);
369
- // too few args for memcpy / memmove call
370
- if (args.size () < 3 )
371
- continue ;
372
- const Token *dst = args[0 ];
373
- const Token *src = args[1 ];
374
-
375
- // check that dst arg is pointer to pointer
376
- int dstIndirectionLevel = 0 ;
377
- while (dst->str () == " *" ) {
378
- dst = dst->astOperand1 ();
379
- dstIndirectionLevel--;
380
- }
381
- if (dst->str () == " &" ) {
382
- dst = dst->astOperand1 ();
383
- dstIndirectionLevel++;
384
- }
385
- if (!dst->isVariable ())
386
- continue ;
387
- if (dstIndirectionLevel + dst->variable ()->valueType ()->pointer != 2 )
388
- continue ;
389
-
390
- // check that src arg is pointer to pointer
391
- int srcIndirectionLevel = 0 ;
392
- while (src->str () == " *" ) {
393
- src = src->astOperand1 ();
394
- srcIndirectionLevel--;
395
- }
396
- if (src->str () == " &" ) {
397
- src = src->astOperand1 ();
398
- srcIndirectionLevel++;
366
+ if (const Library::Function *libFunc = mSettings ->library .getFunction (ftok)) {
367
+ using ArgumentChecks = Library::ArgumentChecks;
368
+ using Direction = ArgumentChecks::Direction;
369
+ const std::vector<const Token *> args = getArguments (ftok);
370
+ const std::map<int , ArgumentChecks> &argChecks = libFunc->argumentChecks ;
371
+ bool hasOutParam = false ;
372
+ for (const auto &pair : argChecks) {
373
+ hasOutParam |= std::any_of (pair.second .direction .cbegin (), pair.second .direction .cend (), [&](const Direction dir) {
374
+ return dir == Direction::DIR_OUT;
375
+ });
376
+ if (hasOutParam)
377
+ break ;
399
378
}
400
- if (!src->isVariable ())
401
- continue ;
402
- if (srcIndirectionLevel + src->variable ()->valueType ()->pointer != 2 )
403
- continue ;
404
-
405
- if (!dst->variable ()->isArgument ()) {
406
- varInfo.alloctype [dst->varId ()].status = VarInfo::AllocStatus::ALLOC;
379
+ if (hasOutParam) {
380
+ for (int i = 0 ; i < args.size (); i++) {
381
+ if (!argChecks.count (i + 1 ))
382
+ continue ;
383
+ const ArgumentChecks argCheck = argChecks.at (i + 1 );
384
+ bool isInParam = std::any_of (argCheck.direction .cbegin (), argCheck.direction .cend (), [&](const Direction dir) {
385
+ return dir == Direction::DIR_IN;
386
+ });
387
+ if (!isInParam)
388
+ continue ;
389
+ const Token *varTok = args[i];
390
+ int indirect = 0 ;
391
+ while (varTok->isUnaryOp (" &" )) {
392
+ varTok = varTok->astOperand1 ();
393
+ indirect++;
394
+ }
395
+ if (varTok->isVariable () && indirect) {
396
+ varInfo.erase (varTok->varId ());
397
+ }
398
+ }
407
399
}
408
-
409
- // no multivariable checking currently (see assignment below)
410
- // treat source pointer as unallocated
411
- varInfo.erase (src->varId ());
412
400
}
413
401
414
402
auto isAssignment = [](const Token* varTok) -> const Token* {
0 commit comments