| 307 | //----------------------------------------------------------------------------- |
| 308 | |
| 309 | void CheckSizeofImpl::sizeofCalculation() |
| 310 | { |
| 311 | if (!mSettings.severity.isEnabled(Severity::warning)) |
| 312 | return; |
| 313 | |
| 314 | logChecker("CheckSizeof::sizeofCalculation"); // warning |
| 315 | |
| 316 | const bool printInconclusive = mSettings.certainty.isEnabled(Certainty::inconclusive); |
| 317 | |
| 318 | for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { |
| 319 | if (!Token::simpleMatch(tok, "sizeof (")) |
| 320 | continue; |
| 321 | |
| 322 | // ignore if the `sizeof` result is cast to void inside a macro, i.e. the calculation is |
| 323 | // expected to be parsed but skipped, such as in a disabled custom ASSERT() macro |
| 324 | if (tok->isExpandedMacro() && tok->previous()) { |
| 325 | const Token *cast_end = (tok->strAt(-1) == "(") ? tok->previous() : tok; |
| 326 | if (Token::simpleMatch(cast_end->tokAt(-3), "( void )") || |
| 327 | Token::simpleMatch(cast_end->tokAt(-4), "static_cast < void >")) { |
| 328 | continue; |
| 329 | } |
| 330 | } |
| 331 | |
| 332 | const Token *argument = tok->next()->astOperand2(); |
| 333 | if (!argument || !argument->isCalculation()) |
| 334 | continue; |
| 335 | |
| 336 | bool inconclusive = false; |
| 337 | if (argument->isExpandedMacro()) |
| 338 | inconclusive = true; |
| 339 | else if (tok->next()->isExpandedMacro()) |
| 340 | inconclusive = true; |
| 341 | |
| 342 | if (!inconclusive || printInconclusive) |
| 343 | sizeofCalculationError(argument, inconclusive); |
| 344 | } |
| 345 | } |
| 346 | |
| 347 | void CheckSizeofImpl::sizeofCalculationError(const Token *tok, bool inconclusive) |
| 348 | { |
no test coverage detected