108 const Stmt *Stmt2,
bool IgnoreSideEffects) {
109 if (!Stmt1 || !Stmt2)
110 return !Stmt1 && !Stmt2;
114 if (Stmt1->getStmtClass() != Stmt2->getStmtClass())
117 const auto *Expr1 = dyn_cast<Expr>(Stmt1);
118 const auto *Expr2 = dyn_cast<Expr>(Stmt2);
120 if (Expr1 && Expr2) {
123 if (!IgnoreSideEffects && Expr1->HasSideEffects(Ctx) &&
124 Expr2->HasSideEffects(Ctx))
128 if ((Expr1->getExprLoc().isMacroID()) || (Expr2->getExprLoc().isMacroID()))
132 if (!llvm::equal(Expr1->children(), Expr2->children(),
133 [&](
const Stmt *S1,
const Stmt *S2) {
134 return isIdenticalStmt(Ctx, S1, S2, IgnoreSideEffects);
139 switch (Stmt1->getStmtClass()) {
142 case Stmt::CallExprClass:
143 case Stmt::ArraySubscriptExprClass:
144 case Stmt::ArraySectionExprClass:
145 case Stmt::OMPArrayShapingExprClass:
146 case Stmt::OMPIteratorExprClass:
147 case Stmt::ImplicitCastExprClass:
148 case Stmt::ParenExprClass:
149 case Stmt::BreakStmtClass:
150 case Stmt::ContinueStmtClass:
151 case Stmt::NullStmtClass:
153 case Stmt::CStyleCastExprClass: {
154 const auto *CastExpr1 = cast<CStyleCastExpr>(Stmt1);
155 const auto *CastExpr2 = cast<CStyleCastExpr>(Stmt2);
157 return CastExpr1->getTypeAsWritten() == CastExpr2->getTypeAsWritten();
159 case Stmt::ReturnStmtClass: {
160 const auto *ReturnStmt1 = cast<ReturnStmt>(Stmt1);
161 const auto *ReturnStmt2 = cast<ReturnStmt>(Stmt2);
164 ReturnStmt2->getRetValue(), IgnoreSideEffects);
166 case Stmt::ForStmtClass: {
167 const auto *ForStmt1 = cast<ForStmt>(Stmt1);
168 const auto *ForStmt2 = cast<ForStmt>(Stmt2);
184 case Stmt::DoStmtClass: {
185 const auto *DStmt1 = cast<DoStmt>(Stmt1);
186 const auto *DStmt2 = cast<DoStmt>(Stmt2);
196 case Stmt::WhileStmtClass: {
197 const auto *WStmt1 = cast<WhileStmt>(Stmt1);
198 const auto *WStmt2 = cast<WhileStmt>(Stmt2);
208 case Stmt::IfStmtClass: {
209 const auto *IStmt1 = cast<IfStmt>(Stmt1);
210 const auto *IStmt2 = cast<IfStmt>(Stmt2);
223 case Stmt::DeferStmtClass: {
224 const auto *DefStmt1 = cast<DeferStmt>(Stmt1);
225 const auto *DefStmt2 = cast<DeferStmt>(Stmt2);
229 case Stmt::CompoundStmtClass: {
230 const auto *CompStmt1 = cast<CompoundStmt>(Stmt1);
231 const auto *CompStmt2 = cast<CompoundStmt>(Stmt2);
232 return llvm::equal(CompStmt1->body(), CompStmt2->body(),
233 [&](
const Stmt *S1,
const Stmt *S2) {
234 return isIdenticalStmt(Ctx, S1, S2, IgnoreSideEffects);
237 case Stmt::CompoundAssignOperatorClass:
238 case Stmt::BinaryOperatorClass: {
239 const auto *BinOp1 = cast<BinaryOperator>(Stmt1);
240 const auto *BinOp2 = cast<BinaryOperator>(Stmt2);
241 return BinOp1->getOpcode() == BinOp2->getOpcode();
243 case Stmt::CharacterLiteralClass: {
244 const auto *CharLit1 = cast<CharacterLiteral>(Stmt1);
245 const auto *CharLit2 = cast<CharacterLiteral>(Stmt2);
246 return CharLit1->getValue() == CharLit2->getValue();
248 case Stmt::DeclRefExprClass: {
249 const auto *DeclRef1 = cast<DeclRefExpr>(Stmt1);
250 const auto *DeclRef2 = cast<DeclRefExpr>(Stmt2);
251 return DeclRef1->getDecl() == DeclRef2->getDecl();
253 case Stmt::IntegerLiteralClass: {
254 const auto *IntLit1 = cast<IntegerLiteral>(Stmt1);
255 const auto *IntLit2 = cast<IntegerLiteral>(Stmt2);
257 const llvm::APInt I1 = IntLit1->getValue();
258 const llvm::APInt I2 = IntLit2->getValue();
259 if (I1.getBitWidth() != I2.getBitWidth())
263 case Stmt::FloatingLiteralClass: {
264 const auto *FloatLit1 = cast<FloatingLiteral>(Stmt1);
265 const auto *FloatLit2 = cast<FloatingLiteral>(Stmt2);
266 return FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue());
268 case Stmt::StringLiteralClass: {
269 const auto *StringLit1 = cast<StringLiteral>(Stmt1);
270 const auto *StringLit2 = cast<StringLiteral>(Stmt2);
271 return StringLit1->getBytes() == StringLit2->getBytes();
273 case Stmt::MemberExprClass: {
274 const auto *MemberStmt1 = cast<MemberExpr>(Stmt1);
275 const auto *MemberStmt2 = cast<MemberExpr>(Stmt2);
276 return MemberStmt1->getMemberDecl() == MemberStmt2->getMemberDecl();
278 case Stmt::UnaryOperatorClass: {
279 const auto *UnaryOp1 = cast<UnaryOperator>(Stmt1);
280 const auto *UnaryOp2 = cast<UnaryOperator>(Stmt2);
281 return UnaryOp1->getOpcode() == UnaryOp2->getOpcode();
287 const ASTContext &Context = *Result.Context;
289 if (
const auto *IS = Result.Nodes.getNodeAs<IfStmt>(
"if")) {
290 const Stmt *Then = IS->getThen();
291 assert(Then &&
"An IfStmt must have a `then` branch!");
293 const Stmt *Else = Result.Nodes.getNodeAs<Stmt>(
"else");
294 assert(Else &&
"We only look for `if` statements with an `else` branch!");
296 if (!isa<IfStmt>(Else)) {
299 Else->IgnoreContainers(), Context)) {
300 diag(IS->getBeginLoc(),
"if with identical then and else branches");
301 diag(IS->getElseLoc(),
"else branch starts here", DiagnosticIDs::Note);
308 llvm::SmallVector<const Stmt *, 4> Branches;
309 const IfStmt *Cur = IS;
312 Branches.push_back(Cur->getThen());
314 Else = Cur->getElse();
320 Cur = dyn_cast<IfStmt>(Else);
323 Branches.push_back(Else);
328 const size_t N = Branches.size();
329 llvm::BitVector KnownAsClone(N);
331 for (
size_t I = 0; I + 1 < N; I++) {
338 for (
size_t J = I + 1; J < N; J++) {
340 Branches[I]->IgnoreContainers(),
341 Branches[J]->IgnoreContainers(), Context))
345 KnownAsClone[J] =
true;
347 if (NumCopies == 2) {
349 diag(Branches[I]->getBeginLoc(),
350 "repeated branch body in conditional chain");
351 const SourceLocation End =
352 Lexer::getLocForEndOfToken(Branches[I]->getEndLoc(), 0,
353 *Result.SourceManager, getLangOpts());
355 diag(End,
"end of the original", DiagnosticIDs::Note);
358 diag(Branches[J]->getBeginLoc(),
"clone %0 starts here",
366 if (
const auto *CO = Result.Nodes.getNodeAs<ConditionalOperator>(
"condOp")) {
370 diag(CO->getQuestionLoc(),
371 "conditional operator with identical true and false expressions");
376 if (
const auto *SS = Result.Nodes.getNodeAs<SwitchStmt>(
"switch")) {
377 const auto *Body = dyn_cast_or_null<CompoundStmt>(SS->getBody());
391 llvm::SmallVector<SwitchBranch, 4> Branches;
392 for (
const Stmt *S : Body->body()) {
394 if (isa<SwitchCase>(S))
395 Branches.emplace_back();
401 if (!Branches.empty())
402 Branches.back().push_back(S);
405 auto *End = Branches.end();
406 auto *BeginCurrent = Branches.begin();
407 while (BeginCurrent < End) {
413 auto *EndCurrent = BeginCurrent + 1;
414 while (EndCurrent < End &&
421 if (EndCurrent == (BeginCurrent + 1)) {
423 BeginCurrent = EndCurrent;
427 diag(BeginCurrent->front()->getBeginLoc(),
428 "switch has %0 consecutive identical branches")
429 << std::distance(BeginCurrent, EndCurrent);
431 SourceLocation EndLoc = (EndCurrent - 1)->back()->getEndLoc();
436 if (EndLoc.isInvalid())
437 EndLoc = (EndCurrent - 1)->back()->getBeginLoc();
438 if (EndLoc.isMacroID())
439 EndLoc = Context.getSourceManager().getExpansionLoc(EndLoc);
440 EndLoc = Lexer::getLocForEndOfToken(EndLoc, 0, *Result.SourceManager,
442 if (EndLoc.isValid())
443 diag(EndLoc,
"last of these clones ends here", DiagnosticIDs::Note);
444 BeginCurrent = EndCurrent;
449 if (
const auto *IS = Result.Nodes.getNodeAs<IfStmt>(
"ifWithDescendantIf")) {
450 const Stmt *Then = IS->getThen();
451 const auto *CS = dyn_cast<CompoundStmt>(Then);
452 if (CS && (!CS->body_empty())) {
453 const auto *InnerIf = dyn_cast<IfStmt>(*CS->body_begin());
454 if (InnerIf &&
isIdenticalStmt(Context, IS->getCond(), InnerIf->getCond(),
456 diag(IS->getBeginLoc(),
"if with identical inner if statement");
457 diag(InnerIf->getBeginLoc(),
"inner if starts here",
458 DiagnosticIDs::Note);
464 llvm_unreachable(
"No if statement and no switch statement.");