Author: jonastoth Date: Wed Dec 5 01:34:18 2018 New Revision: 348344 URL: http://llvm.org/viewvc/llvm-project?rev=348344&view=rev Log: Revert "[clang-tidy] new check: bugprone-branch-clone"
The patch broke on buildbot with assertion-failure. Revert until this is figured out. Removed: clang-tools-extra/trunk/clang-tidy/bugprone/BranchCloneCheck.cpp clang-tools-extra/trunk/clang-tidy/bugprone/BranchCloneCheck.h clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-branch-clone.rst clang-tools-extra/trunk/test/clang-tidy/bugprone-branch-clone.cpp Modified: clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt clang-tools-extra/trunk/docs/ReleaseNotes.rst clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Removed: clang-tools-extra/trunk/clang-tidy/bugprone/BranchCloneCheck.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/BranchCloneCheck.cpp?rev=348343&view=auto ============================================================================== --- clang-tools-extra/trunk/clang-tidy/bugprone/BranchCloneCheck.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/bugprone/BranchCloneCheck.cpp (removed) @@ -1,215 +0,0 @@ -//===--- BranchCloneCheck.cpp - clang-tidy --------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "BranchCloneCheck.h" -#include "clang/AST/ASTContext.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "clang/Analysis/CloneDetection.h" -#include "llvm/Support/Casting.h" - -using namespace clang; -using namespace clang::ast_matchers; - -/// Returns true when the statements are Type I clones of each other. -static bool areStatementsIdentical(const Stmt *LHS, const Stmt *RHS, - const ASTContext &Context) { - llvm::FoldingSetNodeID DataLHS, DataRHS; - LHS->Profile(DataLHS, Context, false); - RHS->Profile(DataRHS, Context, false); - return (DataLHS == DataRHS); -} - -namespace { -/// A branch in a switch may consist of several statements; while a branch in -/// an if/else if/else chain is one statement (which may be a CompoundStmt). -using SwitchBranch = llvm::SmallVector<const Stmt *, 2>; -} // anonymous namespace - -/// Determines if the bodies of two branches in a switch statements are Type I -/// clones of each other. This function only examines the body of the branch -/// and ignores the `case X:` or `default:` at the start of the branch. -static bool areSwitchBranchesIdentical(const SwitchBranch LHS, - const SwitchBranch RHS, - const ASTContext &Context) { - if (LHS.size() != RHS.size()) - return false; - - for (size_t i = 0, Size = LHS.size(); i < Size; i++) { - // NOTE: We strip goto labels and annotations in addition to stripping - // the `case X:` or `default:` labels, but it is very unlikely that this - // would casue false positives in real-world code. - if (!areStatementsIdentical(LHS[i]->stripLabelLikeStatements(), - RHS[i]->stripLabelLikeStatements(), Context)) { - return false; - } - } - - return true; -} - -namespace clang { -namespace tidy { -namespace bugprone { - -void BranchCloneCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher( - ifStmt(stmt().bind("if"), - hasParent(stmt(unless(ifStmt(hasElse(equalsBoundNode("if")))))), - hasElse(stmt().bind("else"))), - this); - Finder->addMatcher(switchStmt().bind("switch"), this); - Finder->addMatcher(conditionalOperator().bind("condOp"), this); -} - -void BranchCloneCheck::check(const MatchFinder::MatchResult &Result) { - const ASTContext &Context = *Result.Context; - - if (const auto *IS = Result.Nodes.getNodeAs<IfStmt>("if")) { - const Stmt *Then = IS->getThen(); - assert(Then && "An IfStmt must have a `then` branch!"); - - const Stmt *Else = Result.Nodes.getNodeAs<Stmt>("else"); - assert(Else && "We only look for `if` statements with an `else` branch!"); - - if (!isa<IfStmt>(Else)) { - // Just a simple if with no `else if` branch. - if (areStatementsIdentical(Then->IgnoreContainers(), - Else->IgnoreContainers(), Context)) { - diag(IS->getBeginLoc(), "if with identical then and else branches"); - diag(IS->getElseLoc(), "else branch starts here", DiagnosticIDs::Note); - } - return; - } - - // This is the complicated case when we start an if/else if/else chain. - // To find all the duplicates, we collect all the branches into a vector. - llvm::SmallVector<const Stmt *, 4> Branches; - const IfStmt *Cur = IS; - while (true) { - // Store the `then` branch. - Branches.push_back(Cur->getThen()); - - Else = Cur->getElse(); - // The chain ends if there is no `else` branch. - if (!Else) - break; - - // Check if there is another `else if`... - Cur = dyn_cast<IfStmt>(Else); - if (!Cur) { - // ...this is just a plain `else` branch at the end of the chain. - Branches.push_back(Else); - break; - } - } - - size_t N = Branches.size(); - llvm::BitVector KnownAsClone(N); - - for (size_t i = 0; i + 1 < N; i++) { - // We have already seen Branches[i] as a clone of an earlier branch. - if (KnownAsClone[i]) - continue; - - int NumCopies = 1; - - for (size_t j = i + 1; j < N; j++) { - if (KnownAsClone[j] || - !areStatementsIdentical(Branches[i]->IgnoreContainers(), - Branches[j]->IgnoreContainers(), Context)) - continue; - - NumCopies++; - KnownAsClone[j] = true; - - if (NumCopies == 2) { - // We report the first occurence only when we find the second one. - diag(Branches[i]->getBeginLoc(), - "repeated branch in conditional chain"); - diag(Lexer::getLocForEndOfToken(Branches[i]->getEndLoc(), 0, - *Result.SourceManager, getLangOpts()), - "end of the original", DiagnosticIDs::Note); - } - - diag(Branches[j]->getBeginLoc(), "clone %0 starts here", - DiagnosticIDs::Note) - << (NumCopies - 1); - } - } - return; - } - - if (const auto *CO = Result.Nodes.getNodeAs<ConditionalOperator>("condOp")) { - // We do not try to detect chains of ?: operators. - if (areStatementsIdentical(CO->getTrueExpr(), CO->getFalseExpr(), Context)) - diag(CO->getQuestionLoc(), - "conditional operator with identical true and false expressions"); - - return; - } - - if (const auto *SS = Result.Nodes.getNodeAs<SwitchStmt>("switch")) { - const CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(SS->getBody()); - - // Code like - // switch (x) case 0: case 1: foobar(); - // is legal and calls foobar() if and only if x is either 0 or 1; - // but we do not try to distinguish branches in such code. - if (!Body) - return; - - // We will first collect the branches of the switch statements. For the - // sake of simplicity we say that branches are delimited by the SwitchCase - // (`case:` or `default:`) children of Body; that is, we ignore `case:` or - // `default:` labels embedded inside other statements and we do not follow - // the effects of `break` and other manipulation of the control-flow. - llvm::SmallVector<SwitchBranch, 4> Branches; - for (const Stmt *S : Body->body()) { - // If this is a `case` or `default`, we start a new, empty branch. - if (isa<SwitchCase>(S)) - Branches.emplace_back(); - - // There may be code before the first branch (which can be dead code - // and can be code reached either through goto or through case labels - // that are embedded inside e.g. inner compound statements); we do not - // store those statements in branches. - if (!Branches.empty()) - Branches.back().push_back(S); - } - - auto End = Branches.end(); - auto BeginCurrent = Branches.begin(); - while (BeginCurrent < End) { - auto EndCurrent = BeginCurrent + 1; - while (EndCurrent < End && - areSwitchBranchesIdentical(*BeginCurrent, *EndCurrent, Context)) { - ++EndCurrent; - } - // At this point the iterator range {BeginCurrent, EndCurrent} contains a - // complete family of consecutive identical branches. - if (EndCurrent > BeginCurrent + 1) { - diag(BeginCurrent->front()->getBeginLoc(), - "switch has %0 consecutive identical branches") - << static_cast<int>(std::distance(BeginCurrent, EndCurrent)); - diag(Lexer::getLocForEndOfToken((EndCurrent - 1)->back()->getEndLoc(), - 0, *Result.SourceManager, - getLangOpts()), - "last of these clones ends here", DiagnosticIDs::Note); - } - BeginCurrent = EndCurrent; - } - return; - } - - llvm_unreachable("No if statement and no switch statement."); -} - -} // namespace bugprone -} // namespace tidy -} // namespace clang Removed: clang-tools-extra/trunk/clang-tidy/bugprone/BranchCloneCheck.h URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/BranchCloneCheck.h?rev=348343&view=auto ============================================================================== --- clang-tools-extra/trunk/clang-tidy/bugprone/BranchCloneCheck.h (original) +++ clang-tools-extra/trunk/clang-tidy/bugprone/BranchCloneCheck.h (removed) @@ -1,39 +0,0 @@ -//===--- BranchCloneCheck.h - clang-tidy ------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BRANCHCLONECHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BRANCHCLONECHECK_H - -#include "../ClangTidy.h" - -namespace clang { -namespace tidy { -namespace bugprone { - -/// A check for detecting if/else if/else chains where two or more branches are -/// Type I clones of each other (that is, they contain identical code), for -/// detecting switch statements where two or more consecutive branches are -/// Type I clones of each other, and for detecting conditional operators where -/// the true and false expressions are Type I clones of each other. -/// -/// For the user-facing documentation see: -/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-branch-clone.html -class BranchCloneCheck : public ClangTidyCheck { -public: - BranchCloneCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} - void registerMatchers(ast_matchers::MatchFinder *Finder) override; - void check(const ast_matchers::MatchFinder::MatchResult &Result) override; -}; - -} // namespace bugprone -} // namespace tidy -} // namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BRANCHCLONECHECK_H Modified: clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp?rev=348344&r1=348343&r2=348344&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp Wed Dec 5 01:34:18 2018 @@ -14,7 +14,6 @@ #include "ArgumentCommentCheck.h" #include "AssertSideEffectCheck.h" #include "BoolPointerImplicitConversionCheck.h" -#include "BranchCloneCheck.h" #include "CopyConstructorInitCheck.h" #include "DanglingHandleCheck.h" #include "ExceptionEscapeCheck.h" @@ -66,8 +65,6 @@ public: "bugprone-assert-side-effect"); CheckFactories.registerCheck<BoolPointerImplicitConversionCheck>( "bugprone-bool-pointer-implicit-conversion"); - CheckFactories.registerCheck<BranchCloneCheck>( - "bugprone-branch-clone"); CheckFactories.registerCheck<CopyConstructorInitCheck>( "bugprone-copy-constructor-init"); CheckFactories.registerCheck<DanglingHandleCheck>( Modified: clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt?rev=348344&r1=348343&r2=348344&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt (original) +++ clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt Wed Dec 5 01:34:18 2018 @@ -4,7 +4,6 @@ add_clang_library(clangTidyBugproneModul ArgumentCommentCheck.cpp AssertSideEffectCheck.cpp BoolPointerImplicitConversionCheck.cpp - BranchCloneCheck.cpp BugproneTidyModule.cpp CopyConstructorInitCheck.cpp DanglingHandleCheck.cpp Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=348344&r1=348343&r2=348344&view=diff ============================================================================== --- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original) +++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Wed Dec 5 01:34:18 2018 @@ -122,13 +122,6 @@ Improvements to clang-tidy Flags uses of ``absl::StrCat()`` to append to a ``std::string``. Suggests ``absl::StrAppend()`` should be used instead. -- New :doc:`bugprone-branch-clone - <clang-tidy/checks/bugprone-branch-clone>` check. - - Checks for repeated branches in ``if/else if/else`` chains, consecutive - repeated branches in ``switch`` statements and indentical true and false - branches in conditional operators. - - New :doc:`bugprone-too-small-loop-variable <clang-tidy/checks/bugprone-too-small-loop-variable>` check. Removed: clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-branch-clone.rst URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-branch-clone.rst?rev=348343&view=auto ============================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-branch-clone.rst (original) +++ clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-branch-clone.rst (removed) @@ -1,90 +0,0 @@ -.. title:: clang-tidy - bugprone-branch-clone - -bugprone-branch-clone -===================== - -Checks for repeated branches in ``if/else if/else`` chains, consecutive -repeated branches in ``switch`` statements and indentical true and false -branches in conditional operators. - -.. code-block:: c++ - - if (test_value(x)) { - y++; - do_something(x, y); - } else { - y++; - do_something(x, y); - } - -In this simple example (which could arise e.g. as a copy-paste error) the -``then`` and ``else`` branches are identical and the code is equivalent the -following shorter and cleaner code: - -.. code-block:: c++ - - test_value(x); // can be omitted unless it has side effects - y++; - do_something(x, y); - - -If this is the inteded behavior, then there is no reason to use a conditional -statement; otherwise the issue can be solved by fixing the branch that is -handled incorrectly. - -The check also detects repeated branches in longer ``if/else if/else`` chains -where it would be even harder to notice the problem. - -In ``switch`` statements the check only reports repeated branches when they are -consecutive, because it is relatively common that the ``case:`` labels have -some natural ordering and rearranging them would decrease the readability of -the code. For example: - -.. code-block:: c++ - - switch (ch) { - case 'a': - return 10; - case 'A': - return 10; - case 'b': - return 11; - case 'B': - return 11; - default: - return 10; - } - -Here the check reports that the ``'a'`` and ``'A'`` branches are identical -(and that the ``'b'`` and ``'B'`` branches are also identical), but does not -report that the ``default:`` branch is also idenical to the first two branches. -If this is indeed the correct behavior, then it could be implemented as: - -.. code-block:: c++ - - switch (ch) { - case 'a': - case 'A': - return 10; - case 'b': - case 'B': - return 11; - default: - return 10; - } - -Here the check does not warn for the repeated ``return 10;``, which is good if -we want to preserve that ``'a'`` is before ``'b'`` and ``default:`` is the last -branch. - -Finally, the check also examines conditional operators and reports code like: - -.. code-block:: c++ - - return test_value(x) ? x : x; - -Unlike if statements, the check does not detect chains of conditional -operators. - -Note: This check also reports situations where branches become identical only -after preprocession. Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=348344&r1=348343&r2=348344&view=diff ============================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original) +++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Wed Dec 5 01:34:18 2018 @@ -31,7 +31,6 @@ Clang-Tidy Checks bugprone-argument-comment bugprone-assert-side-effect bugprone-bool-pointer-implicit-conversion - bugprone-branch-clone bugprone-copy-constructor-init bugprone-dangling-handle bugprone-exception-escape Removed: clang-tools-extra/trunk/test/clang-tidy/bugprone-branch-clone.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/bugprone-branch-clone.cpp?rev=348343&view=auto ============================================================================== --- clang-tools-extra/trunk/test/clang-tidy/bugprone-branch-clone.cpp (original) +++ clang-tools-extra/trunk/test/clang-tidy/bugprone-branch-clone.cpp (removed) @@ -1,1017 +0,0 @@ -// RUN: %check_clang_tidy %s bugprone-branch-clone %t - -void test_basic1(int in, int &out) { - if (in > 77) -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - else -// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here - out++; - - out++; -} - -void test_basic2(int in, int &out) { - if (in > 77) { -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - } - else { -// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here - out++; - } - - out++; -} - -void test_basic3(int in, int &out) { - if (in > 77) { -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - } - else -// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here - out++; - - out++; -} - -void test_basic4(int in, int &out) { - if (in > 77) { - out--; - } - else { - out++; - } -} - -void test_basic5(int in, int &out) { - if (in > 77) { - out++; - } - else { - out++; - out++; - } -} - -void test_basic6(int in, int &out) { - if (in > 77) { - out++; - } - else { - out++, out++; - } -} - -void test_basic7(int in, int &out) { - if (in > 77) { - out++; - out++; - } - else - out++; - - out++; -} - -void test_basic8(int in, int &out) { - if (in > 77) { -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - out++; - } else { -// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here - out++; - out++; - } - - if (in % 2) - out++; -} - -void test_basic9(int in, int &out) { - if (in > 77) { -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - if (in % 2) - out++; - else - out--; - } else { -// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here - if (in % 2) - out++; - else - out--; - } -} - -// If we remove the braces from the previous example, the check recognizes it -// as an `else if`. -void test_basic10(int in, int &out) { - if (in > 77) - if (in % 2) - out++; - else - out--; - else - if (in % 2) - out++; - else - out--; - -} - -void test_basic11(int in, int &out) { - if (in > 77) { -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - if (in % 2) - out++; - else - out--; - if (in % 3) - out++; - else - out--; - } else { -// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here - if (in % 2) - out++; - else - out--; - if (in % 3) - out++; - else - out--; - } -} - -void test_basic12(int in, int &out) { - if (in > 77) { -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - } else { -// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here - } -} - -void test_basic13(int in, int &out) { - if (in > 77) { - // Empty compound statement is not identical to null statement. - } else; -} - -// We use a comparison that ignores redundant parentheses: -void test_basic14(int in, int &out) { - if (in > 77) - out += 2; -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - else -// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here - (out) += (2); -} - -void test_basic15(int in, int &out) { - if (in > 77) -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - ((out += 2)); - else -// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here - out += 2; -} - -// ..but does not apply additional simplifications: -void test_basic16(int in, int &out) { - if (in > 77) - out += 2; - else - out += 1 + 1; -} - -// ..and does not forget important parentheses: -int test_basic17(int a, int b, int c, int mode) { - if (mode>8) - return (a + b) * c; - else - return a + b * c; -} - -//=========--------------------==========// - -#define PASTE_CODE(x) x - -void test_macro1(int in, int &out) { - PASTE_CODE( - if (in > 77) -// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - else -// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here - out++; - ) - - out--; -} - -void test_macro2(int in, int &out) { - PASTE_CODE( - if (in > 77) -// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - ) - else -// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here - out++; -} - -void test_macro3(int in, int &out) { - if (in > 77) -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - PASTE_CODE( - else -// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here - out++; - ) -} - -void test_macro4(int in, int &out) { - if (in > 77) -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - else -// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here - PASTE_CODE( - out++; - ) -} - -void test_macro5(int in, int &out) { - PASTE_CODE(if) (in > 77) -// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - PASTE_CODE(else) -// CHECK-MESSAGES: :[[@LINE-1]]:14: note: else branch starts here - out++; -} - -#define OTHERWISE_INCREASE else out++ - -void test_macro6(int in, int &out) { - if (in > 77) - out++; -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - OTHERWISE_INCREASE; -// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here -// CHECK-MESSAGES: :[[@LINE-8]]:28: note: expanded from macro 'OTHERWISE_INCREASE' -} - -#define COND_INCR(a, b, c) \ - do { \ - if ((a)) \ - (b)++; \ - else \ - (c)++; \ - } while (0) - -void test_macro7(int in, int &out1, int &out2) { - COND_INCR(in, out1, out1); -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] -// CHECK-MESSAGES: :[[@LINE-9]]:5: note: expanded from macro 'COND_INCR' -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: else branch starts here -// CHECK-MESSAGES: :[[@LINE-8]]:5: note: expanded from macro 'COND_INCR' -} - -void test_macro8(int in, int &out1, int &out2) { - COND_INCR(in, out1, out2); -} - -void test_macro9(int in, int &out1, int &out2) { - COND_INCR(in, out2, out2); -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] -// CHECK-MESSAGES: :[[@LINE-21]]:5: note: expanded from macro 'COND_INCR' -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: else branch starts here -// CHECK-MESSAGES: :[[@LINE-20]]:5: note: expanded from macro 'COND_INCR' -} - -#define CONCAT(a, b) a##b - -void test_macro10(int in, int &out) { - CONCAT(i, f) (in > 77) -// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - CONCAT(el, se) -// CHECK-MESSAGES: :[[@LINE-1]]:10: note: else branch starts here - out++; -} - -#define PROBLEM (-1) - -int test_macro11(int count) { - if (!count) -// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch in conditional chain [bugprone-branch-clone] - return PROBLEM; -// CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original - else if (count == 13) -// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here - return -1; - else - return count * 2; -} - -#define IF if ( -#define THEN ) { -#define ELSE } else { -#define END } - -void test_macro12(int in, int &out) { - IF in > 77 THEN -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] -// CHECK-MESSAGES: :[[@LINE-8]]:12: note: expanded from macro 'IF' - out++; - out++; - ELSE -// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here -// CHECK-MESSAGES: :[[@LINE-12]]:14: note: expanded from macro 'IF' - out++; - out++; - END -} - -// A hack for implementing a switch with no fallthrough: -#define SWITCH(x) switch (x) { -#define CASE(x) break; case (x): -#define DEFAULT break; default: - -void test_macro13(int in, int &out) { - SWITCH(in) -// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] -// CHECK-MESSAGES: :[[@LINE-6]]:24: note: expanded from macro 'CASE' - CASE(1) - out++; - out++; - CASE(2) - out++; - out++; - CASE(3) - out++; - out++; -// CHECK-MESSAGES: :[[@LINE+1]]:5: note: last of these clones ends here -// CHECK-MESSAGES: :[[@LINE-17]]:22: note: expanded from macro 'CASE' - CASE(4) - out++; - CASE(5) -// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone] -// CHECK-MESSAGES: :[[@LINE-22]]:24: note: expanded from macro 'CASE' - CASE(6) - out--; - CASE(7) - out--; -// CHECK-MESSAGES: :[[@LINE+1]]:5: note: last of these clones ends here -// CHECK-MESSAGES: :[[@LINE-28]]:22: note: expanded from macro 'CASE' -// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone] -// CHECK-MESSAGES: :[[@LINE-30]]:24: note: expanded from macro 'CASE' - CASE(8) - out++; - out++; - CASE(9) - out++; - out++; -// CHECK-MESSAGES: :[[@LINE+1]]:5: note: last of these clones ends here -// CHECK-MESSAGES: :[[@LINE-37]]:22: note: expanded from macro 'DEFAULT' -// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone] -// CHECK-MESSAGES: :[[@LINE-39]]:24: note: expanded from macro 'DEFAULT' - DEFAULT - out--; - out--; - CASE(10) - out--; - out--; -// CHECK-MESSAGES: :[[@LINE+1]]:5: note: last of these clones ends here -// CHECK-MESSAGES: :[[@LINE-48]]:22: note: expanded from macro 'CASE' - CASE(12) - out++; - CASE(13) - out++; - END -} - -//=========--------------------==========// - -void test_chain1(int in, int &out) { - if (in > 77) -// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch in conditional chain [bugprone-branch-clone] - out++; -// CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original - else if (in > 55) -// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here - out++; - - out++; -} - -void test_chain2(int in, int &out) { - if (in > 77) -// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch in conditional chain [bugprone-branch-clone] - out++; -// CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original - else if (in > 55) -// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here - out++; - else if (in > 42) - out--; - else if (in > 28) -// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 2 starts here - out++; - else if (in > 12) { - out++; - out *= 7; - } else if (in > 7) { -// CHECK-MESSAGES: :[[@LINE-1]]:22: note: clone 3 starts here - out++; - } -} - -void test_chain3(int in, int &out) { - if (in > 77) { -// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch in conditional chain [bugprone-branch-clone] - out++; - out++; -// CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the original - } else if (in > 55) { -// CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here - out++; - out++; - } else if (in > 42) - out--; - else if (in > 28) { -// CHECK-MESSAGES: :[[@LINE-1]]:21: note: clone 2 starts here - out++; - out++; - } else if (in > 12) { - out++; - out++; - out++; - out *= 7; - } else if (in > 7) { -// CHECK-MESSAGES: :[[@LINE-1]]:22: note: clone 3 starts here - out++; - out++; - } -} - -// In this chain there are two clone families; notice that the checker -// describes all branches of the first one before mentioning the second one. -void test_chain4(int in, int &out) { - if (in > 77) { -// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch in conditional chain [bugprone-branch-clone] - out++; - out++; -// CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the original - } else if (in > 55) { -// CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here -// CHECK-MESSAGES: :[[@LINE+8]]:21: note: clone 2 starts here -// CHECK-MESSAGES: :[[@LINE+15]]:22: note: clone 3 starts here - out++; - out++; - } else if (in > 42) -// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch in conditional chain [bugprone-branch-clone] - out--; -// CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original - else if (in > 28) { - out++; - out++; - } else if (in > 12) { - out++; - out++; - out++; - out *= 7; - } else if (in > 7) { - out++; - out++; - } else if (in > -3) { -// CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here - out--; - } -} - -void test_chain5(int in, int &out) { - if (in > 77) -// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch in conditional chain [bugprone-branch-clone] - out++; -// CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original - else if (in > 55) -// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here - out++; - else if (in > 42) - out--; - else if (in > 28) -// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 2 starts here - out++; - else if (in > 12) { - out++; - out *= 7; - } else { -// CHECK-MESSAGES: :[[@LINE-1]]:10: note: clone 3 starts here - out++; - } -} - -void test_chain6(int in, int &out) { - if (in > 77) { -// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch in conditional chain [bugprone-branch-clone] - out++; - out++; -// CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the original - } else if (in > 55) { -// CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here - out++; - out++; - } else if (in > 42) - out--; - else if (in > 28) { -// CHECK-MESSAGES: :[[@LINE-1]]:21: note: clone 2 starts here - out++; - out++; - } else if (in > 12) { - out++; - out++; - out++; - out *= 7; - } else { -// CHECK-MESSAGES: :[[@LINE-1]]:10: note: clone 3 starts here - out++; - out++; - } -} - -void test_nested(int a, int b, int c, int &out) { - if (a > 5) { -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] -// CHECK-MESSAGES: :[[@LINE+27]]:5: note: else branch starts here - if (b > 5) { -// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch in conditional chain [bugprone-branch-clone] -// CHECK-MESSAGES: :[[@LINE+9]]:6: note: end of the original -// CHECK-MESSAGES: :[[@LINE+8]]:24: note: clone 1 starts here -// CHECK-MESSAGES: :[[@LINE+14]]:12: note: clone 2 starts here - if (c > 5) -// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - else -// CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here - out++; - } else if (b > 15) { - if (c > 5) -// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - else -// CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here - out++; - } else { - if (c > 5) -// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - else -// CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here - out++; - } - } else { - if (b > 5) { -// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch in conditional chain [bugprone-branch-clone] -// CHECK-MESSAGES: :[[@LINE+9]]:6: note: end of the original -// CHECK-MESSAGES: :[[@LINE+8]]:24: note: clone 1 starts here -// CHECK-MESSAGES: :[[@LINE+14]]:12: note: clone 2 starts here - if (c > 5) -// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - else -// CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here - out++; - } else if (b > 15) { - if (c > 5) -// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - else -// CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here - out++; - } else { - if (c > 5) -// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone] - out++; - else -// CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here - out++; - } - } -} - -//=========--------------------==========// - -template <class T> -void test_template_not_instantiated(const T &t) { - int a; - if (t) -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - a++; - else -// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here - a++; -} - -template <class T> -void test_template_instantiated(const T &t) { - int a; - if (t) -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - a++; - else -// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here - a++; -} - -template void test_template_instantiated<int>(const int &t); - -template <class T> -void test_template2(T t, int a) { - if (a) { - T b(0); - a += b; - } else { - int b(0); - a += b; - } -} - -template void test_template2<int>(int t, int a); - -template <class T> -void test_template3(T t, int a) { - if (a) { - T b(0); - a += b; - } else { - int b(0); - a += b; - } -} - -template void test_template3<short>(short t, int a); - -template <class T> -void test_template_two_instances(T t, int &a) { - if (a) { -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - a += int(t); - } else { -// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here - a += int(t); - } -} - -template void test_template_two_instances<short>(short t, int &a); -template void test_template_two_instances<long>(long t, int &a); - -class C { - int member; - void inline_method(int arg) { - if (arg) -// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if with identical then and else branches [bugprone-branch-clone] - member = 3; - else -// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here - member = 3; - } - int other_method(); -}; - -int C::other_method() { - if (member) { -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] - return 8; - } else { -// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here - return 8; - } -} - -//=========--------------------==========// - -int simple_switch(char ch) { - switch (ch) { -// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone] - case 'a': - return 10; - case 'A': - return 10; -// CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here -// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone] - case 'b': - return 11; - case 'B': - return 11; -// CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here -// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone] - case 'c': - return 10; - case 'C': - return 10; -// CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here - default: - return 0; - } -} - -int long_sequence_switch(char ch) { - switch (ch) { -// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 7 consecutive identical branches [bugprone-branch-clone] - case 'a': - return 10; - case 'A': - return 10; - case 'b': - return 10; - case 'B': - return 10; - case 'c': - return 10; - case 'C': - return 10; - default: - return 10; -// CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here - } -} - -int nested_switch(int a, int b, int c) { - switch (a) { -// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] -// CHECK-MESSAGES: :[[@LINE+114]]:6: note: last of these clones ends here - case 1: - switch (b) { -// CHECK-MESSAGES: :[[@LINE+2]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] -// CHECK-MESSAGES: :[[@LINE+33]]:8: note: last of these clones ends here - case 1: - switch (c) { -// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] - case 1: - return 42; - case 2: - return 42; - default: - return 42; -// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here - } - case 2: - switch (c) { -// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] - case 1: - return 42; - case 2: - return 42; - default: - return 42; -// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here - } - default: - switch (c) { -// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] - case 1: - return 42; - case 2: - return 42; - default: - return 42; -// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here - } - } - case 2: - switch (b) { -// CHECK-MESSAGES: :[[@LINE+2]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] -// CHECK-MESSAGES: :[[@LINE+33]]:8: note: last of these clones ends here - case 1: - switch (c) { -// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] - case 1: - return 42; - case 2: - return 42; - default: - return 42; -// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here - } - case 2: - switch (c) { -// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] - case 1: - return 42; - case 2: - return 42; - default: - return 42; -// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here - } - default: - switch (c) { -// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] - case 1: - return 42; - case 2: - return 42; - default: - return 42; -// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here - } - } - default: - switch (b) { -// CHECK-MESSAGES: :[[@LINE+2]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] -// CHECK-MESSAGES: :[[@LINE+33]]:8: note: last of these clones ends here - case 1: - switch (c) { -// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] - case 1: - return 42; - case 2: - return 42; - default: - return 42; -// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here - } - case 2: - switch (c) { -// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] - case 1: - return 42; - case 2: - return 42; - default: - return 42; -// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here - } - default: - switch (c) { -// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] - case 1: - return 42; - case 2: - return 42; - default: - return 42; -// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here - } - } - } -} - -//=========--------------------==========// - -// This should not produce warnings, as in switch statements we only report -// identical branches when they are consecutive. Also note that a branch -// terminated by a break is different from a branch terminated by the end of -// the switch statement. -int interleaved_cases(int a, int b) { - switch (a) { - case 3: - case 4: - b = 2; - break; - case 5: - b = 3; - break; - case 6: - b = 2; - break; - case 7: - if (b % 2) { - b++; - } else { - b++; - break; - } - b = 2; - break; - case 8: - b = 2; - case 9: - b = 3; - break; - default: - b = 3; - } - return b; -} - - -// A case: or default: is only considered to be the start of a branch if it is a direct child of the CompoundStmt forming the body of the switch -int buried_cases(int foo) { - switch (foo) { - { - case 36: - return 8; - default: - return 8; - } - } -} - -// Here the `case 7:` is a child statement of the GotoLabelStmt, so the checker -// thinks that it is part of the `case 9:` branch. While this result is -// counterintuitve, mixing goto labels and switch statements in this fashion is -// pretty rare, so it does not deserve a special case in the checker code. -int decorated_cases(int z) { - if (!(z % 777)) { - goto lucky; - } - switch (z) { -// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone] - case 1: - case 2: - case 3: - z++; - break; - case 4: - case 5: - z++; - break; -// CHECK-MESSAGES: :[[@LINE-1]]:10: note: last of these clones ends here - case 9: - z++; - break; - lucky: - case 7: - z += 3; - z *= 2; - break; - case 92: - z += 3; - z *= 2; - break; - default: - z++; - } - return z + 92; -} - -// The child of the switch statement is not neccessarily a compound statement, -// do not crash in this unusual case. -char no_real_body(int in, int &out) { - switch (in) - case 42: - return 'A'; - - if (in > 77) -// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch in conditional chain [bugprone-branch-clone] - out++; -// CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original - else if (in > 55) -// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here - out++; - else if (in > 34) -// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 2 starts here - out++; - - return '|'; -} - -// Duff's device [https://en.wikipedia.org/wiki/Duff's_device] -// The check does not try to distinguish branches in this sort of convoluted -// code, but it should avoid crashing. -void send(short *to, short *from, int count) -{ - int n = (count + 7) / 8; - switch (count % 8) { - case 0: do { *to = *from++; - case 7: *to = *from++; - case 6: *to = *from++; - case 5: *to = *from++; - case 4: *to = *from++; - case 3: *to = *from++; - case 2: *to = *from++; - case 1: *to = *from++; - } while (--n > 0); - } -} - -//=========--------------------==========// - -void ternary1(bool b, int &x) { -// CHECK-MESSAGES: :[[@LINE+1]]:6: warning: conditional operator with identical true and false expressions [bugprone-branch-clone] - (b ? x : x) = 42; -} - -int ternary2(bool b, int x) { -// CHECK-MESSAGES: :[[@LINE+1]]:12: warning: conditional operator with identical true and false expressions [bugprone-branch-clone] - return b ? 42 : 42; -} - -int ternary3(bool b, int x) { - return b ? 42 : 43; -} - -int ternary4(bool b, int x) { - return b ? true ? 45 : 44 : false ? 45 : 44; -} - -// We do not detect chains of conditional operators. -int ternary5(bool b1, bool b2 int x) { - return b1 ? 42 : b2 ? 43 : 42; -} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits