[clang-tools-extra] [clang-tidy] `modernize-use-trailing-return-type`: add an option to apply to `void`-returning functions as well (PR #129406)

via cfe-commits cfe-commits at lists.llvm.org
Sat Mar 1 15:55:04 PST 2025


https://github.com/khuldraeseth created https://github.com/llvm/llvm-project/pull/129406

Adds an option `modernize-use-trailing-return-type.EvenWhenVoid` that when `true` enforces this check for declarations like `void foo();`. Default is `false` to preserve existing behavior.

>From cd7e8c60fb3d5d571b6f3398aa7b1fa0af88667c Mon Sep 17 00:00:00 2001
From: khuldraeseth <28711596+khuldraeseth at users.noreply.github.com>
Date: Wed, 26 Feb 2025 11:28:37 -0600
Subject: [PATCH 1/5] add EvenWhenVoid option to
 modernize-use-trailing-return-type check

---
 .../modernize/UseTrailingReturnTypeCheck.cpp     | 16 +++++++++++-----
 .../modernize/UseTrailingReturnTypeCheck.h       |  8 +++++++-
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
index 9774e988d71e2..140d51e77fc70 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
@@ -8,8 +8,10 @@
 
 #include "UseTrailingReturnTypeCheck.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Tooling/FixIt.h"
 #include "llvm/ADT/StringExtras.h"
@@ -287,7 +289,6 @@ SourceRange UseTrailingReturnTypeCheck::findReturnTypeAndCVSourceRange(
     return {};
   }
 
-
   // If the return type has no local qualifiers, it's source range is accurate.
   if (!hasAnyNestedLocalQualifiers(F.getReturnType()))
     return ReturnTypeRange;
@@ -384,10 +385,15 @@ void UseTrailingReturnTypeCheck::keepSpecifiers(
 }
 
 void UseTrailingReturnTypeCheck::registerMatchers(MatchFinder *Finder) {
-  auto F = functionDecl(
-               unless(anyOf(hasTrailingReturn(), returns(voidType()),
-                            cxxConversionDecl(), cxxMethodDecl(isImplicit()))))
-               .bind("Func");
+  auto const where =
+      EvenWhenVoid
+          ? functionDecl(unless(anyOf(hasTrailingReturn(), cxxConversionDecl(),
+                                      cxxMethodDecl(isImplicit()))))
+          : functionDecl(unless(anyOf(hasTrailingReturn(), returns(voidType()),
+                                      cxxConversionDecl(),
+                                      cxxMethodDecl(isImplicit()))));
+
+  auto F = where.bind("Func");
 
   Finder->addMatcher(F, this);
   Finder->addMatcher(friendDecl(hasDescendant(F)).bind("Friend"), this);
diff --git a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
index 5fb6ae945f466..fdd8be285c03b 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
+++ b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
@@ -28,7 +28,8 @@ struct ClassifiedToken {
 class UseTrailingReturnTypeCheck : public ClangTidyCheck {
 public:
   UseTrailingReturnTypeCheck(StringRef Name, ClangTidyContext *Context)
-      : ClangTidyCheck(Name, Context) {}
+      : ClangTidyCheck(Name, Context),
+        EvenWhenVoid(Options.get("EvenWhenVoid", false)) {}
   bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
     return LangOpts.CPlusPlus11;
   }
@@ -39,6 +40,7 @@ class UseTrailingReturnTypeCheck : public ClangTidyCheck {
 
 private:
   Preprocessor *PP = nullptr;
+  bool const EvenWhenVoid;
 
   SourceLocation findTrailingReturnTypeSourceLocation(
       const FunctionDecl &F, const FunctionTypeLoc &FTL, const ASTContext &Ctx,
@@ -56,6 +58,10 @@ class UseTrailingReturnTypeCheck : public ClangTidyCheck {
                       SourceRange ReturnTypeCVRange, const FunctionDecl &F,
                       const FriendDecl *Fr, const ASTContext &Ctx,
                       const SourceManager &SM, const LangOptions &LangOpts);
+
+  auto storeOptions(ClangTidyOptions::OptionMap &Opts) -> void override {
+    Options.store(Opts, "EvenWhenVoid", EvenWhenVoid);
+  }
 };
 
 } // namespace clang::tidy::modernize

>From 305cbb6b44a4d16e8d4bd349548c98880b870480 Mon Sep 17 00:00:00 2001
From: khuldraeseth <28711596+khuldraeseth at users.noreply.github.com>
Date: Sat, 1 Mar 2025 15:47:01 -0600
Subject: [PATCH 2/5] document EvenWhenVoid check option

---
 .../checks/modernize/use-trailing-return-type.rst         | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst
index 0593a35326aaa..1187c931fca43 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst
@@ -25,6 +25,14 @@ transforms to:
   inline auto f2(int arg) -> int noexcept;
   virtual auto f3() const && -> float = delete;
 
+Options
+-------
+
+.. option:: EvenWhenVoid
+
+  If the option is set to `true`, the check will apply even to function signatures
+  with return type `void`. Default is `false`.
+
 Known Limitations
 -----------------
 

>From a0757c09a8f4e29a92d6ca3b42b2669de75fabbb Mon Sep 17 00:00:00 2001
From: khuldraeseth <28711596+khuldraeseth at users.noreply.github.com>
Date: Sat, 1 Mar 2025 17:01:47 -0600
Subject: [PATCH 3/5] update modernize-use-trailing-return-type tests for
 EvenWhenVoid

---
 .../modernize/use-trailing-return-type.cpp    | 32 ++++++++++++++++---
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type.cpp
index e1f36c52a7c01..d8bef1b64f217 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type.cpp
@@ -1,4 +1,12 @@
-// RUN: %check_clang_tidy -std=c++14-or-later %s modernize-use-trailing-return-type %t -- -- -fdeclspec -fexceptions -DCOMMAND_LINE_INT=int
+// RUN: %check_clang_tidy                                                   \
+// RUN:   -std=c++14-or-later %s modernize-use-trailing-return-type %t --   \
+// RUN:   -- -fdeclspec -fexceptions -DCOMMAND_LINE_INT=int
+// RUN: %check_clang_tidy -check-suffixes=,EVEN-WHEN-VOID                   \
+// RUN:   -std=c++14-or-later %s modernize-use-trailing-return-type %t --   \
+// RUN:   -config="{CheckOptions: {                                         \
+// RUN:              modernize-use-trailing-return-type.EvenWhenVoid: true, \
+// RUN:            }}"                                                      \
+// RUN:   -- -fdeclspec -fexceptions -DCOMMAND_LINE_INT=int
 
 namespace std {
     template <typename T>
@@ -566,6 +574,24 @@ ostream& operator<<(ostream& ostream, int i);
 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
 // CHECK-FIXES: {{^}}ostream& operator<<(ostream& ostream, int i);{{$}}
 
+//
+// EvenWhenVoid option
+//
+
+void leadingVoid();
+// CHECK-MESSAGES-EVEN-WHEN-VOID: :[[@LINE-1]]:6: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES-EVEN-WHEN-VOID: {{^}}auto leadingVoid() -> void;{{$}}
+void leadingVoid(int arg);
+// CHECK-MESSAGES-EVEN-WHEN-VOID: :[[@LINE-1]]:6: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES-EVEN-WHEN-VOID: {{^}}auto leadingVoid(int arg) -> void;{{$}}
+void leadingVoid(int arg) { return; }
+// CHECK-MESSAGES-EVEN-WHEN-VOID: :[[@LINE-1]]:6: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES-EVEN-WHEN-VOID: {{^}}auto leadingVoid(int arg) -> void { return; }{{$}}
+
+auto trailingVoid() -> void;
+auto trailingVoid(int arg) -> void;
+auto trailingVoid(int arg) -> void { return; }
+
 //
 // Samples which do not trigger the check
 //
@@ -579,10 +605,6 @@ template <typename T> auto f(T t) -> int;
 
 auto ff();
 
-void c();
-void c(int arg);
-void c(int arg) { return; }
-
 struct D2 : B {
     D2();
     virtual ~D2();

>From ee659eba71f26b6ad835d9efe1236e800c5ef5a3 Mon Sep 17 00:00:00 2001
From: khuldraeseth <28711596+khuldraeseth at users.noreply.github.com>
Date: Sat, 1 Mar 2025 17:02:32 -0600
Subject: [PATCH 4/5] fix ctor/dtor false positive with EvenWhenVoid

---
 .../modernize/UseTrailingReturnTypeCheck.cpp       | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
index 140d51e77fc70..12448303fdcd8 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
@@ -385,13 +385,13 @@ void UseTrailingReturnTypeCheck::keepSpecifiers(
 }
 
 void UseTrailingReturnTypeCheck::registerMatchers(MatchFinder *Finder) {
-  auto const where =
-      EvenWhenVoid
-          ? functionDecl(unless(anyOf(hasTrailingReturn(), cxxConversionDecl(),
-                                      cxxMethodDecl(isImplicit()))))
-          : functionDecl(unless(anyOf(hasTrailingReturn(), returns(voidType()),
-                                      cxxConversionDecl(),
-                                      cxxMethodDecl(isImplicit()))));
+  const auto hasNoWrittenReturnType =
+      anyOf(cxxConversionDecl(), cxxConstructorDecl(), cxxDestructorDecl(),
+            cxxMethodDecl(isImplicit()));
+
+  const auto where = functionDecl(
+      unless(anyOf(hasTrailingReturn(), hasNoWrittenReturnType,
+                   EvenWhenVoid ? unless(anything()) : returns(voidType()))));
 
   auto F = where.bind("Func");
 

>From 57cbd50604f496bfa9d9bfc70225c845297c4cd2 Mon Sep 17 00:00:00 2001
From: khuldraeseth <28711596+khuldraeseth at users.noreply.github.com>
Date: Sat, 1 Mar 2025 17:52:19 -0600
Subject: [PATCH 5/5] update release notes

---
 clang-tools-extra/docs/ReleaseNotes.rst | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 2dcefa2ddec83..93b2202ce8635 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -120,6 +120,11 @@ Changes in existing checks
   tolerating fix-it breaking compilation when functions is used as pointers 
   to avoid matching usage of functions within the current compilation unit.
 
+- Improved :doc:`modernize/use-trailing-return-type
+  <clang-tidy/checks/modernize/use-trailing-return-type>` check by adding the
+  option ``EvenWhenVoid`` that applies the check to ``void``-returning functions
+  that by default are excluded from this check.
+
 Removed checks
 ^^^^^^^^^^^^^^
 



More information about the cfe-commits mailing list