| 2349 | } |
| 2350 | |
| 2351 | void CheckOtherImpl::checkIncompleteStatement() |
| 2352 | { |
| 2353 | if (!mSettings.severity.isEnabled(Severity::warning) && |
| 2354 | !mSettings.isPremiumEnabled("constStatement")) |
| 2355 | return; |
| 2356 | |
| 2357 | logChecker("CheckOther::checkIncompleteStatement"); // warning |
| 2358 | |
| 2359 | for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { |
| 2360 | const Scope *scope = tok->scope(); |
| 2361 | if (scope && !scope->isExecutable()) |
| 2362 | continue; |
| 2363 | if (!isConstTop(tok)) |
| 2364 | continue; |
| 2365 | if (tok->str() == "," && Token::simpleMatch(tok->astTop()->previous(), "for (")) |
| 2366 | continue; |
| 2367 | |
| 2368 | // Do not warn for statement when both lhs and rhs has side effects: |
| 2369 | // dostuff() || x=213; |
| 2370 | if (Token::Match(tok, "%oror%|&&")) { |
| 2371 | bool warn = false; |
| 2372 | visitAstNodes(tok, [&warn](const Token *child) { |
| 2373 | if (Token::Match(child, "%oror%|&&")) |
| 2374 | return ChildrenToVisit::op1_and_op2; |
| 2375 | if (child->isAssignmentOp()) |
| 2376 | return ChildrenToVisit::none; |
| 2377 | if (child->tokType() == Token::Type::eIncDecOp) |
| 2378 | return ChildrenToVisit::none; |
| 2379 | if (Token::Match(child->previous(), "%name% (")) |
| 2380 | return ChildrenToVisit::none; |
| 2381 | warn = true; |
| 2382 | return ChildrenToVisit::done; |
| 2383 | }); |
| 2384 | if (!warn) |
| 2385 | continue; |
| 2386 | } |
| 2387 | |
| 2388 | const Token *rtok = nextAfterAstRightmostLeaf(tok); |
| 2389 | if (!Token::simpleMatch(tok->astParent(), ";") && !Token::simpleMatch(rtok, ";") && |
| 2390 | !Token::Match(tok->previous(), ";|}|{ %any% ;") && |
| 2391 | !(tok->isCpp() && tok->isCast() && !tok->astParent()) && |
| 2392 | !(!tok->astParent() && tok->astOperand1() && Token::Match(tok->previous(), "%name% (") && tok->previous()->isKeyword()) && |
| 2393 | !Token::simpleMatch(tok->tokAt(-2), "for (") && |
| 2394 | !Token::Match(tok->tokAt(-1), "%var% [") && |
| 2395 | !(tok->str() == "," && tok->astParent() && tok->astParent()->isAssignmentOp())) |
| 2396 | continue; |
| 2397 | // Skip statement expressions |
| 2398 | if (Token::simpleMatch(rtok, "; } )")) |
| 2399 | continue; |
| 2400 | if (!isConstStatement(tok, mSettings.library, false)) |
| 2401 | continue; |
| 2402 | if (isVoidStmt(tok)) |
| 2403 | continue; |
| 2404 | if (tok->isCpp() && tok->str() == "&" && !(tok->astOperand1() && tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->isIntegral())) |
| 2405 | // Possible archive |
| 2406 | continue; |
| 2407 | const bool inconclusive = tok->isConstOp() && !mSettings.isPremiumEnabled("constStatement"); |
| 2408 | if (mSettings.certainty.isEnabled(Certainty::inconclusive) || !inconclusive) |