[clang-tools-extra] [clang-tidy] Extend readability-else-after-return to remove else after calls to [[noreturn]] functions (PR #185202)

via cfe-commits cfe-commits at lists.llvm.org
Sat Mar 7 08:47:26 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-tools-extra

Author: Berkay Sahin (berkaysahiin)

<details>
<summary>Changes</summary>

Closes #<!-- -->184930

---
Full diff: https://github.com/llvm/llvm-project/pull/185202.diff


3 Files Affected:

- (modified) clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp (+21-1) 
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+7-2) 
- (modified) clang-tools-extra/test/clang-tidy/checkers/readability/else-after-return.cpp (+12) 


``````````diff
diff --git a/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp b/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp
index 7e93d619e2a9f..4160f0fcf1dc1 100644
--- a/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp
@@ -39,6 +39,23 @@ class PPConditionalCollector : public PPCallbacks {
   const SourceManager &SM;
 };
 
+bool isNoReturnStmt(const Stmt &Stmt) {
+  const auto *Call = dyn_cast<CallExpr>(&Stmt);
+  if (!Call)
+    return false;
+
+  const FunctionDecl *Func = Call->getDirectCallee();
+  if (!Func)
+    return false;
+
+  return Func->isNoReturn();
+}
+
+AST_MATCHER(Stmt, isNoReturnStmt) {
+  const Stmt &S = Node;
+  return isNoReturnStmt(S);
+}
+
 AST_MATCHER_P(Stmt, stripLabelLikeStatements,
               ast_matchers::internal::Matcher<Stmt>, InnerMatcher) {
   const Stmt *S = Node.stripLabelLikeStatements();
@@ -174,7 +191,8 @@ void ElseAfterReturnCheck::registerPPCallbacks(const SourceManager &SM,
 void ElseAfterReturnCheck::registerMatchers(MatchFinder *Finder) {
   const auto InterruptsControlFlow = stmt(anyOf(
       returnStmt().bind(InterruptingStr), continueStmt().bind(InterruptingStr),
-      breakStmt().bind(InterruptingStr), cxxThrowExpr().bind(InterruptingStr)));
+      breakStmt().bind(InterruptingStr), cxxThrowExpr().bind(InterruptingStr),
+      stmt(isNoReturnStmt()).bind(InterruptingStr)));
 
   const auto IfWithInterruptingThenElse =
       ifStmt(unless(isConstexpr()), unless(isConsteval()),
@@ -237,6 +255,8 @@ static StringRef getControlFlowString(const Stmt &Stmt) {
     return "break";
   if (isa<CXXThrowExpr>(Stmt))
     return "throw";
+  if (isNoReturnStmt(Stmt))
+    return "noreturn";
   llvm_unreachable("Unknown control flow interrupter");
 }
 
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index b0b4cd646c3bd..33437d2004079 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -295,8 +295,13 @@ Changes in existing checks
   when a member expression has a non-identifier name.
 
 - Improved :doc:`readability-else-after-return
-  <clang-tidy/checks/readability/else-after-return>` check by fixing missed
-  diagnostics when ``if`` statements appear in unbraced ``switch`` case labels.
+  <clang-tidy/checks/readability/else-after-return>` check:
+
+  - Fixed missed diagnostics when ``if`` statements appear in unbraced
+    ``switch`` case labels.
+
+  - Diagnose and remove redundant ``else`` branches after calls to
+    ``[[noreturn]]`` functions.
 
 - Improved :doc:`readability-enum-initial-value
   <clang-tidy/checks/readability/enum-initial-value>` check: the warning message
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/else-after-return.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/else-after-return.cpp
index e987687a764cd..f0788dbf3221b 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/else-after-return.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/else-after-return.cpp
@@ -438,3 +438,15 @@ void testLabels(bool b) {
       f(0);
   }
 }
+
+[[noreturn]] void noReturn();
+
+void testNoReturn() {
+  if (true) {
+    noReturn();
+  } else { // comment-28
+    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'noreturn'
+    // CHECK-FIXES: {{^}}  } // comment-28
+    f(0);
+  }
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/185202


More information about the cfe-commits mailing list