[PATCH] D54757: [clang-tidy] new check: bugprone-branch-clone
Jonas Toth via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 22 11:24:34 PST 2018
JonasToth added a comment.
Thank you for this great patch!
Did you consider using `clang/Tooling/ASTDiff/*` functionality, as there is the possibility of just comparing the AST 'below' the branches?
Please add tests that contain macros as well, and what do you think should happen with them? I think it would be very valuable to figure out that different macro expansion result in the same code.
================
Comment at: clang-tidy/bugprone/BranchCloneCheck.cpp:31
+/// an if/else if/else chain is one statement (which may be a CompoundStmt).
+using SwitchBranch = llvm::SmallVector<const Stmt *, 2>;
+} // anonymous namespace
----------------
maybe plural for the typename would fit better, as its a vector of multiple elements?
================
Comment at: clang-tidy/bugprone/BranchCloneCheck.cpp:46
+ RHS[i]->stripLabelLikeStatements(), Context)) {
+ // NOTE: We strip goto labels and annotations in addition to stripping
+ // the `case X:` or `default:` labels, but it is very unlikely that this
----------------
You can ellide the single-stmt braces here, maybe its better to move the comment above the for then?
================
Comment at: clang-tidy/bugprone/BranchCloneCheck.cpp:71
+ // Check whether this `if` is part of an `else if`:
+ if (const auto *IP =
+ dyn_cast<IfStmt>(Result.Nodes.getNodeAs<Stmt>("ifParent"))) {
----------------
This if should always be true, no? The matcher will always bind `ifParent`
================
Comment at: clang-tidy/bugprone/BranchCloneCheck.cpp:83
+ assert(Then && "An IfStmt must have a `then` branch!");
+ const Stmt *Else = IS->getElse();
+ if (!Else) {
----------------
This detection can and should land in the matcher, to filter as much as possible already while matching.
================
Comment at: clang-tidy/bugprone/BranchCloneCheck.cpp:88
+ return;
+ } else if (!isa<IfStmt>(Else)) {
+ // Just a simple if with no `else if` branch.
----------------
Please don't use `else` after return. You can ellide the braces in the `if` as well.
================
Comment at: clang-tidy/bugprone/BranchCloneCheck.cpp:113
+ Cur = dyn_cast<IfStmt>(Else);
+ if (!Cur) {
+ // ...this is just a plain `else` branch; we store it.
----------------
you can ellide the braces.
================
Comment at: clang-tidy/bugprone/BranchCloneCheck.cpp:116
+ Branches.push_back(Else);
+ // Note: We will exit the while loop here.
+ }
----------------
This note is misplaced? The exit is at the `break`.
================
Comment at: clang-tidy/bugprone/BranchCloneCheck.cpp:120
+
+ const size_t N = Branches.size();
+ llvm::BitVector KnownAsClone(N);
----------------
please dont use `const` for values, only pointers and references
================
Comment at: clang-tidy/bugprone/BranchCloneCheck.cpp:124
+ for (size_t i = 0; i + 1 < N; i++) {
+ if (KnownAsClone[i]) {
+ // We have already seen Branches[i] as a clone of an earlier branch.
----------------
braces, i will stop pointing at it. Please do it on the other parts as well
================
Comment at: clang-tidy/bugprone/BranchCloneCheck.cpp:153
+ }
+ }
+ } else if (const auto *SS = Result.Nodes.getNodeAs<SwitchStmt>("switch")) {
----------------
i think you can use early return here, if yes, no `else` afterwards.
================
Comment at: clang-tidy/bugprone/BranchCloneCheck.cpp:164
+
+ // We will first collect the branhces of the switch statements. For the
+ // sake of simplicity we say that branches are delimited by the SwitchCase
----------------
typo, branhces
================
Comment at: clang-tidy/bugprone/BranchCloneCheck.cpp:187
+ while (FamilyBegin < End) {
+ auto FamilyEnd = FamilyBegin + 1;
+ while (FamilyEnd < End &&
----------------
i think the name `FamilyEnd` is not very descriptive, maybe `SubsequentBranch` or so?
================
Comment at: clang-tidy/bugprone/BranchCloneCheck.cpp:196-197
+ diag(FamilyBegin->front()->getBeginLoc(),
+ "switch has %0 consecutive identical branches")
+ << static_cast<int>(FamilyEnd - FamilyBegin);
+ diag(Lexer::getLocForEndOfToken((FamilyEnd - 1)->back()->getEndLoc(), 0,
----------------
please use `std::distance` instead
================
Comment at: docs/clang-tidy/checks/list.rst:13
abseil-str-cat-append
+ abseil-string-find-startswith
android-cloexec-accept
----------------
spurious change
================
Comment at: test/clang-tidy/bugprone-branch-clone.cpp:4
+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]
----------------
could you please add tests for ternary operators?
Repository:
rCTE Clang Tools Extra
https://reviews.llvm.org/D54757
More information about the cfe-commits
mailing list