| 3424 | } |
| 3425 | |
| 3426 | static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings& settings) |
| 3427 | { |
| 3428 | const bool addressOf = tok->astParent() && tok->astParent()->isUnaryOp("&"); |
| 3429 | |
| 3430 | int argnr; |
| 3431 | const Token* ftok = getTokenArgumentFunction(tok, argnr); |
| 3432 | if (!ftok) |
| 3433 | return ExprUsage::None; |
| 3434 | const Function* func = ftok->function(); |
| 3435 | // variable init/constructor call? |
| 3436 | if (!func && ftok->variable() && ftok == ftok->variable()->nameToken()) { |
| 3437 | // STL types or containers don't initialize external variables |
| 3438 | if (indirect == 0 && (ftok->variable()->isStlType() || (ftok->variable()->valueType() && ftok->variable()->valueType()->container))) |
| 3439 | return ExprUsage::Used; |
| 3440 | // TODO: resolve multiple constructors |
| 3441 | if (ftok->variable()->type() && ftok->variable()->type()->classScope) { |
| 3442 | const int nCtor = ftok->variable()->type()->classScope->numConstructors; |
| 3443 | if (nCtor == 0) { |
| 3444 | if (indirect > 0) { |
| 3445 | const std::vector<const Variable*> argvar = getArgumentVars(ftok->astParent(), argnr); |
| 3446 | if (argvar.size() == 1 && argvar[0]->valueType() && argvar[0]->valueType()->pointer == indirect) |
| 3447 | return ExprUsage::NotUsed; |
| 3448 | } |
| 3449 | return ExprUsage::Used; |
| 3450 | } |
| 3451 | if (nCtor == 1) { |
| 3452 | const Scope* scope = ftok->variable()->type()->classScope; |
| 3453 | auto it = std::find_if(scope->functionList.begin(), scope->functionList.end(), [](const Function& f) { |
| 3454 | return f.isConstructor(); |
| 3455 | }); |
| 3456 | if (it != scope->functionList.end()) |
| 3457 | func = &*it; |
| 3458 | } |
| 3459 | } |
| 3460 | } |
| 3461 | if (func) { |
| 3462 | std::vector<const Variable*> args = getArgumentVars(ftok, argnr); |
| 3463 | for (const Variable* arg : args) { |
| 3464 | if (!arg) |
| 3465 | continue; |
| 3466 | if (arg->isReference() || (arg->isPointer() && indirect == 1)) { |
| 3467 | if (!func->hasBody()) |
| 3468 | return ExprUsage::PassedByReference; |
| 3469 | for (const Token* bodytok = func->functionScope->bodyStart; bodytok != func->functionScope->bodyEnd; bodytok = bodytok->next()) { |
| 3470 | if (bodytok->variable() == arg) { |
| 3471 | if (arg->isReference()) |
| 3472 | return ExprUsage::PassedByReference; |
| 3473 | if (Token::Match(bodytok->astParent(), "%comp%|!")) |
| 3474 | return ExprUsage::NotUsed; |
| 3475 | return ExprUsage::PassedByReference; |
| 3476 | } |
| 3477 | } |
| 3478 | return ExprUsage::NotUsed; |
| 3479 | } |
| 3480 | } |
| 3481 | if (!args.empty() && indirect == 0 && !addressOf) |
| 3482 | return ExprUsage::Used; |
| 3483 | } else if (ftok->isControlFlowKeyword()) { |
no test coverage detected