Skip to content

Commit 6ccb806

Browse files
committed
[clang-tidy] Extract areStatementsIdentical
Move areStatementsIdentical from BranchCloneCheck into ASTUtils. Add small improvments. Use it in LoopConvertUtils. Reviewed By: carlosgalvezp Differential Revision: https://reviews.llvm.org/D148995
1 parent 6b22608 commit 6ccb806

File tree

4 files changed

+42
-35
lines changed

4 files changed

+42
-35
lines changed

clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "BranchCloneCheck.h"
10+
#include "../utils/ASTUtils.h"
1011
#include "clang/AST/ASTContext.h"
1112
#include "clang/ASTMatchers/ASTMatchFinder.h"
1213
#include "clang/Analysis/CloneDetection.h"
@@ -16,26 +17,6 @@
1617
using namespace clang;
1718
using namespace clang::ast_matchers;
1819

19-
/// Returns true when the statements are Type I clones of each other.
20-
static bool areStatementsIdentical(const Stmt *LHS, const Stmt *RHS,
21-
const ASTContext &Context) {
22-
if (isa<Expr>(LHS) && isa<Expr>(RHS)) {
23-
// If we have errors in expressions, we will be unable
24-
// to accurately profile and compute hashes for each
25-
// of the left and right statements.
26-
const auto *LHSExpr = llvm::cast<Expr>(LHS);
27-
const auto *RHSExpr = llvm::cast<Expr>(RHS);
28-
if (LHSExpr->containsErrors() && RHSExpr->containsErrors()) {
29-
return false;
30-
}
31-
}
32-
33-
llvm::FoldingSetNodeID DataLHS, DataRHS;
34-
LHS->Profile(DataLHS, Context, false);
35-
RHS->Profile(DataRHS, Context, false);
36-
return (DataLHS == DataRHS);
37-
}
38-
3920
namespace {
4021
/// A branch in a switch may consist of several statements; while a branch in
4122
/// an if/else if/else chain is one statement (which may be a CompoundStmt).
@@ -55,8 +36,9 @@ static bool areSwitchBranchesIdentical(const SwitchBranch LHS,
5536
// NOTE: We strip goto labels and annotations in addition to stripping
5637
// the `case X:` or `default:` labels, but it is very unlikely that this
5738
// would cause false positives in real-world code.
58-
if (!areStatementsIdentical(LHS[I]->stripLabelLikeStatements(),
59-
RHS[I]->stripLabelLikeStatements(), Context)) {
39+
if (!tidy::utils::areStatementsIdentical(LHS[I]->stripLabelLikeStatements(),
40+
RHS[I]->stripLabelLikeStatements(),
41+
Context)) {
6042
return false;
6143
}
6244
}
@@ -89,8 +71,8 @@ void BranchCloneCheck::check(const MatchFinder::MatchResult &Result) {
8971

9072
if (!isa<IfStmt>(Else)) {
9173
// Just a simple if with no `else if` branch.
92-
if (areStatementsIdentical(Then->IgnoreContainers(),
93-
Else->IgnoreContainers(), Context)) {
74+
if (utils::areStatementsIdentical(Then->IgnoreContainers(),
75+
Else->IgnoreContainers(), Context)) {
9476
diag(IS->getBeginLoc(), "if with identical then and else branches");
9577
diag(IS->getElseLoc(), "else branch starts here", DiagnosticIDs::Note);
9678
}
@@ -130,9 +112,9 @@ void BranchCloneCheck::check(const MatchFinder::MatchResult &Result) {
130112
int NumCopies = 1;
131113

132114
for (size_t J = I + 1; J < N; J++) {
133-
if (KnownAsClone[J] ||
134-
!areStatementsIdentical(Branches[I]->IgnoreContainers(),
135-
Branches[J]->IgnoreContainers(), Context))
115+
if (KnownAsClone[J] || !utils::areStatementsIdentical(
116+
Branches[I]->IgnoreContainers(),
117+
Branches[J]->IgnoreContainers(), Context))
136118
continue;
137119

138120
NumCopies++;
@@ -160,7 +142,8 @@ void BranchCloneCheck::check(const MatchFinder::MatchResult &Result) {
160142

161143
if (const auto *CO = Result.Nodes.getNodeAs<ConditionalOperator>("condOp")) {
162144
// We do not try to detect chains of ?: operators.
163-
if (areStatementsIdentical(CO->getTrueExpr(), CO->getFalseExpr(), Context))
145+
if (utils::areStatementsIdentical(CO->getTrueExpr(), CO->getFalseExpr(),
146+
Context))
164147
diag(CO->getQuestionLoc(),
165148
"conditional operator with identical true and false expressions");
166149

clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "LoopConvertUtils.h"
10+
#include "../utils/ASTUtils.h"
1011
#include "clang/Basic/IdentifierTable.h"
1112
#include "clang/Basic/LLVM.h"
1213
#include "clang/Basic/Lambda.h"
@@ -190,13 +191,7 @@ const Expr *digThroughConstructorsConversions(const Expr *E) {
190191

191192
/// Returns true when two Exprs are equivalent.
192193
bool areSameExpr(ASTContext *Context, const Expr *First, const Expr *Second) {
193-
if (!First || !Second)
194-
return false;
195-
196-
llvm::FoldingSetNodeID FirstID, SecondID;
197-
First->Profile(FirstID, *Context, true);
198-
Second->Profile(SecondID, *Context, true);
199-
return FirstID == SecondID;
194+
return utils::areStatementsIdentical(First, Second, *Context, true);
200195
}
201196

202197
/// Returns the DeclRefExpr represented by E, or NULL if there isn't one.

clang-tools-extra/clang-tidy/utils/ASTUtils.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,29 @@ bool rangeCanBeFixed(SourceRange Range, const SourceManager *SM) {
8888
!utils::rangeContainsMacroExpansion(Range, SM);
8989
}
9090

91+
bool areStatementsIdentical(const Stmt *FirstStmt, const Stmt *SecondStmt,
92+
const ASTContext &Context, bool Canonical) {
93+
if (!FirstStmt || !SecondStmt)
94+
return false;
95+
96+
if (FirstStmt == SecondStmt)
97+
return true;
98+
99+
if (FirstStmt->getStmtClass() != FirstStmt->getStmtClass())
100+
return false;
101+
102+
if (isa<Expr>(FirstStmt) && isa<Expr>(SecondStmt)) {
103+
// If we have errors in expressions, we will be unable
104+
// to accurately profile and compute hashes for each statements.
105+
if (llvm::cast<Expr>(FirstStmt)->containsErrors() ||
106+
llvm::cast<Expr>(SecondStmt)->containsErrors())
107+
return false;
108+
}
109+
110+
llvm::FoldingSetNodeID DataFirst, DataSecond;
111+
FirstStmt->Profile(DataFirst, Context, Canonical);
112+
SecondStmt->Profile(DataSecond, Context, Canonical);
113+
return DataFirst == DataSecond;
114+
}
115+
91116
} // namespace clang::tidy::utils

clang-tools-extra/clang-tidy/utils/ASTUtils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ bool rangeContainsMacroExpansion(SourceRange Range, const SourceManager *SM);
3636
// FIXME: false-negative if the entire range is fully expanded from a macro.
3737
bool rangeCanBeFixed(SourceRange Range, const SourceManager *SM);
3838

39+
// Check if statements are same
40+
bool areStatementsIdentical(const Stmt *FirstStmt, const Stmt *SecondStmt,
41+
const ASTContext &Context, bool Canonical = false);
42+
3943
} // namespace clang::tidy::utils
4044

4145
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ASTUTILS_H

0 commit comments

Comments
 (0)