Skip to content

Commit 9c182f7

Browse files
authored
[clang-tidy] Extend readability-else-after-return to remove else after calls to [[noreturn]] functions (llvm#185202)
Closes llvm#184930.
1 parent c27fbb5 commit 9c182f7

File tree

3 files changed

+37
-6
lines changed

3 files changed

+37
-6
lines changed

clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ AST_MATCHER_P(Stmt, stripLabelLikeStatements,
4848
} // namespace
4949

5050
static constexpr char InterruptingStr[] = "interrupting";
51-
static constexpr char WarningMessage[] = "do not use 'else' after '%0'";
51+
static constexpr char WarningMessage[] = "do not use 'else' after %0";
5252
static constexpr char WarnOnUnfixableStr[] = "WarnOnUnfixable";
5353
static constexpr char WarnOnConditionVariablesStr[] =
5454
"WarnOnConditionVariables";
@@ -174,7 +174,8 @@ void ElseAfterReturnCheck::registerPPCallbacks(const SourceManager &SM,
174174
void ElseAfterReturnCheck::registerMatchers(MatchFinder *Finder) {
175175
const auto InterruptsControlFlow = stmt(anyOf(
176176
returnStmt().bind(InterruptingStr), continueStmt().bind(InterruptingStr),
177-
breakStmt().bind(InterruptingStr), cxxThrowExpr().bind(InterruptingStr)));
177+
breakStmt().bind(InterruptingStr), cxxThrowExpr().bind(InterruptingStr),
178+
callExpr(callee(functionDecl(isNoReturn()))).bind(InterruptingStr)));
178179

179180
const auto IfWithInterruptingThenElse =
180181
ifStmt(unless(isConstexpr()), unless(isConsteval()),
@@ -231,13 +232,15 @@ static bool hasPreprocessorBranchEndBetweenLocations(
231232

232233
static StringRef getControlFlowString(const Stmt &Stmt) {
233234
if (isa<ReturnStmt>(Stmt))
234-
return "return";
235+
return "'return'";
235236
if (isa<ContinueStmt>(Stmt))
236-
return "continue";
237+
return "'continue'";
237238
if (isa<BreakStmt>(Stmt))
238-
return "break";
239+
return "'break'";
239240
if (isa<CXXThrowExpr>(Stmt))
240-
return "throw";
241+
return "'throw'";
242+
if (isa<CallExpr>(Stmt))
243+
return "calling a function that doesn't return";
241244
llvm_unreachable("Unknown control flow interrupter");
242245
}
243246

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@ Changes in existing checks
333333
- Added support for handling attributed ``if`` then-branches such as
334334
``[[likely]]`` and ``[[unlikely]]``.
335335

336+
- Diagnose and remove redundant ``else`` branches after calls to
337+
``[[noreturn]]`` functions.
338+
336339
- Improved :doc:`readability-enum-initial-value
337340
<clang-tidy/checks/readability/enum-initial-value>` check: the warning message
338341
now uses separate note diagnostics for each uninitialized enumerator, making

clang-tools-extra/test/clang-tidy/checkers/readability/else-after-return.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,3 +438,28 @@ void testLabels(bool b) {
438438
f(0);
439439
}
440440
}
441+
442+
[[noreturn]] void noReturn();
443+
444+
struct NoReturnMember {
445+
[[noreturn]] void noReturn();
446+
};
447+
448+
void testNoReturn() {
449+
if (true) {
450+
noReturn();
451+
} else { // comment-28
452+
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after calling a function that doesn't return
453+
// CHECK-FIXES: {{^}} } // comment-28
454+
f(0);
455+
}
456+
457+
if (true) {
458+
NoReturnMember f;
459+
f.noReturn();
460+
} else { // comment-29
461+
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after calling a function that doesn't return
462+
// CHECK-FIXES: {{^}} } // comment-29
463+
f(0);
464+
}
465+
}

0 commit comments

Comments
 (0)