109 const Stmt *Stmt2,
bool IgnoreSideEffects) {
110 if (!Stmt1 || !Stmt2)
111 return !Stmt1 && !Stmt2;
115 if (Stmt1->getStmtClass() != Stmt2->getStmtClass())
118 const auto *Expr1 = dyn_cast<Expr>(Stmt1);
119 const auto *Expr2 = dyn_cast<Expr>(Stmt2);
121 if (Expr1 && Expr2) {
124 if (!IgnoreSideEffects && Expr1->HasSideEffects(Ctx) &&
125 Expr2->HasSideEffects(Ctx))
129 if ((Expr1->getExprLoc().isMacroID()) || (Expr2->getExprLoc().isMacroID()))
133 if (!llvm::equal(Expr1->children(), Expr2->children(),
134 [&](
const Stmt *S1,
const Stmt *S2) {
135 return isIdenticalStmt(Ctx, S1, S2, IgnoreSideEffects);
140 switch (Stmt1->getStmtClass()) {
143 case Stmt::CallExprClass:
144 case Stmt::ArraySubscriptExprClass:
145 case Stmt::ArraySectionExprClass:
146 case Stmt::OMPArrayShapingExprClass:
147 case Stmt::OMPIteratorExprClass:
148 case Stmt::ImplicitCastExprClass:
149 case Stmt::ParenExprClass:
150 case Stmt::BreakStmtClass:
151 case Stmt::ContinueStmtClass:
152 case Stmt::NullStmtClass:
154 case Stmt::CStyleCastExprClass: {
155 const auto *CastExpr1 = cast<CStyleCastExpr>(Stmt1);
156 const auto *CastExpr2 = cast<CStyleCastExpr>(Stmt2);
158 return CastExpr1->getTypeAsWritten() == CastExpr2->getTypeAsWritten();
160 case Stmt::ReturnStmtClass: {
161 const auto *ReturnStmt1 = cast<ReturnStmt>(Stmt1);
162 const auto *ReturnStmt2 = cast<ReturnStmt>(Stmt2);
165 ReturnStmt2->getRetValue(), IgnoreSideEffects);
167 case Stmt::ForStmtClass: {
168 const auto *ForStmt1 = cast<ForStmt>(Stmt1);
169 const auto *ForStmt2 = cast<ForStmt>(Stmt2);
185 case Stmt::DoStmtClass: {
186 const auto *DStmt1 = cast<DoStmt>(Stmt1);
187 const auto *DStmt2 = cast<DoStmt>(Stmt2);
197 case Stmt::WhileStmtClass: {
198 const auto *WStmt1 = cast<WhileStmt>(Stmt1);
199 const auto *WStmt2 = cast<WhileStmt>(Stmt2);
209 case Stmt::IfStmtClass: {
210 const auto *IStmt1 = cast<IfStmt>(Stmt1);
211 const auto *IStmt2 = cast<IfStmt>(Stmt2);
224 case Stmt::DeferStmtClass: {
225 const auto *DefStmt1 = cast<DeferStmt>(Stmt1);
226 const auto *DefStmt2 = cast<DeferStmt>(Stmt2);
230 case Stmt::CompoundStmtClass: {
231 const auto *CompStmt1 = cast<CompoundStmt>(Stmt1);
232 const auto *CompStmt2 = cast<CompoundStmt>(Stmt2);
233 return llvm::equal(CompStmt1->body(), CompStmt2->body(),
234 [&](
const Stmt *S1,
const Stmt *S2) {
235 return isIdenticalStmt(Ctx, S1, S2, IgnoreSideEffects);
238 case Stmt::CompoundAssignOperatorClass:
239 case Stmt::BinaryOperatorClass: {
240 const auto *BinOp1 = cast<BinaryOperator>(Stmt1);
241 const auto *BinOp2 = cast<BinaryOperator>(Stmt2);
242 return BinOp1->getOpcode() == BinOp2->getOpcode();
244 case Stmt::CharacterLiteralClass: {
245 const auto *CharLit1 = cast<CharacterLiteral>(Stmt1);
246 const auto *CharLit2 = cast<CharacterLiteral>(Stmt2);
247 return CharLit1->getValue() == CharLit2->getValue();
249 case Stmt::DeclRefExprClass: {
250 const auto *DeclRef1 = cast<DeclRefExpr>(Stmt1);
251 const auto *DeclRef2 = cast<DeclRefExpr>(Stmt2);
252 return DeclRef1->getDecl() == DeclRef2->getDecl();
254 case Stmt::IntegerLiteralClass: {
255 const auto *IntLit1 = cast<IntegerLiteral>(Stmt1);
256 const auto *IntLit2 = cast<IntegerLiteral>(Stmt2);
258 const llvm::APInt I1 = IntLit1->getValue();
259 const llvm::APInt I2 = IntLit2->getValue();
260 if (I1.getBitWidth() != I2.getBitWidth())
264 case Stmt::FloatingLiteralClass: {
265 const auto *FloatLit1 = cast<FloatingLiteral>(Stmt1);
266 const auto *FloatLit2 = cast<FloatingLiteral>(Stmt2);
267 return FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue());
269 case Stmt::StringLiteralClass: {
270 const auto *StringLit1 = cast<StringLiteral>(Stmt1);
271 const auto *StringLit2 = cast<StringLiteral>(Stmt2);
272 return StringLit1->getBytes() == StringLit2->getBytes();
274 case Stmt::MemberExprClass: {
275 const auto *MemberStmt1 = cast<MemberExpr>(Stmt1);
276 const auto *MemberStmt2 = cast<MemberExpr>(Stmt2);
277 return MemberStmt1->getMemberDecl() == MemberStmt2->getMemberDecl();
279 case Stmt::UnaryOperatorClass: {
280 const auto *UnaryOp1 = cast<UnaryOperator>(Stmt1);
281 const auto *UnaryOp2 = cast<UnaryOperator>(Stmt2);
282 return UnaryOp1->getOpcode() == UnaryOp2->getOpcode();
288 const ASTContext &Context = *Result.Context;
290 if (
const auto *IS = Result.Nodes.getNodeAs<IfStmt>(
"if")) {
291 const Stmt *Then = IS->getThen();
292 assert(Then &&
"An IfStmt must have a `then` branch!");
294 const Stmt *Else = Result.Nodes.getNodeAs<Stmt>(
"else");
295 assert(Else &&
"We only look for `if` statements with an `else` branch!");
297 if (!isa<IfStmt>(Else)) {
300 Else->IgnoreContainers(), Context)) {
301 diag(IS->getBeginLoc(),
"if with identical then and else branches");
302 diag(IS->getElseLoc(),
"else branch starts here", DiagnosticIDs::Note);
309 llvm::SmallVector<const Stmt *, 4> Branches;
310 const IfStmt *Cur = IS;
313 Branches.push_back(Cur->getThen());
315 Else = Cur->getElse();
321 Cur = dyn_cast<IfStmt>(Else);
324 Branches.push_back(Else);
329 const size_t N = Branches.size();
330 llvm::BitVector KnownAsClone(N);
332 for (
size_t I = 0; I + 1 < N; I++) {
339 for (
size_t J = I + 1; J < N; J++) {
341 Branches[I]->IgnoreContainers(),
342 Branches[J]->IgnoreContainers(), Context))
346 KnownAsClone[J] =
true;
348 if (NumCopies == 2) {
350 diag(Branches[I]->getBeginLoc(),
351 "repeated branch body in conditional chain");
352 const SourceLocation End =
353 Lexer::getLocForEndOfToken(Branches[I]->getEndLoc(), 0,
354 *Result.SourceManager, getLangOpts());
356 diag(End,
"end of the original", DiagnosticIDs::Note);
360 diag(Branches[J]->getBeginLoc(),
"clone %0 starts here",
368 if (
const auto *CO = Result.Nodes.getNodeAs<ConditionalOperator>(
"condOp")) {
372 diag(CO->getQuestionLoc(),
373 "conditional operator with identical true and false expressions");
378 if (
const auto *SS = Result.Nodes.getNodeAs<SwitchStmt>(
"switch")) {
379 const auto *Body = dyn_cast_or_null<CompoundStmt>(SS->getBody());
393 llvm::SmallVector<SwitchBranch, 4> Branches;
394 for (
const Stmt *S : Body->body()) {
396 if (isa<SwitchCase>(S))
397 Branches.emplace_back();
403 if (!Branches.empty())
404 Branches.back().push_back(S);
407 auto *End = Branches.end();
408 auto *BeginCurrent = Branches.begin();
409 while (BeginCurrent < End) {
415 auto *EndCurrent = BeginCurrent + 1;
416 while (EndCurrent < End &&
423 if (EndCurrent == (BeginCurrent + 1)) {
425 BeginCurrent = EndCurrent;
429 diag(BeginCurrent->front()->getBeginLoc(),
430 "switch has %0 consecutive identical branches")
431 << std::distance(BeginCurrent, EndCurrent);
433 SourceLocation EndLoc = (EndCurrent - 1)->back()->getEndLoc();
438 if (EndLoc.isInvalid())
439 EndLoc = (EndCurrent - 1)->back()->getBeginLoc();
440 if (EndLoc.isMacroID())
441 EndLoc = Context.getSourceManager().getExpansionLoc(EndLoc);
442 EndLoc = Lexer::getLocForEndOfToken(EndLoc, 0, *Result.SourceManager,
444 if (EndLoc.isValid()) {
445 diag(EndLoc,
"last of these clones ends here", DiagnosticIDs::Note);
447 BeginCurrent = EndCurrent;
452 if (
const auto *IS = Result.Nodes.getNodeAs<IfStmt>(
"ifWithDescendantIf")) {
453 const Stmt *Then = IS->getThen();
454 const auto *CS = dyn_cast<CompoundStmt>(Then);
455 if (CS && (!CS->body_empty())) {
456 const auto *InnerIf = dyn_cast<IfStmt>(*CS->body_begin());
457 if (InnerIf &&
isIdenticalStmt(Context, IS->getCond(), InnerIf->getCond(),
459 diag(IS->getBeginLoc(),
"if with identical inner if statement");
460 diag(InnerIf->getBeginLoc(),
"inner if starts here",
461 DiagnosticIDs::Note);
467 llvm_unreachable(
"No if statement and no switch statement.");