| 630 | } |
| 631 | |
| 632 | void CheckConditionImpl::multiCondition2() |
| 633 | { |
| 634 | if (!mSettings.severity.isEnabled(Severity::warning) && |
| 635 | !mSettings.isPremiumEnabled("identicalConditionAfterEarlyExit") && |
| 636 | !mSettings.isPremiumEnabled("identicalInnerCondition")) |
| 637 | return; |
| 638 | |
| 639 | logChecker("CheckCondition::multiCondition2"); // warning |
| 640 | |
| 641 | const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 642 | |
| 643 | for (const Scope &scope : symbolDatabase->scopeList) { |
| 644 | const Token *condTok = nullptr; |
| 645 | if (scope.type == ScopeType::eIf || scope.type == ScopeType::eWhile) |
| 646 | condTok = scope.classDef->next()->astOperand2(); |
| 647 | else if (scope.type == ScopeType::eFor) { |
| 648 | condTok = scope.classDef->next()->astOperand2(); |
| 649 | if (!condTok || condTok->str() != ";") |
| 650 | continue; |
| 651 | condTok = condTok->astOperand2(); |
| 652 | if (!condTok || condTok->str() != ";") |
| 653 | continue; |
| 654 | condTok = condTok->astOperand1(); |
| 655 | } |
| 656 | if (!condTok) |
| 657 | continue; |
| 658 | const Token * const cond1 = condTok; |
| 659 | |
| 660 | if (!Token::simpleMatch(scope.classDef->linkAt(1), ") {")) |
| 661 | continue; |
| 662 | |
| 663 | bool functionCall = false; |
| 664 | bool nonConstFunctionCall = false; |
| 665 | bool nonlocal = false; // nonlocal variable used in condition |
| 666 | std::set<int> vars; // variables used in condition |
| 667 | visitAstNodes(condTok, |
| 668 | [&](const Token *cond) { |
| 669 | if (Token::Match(cond, "%name% (")) { |
| 670 | functionCall = true; |
| 671 | nonConstFunctionCall = isNonConstFunctionCall(cond, mSettings.library); |
| 672 | if (nonConstFunctionCall) |
| 673 | return ChildrenToVisit::done; |
| 674 | } |
| 675 | |
| 676 | if (cond->varId()) { |
| 677 | vars.insert(cond->varId()); |
| 678 | const Variable *var = cond->variable(); |
| 679 | if (!nonlocal && var) { |
| 680 | if (!(var->isLocal() || var->isArgument())) |
| 681 | nonlocal = true; |
| 682 | else if ((var->isPointer() || var->isReference() || var->isArray()) && !Token::Match(cond->astParent(), "%oror%|&&|!")) |
| 683 | // TODO: if var is pointer check what it points at |
| 684 | nonlocal = true; |
| 685 | } |
| 686 | } else if (!nonlocal && cond->isName()) { |
| 687 | // varid is 0. this is possibly a nonlocal variable.. |
| 688 | nonlocal = Token::Match(cond->astParent(), "%cop%|(|[") || Token::Match(cond, "%name% .") || (cond->isCpp() && cond->str() == "this"); |
| 689 | } else { |
no test coverage detected