| 1015 | } |
| 1016 | |
| 1017 | void CheckLeakAutoVarImpl::functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af) |
| 1018 | { |
| 1019 | // Ignore function call? |
| 1020 | const bool isLeakIgnore = mSettings.library.isLeakIgnore(mSettings.library.getFunctionName(tokName)); |
| 1021 | if (mSettings.library.getReallocFuncInfo(tokName)) |
| 1022 | return; |
| 1023 | if (tokName->next()->valueType() && tokName->next()->valueType()->container && tokName->next()->valueType()->container->stdStringLike) |
| 1024 | return; |
| 1025 | |
| 1026 | const Token * const tokFirstArg = tokOpeningPar->next(); |
| 1027 | if (!tokFirstArg || tokFirstArg->str() == ")") { |
| 1028 | // no arguments |
| 1029 | return; |
| 1030 | } |
| 1031 | |
| 1032 | int argNr = 1; |
| 1033 | for (const Token *funcArg = tokFirstArg; funcArg; funcArg = funcArg->nextArgument()) { |
| 1034 | const Token* arg = funcArg; |
| 1035 | if (arg->isCpp()) { |
| 1036 | int tokAdvance = 0; |
| 1037 | if (arg->str() == "new") |
| 1038 | tokAdvance = 1; |
| 1039 | else if (Token::simpleMatch(arg, "* new")) |
| 1040 | tokAdvance = 2; |
| 1041 | if (tokAdvance > 0) { |
| 1042 | arg = arg->tokAt(tokAdvance); |
| 1043 | if (Token::simpleMatch(arg, "( std :: nothrow )")) |
| 1044 | arg = arg->tokAt(5); |
| 1045 | } |
| 1046 | } |
| 1047 | |
| 1048 | // Skip casts |
| 1049 | if (arg->isKeyword() && arg->astParent() && arg->astParent()->isCast()) |
| 1050 | arg = arg->astParent(); |
| 1051 | while (arg && arg->isCast()) |
| 1052 | arg = arg->astOperand2() ? arg->astOperand2() : arg->astOperand1(); |
| 1053 | const Token * const argTypeStartTok = arg; |
| 1054 | |
| 1055 | if (Token::simpleMatch(arg, ".")) |
| 1056 | arg = arg->next(); |
| 1057 | |
| 1058 | while (Token::Match(arg, "%name% .|:: %name%")) |
| 1059 | arg = arg->tokAt(2); |
| 1060 | |
| 1061 | if ((Token::Match(arg, "%var% [-,)] !!.") && !(arg->variable() && arg->variable()->isArray())) || |
| 1062 | (Token::Match(arg, "& %var% !!.") && !(arg->next()->variable() && arg->next()->variable()->isArray()))) { |
| 1063 | // goto variable |
| 1064 | const bool isAddressOf = arg->str() == "&"; |
| 1065 | if (isAddressOf) |
| 1066 | arg = arg->next(); |
| 1067 | |
| 1068 | const bool isnull = !isAddressOf && (arg->hasKnownIntValue() && arg->getKnownIntValue() == 0); |
| 1069 | |
| 1070 | // Is variable allocated? |
| 1071 | if (!isnull && (!af || af->arg == argNr)) { |
| 1072 | const Library::AllocFunc* deallocFunc = mSettings.library.getDeallocFuncInfo(tokName); |
| 1073 | VarInfo::AllocInfo dealloc(deallocFunc ? deallocFunc->groupId : 0, VarInfo::DEALLOC, tokName); |
| 1074 | if (const Library::AllocFunc* allocFunc = mSettings.library.getAllocFuncInfo(tokName)) { |
nothing calls this directly
no test coverage detected