| 1445 | } |
| 1446 | |
| 1447 | void CheckClassImpl::checkMemset() |
| 1448 | { |
| 1449 | logChecker("CheckClass::checkMemset"); |
| 1450 | const bool printWarnings = mSettings.severity.isEnabled(Severity::warning); |
| 1451 | for (const Scope *scope : mSymbolDatabase->functionScopes) { |
| 1452 | for (const Token *tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) { |
| 1453 | if (Token::Match(tok, "memset|memcpy|memmove (")) { |
| 1454 | const Token* arg1 = tok->tokAt(2); |
| 1455 | const Token* arg3 = arg1->nextArgument(); |
| 1456 | if (arg3) |
| 1457 | arg3 = arg3->nextArgument(); |
| 1458 | if (!arg3) |
| 1459 | // weird, shouldn't happen: memset etc should have |
| 1460 | // 3 arguments. |
| 1461 | continue; |
| 1462 | |
| 1463 | const Token *typeTok = nullptr; |
| 1464 | const Scope *type = nullptr; |
| 1465 | const Token* sizeofTok = arg3->previous()->astOperand2(); // try to find sizeof() in argument expression |
| 1466 | if (sizeofTok && sizeofTok->astOperand1() && Token::simpleMatch(sizeofTok->astOperand1()->previous(), "sizeof (")) |
| 1467 | sizeofTok = sizeofTok->astOperand1(); |
| 1468 | else if (sizeofTok && sizeofTok->astOperand2() && Token::simpleMatch(sizeofTok->astOperand2()->previous(), "sizeof (")) |
| 1469 | sizeofTok = sizeofTok->astOperand2(); |
| 1470 | if (Token::simpleMatch(sizeofTok, "(")) |
| 1471 | sizeofTok = sizeofTok->previous(); |
| 1472 | if (Token::Match(sizeofTok, "sizeof ( %type% )")) |
| 1473 | typeTok = sizeofTok->tokAt(2); |
| 1474 | else if (Token::Match(sizeofTok, "sizeof ( %type% :: %type% )")) |
| 1475 | typeTok = sizeofTok->tokAt(4); |
| 1476 | else if (Token::Match(sizeofTok, "sizeof ( struct %type% )")) |
| 1477 | typeTok = sizeofTok->tokAt(3); |
| 1478 | else if (Token::simpleMatch(sizeofTok, "sizeof ( * this )") || Token::simpleMatch(arg1, "this ,")) { |
| 1479 | type = findFunctionOf(sizeofTok->scope()); |
| 1480 | } else if (Token::Match(arg1, "&|*|%var%")) { |
| 1481 | int numIndirToVariableType = 0; // Offset to the actual type in terms of dereference/addressof |
| 1482 | for (;; arg1 = arg1->next()) { |
| 1483 | if (arg1->str() == "&") |
| 1484 | ++numIndirToVariableType; |
| 1485 | else if (arg1->str() == "*") |
| 1486 | --numIndirToVariableType; |
| 1487 | else |
| 1488 | break; |
| 1489 | } |
| 1490 | |
| 1491 | const Variable * const var = arg1->variable(); |
| 1492 | if (var && arg1->strAt(1) == ",") { |
| 1493 | if (var->isArrayOrPointer()) { |
| 1494 | const Token *endTok = var->typeEndToken(); |
| 1495 | while (Token::simpleMatch(endTok, "*")) { |
| 1496 | ++numIndirToVariableType; |
| 1497 | endTok = endTok->previous(); |
| 1498 | } |
| 1499 | } |
| 1500 | |
| 1501 | if (var->isArray()) |
| 1502 | numIndirToVariableType += int(var->dimensions().size()); |
| 1503 | |
| 1504 | if (numIndirToVariableType == 1) |