| 1539 | } |
| 1540 | |
| 1541 | void CheckOtherImpl::checkPassByReference() |
| 1542 | { |
| 1543 | if (!mSettings.severity.isEnabled(Severity::performance) || mTokenizer->isC()) |
| 1544 | return; |
| 1545 | |
| 1546 | logChecker("CheckOther::checkPassByReference"); // performance,c++ |
| 1547 | |
| 1548 | const SymbolDatabase * const symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 1549 | |
| 1550 | for (const Variable* var : symbolDatabase->variableList()) { |
| 1551 | if (!var || !var->isClass() || var->isPointer() || (var->isArray() && !var->isStlType()) || var->isReference() || var->isEnumType()) |
| 1552 | continue; |
| 1553 | |
| 1554 | const bool isRangeBasedFor = astIsRangeBasedForDecl(var->nameToken()); |
| 1555 | if (!var->isArgument() && !isRangeBasedFor) |
| 1556 | continue; |
| 1557 | |
| 1558 | if (!isRangeBasedFor && var->scope() && var->scope()->function->arg->link()->strAt(-1) == "...") |
| 1559 | continue; // references could not be used as va_start parameters (#5824) |
| 1560 | |
| 1561 | const Token * const varDeclEndToken = var->declEndToken(); |
| 1562 | if ((varDeclEndToken && varDeclEndToken->isExternC()) || |
| 1563 | (var->scope() && var->scope()->function && var->scope()->function->tokenDef && var->scope()->function->tokenDef->isExternC())) |
| 1564 | continue; // references cannot be used in functions in extern "C" blocks |
| 1565 | |
| 1566 | bool inconclusive = false; |
| 1567 | |
| 1568 | const bool isContainer = var->valueType() && var->valueType()->type == ValueType::Type::CONTAINER && var->valueType()->container && !var->valueType()->container->view; |
| 1569 | if (isContainer && !isLargeContainer(var, mSettings)) |
| 1570 | continue; |
| 1571 | if (!isContainer) { |
| 1572 | if (var->type() && !var->type()->isEnumType()) { // Check if type is a struct or class. |
| 1573 | // Ensure that it is a large object. |
| 1574 | if (!var->type()->classScope) |
| 1575 | inconclusive = true; |
| 1576 | else if (!var->valueType() || var->valueType()->getSizeOf(mSettings, ValueType::Accuracy::LowerBound, ValueType::SizeOf::Pointer) <= 2 * mSettings.platform.sizeof_pointer) |
| 1577 | continue; |
| 1578 | } |
| 1579 | else |
| 1580 | continue; |
| 1581 | } |
| 1582 | |
| 1583 | if (inconclusive && !mSettings.certainty.isEnabled(Certainty::inconclusive)) |
| 1584 | continue; |
| 1585 | |
| 1586 | if (var->isArray() && (!var->isStlType() || Token::simpleMatch(var->nameToken()->next(), "["))) |
| 1587 | continue; |
| 1588 | |
| 1589 | if (var->isArgument()) { |
| 1590 | const Token *tok = var->typeStartToken(); |
| 1591 | for (; tok; tok = tok->next()) { |
| 1592 | if (Token::simpleMatch(tok, "(")) { |
| 1593 | tok = tok->link(); |
| 1594 | continue; |
| 1595 | } |
| 1596 | if (Token::simpleMatch(tok, ")")) |
| 1597 | break; |
| 1598 | } |
no test coverage detected