| 1177 | } |
| 1178 | |
| 1179 | void CheckLeakAutoVarImpl::ret(const Token *tok, VarInfo &varInfo, const bool isEndOfScope) |
| 1180 | { |
| 1181 | const std::map<int, VarInfo::AllocInfo> &alloctype = varInfo.alloctype; |
| 1182 | const auto& possibleUsage = varInfo.possibleUsage; |
| 1183 | std::vector<int> toRemove; |
| 1184 | |
| 1185 | const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 1186 | for (auto it = alloctype.cbegin(); it != alloctype.cend(); ++it) { |
| 1187 | // don't warn if variable is conditionally allocated, unless it leaves the scope |
| 1188 | if (!isEndOfScope && !it->second.managed() && varInfo.conditionalAlloc.find(it->first) != varInfo.conditionalAlloc.end()) |
| 1189 | continue; |
| 1190 | |
| 1191 | // don't warn if there is a reference of the variable |
| 1192 | if (varInfo.referenced.find(it->first) != varInfo.referenced.end()) |
| 1193 | continue; |
| 1194 | |
| 1195 | const int varid = it->first; |
| 1196 | const Variable *var = symbolDatabase->getVariableFromVarId(varid); |
| 1197 | if (var) { |
| 1198 | // don't warn if we leave an inner scope |
| 1199 | if (isEndOfScope && var->scope() && tok != var->scope()->bodyEnd) |
| 1200 | continue; |
| 1201 | enum class PtrUsage : std::uint8_t { NONE, DEREF, PTR } used = PtrUsage::NONE; |
| 1202 | for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) { |
| 1203 | if (tok2->str() == ";") |
| 1204 | break; |
| 1205 | if (!Token::Match(tok2, "return|(|{|,|*")) |
| 1206 | continue; |
| 1207 | |
| 1208 | const Token* tok3 = tok2->next(); |
| 1209 | while (tok3 && tok3->isCast() && |
| 1210 | (!tok3->valueType() || |
| 1211 | tok3->valueType()->pointer || |
| 1212 | isSafeCast(tok3->valueType(), mSettings))) |
| 1213 | tok3 = tok3->astOperand2() ? tok3->astOperand2() : tok3->astOperand1(); |
| 1214 | if (tok3 && tok3->varId() == varid) |
| 1215 | tok2 = tok3->next(); |
| 1216 | else if (Token::Match(tok3, "& %varid% . %name%", varid)) |
| 1217 | tok2 = tok3->tokAt(4); |
| 1218 | else if (Token::simpleMatch(tok3, "*") && tok3->next()->varId() == varid) |
| 1219 | tok2 = tok3; |
| 1220 | else |
| 1221 | continue; |
| 1222 | if (Token::Match(tok2, "[});,+]") && (!astIsBool(tok) || tok2->str() != ";")) { |
| 1223 | used = PtrUsage::PTR; |
| 1224 | break; |
| 1225 | } |
| 1226 | if (Token::Match(tok2, "[|.|*")) { |
| 1227 | used = PtrUsage::DEREF; |
| 1228 | break; |
| 1229 | } |
| 1230 | } |
| 1231 | |
| 1232 | // don't warn when returning after checking return value of outparam allocation |
| 1233 | const Token* outparamFunc{}; |
| 1234 | if ((tok->scope()->type == ScopeType::eIf || tok->scope()->type== ScopeType::eElse) && |
| 1235 | (outparamFunc = getOutparamAllocation(it->second.allocTok, mSettings))) { |
| 1236 | const Scope* scope = tok->scope(); |
nothing calls this directly
no test coverage detected