[clang-tools-extra] 96266b7 - [clang-tidy] Add `readability-redundant-lambda-parameter-list` (#190438)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 17 04:13:34 PDT 2026
Author: Kryptonite
Date: 2026-04-17T11:13:28Z
New Revision: 96266b71214a2fa0925ea11fe2d01a349eb702e0
URL: https://github.com/llvm/llvm-project/commit/96266b71214a2fa0925ea11fe2d01a349eb702e0
DIFF: https://github.com/llvm/llvm-project/commit/96266b71214a2fa0925ea11fe2d01a349eb702e0.diff
LOG: [clang-tidy] Add `readability-redundant-lambda-parameter-list` (#190438)
Adds a new clang-tidy check that removes redundant empty parameter lists
from lambda expressions when the rewrite is valid for the active
language standard.
Fixes #190396
Assisted by Claude (Anthropic), all decisions taken in
this PR involved my active judgment
Added:
clang-tools-extra/clang-tidy/readability/RedundantLambdaParameterListCheck.cpp
clang-tools-extra/clang-tidy/readability/RedundantLambdaParameterListCheck.h
clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parameter-list.rst
clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parameter-list.cpp
Modified:
clang-tools-extra/clang-tidy/readability/CMakeLists.txt
clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/docs/clang-tidy/checks/list.rst
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
index 686e7c19d650b..0dfdbe69c880d 100644
--- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -44,6 +44,7 @@ add_clang_library(clangTidyReadabilityModule STATIC
RedundantControlFlowCheck.cpp
RedundantDeclarationCheck.cpp
RedundantFunctionPtrDereferenceCheck.cpp
+ RedundantLambdaParameterListCheck.cpp
RedundantMemberInitCheck.cpp
RedundantParenthesesCheck.cpp
RedundantPreprocessorCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
index 8e9e00b23c84a..86e4f4dcc1de1 100644
--- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -46,6 +46,7 @@
#include "RedundantDeclarationCheck.h"
#include "RedundantFunctionPtrDereferenceCheck.h"
#include "RedundantInlineSpecifierCheck.h"
+#include "RedundantLambdaParameterListCheck.h"
#include "RedundantMemberInitCheck.h"
#include "RedundantParenthesesCheck.h"
#include "RedundantPreprocessorCheck.h"
@@ -143,6 +144,8 @@ class ReadabilityModule : public ClangTidyModule {
"readability-redundant-casting");
CheckFactories.registerCheck<RedundantFunctionPtrDereferenceCheck>(
"readability-redundant-function-ptr-dereference");
+ CheckFactories.registerCheck<RedundantLambdaParameterListCheck>(
+ "readability-redundant-lambda-parameter-list");
CheckFactories.registerCheck<RedundantMemberInitCheck>(
"readability-redundant-member-init");
CheckFactories.registerCheck<RedundantParenthesesCheck>(
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParameterListCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParameterListCheck.cpp
new file mode 100644
index 0000000000000..1b12a199c1fdb
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParameterListCheck.cpp
@@ -0,0 +1,66 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RedundantLambdaParameterListCheck.h"
+#include "../utils/LexerUtils.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+namespace {
+
+AST_MATCHER(LambdaExpr, hasRedundantParens) {
+ return Node.hasExplicitParameters() &&
+ Node.getCallOperator()->getNumParams() == 0 &&
+ !Node.getCallOperator()->getTrailingRequiresClause();
+}
+
+} // namespace
+
+void RedundantLambdaParameterListCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(lambdaExpr(hasRedundantParens()).bind("lambda"), this);
+}
+
+void RedundantLambdaParameterListCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ const auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda");
+
+ const LangOptions &LangOpts = getLangOpts();
+
+ const FunctionTypeLoc FTL = Lambda->getCallOperator()->getFunctionTypeLoc();
+ const SourceLocation LParenLoc = FTL.getLParenLoc();
+ const SourceLocation RParenLoc = FTL.getRParenLoc();
+
+ if (LParenLoc.isInvalid() || RParenLoc.isInvalid())
+ return;
+
+ // Ensure parens are truly empty (reject "(void)")
+ const std::optional<Token> FirstInParens =
+ utils::lexer::findNextTokenSkippingComments(
+ LParenLoc, *Result.SourceManager, LangOpts);
+
+ if (!FirstInParens || FirstInParens->getLocation() != RParenLoc)
+ return;
+
+ const std::optional<Token> NextAfterParenTok =
+ utils::lexer::findNextTokenSkippingComments(
+ RParenLoc, *Result.SourceManager, LangOpts);
+
+ if (!NextAfterParenTok || NextAfterParenTok->is(tok::l_square))
+ return;
+
+ if (!LangOpts.CPlusPlus23 && NextAfterParenTok->isNot(tok::l_brace))
+ return;
+
+ diag(LParenLoc, "redundant empty parameter list in lambda expression")
+ << FixItHint::CreateRemoval(LParenLoc)
+ << FixItHint::CreateRemoval(RParenLoc);
+}
+
+} // namespace clang::tidy::readability
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParameterListCheck.h b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParameterListCheck.h
new file mode 100644
index 0000000000000..408cfa8ddf7e9
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParameterListCheck.h
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTLAMBDAPARAMETERLISTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTLAMBDAPARAMETERLISTCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::readability {
+
+/// Finds lambda expressions with a redundant empty parameter list and removes
+/// it.
+///
+/// For the user-facing documentation see:
+/// https://clang.llvm.org/extra/clang-tidy/checks/readability/redundant-lambda-parameter-list.html
+class RedundantLambdaParameterListCheck : public ClangTidyCheck {
+public:
+ RedundantLambdaParameterListCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+
+ std::optional<TraversalKind> getCheckTraversalKind() const override {
+ return TK_IgnoreUnlessSpelledInSource;
+ }
+
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return LangOpts.CPlusPlus11;
+ }
+};
+
+} // namespace clang::tidy::readability
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTLAMBDAPARAMETERLISTCHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 3d126910d2e2e..cc1c6bae65e2b 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -175,6 +175,11 @@ New checks
Suggests insertion of ``std::move(...)`` to turn copy assignment operator
calls into move assignment ones, when deemed valid and profitable.
+- New :doc:`readability-redundant-lambda-parameter-list
+ <clang-tidy/checks/readability/redundant-lambda-parameter-list>` check.
+
+ Finds lambda expressions with a redundant empty parameter list and removes it.
+
- New :doc:`readability-redundant-qualified-alias
<clang-tidy/checks/readability/redundant-qualified-alias>` check.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index df869d422f1a1..71b312a7112ee 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -416,6 +416,7 @@ Clang-Tidy Checks
:doc:`readability-redundant-declaration <readability/redundant-declaration>`, "Yes"
:doc:`readability-redundant-function-ptr-dereference <readability/redundant-function-ptr-dereference>`, "Yes"
:doc:`readability-redundant-inline-specifier <readability/redundant-inline-specifier>`, "Yes"
+ :doc:`readability-redundant-lambda-parameter-list <readability/redundant-lambda-parameter-list>`, "Yes"
:doc:`readability-redundant-member-init <readability/redundant-member-init>`, "Yes"
:doc:`readability-redundant-parentheses <readability/redundant-parentheses>`, "Yes"
:doc:`readability-redundant-preprocessor <readability/redundant-preprocessor>`,
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parameter-list.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parameter-list.rst
new file mode 100644
index 0000000000000..5233be86ceb77
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parameter-list.rst
@@ -0,0 +1,35 @@
+.. title:: clang-tidy - readability-redundant-lambda-parameter-list
+
+readability-redundant-lambda-parameter-list
+===========================================
+
+Finds lambda expressions with a redundant empty parameter list and removes it.
+
+In C++11 and later, a lambda with no parameters does not require an explicit
+``()`` unless it has a specifier such as ``mutable``, ``noexcept``, or a
+trailing return type. In C++23 and later, ``()`` is redundant even when such
+specifiers are present.
+
+.. code-block:: c++
+
+ // C++11 and later - the following lambdas will be rewritten:
+ auto a = []() { return 42; };
+ // becomes:
+ auto a = [] { return 42; };
+
+ auto b = [x = 1]() { return x; };
+ // becomes:
+ auto b = [x = 1] { return x; };
+
+ // C++23 and later - the following lambdas will also be rewritten:
+ auto c = []() mutable {};
+ // becomes:
+ auto c = [] mutable {};
+
+ auto d = []() noexcept {};
+ // becomes:
+ auto d = [] noexcept {};
+
+ auto e = []() -> int { return 0; };
+ // becomes:
+ auto e = [] -> int { return 0; };
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parameter-list.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parameter-list.cpp
new file mode 100644
index 0000000000000..d21e5839ca147
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parameter-list.cpp
@@ -0,0 +1,126 @@
+// RUN: %check_clang_tidy -std=c++11,c++14,c++17 %s readability-redundant-lambda-parameter-list %t
+// RUN: %check_clang_tidy -std=c++20 -check-suffixes=,CXX20 %s readability-redundant-lambda-parameter-list %t
+// RUN: %check_clang_tidy -std=c++23-or-later -check-suffixes=,CXX20,CXX23 %s readability-redundant-lambda-parameter-list %t
+
+
+int main() {
+ auto a = []() { return 42; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES: auto a = [] { return 42; };
+
+ auto b = [x = 1]() { return x; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES: auto b = [x = 1] { return x; };
+
+ auto c = []() {};
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES: auto c = [] {};
+
+ auto v = 1;
+ auto call = [&v]() { return v; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES: auto call = [&v] { return v; };
+
+ auto d = [](int x) { return x; };
+ auto e = [](int x, int y) { return x + y; };
+
+#define LAMBDA []() { return 42; }
+ auto k = LAMBDA;
+#undef LAMBDA
+
+#if __cplusplus >= 202002L
+ auto f = []<class T>() { return sizeof(T); };
+ // CHECK-MESSAGES-CXX20: :[[@LINE-1]]:23: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES-CXX20: auto f = []<class T> { return sizeof(T); };
+
+ auto g = []<class T>() requires (sizeof(T) > 0) {};
+
+ auto h = []<class T>(T x) { return x; };
+#endif
+
+ auto i = []() mutable {};
+ // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES-CXX23: auto i = [] mutable {};
+
+ auto j = []() noexcept {};
+ // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES-CXX23: auto j = [] noexcept {};
+
+ auto l = []() -> int { return 0; };
+ // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES-CXX23: auto l = [] -> int { return 0; };
+
+ auto m = []() mutable noexcept {};
+ // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES-CXX23: auto m = [] mutable noexcept {};
+
+ auto n = []() constexpr { return 42; };
+ // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES-CXX23: auto n = [] constexpr { return 42; };
+
+#if __cplusplus >= 202002L
+ auto o = []() consteval { return 42; };
+ // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES-CXX23: auto o = [] consteval { return 42; };
+#endif
+
+ auto p = []() [[]] {};
+
+ auto q = [] [[]] () {};
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES: auto q = [] {{\[\[}}{{\]\]}} {};
+
+ auto r = [] [[]] () [[]] {};
+
+ auto s = []() noexcept [[]] {};
+ // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES-CXX23: auto s = [] noexcept {{\[\[}}{{\]\]}} {};
+
+ auto t = []( /* comment */ ) { return 42; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES: auto t = [] /* comment */ { return 42; };
+
+ auto u = []() /* comment */ { return 42; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES: auto u = [] /* comment */ { return 42; };
+
+ auto w = [](/* comment */) { return 42; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES: auto w = []/* comment */ { return 42; };
+
+ auto x = [] /* comment */ () { return 42; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES: auto x = [] /* comment */ { return 42; };
+
+ auto void1 = [](void) {};
+ auto void2 = [] (void) {};
+
+#define EMPTY
+#define VOID void
+ auto macro1 = [](EMPTY) {};
+ auto macro2 = [](VOID) {};
+#undef EMPTY
+#undef VOID
+
+#define LPAREN (
+#define RPAREN )
+#define PARENS ()
+ auto macro3 = []LPAREN RPAREN {};
+ auto macro4 = []PARENS {};
+#undef LPAREN
+#undef RPAREN
+#undef PARENS
+}
+
+#if __cplusplus >= 202002L
+template <bool B>
+void testRequires() {
+ auto f1 = []() requires B {};
+ auto f2 = []() noexcept requires B {};
+ auto f3 = []<typename T>() requires B {};
+
+ auto f4 = []<typename T> requires B () {};
+ // CHECK-MESSAGES-CXX20: :[[@LINE-1]]:39: warning: redundant empty parameter list in lambda expression
+ // CHECK-FIXES-CXX20: auto f4 = []<typename T> requires B {};
+}
+#endif
More information about the cfe-commits
mailing list