| 888 | |
| 889 | |
| 890 | const Token * CheckLeakAutoVarImpl::checkTokenInsideExpression(const Token * const tok, VarInfo &varInfo, bool inFuncCall) |
| 891 | { |
| 892 | // Deallocation and then dereferencing pointer.. |
| 893 | if (tok->varId() > 0) { |
| 894 | // TODO : Write a separate checker for this that uses valueFlowForward. |
| 895 | const auto var = utils::as_const(varInfo.alloctype).find(tok->varId()); |
| 896 | if (var != varInfo.alloctype.end()) { |
| 897 | bool unknown = false; |
| 898 | if (var->second.status == VarInfo::DEALLOC && tok->valueType() && tok->valueType()->pointer && |
| 899 | CheckNullPointerImpl::isPointerDeRef(tok, unknown, mSettings, /*checkNullArg*/ false) && !unknown) { |
| 900 | deallocUseError(tok, tok->str()); |
| 901 | } else if (Token::simpleMatch(tok->tokAt(-2), "= &")) { |
| 902 | varInfo.erase(tok->varId()); |
| 903 | } else { |
| 904 | // check if tok is assigned into another variable |
| 905 | const Token *rhs = tok; |
| 906 | bool isAssignment = false; |
| 907 | while (rhs->astParent()) { |
| 908 | if (rhs->astParent()->str() == "=") { |
| 909 | isAssignment = true; |
| 910 | break; |
| 911 | } |
| 912 | rhs = rhs->astParent(); |
| 913 | } |
| 914 | while (rhs->isCast()) { |
| 915 | rhs = rhs->astOperand2() ? rhs->astOperand2() : rhs->astOperand1(); |
| 916 | } |
| 917 | if ((rhs->str() == "." || rhs->varId() == tok->varId()) && isAssignment) { |
| 918 | // simple assignment |
| 919 | varInfo.erase(tok->varId()); |
| 920 | } else if (rhs->astParent() && rhs->str() == "(" && !mSettings.library.returnValue(rhs->astOperand1()).empty()) { |
| 921 | // #9298, assignment through return value of a function |
| 922 | const std::string &returnValue = mSettings.library.returnValue(rhs->astOperand1()); |
| 923 | if (startsWith(returnValue, "arg")) { |
| 924 | int argn; |
| 925 | const Token *func = getTokenArgumentFunction(tok, argn); |
| 926 | if (func) { |
| 927 | const std::string arg = "arg" + std::to_string(argn + 1); |
| 928 | if (returnValue == arg) { |
| 929 | varInfo.erase(tok->varId()); |
| 930 | } |
| 931 | } |
| 932 | } |
| 933 | } |
| 934 | } |
| 935 | } else if (Token::Match(tok->previous(), "& %name% = %var% ;")) { |
| 936 | varInfo.referenced.insert(tok->tokAt(2)->varId()); |
| 937 | } |
| 938 | } |
| 939 | |
| 940 | // check for function call |
| 941 | const Token * const openingPar = inFuncCall ? nullptr : isFunctionCall(tok); |
| 942 | if (openingPar) { |
| 943 | const Library::AllocFunc* allocFunc = mSettings.library.getDeallocFuncInfo(tok); |
| 944 | VarInfo::AllocInfo alloc(allocFunc ? allocFunc->groupId : 0, VarInfo::DEALLOC, tok); |
| 945 | if (alloc.type == 0) |
| 946 | alloc.status = VarInfo::NOALLOC; |
| 947 | functionCall(tok, openingPar, varInfo, alloc, nullptr); |
nothing calls this directly
no test coverage detected