| 1541 | } |
| 1542 | |
| 1543 | void CheckClassImpl::checkMemsetType(const Scope *start, const Token *tok, const Scope *type, bool allocation, std::set<const Scope *> parsedTypes) |
| 1544 | { |
| 1545 | // If type has been checked there is no need to check it again |
| 1546 | if (parsedTypes.find(type) != parsedTypes.end()) |
| 1547 | return; |
| 1548 | parsedTypes.insert(type); |
| 1549 | |
| 1550 | const bool printPortability = mSettings.severity.isEnabled(Severity::portability); |
| 1551 | |
| 1552 | // recursively check all parent classes |
| 1553 | for (const Type::BaseInfo & i : type->definedType->derivedFrom) { |
| 1554 | const Type* derivedFrom = i.type; |
| 1555 | if (derivedFrom && derivedFrom->classScope) |
| 1556 | checkMemsetType(start, tok, derivedFrom->classScope, allocation, parsedTypes); |
| 1557 | } |
| 1558 | |
| 1559 | // Warn if type is a class that contains any virtual functions |
| 1560 | for (const Function &func : type->functionList) { |
| 1561 | if (func.hasVirtualSpecifier()) { |
| 1562 | if (allocation) |
| 1563 | mallocOnClassError(tok, tok->str(), type->classDef, "virtual function"); |
| 1564 | else |
| 1565 | memsetError(tok, tok->str(), "virtual function", type->classDef->str()); |
| 1566 | } |
| 1567 | } |
| 1568 | |
| 1569 | // Warn if type is a class or struct that contains any std::* variables |
| 1570 | for (const Variable &var : type->varlist) { |
| 1571 | if (var.isReference() && !var.isStatic()) { |
| 1572 | memsetErrorReference(tok, tok->str(), type->classDef->str()); |
| 1573 | continue; |
| 1574 | } |
| 1575 | // don't warn if variable static or const, pointer or array of pointers |
| 1576 | if (!var.isStatic() && !var.isConst() && !var.isPointer() && (!var.isArray() || var.typeEndToken()->str() != "*")) { |
| 1577 | const Token *tok1 = var.typeStartToken(); |
| 1578 | const Scope *typeScope = var.typeScope(); |
| 1579 | |
| 1580 | std::string typeName; |
| 1581 | if (Token::Match(tok1, "%type% ::")) { |
| 1582 | const Token *typeTok = tok1; |
| 1583 | while (Token::Match(typeTok, "%type% ::")) { |
| 1584 | typeName += typeTok->str() + "::"; |
| 1585 | typeTok = typeTok->tokAt(2); |
| 1586 | } |
| 1587 | typeName += typeTok->str(); |
| 1588 | } |
| 1589 | |
| 1590 | // check for std:: type |
| 1591 | if (var.isStlType() && typeName != "std::array" && !mSettings.library.podtype(typeName)) { |
| 1592 | if (allocation) |
| 1593 | mallocOnClassError(tok, tok->str(), type->classDef, "'" + typeName + "'"); |
| 1594 | else |
| 1595 | memsetError(tok, tok->str(), "'" + typeName + "'", type->classDef->str()); |
| 1596 | } |
| 1597 | |
| 1598 | // check for known type |
| 1599 | else if (typeScope && typeScope != type) |
| 1600 | checkMemsetType(start, tok, typeScope, allocation, parsedTypes); |