----------------------------------------------------------------------------- check for duplicate code in if and else branches if (a) { b = true; } else { b = true; } -----------------------------------------------------------------------------
| 2642 | // if (a) { b = true; } else { b = true; } |
| 2643 | //----------------------------------------------------------------------------- |
| 2644 | void CheckOtherImpl::checkDuplicateBranch() |
| 2645 | { |
| 2646 | // This is inconclusive since in practice most warnings are noise: |
| 2647 | // * There can be unfixed low-priority todos. The code is fine as it |
| 2648 | // is but it could be possible to enhance it. Writing a warning |
| 2649 | // here is noise since the code is fine (see cppcheck, abiword, ..) |
| 2650 | // * There can be overspecified code so some conditions can't be true |
| 2651 | // and their conditional code is a duplicate of the condition that |
| 2652 | // is always true just in case it would be false. See for instance |
| 2653 | // abiword. |
| 2654 | if (!mSettings.severity.isEnabled(Severity::style) || !mSettings.certainty.isEnabled(Certainty::inconclusive)) |
| 2655 | return; |
| 2656 | |
| 2657 | logChecker("CheckOther::checkDuplicateBranch"); // style,inconclusive |
| 2658 | |
| 2659 | const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 2660 | |
| 2661 | for (const Scope & scope : symbolDatabase->scopeList) { |
| 2662 | if (scope.type != ScopeType::eIf) |
| 2663 | continue; |
| 2664 | |
| 2665 | // check all the code in the function for if (..) else |
| 2666 | if (Token::simpleMatch(scope.bodyEnd, "} else {")) { |
| 2667 | // Make sure there are no macros (different macros might be expanded |
| 2668 | // to the same code) |
| 2669 | bool macro = false; |
| 2670 | for (const Token *tok = scope.bodyStart; tok != scope.bodyEnd->linkAt(2); tok = tok->next()) { |
| 2671 | if (tok->isExpandedMacro()) { |
| 2672 | macro = true; |
| 2673 | break; |
| 2674 | } |
| 2675 | } |
| 2676 | if (macro) |
| 2677 | continue; |
| 2678 | |
| 2679 | const Token * const tokIf = scope.bodyStart->next(); |
| 2680 | const Token * const tokElse = scope.bodyEnd->tokAt(3); |
| 2681 | |
| 2682 | // compare first tok before stringifying the whole blocks |
| 2683 | const std::string tokIfStr = tokIf->stringify(false, true, false); |
| 2684 | if (tokIfStr.empty()) |
| 2685 | continue; |
| 2686 | |
| 2687 | const std::string tokElseStr = tokElse->stringify(false, true, false); |
| 2688 | |
| 2689 | if (tokIfStr == tokElseStr) { |
| 2690 | // save if branch code |
| 2691 | const std::string branch1 = tokIf->stringifyList(scope.bodyEnd); |
| 2692 | |
| 2693 | if (branch1.empty()) |
| 2694 | continue; |
| 2695 | |
| 2696 | // save else branch code |
| 2697 | const std::string branch2 = tokElse->stringifyList(scope.bodyEnd->linkAt(2)); |
| 2698 | |
| 2699 | // check for duplicates |
| 2700 | if (branch1 == branch2 && branch1 != ";") { |
| 2701 | duplicateBranchError(scope.classDef, scope.bodyEnd->next(), ErrorPath{}); |
no test coverage detected