--------------------------------------------------------------------------- This check rule works for checking the "const A a = getA()" usage when getA() returns "const A &" or "A &". In most scenarios, "const A & a = getA()" will be more efficient. ---------------------------------------------------------------------------
| 3336 | // In most scenarios, "const A & a = getA()" will be more efficient. |
| 3337 | //--------------------------------------------------------------------------- |
| 3338 | static bool checkFunctionReturnsRef(const Token* tok, const Settings& settings) |
| 3339 | { |
| 3340 | if (!Token::Match(tok->previous(), "%name% (")) |
| 3341 | return false; |
| 3342 | if (!Token::Match(tok->link(), ") )|}| ;")) // bailout for usage like "const A a = getA()+3" |
| 3343 | return false; |
| 3344 | const Token* dot = tok->astOperand1(); |
| 3345 | if (Token::simpleMatch(dot, ".")) { |
| 3346 | const Token* varTok = dot->astOperand1(); |
| 3347 | const int indirect = varTok->valueType() ? varTok->valueType()->pointer : 0; |
| 3348 | if (isVariableChanged(tok, tok->scope()->bodyEnd, indirect, varTok->varId(), /*globalvar*/ true, settings)) |
| 3349 | return false; |
| 3350 | if (isTemporary(dot, &settings.library, /*unknown*/ true)) |
| 3351 | return false; |
| 3352 | } |
| 3353 | if (exprDependsOnThis(tok->previous())) |
| 3354 | return false; |
| 3355 | const Function* func = tok->previous()->function(); |
| 3356 | if (func && func->tokenDef->strAt(-1) == "&") { |
| 3357 | const Scope* fScope = func->functionScope; |
| 3358 | if (fScope && fScope->bodyEnd && Token::Match(fScope->bodyEnd->tokAt(-3), "return %var% ;")) { |
| 3359 | const Token* varTok = fScope->bodyEnd->tokAt(-2); |
| 3360 | if (isLargeObject(varTok->variable(), settings)) |
| 3361 | return true; |
| 3362 | } |
| 3363 | } |
| 3364 | return false; |
| 3365 | } |
| 3366 | |
| 3367 | static bool checkVariableAssignment(const Token* tok, const ValueType* vtLhs, const Settings& settings) |
| 3368 | { |
no test coverage detected