| 746 | } |
| 747 | |
| 748 | void CheckMemoryLeakStructMemberImpl::checkStructVariable(const Variable* const variable) const |
| 749 | { |
| 750 | if (!variable) |
| 751 | return; |
| 752 | // Is struct variable a pointer? |
| 753 | if (variable->isArrayOrPointer()) { |
| 754 | // Check that variable is allocated with malloc |
| 755 | if (!isMalloc(variable)) |
| 756 | return; |
| 757 | } else if (!mTokenizer->isC() && (!variable->typeScope() || variable->typeScope()->getDestructor())) { |
| 758 | // For non-C code a destructor might cleanup members |
| 759 | return; |
| 760 | } |
| 761 | |
| 762 | // Check struct.. |
| 763 | int indentlevel2 = 0; |
| 764 | |
| 765 | auto deallocInFunction = [this](const Token* tok, int structid) -> bool { |
| 766 | // Calling non-function / function that doesn't deallocate? |
| 767 | if (tok->isKeyword() || mSettings.library.isLeakIgnore(tok->str())) |
| 768 | return false; |
| 769 | |
| 770 | // Check if the struct is used.. |
| 771 | bool deallocated = false; |
| 772 | const Token* const end = tok->linkAt(1); |
| 773 | for (const Token* tok2 = tok; tok2 != end; tok2 = tok2->next()) { |
| 774 | if (Token::Match(tok2, "%varid%", structid)) { |
| 775 | /** @todo check if the function deallocates the memory */ |
| 776 | deallocated = true; |
| 777 | break; |
| 778 | } |
| 779 | |
| 780 | if (Token::Match(tok2, "[(,] &| %varid% . %name% [,)]", structid)) { |
| 781 | /** @todo check if the function deallocates the memory */ |
| 782 | deallocated = true; |
| 783 | break; |
| 784 | } |
| 785 | } |
| 786 | |
| 787 | return deallocated; |
| 788 | }; |
| 789 | |
| 790 | // return { memberTok, rhsTok } |
| 791 | auto isMemberAssignment = [](const Token* varTok, int varId) -> std::pair<const Token*, const Token*> { |
| 792 | if (varTok->varId() != varId) |
| 793 | return {}; |
| 794 | const Token* top = varTok; |
| 795 | while (top->astParent()) { |
| 796 | if (Token::Match(top->astParent(), "(|[")) |
| 797 | return {}; |
| 798 | top = top->astParent(); |
| 799 | } |
| 800 | if (!Token::simpleMatch(top, "=") || !precedes(varTok, top)) |
| 801 | return {}; |
| 802 | const Token* dot = top->astOperand1(); |
| 803 | while (dot && dot->str() != ".") |
| 804 | dot = dot->astOperand1(); |
| 805 | if (!dot) |
nothing calls this directly
no test coverage detected