[clang-tools-extra] [clang-tidy] Add readability-redundant-lambda-parameter-list (PR #190438)
Daniil Dudkin via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 17 03:53:52 PDT 2026
https://github.com/unterumarmung updated https://github.com/llvm/llvm-project/pull/190438
>From b1de6aa2612f0897cc544444070130b0691003a1 Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Sat, 4 Apr 2026 03:45:48 +0300
Subject: [PATCH 01/20] [clang-tidy] Add
readability-redundant-lambda-parentheses check
---
.../clang-tidy/readability/CMakeLists.txt | 1 +
.../readability/ReadabilityTidyModule.cpp | 3 +
.../RedundantLambdaParenthesesCheck.cpp | 90 +++++++++++++++++++
.../RedundantLambdaParenthesesCheck.h | 34 +++++++
clang-tools-extra/docs/ReleaseNotes.rst | 5 ++
.../docs/clang-tidy/checks/list.rst | 3 +-
.../redundant-lambda-parentheses.rst | 35 ++++++++
.../redundant-lambda-parentheses-cxx20.cpp | 19 ++++
.../redundant-lambda-parentheses-cxx23.cpp | 41 +++++++++
.../redundant-lambda-parentheses.cpp | 38 ++++++++
10 files changed, 267 insertions(+), 2 deletions(-)
create mode 100644 clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
create mode 100644 clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.h
create mode 100644 clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parentheses.rst
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
index 686e7c19d650b..3702600e0496c 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
+ RedundantLambdaParenthesesCheck.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..6bfeb6c548f48 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 "RedundantLambdaParenthesesCheck.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<RedundantLambdaParenthesesCheck>(
+ "readability-redundant-lambda-parentheses");
CheckFactories.registerCheck<RedundantMemberInitCheck>(
"readability-redundant-member-init");
CheckFactories.registerCheck<RedundantParenthesesCheck>(
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
new file mode 100644
index 0000000000000..275eba3448d4c
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
@@ -0,0 +1,90 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "RedundantLambdaParenthesesCheck.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+void RedundantLambdaParenthesesCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(lambdaExpr().bind("lambda"), this);
+}
+
+void RedundantLambdaParenthesesCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ const auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda");
+
+ if (Lambda->getBeginLoc().isMacroID())
+ return;
+
+ if (!Lambda->hasExplicitParameters() && !Lambda->isGenericLambda())
+ return;
+
+ if (Lambda->getCallOperator()->getNumParams() != 0)
+ return;
+
+ if (Lambda->isGenericLambda() && !getLangOpts().CPlusPlus20)
+ return;
+
+ const LangOptions &LangOpts = getLangOpts();
+
+ SourceLocation ScanFrom;
+ if (Lambda->isGenericLambda()) {
+ TemplateParameterList *TPL = Lambda->getTemplateParameterList();
+ ScanFrom = Lexer::getLocForEndOfToken(TPL->getRAngleLoc(), 0,
+ *Result.SourceManager, LangOpts);
+ } else {
+ ScanFrom = Lexer::getLocForEndOfToken(Lambda->getIntroducerRange().getEnd(),
+ 0, *Result.SourceManager, LangOpts);
+ }
+
+ Token Tok;
+ if (Lexer::getRawToken(ScanFrom, Tok, *Result.SourceManager, LangOpts,
+ /*IgnoreWhiteSpace=*/true))
+ return;
+
+ if (Tok.isNot(tok::l_paren))
+ return;
+
+ SourceLocation LParenLoc = Tok.getLocation();
+ SourceLocation RParenLoc = Lexer::findLocationAfterToken(
+ LParenLoc, tok::r_paren, *Result.SourceManager, LangOpts,
+ /*SkipTrailingWhitespaceAndNewLine=*/false);
+
+ if (LParenLoc.isInvalid() || RParenLoc.isInvalid())
+ return;
+
+ if (!LangOpts.CPlusPlus23) {
+ std::optional<Token> RParen =
+ Lexer::findNextToken(LParenLoc, *Result.SourceManager, LangOpts);
+ if (!RParen || RParen->isNot(tok::r_paren))
+ return;
+ std::optional<Token> NextTok = Lexer::findNextToken(
+ RParen->getLocation(), *Result.SourceManager, LangOpts);
+ if (NextTok && NextTok->is(tok::raw_identifier)) {
+ StringRef Id = NextTok->getRawIdentifier();
+ if (Id == "constexpr" || Id == "consteval" || Id == "mutable" ||
+ Id == "noexcept")
+ return;
+ }
+ if (NextTok && NextTok->is(tok::arrow))
+ return;
+ }
+
+ CharSourceRange ParenRange =
+ CharSourceRange::getCharRange(LParenLoc, RParenLoc);
+
+ diag(LParenLoc, "redundant empty parameter list in lambda expression")
+ << FixItHint::CreateRemoval(ParenRange);
+}
+
+} // namespace clang::tidy::readability
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.h b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.h
new file mode 100644
index 0000000000000..3437d703da1f4
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.h
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_REDUNDANTLAMBDAPARENTHESESCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTLAMBDAPARENTHESESCHECK_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-parentheses.html
+class RedundantLambdaParenthesesCheck : public ClangTidyCheck {
+public:
+ RedundantLambdaParenthesesCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ 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_REDUNDANTLAMBDAPARENTHESESCHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 36e311341f336..9672664901f0a 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -163,6 +163,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-parentheses
+ <clang-tidy/checks/readability/redundant-lambda-parentheses>` check.
+
+ FIXME: Write a short description.
+
- 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 2b5be931271ec..3f69d9f51d73f 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -241,7 +241,6 @@ Clang-Tidy Checks
:doc:`google-runtime-int <google/runtime-int>`,
:doc:`google-runtime-operator <google/runtime-operator>`,
:doc:`google-upgrade-googletest-case <google/upgrade-googletest-case>`, "Yes"
- :doc:`hicpp-exception-baseclass <hicpp/exception-baseclass>`,
:doc:`hicpp-multiway-paths-covered <hicpp/multiway-paths-covered>`,
:doc:`hicpp-signed-bitwise <hicpp/signed-bitwise>`,
:doc:`linuxkernel-must-check-errs <linuxkernel/must-check-errs>`,
@@ -351,7 +350,6 @@ Clang-Tidy Checks
:doc:`openmp-use-default-none <openmp/use-default-none>`,
:doc:`performance-avoid-endl <performance/avoid-endl>`, "Yes"
:doc:`performance-enum-size <performance/enum-size>`,
- :doc:`performance-faster-string-find <performance/faster-string-find>`, "Yes"
:doc:`performance-for-range-copy <performance/for-range-copy>`, "Yes"
:doc:`performance-implicit-conversion-in-loop <performance/implicit-conversion-in-loop>`,
:doc:`performance-inefficient-algorithm <performance/inefficient-algorithm>`, "Yes"
@@ -415,6 +413,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-parentheses <readability/redundant-lambda-parentheses>`, "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-parentheses.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parentheses.rst
new file mode 100644
index 0000000000000..3167b841b38bc
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parentheses.rst
@@ -0,0 +1,35 @@
+.. title:: clang-tidy - readability-redundant-lambda-parentheses
+
+readability-redundant-lambda-parentheses
+========================================
+
+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; };
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp
new file mode 100644
index 0000000000000..769ffad629d03
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp
@@ -0,0 +1,19 @@
+// RUN: %check_clang_tidy -std=c++20 %s readability-redundant-lambda-parentheses %t
+
+int main() {
+ // Generic lambdas - should warn in C++20 and later
+ auto a = []<class T>() { return sizeof(T); };
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: {{^}} auto a = []<class T> { return sizeof(T); };{{$}}
+
+ auto b = []<class T>() requires true { return sizeof(T); };
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: {{^}} auto b = []<class T> requires true { return sizeof(T); };{{$}}
+
+ // Should NOT warn - has parameters
+ auto c = []<class T>(T x) { return x; };
+
+ // Should NOT warn - has specifiers
+ auto d = []<class T>() mutable { return sizeof(T); };
+ auto e = []<class T>() noexcept { return sizeof(T); };
+}
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp
new file mode 100644
index 0000000000000..4a9378564c149
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp
@@ -0,0 +1,41 @@
+// RUN: %check_clang_tidy -std=c++23 %s readability-redundant-lambda-parentheses %t
+
+int main() {
+ // Basic cases - should warn
+ auto a = []() { return 42; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: {{^}} auto a = [] { return 42; };{{$}}
+
+ // Specifier cases - should also warn in C++23
+ auto b = []() mutable {};
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: {{^}} auto b = [] mutable {};{{$}}
+
+ auto c = []() noexcept {};
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: {{^}} auto c = [] noexcept {};{{$}}
+
+ auto d = []() -> int { return 0; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: {{^}} auto d = [] -> int { return 0; };{{$}}
+
+ auto e = []() mutable noexcept {};
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: {{^}} auto e = [] mutable noexcept {};{{$}}
+
+ auto f = []() constexpr { return 42; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: {{^}} auto f = [] constexpr { return 42; };{{$}}
+
+ auto g = []() consteval { return 42; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: {{^}} auto g = [] consteval { return 42; };{{$}}
+
+ // Should NOT warn - has parameters
+ auto h = [](int x) { return x; };
+
+ // Should NOT warn - macro
+#define LAMBDA []() { return 42; }
+ auto i = LAMBDA;
+#undef LAMBDA
+}
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
new file mode 100644
index 0000000000000..e04dca093dba5
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
@@ -0,0 +1,38 @@
+// RUN: %check_clang_tidy -std=c++17 %s readability-redundant-lambda-parentheses %t
+
+int main() {
+ // Basic cases - should warn
+ auto a = []() { return 42; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: {{^}} auto b = [x = 1] { return x; };{{$}}
+
+ // Lambda with no captures
+ auto c = []() {};
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: {{^}} auto c = [] {};{{$}}
+
+ // Lambda inside a function call
+ auto v = 1;
+ auto call = [&v]() { return v; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: {{^}} auto call = [&v] { return v; };{{$}}
+
+ // Should NOT warn - has parameters
+ auto d = [](int x) { return x; };
+ auto e = [](int x, int y) { return x + y; };
+
+ // Should NOT warn - has specifiers, needs C++23
+ auto f = []() mutable {};
+ auto g = []() noexcept {};
+ auto h = []() -> int { return 0; };
+ auto i = []() constexpr { return 42; };
+
+ // Should NOT warn - macro
+#define LAMBDA []() { return 42; }
+ auto k = LAMBDA;
+#undef LAMBDA
+}
\ No newline at end of file
>From b9cd06c0503c495121ce87e50a76316a87bd8125 Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Sat, 4 Apr 2026 04:13:45 +0300
Subject: [PATCH 02/20] [clang-tidy] Fix missing newlines, release notes, and
list.rst entries
---
clang-tools-extra/docs/ReleaseNotes.rst | 3 ++-
clang-tools-extra/docs/clang-tidy/checks/list.rst | 2 ++
.../checks/readability/redundant-lambda-parentheses.rst | 2 +-
.../readability/redundant-lambda-parentheses-cxx20.cpp | 2 +-
.../readability/redundant-lambda-parentheses-cxx23.cpp | 2 +-
.../checkers/readability/redundant-lambda-parentheses.cpp | 2 +-
6 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 9672664901f0a..4265710225b56 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -166,7 +166,8 @@ New checks
- New :doc:`readability-redundant-lambda-parentheses
<clang-tidy/checks/readability/redundant-lambda-parentheses>` check.
- FIXME: Write a short description.
+ Finds and removes redundant empty parameter lists from lambda expressions
+ when the rewrite is valid for the active language standard.
- 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 3f69d9f51d73f..864df613a332a 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -241,6 +241,7 @@ Clang-Tidy Checks
:doc:`google-runtime-int <google/runtime-int>`,
:doc:`google-runtime-operator <google/runtime-operator>`,
:doc:`google-upgrade-googletest-case <google/upgrade-googletest-case>`, "Yes"
+ :doc:`hicpp-exception-baseclass <hicpp/exception-baseclass>`,
:doc:`hicpp-multiway-paths-covered <hicpp/multiway-paths-covered>`,
:doc:`hicpp-signed-bitwise <hicpp/signed-bitwise>`,
:doc:`linuxkernel-must-check-errs <linuxkernel/must-check-errs>`,
@@ -350,6 +351,7 @@ Clang-Tidy Checks
:doc:`openmp-use-default-none <openmp/use-default-none>`,
:doc:`performance-avoid-endl <performance/avoid-endl>`, "Yes"
:doc:`performance-enum-size <performance/enum-size>`,
+ :doc:`performance-faster-string-find <performance/faster-string-find>`, "Yes"
:doc:`performance-for-range-copy <performance/for-range-copy>`, "Yes"
:doc:`performance-implicit-conversion-in-loop <performance/implicit-conversion-in-loop>`,
:doc:`performance-inefficient-algorithm <performance/inefficient-algorithm>`, "Yes"
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parentheses.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parentheses.rst
index 3167b841b38bc..04b870830bedf 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parentheses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parentheses.rst
@@ -32,4 +32,4 @@ specifiers are present.
auto e = []() -> int { return 0; };
// becomes:
- auto e = [] -> int { return 0; };
\ No newline at end of file
+ auto e = [] -> int { return 0; };
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp
index 769ffad629d03..e28da89a8ad6f 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp
@@ -16,4 +16,4 @@ int main() {
// Should NOT warn - has specifiers
auto d = []<class T>() mutable { return sizeof(T); };
auto e = []<class T>() noexcept { return sizeof(T); };
-}
\ No newline at end of file
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp
index 4a9378564c149..21a6e90508530 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp
@@ -38,4 +38,4 @@ int main() {
#define LAMBDA []() { return 42; }
auto i = LAMBDA;
#undef LAMBDA
-}
\ No newline at end of file
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
index e04dca093dba5..2e7fe14f5da29 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
@@ -35,4 +35,4 @@ int main() {
#define LAMBDA []() { return 42; }
auto k = LAMBDA;
#undef LAMBDA
-}
\ No newline at end of file
+}
>From 4063ef5569b7996c0e4c4cf626793a4b9d5ad624 Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Sat, 4 Apr 2026 04:33:58 +0300
Subject: [PATCH 03/20] [clang-tidy] Remove unnecessary includes
---
.../clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
index 275eba3448d4c..90b1237cf5987 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
@@ -7,8 +7,6 @@
//===----------------------------------------------------------------------===//
#include "RedundantLambdaParenthesesCheck.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
>From 53d2c84879d8ae09c0b14f1d348be56a7f5ccff5 Mon Sep 17 00:00:00 2001
From: Kryptonite <oalazizi75 at gmail.com>
Date: Sat, 4 Apr 2026 07:47:48 +0300
Subject: [PATCH 04/20] "[clang-tidy] Sync release notes with check
documentation
---
clang-tools-extra/docs/ReleaseNotes.rst | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 4265710225b56..24d4ad2abe64d 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -166,8 +166,7 @@ New checks
- New :doc:`readability-redundant-lambda-parentheses
<clang-tidy/checks/readability/redundant-lambda-parentheses>` check.
- Finds and removes redundant empty parameter lists from lambda expressions
- when the rewrite is valid for the active language standard.
+ 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.
>From 15cea8ad210f838eaf0da36ec0248f0536ff92b6 Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Sat, 4 Apr 2026 19:08:59 +0300
Subject: [PATCH 05/20] [clang-tidy] Address review: move checks into matchers
and add TK_IgnoreUnlessSpelledInSource
---
.../RedundantLambdaParenthesesCheck.cpp | 59 +++++++++++--------
.../RedundantLambdaParenthesesCheck.h | 5 ++
2 files changed, 41 insertions(+), 23 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
index 90b1237cf5987..9241352e09cf4 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
@@ -7,43 +7,56 @@
//===----------------------------------------------------------------------===//
#include "RedundantLambdaParenthesesCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
+namespace {
+
+AST_MATCHER(clang::LambdaExpr, hasNoParameters) {
+ return Node.getCallOperator()->getNumParams() == 0;
+}
+
+AST_MATCHER(clang::LambdaExpr, hasExplicitOrGenericParameters) {
+ return Node.hasExplicitParameters() || Node.isGenericLambda();
+}
+
+AST_MATCHER(clang::LambdaExpr, isGenericLambdaInCxx20OrLater) {
+ return !Node.isGenericLambda() ||
+ Finder->getASTContext().getLangOpts().CPlusPlus20;
+}
+
+} // namespace
+
namespace clang::tidy::readability {
void RedundantLambdaParenthesesCheck::registerMatchers(MatchFinder *Finder) {
- Finder->addMatcher(lambdaExpr().bind("lambda"), this);
+ Finder->addMatcher(
+ lambdaExpr(hasExplicitOrGenericParameters(), hasNoParameters(),
+ isGenericLambdaInCxx20OrLater())
+ .bind("lambda"),
+ this);
}
void RedundantLambdaParenthesesCheck::check(
const MatchFinder::MatchResult &Result) {
const auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda");
- if (Lambda->getBeginLoc().isMacroID())
- return;
-
- if (!Lambda->hasExplicitParameters() && !Lambda->isGenericLambda())
- return;
- if (Lambda->getCallOperator()->getNumParams() != 0)
- return;
-
- if (Lambda->isGenericLambda() && !getLangOpts().CPlusPlus20)
+ if (Lambda->getBeginLoc().isMacroID())
return;
const LangOptions &LangOpts = getLangOpts();
- SourceLocation ScanFrom;
- if (Lambda->isGenericLambda()) {
- TemplateParameterList *TPL = Lambda->getTemplateParameterList();
- ScanFrom = Lexer::getLocForEndOfToken(TPL->getRAngleLoc(), 0,
- *Result.SourceManager, LangOpts);
- } else {
- ScanFrom = Lexer::getLocForEndOfToken(Lambda->getIntroducerRange().getEnd(),
- 0, *Result.SourceManager, LangOpts);
- }
+ const SourceLocation ScanFrom =
+ Lambda->isGenericLambda()
+ ? Lexer::getLocForEndOfToken(
+ Lambda->getTemplateParameterList()->getRAngleLoc(), 0,
+ *Result.SourceManager, LangOpts)
+ : Lexer::getLocForEndOfToken(
+ Lambda->getIntroducerRange().getEnd(), 0,
+ *Result.SourceManager, LangOpts);
Token Tok;
if (Lexer::getRawToken(ScanFrom, Tok, *Result.SourceManager, LangOpts,
@@ -53,8 +66,8 @@ void RedundantLambdaParenthesesCheck::check(
if (Tok.isNot(tok::l_paren))
return;
- SourceLocation LParenLoc = Tok.getLocation();
- SourceLocation RParenLoc = Lexer::findLocationAfterToken(
+ const SourceLocation LParenLoc = Tok.getLocation();
+ const SourceLocation RParenLoc = Lexer::findLocationAfterToken(
LParenLoc, tok::r_paren, *Result.SourceManager, LangOpts,
/*SkipTrailingWhitespaceAndNewLine=*/false);
@@ -78,11 +91,11 @@ void RedundantLambdaParenthesesCheck::check(
return;
}
- CharSourceRange ParenRange =
+ const CharSourceRange ParenRange =
CharSourceRange::getCharRange(LParenLoc, RParenLoc);
diag(LParenLoc, "redundant empty parameter list in lambda expression")
<< FixItHint::CreateRemoval(ParenRange);
}
-} // namespace clang::tidy::readability
+} // namespace clang::tidy::readability
\ No newline at end of file
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.h b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.h
index 3437d703da1f4..0dfce17ccf13e 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.h
@@ -22,6 +22,11 @@ class RedundantLambdaParenthesesCheck : public ClangTidyCheck {
public:
RedundantLambdaParenthesesCheck(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 {
>From 8e51535597355e3967f413e38ecd66d8952be745 Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Sat, 4 Apr 2026 19:17:13 +0300
Subject: [PATCH 06/20] Add newline to the end of the file
---
.../clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
index 9241352e09cf4..938ca06226353 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
@@ -98,4 +98,4 @@ void RedundantLambdaParenthesesCheck::check(
<< FixItHint::CreateRemoval(ParenRange);
}
-} // namespace clang::tidy::readability
\ No newline at end of file
+} // namespace clang::tidy::readability
>From 61fda54dc25d59472c7d23dd91045f6b8c4e7e37 Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Sat, 4 Apr 2026 19:42:04 +0300
Subject: [PATCH 07/20] [clang-tidy] Fix clang-format issues
---
.../RedundantLambdaParenthesesCheck.cpp | 16 +++++++---------
.../RedundantLambdaParenthesesCheck.h | 2 +-
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
index 938ca06226353..45f861a5e21d6 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
@@ -32,18 +32,17 @@ AST_MATCHER(clang::LambdaExpr, isGenericLambdaInCxx20OrLater) {
namespace clang::tidy::readability {
void RedundantLambdaParenthesesCheck::registerMatchers(MatchFinder *Finder) {
- Finder->addMatcher(
- lambdaExpr(hasExplicitOrGenericParameters(), hasNoParameters(),
- isGenericLambdaInCxx20OrLater())
- .bind("lambda"),
- this);
+ Finder->addMatcher(lambdaExpr(hasExplicitOrGenericParameters(),
+ hasNoParameters(),
+ isGenericLambdaInCxx20OrLater())
+ .bind("lambda"),
+ this);
}
void RedundantLambdaParenthesesCheck::check(
const MatchFinder::MatchResult &Result) {
const auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda");
-
if (Lambda->getBeginLoc().isMacroID())
return;
@@ -54,9 +53,8 @@ void RedundantLambdaParenthesesCheck::check(
? Lexer::getLocForEndOfToken(
Lambda->getTemplateParameterList()->getRAngleLoc(), 0,
*Result.SourceManager, LangOpts)
- : Lexer::getLocForEndOfToken(
- Lambda->getIntroducerRange().getEnd(), 0,
- *Result.SourceManager, LangOpts);
+ : Lexer::getLocForEndOfToken(Lambda->getIntroducerRange().getEnd(), 0,
+ *Result.SourceManager, LangOpts);
Token Tok;
if (Lexer::getRawToken(ScanFrom, Tok, *Result.SourceManager, LangOpts,
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.h b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.h
index 0dfce17ccf13e..2f2a716de70cf 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.h
@@ -22,7 +22,7 @@ class RedundantLambdaParenthesesCheck : public ClangTidyCheck {
public:
RedundantLambdaParenthesesCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
-
+
std::optional<TraversalKind> getCheckTraversalKind() const override {
return TK_IgnoreUnlessSpelledInSource;
}
>From 8a0f91c3b01fe50ed27a94f8bceeae92e1b3ee41 Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Sat, 4 Apr 2026 23:59:53 +0300
Subject: [PATCH 08/20] [clang-tidy] Address review: use FunctionTypeLoc, move
matchers, remove unnecessary regex
---
.../RedundantLambdaParenthesesCheck.cpp | 36 +++++--------------
.../redundant-lambda-parentheses-cxx20.cpp | 4 +--
.../redundant-lambda-parentheses-cxx23.cpp | 14 ++++----
.../redundant-lambda-parentheses.cpp | 8 ++---
4 files changed, 22 insertions(+), 40 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
index 45f861a5e21d6..80b5316c77702 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
@@ -7,30 +7,29 @@
//===----------------------------------------------------------------------===//
#include "RedundantLambdaParenthesesCheck.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
+namespace clang::tidy::readability {
+
namespace {
-AST_MATCHER(clang::LambdaExpr, hasNoParameters) {
+AST_MATCHER(LambdaExpr, hasNoParameters) {
return Node.getCallOperator()->getNumParams() == 0;
}
-AST_MATCHER(clang::LambdaExpr, hasExplicitOrGenericParameters) {
+AST_MATCHER(LambdaExpr, hasExplicitOrGenericParameters) {
return Node.hasExplicitParameters() || Node.isGenericLambda();
}
-AST_MATCHER(clang::LambdaExpr, isGenericLambdaInCxx20OrLater) {
+AST_MATCHER(LambdaExpr, isGenericLambdaInCxx20OrLater) {
return !Node.isGenericLambda() ||
Finder->getASTContext().getLangOpts().CPlusPlus20;
}
} // namespace
-namespace clang::tidy::readability {
-
void RedundantLambdaParenthesesCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(lambdaExpr(hasExplicitOrGenericParameters(),
hasNoParameters(),
@@ -48,26 +47,9 @@ void RedundantLambdaParenthesesCheck::check(
const LangOptions &LangOpts = getLangOpts();
- const SourceLocation ScanFrom =
- Lambda->isGenericLambda()
- ? Lexer::getLocForEndOfToken(
- Lambda->getTemplateParameterList()->getRAngleLoc(), 0,
- *Result.SourceManager, LangOpts)
- : Lexer::getLocForEndOfToken(Lambda->getIntroducerRange().getEnd(), 0,
- *Result.SourceManager, LangOpts);
-
- Token Tok;
- if (Lexer::getRawToken(ScanFrom, Tok, *Result.SourceManager, LangOpts,
- /*IgnoreWhiteSpace=*/true))
- return;
-
- if (Tok.isNot(tok::l_paren))
- return;
-
- const SourceLocation LParenLoc = Tok.getLocation();
- const SourceLocation RParenLoc = Lexer::findLocationAfterToken(
- LParenLoc, tok::r_paren, *Result.SourceManager, LangOpts,
- /*SkipTrailingWhitespaceAndNewLine=*/false);
+ const auto FTL = Lambda->getCallOperator()->getFunctionTypeLoc();
+ const SourceLocation LParenLoc = FTL.getLParenLoc();
+ const SourceLocation RParenLoc = FTL.getRParenLoc();
if (LParenLoc.isInvalid() || RParenLoc.isInvalid())
return;
@@ -90,7 +72,7 @@ void RedundantLambdaParenthesesCheck::check(
}
const CharSourceRange ParenRange =
- CharSourceRange::getCharRange(LParenLoc, RParenLoc);
+ CharSourceRange::getCharRange(LParenLoc, Lexer::getLocForEndOfToken(RParenLoc, 0, *Result.SourceManager, LangOpts));
diag(LParenLoc, "redundant empty parameter list in lambda expression")
<< FixItHint::CreateRemoval(ParenRange);
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp
index e28da89a8ad6f..0921741fdb718 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp
@@ -4,11 +4,11 @@ int main() {
// Generic lambdas - should warn in C++20 and later
auto a = []<class T>() { return sizeof(T); };
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: {{^}} auto a = []<class T> { return sizeof(T); };{{$}}
+ // CHECK-FIXES: auto a = []<class T> { return sizeof(T); };
auto b = []<class T>() requires true { return sizeof(T); };
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: {{^}} auto b = []<class T> requires true { return sizeof(T); };{{$}}
+ // CHECK-FIXES: auto b = []<class T> requires true { return sizeof(T); };
// Should NOT warn - has parameters
auto c = []<class T>(T x) { return x; };
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp
index 21a6e90508530..4428d0cb0d257 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp
@@ -4,32 +4,32 @@ int main() {
// Basic cases - should warn
auto a = []() { return 42; };
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: {{^}} auto a = [] { return 42; };{{$}}
+ // CHECK-FIXES: auto a = [] { return 42; };
// Specifier cases - should also warn in C++23
auto b = []() mutable {};
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: {{^}} auto b = [] mutable {};{{$}}
+ // CHECK-FIXES: auto b = [] mutable {};
auto c = []() noexcept {};
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: {{^}} auto c = [] noexcept {};{{$}}
+ // CHECK-FIXES: auto c = [] noexcept {};
auto d = []() -> int { return 0; };
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: {{^}} auto d = [] -> int { return 0; };{{$}}
+ // CHECK-FIXES: auto d = [] -> int { return 0; };
auto e = []() mutable noexcept {};
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: {{^}} auto e = [] mutable noexcept {};{{$}}
+ // CHECK-FIXES: auto e = [] mutable noexcept {};
auto f = []() constexpr { return 42; };
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: {{^}} auto f = [] constexpr { return 42; };{{$}}
+ // CHECK-FIXES: auto f = [] constexpr { return 42; };
auto g = []() consteval { return 42; };
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: {{^}} auto g = [] consteval { return 42; };{{$}}
+ // CHECK-FIXES: auto g = [] consteval { return 42; };
// Should NOT warn - has parameters
auto h = [](int x) { return x; };
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
index 2e7fe14f5da29..02f575edf6ec8 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
@@ -4,22 +4,22 @@ int main() {
// Basic cases - should warn
auto a = []() { return 42; };
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: {{^}} auto a = [] { return 42; };{{$}}
+ // 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 [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: {{^}} auto b = [x = 1] { return x; };{{$}}
+ // CHECK-FIXES: auto b = [x = 1] { return x; };
// Lambda with no captures
auto c = []() {};
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: {{^}} auto c = [] {};{{$}}
+ // CHECK-FIXES: auto c = [] {};
// Lambda inside a function call
auto v = 1;
auto call = [&v]() { return v; };
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: {{^}} auto call = [&v] { return v; };{{$}}
+ // CHECK-FIXES: auto call = [&v] { return v; };
// Should NOT warn - has parameters
auto d = [](int x) { return x; };
>From 1891ec1ddcdaf95b5269b2c8d0b2ce12d1895bf3 Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Sun, 5 Apr 2026 00:10:16 +0300
Subject: [PATCH 09/20] [clang-tidy] Fix clang-format line wrapping
---
.../readability/RedundantLambdaParenthesesCheck.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
index 80b5316c77702..2b1cb18cd376b 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
@@ -71,8 +71,9 @@ void RedundantLambdaParenthesesCheck::check(
return;
}
- const CharSourceRange ParenRange =
- CharSourceRange::getCharRange(LParenLoc, Lexer::getLocForEndOfToken(RParenLoc, 0, *Result.SourceManager, LangOpts));
+ const CharSourceRange ParenRange = CharSourceRange::getCharRange(
+ LParenLoc, Lexer::getLocForEndOfToken(RParenLoc, 0, *Result.SourceManager,
+ LangOpts));
diag(LParenLoc, "redundant empty parameter list in lambda expression")
<< FixItHint::CreateRemoval(ParenRange);
>From 8fffd05bd0cde5f4f35969d638e94518d1432e58 Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Mon, 6 Apr 2026 01:53:08 +0300
Subject: [PATCH 10/20] [clang-tidy] Address review: use or-later standards and
add guarded specifier cases
---
.../redundant-lambda-parentheses-cxx20.cpp | 10 ++++++----
.../readability/redundant-lambda-parentheses.cpp | 16 ++++++++--------
2 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp
index 0921741fdb718..433a19b681848 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp
@@ -1,19 +1,21 @@
-// RUN: %check_clang_tidy -std=c++20 %s readability-redundant-lambda-parentheses %t
+// RUN: %check_clang_tidy -std=c++20-or-later %s readability-redundant-lambda-parentheses %t
int main() {
// Generic lambdas - should warn in C++20 and later
auto a = []<class T>() { return sizeof(T); };
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto a = []<class T> { return sizeof(T); };
+ // CHECK-FIXES: auto a = []<class T> { return sizeof(T); };
auto b = []<class T>() requires true { return sizeof(T); };
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto b = []<class T> requires true { return sizeof(T); };
+ // CHECK-FIXES: auto b = []<class T> requires true { return sizeof(T); };
// Should NOT warn - has parameters
auto c = []<class T>(T x) { return x; };
- // Should NOT warn - has specifiers
+ // Should NOT warn under C++20 - has specifiers (only valid to remove in C++23+)
+#if __cplusplus < 202302L
auto d = []<class T>() mutable { return sizeof(T); };
auto e = []<class T>() noexcept { return sizeof(T); };
+#endif
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
index 02f575edf6ec8..b5565a5a428fb 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
@@ -1,35 +1,35 @@
-// RUN: %check_clang_tidy -std=c++17 %s readability-redundant-lambda-parentheses %t
+// RUN: %check_clang_tidy -std=c++17-or-later %s readability-redundant-lambda-parentheses %t
int main() {
// Basic cases - should warn
auto a = []() { return 42; };
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto a = [] { return 42; };
+ // 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 [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto b = [x = 1] { return x; };
+ // CHECK-FIXES: auto b = [x = 1] { return x; };
- // Lambda with no captures
auto c = []() {};
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto c = [] {};
+ // CHECK-FIXES: auto c = [] {};
- // Lambda inside a function call
auto v = 1;
auto call = [&v]() { return v; };
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto call = [&v] { return v; };
+ // CHECK-FIXES: auto call = [&v] { return v; };
// Should NOT warn - has parameters
auto d = [](int x) { return x; };
auto e = [](int x, int y) { return x + y; };
- // Should NOT warn - has specifiers, needs C++23
+ // Should NOT warn under C++17/20 - has specifiers (only valid to remove in C++23+)
+#if __cplusplus < 202302L
auto f = []() mutable {};
auto g = []() noexcept {};
auto h = []() -> int { return 0; };
auto i = []() constexpr { return 42; };
+#endif
// Should NOT warn - macro
#define LAMBDA []() { return 42; }
>From a2626b47f1feb20265d8ef2936c507a09ea1abe8 Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Mon, 6 Apr 2026 15:29:47 +0300
Subject: [PATCH 11/20] [clang-tidy] Address review: merge test files into
single file with check-suffixes
---
.../RedundantLambdaParenthesesCheck.cpp | 28 +++-------
.../redundant-lambda-parentheses-cxx20.cpp | 21 -------
.../redundant-lambda-parentheses-cxx23.cpp | 41 --------------
.../redundant-lambda-parentheses.cpp | 56 +++++++++++++++----
4 files changed, 53 insertions(+), 93 deletions(-)
delete mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp
delete mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
index 2b1cb18cd376b..7ed77276e2043 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
@@ -15,27 +15,17 @@ namespace clang::tidy::readability {
namespace {
-AST_MATCHER(LambdaExpr, hasNoParameters) {
- return Node.getCallOperator()->getNumParams() == 0;
-}
-
-AST_MATCHER(LambdaExpr, hasExplicitOrGenericParameters) {
- return Node.hasExplicitParameters() || Node.isGenericLambda();
-}
-
-AST_MATCHER(LambdaExpr, isGenericLambdaInCxx20OrLater) {
- return !Node.isGenericLambda() ||
- Finder->getASTContext().getLangOpts().CPlusPlus20;
+AST_MATCHER(LambdaExpr, hasRedundantParens) {
+ return (Node.hasExplicitParameters() || Node.isGenericLambda()) &&
+ Node.getCallOperator()->getNumParams() == 0 &&
+ (!Node.isGenericLambda() ||
+ Finder->getASTContext().getLangOpts().CPlusPlus20);
}
} // namespace
void RedundantLambdaParenthesesCheck::registerMatchers(MatchFinder *Finder) {
- Finder->addMatcher(lambdaExpr(hasExplicitOrGenericParameters(),
- hasNoParameters(),
- isGenericLambdaInCxx20OrLater())
- .bind("lambda"),
- this);
+ Finder->addMatcher(lambdaExpr(hasRedundantParens()).bind("lambda"), this);
}
void RedundantLambdaParenthesesCheck::check(
@@ -71,12 +61,8 @@ void RedundantLambdaParenthesesCheck::check(
return;
}
- const CharSourceRange ParenRange = CharSourceRange::getCharRange(
- LParenLoc, Lexer::getLocForEndOfToken(RParenLoc, 0, *Result.SourceManager,
- LangOpts));
-
diag(LParenLoc, "redundant empty parameter list in lambda expression")
- << FixItHint::CreateRemoval(ParenRange);
+ << FixItHint::CreateRemoval({LParenLoc, RParenLoc});
}
} // namespace clang::tidy::readability
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp
deleted file mode 100644
index 433a19b681848..0000000000000
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx20.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-// RUN: %check_clang_tidy -std=c++20-or-later %s readability-redundant-lambda-parentheses %t
-
-int main() {
- // Generic lambdas - should warn in C++20 and later
- auto a = []<class T>() { return sizeof(T); };
- // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto a = []<class T> { return sizeof(T); };
-
- auto b = []<class T>() requires true { return sizeof(T); };
- // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto b = []<class T> requires true { return sizeof(T); };
-
- // Should NOT warn - has parameters
- auto c = []<class T>(T x) { return x; };
-
- // Should NOT warn under C++20 - has specifiers (only valid to remove in C++23+)
-#if __cplusplus < 202302L
- auto d = []<class T>() mutable { return sizeof(T); };
- auto e = []<class T>() noexcept { return sizeof(T); };
-#endif
-}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp
deleted file mode 100644
index 4428d0cb0d257..0000000000000
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses-cxx23.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-// RUN: %check_clang_tidy -std=c++23 %s readability-redundant-lambda-parentheses %t
-
-int main() {
- // Basic cases - should warn
- auto a = []() { return 42; };
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto a = [] { return 42; };
-
- // Specifier cases - should also warn in C++23
- auto b = []() mutable {};
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto b = [] mutable {};
-
- auto c = []() noexcept {};
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto c = [] noexcept {};
-
- auto d = []() -> int { return 0; };
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto d = [] -> int { return 0; };
-
- auto e = []() mutable noexcept {};
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto e = [] mutable noexcept {};
-
- auto f = []() constexpr { return 42; };
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto f = [] constexpr { return 42; };
-
- auto g = []() consteval { return 42; };
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto g = [] consteval { return 42; };
-
- // Should NOT warn - has parameters
- auto h = [](int x) { return x; };
-
- // Should NOT warn - macro
-#define LAMBDA []() { return 42; }
- auto i = LAMBDA;
-#undef LAMBDA
-}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
index b5565a5a428fb..a823eca8113ca 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
@@ -1,7 +1,9 @@
-// RUN: %check_clang_tidy -std=c++17-or-later %s readability-redundant-lambda-parentheses %t
+// RUN: %check_clang_tidy -std=c++11,c++14,c++17 %s readability-redundant-lambda-parentheses %t
+// RUN: %check_clang_tidy -std=c++20 -check-suffixes=,CXX20 %s readability-redundant-lambda-parentheses %t
+// RUN: %check_clang_tidy -std=c++23-or-later -check-suffixes=,CXX20,CXX23 %s readability-redundant-lambda-parentheses %t
int main() {
- // Basic cases - should warn
+ // Basic cases - warn in all standards
auto a = []() { return 42; };
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
// CHECK-FIXES: auto a = [] { return 42; };
@@ -23,16 +25,50 @@ int main() {
auto d = [](int x) { return x; };
auto e = [](int x, int y) { return x + y; };
- // Should NOT warn under C++17/20 - has specifiers (only valid to remove in C++23+)
-#if __cplusplus < 202302L
- auto f = []() mutable {};
- auto g = []() noexcept {};
- auto h = []() -> int { return 0; };
- auto i = []() constexpr { return 42; };
-#endif
-
// Should NOT warn - macro
#define LAMBDA []() { return 42; }
auto k = LAMBDA;
#undef LAMBDA
+
+ // Generic lambda - warns in C++20 and later
+#if __cplusplus >= 202002L
+ auto f = []<class T>() { return sizeof(T); };
+ // CHECK-MESSAGES-CXX20: :[[@LINE-1]]:23: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES-CXX20: auto f = []<class T> { return sizeof(T); };
+
+ auto g = []<class T>() requires true { return sizeof(T); };
+ // CHECK-MESSAGES-CXX20: :[[@LINE-1]]:23: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES-CXX20: auto g = []<class T> requires true { return sizeof(T); };
+
+ // Should NOT warn - has parameters
+ auto h = []<class T>(T x) { return x; };
+#endif
+
+ // Specifier cases - warn only in C++23, valid syntax in all standards
+ auto i = []() mutable {};
+ // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES-CXX23: auto i = [] mutable {};
+
+ auto j = []() noexcept {};
+ // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES-CXX23: auto n = [] constexpr { return 42; };
+
+ // consteval only valid in C++20+
+#if __cplusplus >= 202002L
+ auto o = []() consteval { return 42; };
+ // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES-CXX23: auto o = [] consteval { return 42; };
+#endif
}
>From 8f246ffd80382a5e5580b7c262a46e6b58633f4b Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Tue, 7 Apr 2026 22:03:28 +0300
Subject: [PATCH 12/20] [clang-tidy] Address review: simplify matcher, add
attribute and requires guards, update tests
---
.../RedundantLambdaParenthesesCheck.cpp | 23 +++++++++++--------
.../redundant-lambda-parentheses.cpp | 20 +++++++++++++---
2 files changed, 30 insertions(+), 13 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
index 7ed77276e2043..80eb0e5a7c091 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
@@ -16,10 +16,8 @@ namespace clang::tidy::readability {
namespace {
AST_MATCHER(LambdaExpr, hasRedundantParens) {
- return (Node.hasExplicitParameters() || Node.isGenericLambda()) &&
- Node.getCallOperator()->getNumParams() == 0 &&
- (!Node.isGenericLambda() ||
- Finder->getASTContext().getLangOpts().CPlusPlus20);
+ return Node.hasExplicitParameters() &&
+ Node.getCallOperator()->getNumParams() == 0;
}
} // namespace
@@ -44,13 +42,18 @@ void RedundantLambdaParenthesesCheck::check(
if (LParenLoc.isInvalid() || RParenLoc.isInvalid())
return;
+ std::optional<Token> NextTok =
+ Lexer::findNextToken(RParenLoc, *Result.SourceManager, LangOpts);
+
+ // Attributes after '()' have different semantics depending on position.
+ if (NextTok && NextTok->is(tok::l_square))
+ return;
+
+ // requires clause after '()' means parens cannot be removed.
+ if (Lambda->getCallOperator()->getTrailingRequiresClause())
+ return;
+
if (!LangOpts.CPlusPlus23) {
- std::optional<Token> RParen =
- Lexer::findNextToken(LParenLoc, *Result.SourceManager, LangOpts);
- if (!RParen || RParen->isNot(tok::r_paren))
- return;
- std::optional<Token> NextTok = Lexer::findNextToken(
- RParen->getLocation(), *Result.SourceManager, LangOpts);
if (NextTok && NextTok->is(tok::raw_identifier)) {
StringRef Id = NextTok->getRawIdentifier();
if (Id == "constexpr" || Id == "consteval" || Id == "mutable" ||
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
index a823eca8113ca..e7919d6e4d29c 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
@@ -2,6 +2,21 @@
// RUN: %check_clang_tidy -std=c++20 -check-suffixes=,CXX20 %s readability-redundant-lambda-parentheses %t
// RUN: %check_clang_tidy -std=c++23-or-later -check-suffixes=,CXX20,CXX23 %s readability-redundant-lambda-parentheses %t
+#if __cplusplus >= 202002L
+template <bool B>
+void testRequires() {
+ // Should NOT warn - requires clause after parens
+ auto f1 = []() requires B {};
+ auto f2 = []() noexcept requires B {};
+ auto f3 = []<typename T>() requires B {};
+
+ // Should warn - requires clause is before parens, parens are removable
+ auto f4 = []<typename T> requires B () {};
+ // CHECK-MESSAGES-CXX20: :[[@LINE-1]]:39: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES-CXX20: auto f4 = []<typename T> requires B {};
+}
+#endif
+
int main() {
// Basic cases - warn in all standards
auto a = []() { return 42; };
@@ -36,9 +51,8 @@ int main() {
// CHECK-MESSAGES-CXX20: :[[@LINE-1]]:23: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
// CHECK-FIXES-CXX20: auto f = []<class T> { return sizeof(T); };
- auto g = []<class T>() requires true { return sizeof(T); };
- // CHECK-MESSAGES-CXX20: :[[@LINE-1]]:23: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES-CXX20: auto g = []<class T> requires true { return sizeof(T); };
+ // Should NOT warn - requires clause after parens
+ auto g = []<class T>() requires (sizeof(T) > 0) {};
// Should NOT warn - has parameters
auto h = []<class T>(T x) { return x; };
>From b0a4c3e544b67802047a62a12ed4e6bba3f3ade6 Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Wed, 8 Apr 2026 02:08:10 +0300
Subject: [PATCH 13/20] [clang-tidy] Address review: add tests with empty
attributes
---
.../checkers/readability/redundant-lambda-parentheses.cpp | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
index e7919d6e4d29c..673e7a79c4874 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
@@ -85,4 +85,12 @@ int main() {
// CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
// CHECK-FIXES-CXX23: auto o = [] consteval { return 42; };
#endif
+
+ // Should NOT warn - attribute after parens
+ auto p = []() [[]] {};
+
+ // Should warn - attribute before parens
+ auto q = [] [[]] () {};
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: auto q = [] {{\[\[}}{{\]\]}} {};
}
>From 50c9b4d7dd60fe4382f33b67f344925649ee2ccb Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Wed, 8 Apr 2026 02:13:39 +0300
Subject: [PATCH 14/20] [clang-tidy] Add more attribute test cases with empty
attributes
---
.../checkers/readability/redundant-lambda-parentheses.cpp | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
index 673e7a79c4874..d923deb56c51d 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
@@ -93,4 +93,11 @@ int main() {
auto q = [] [[]] () {};
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
// CHECK-FIXES: auto q = [] {{\[\[}}{{\]\]}} {};
+
+ // Should NOT warn - attribute both before and after parens
+ auto r = [] [[]] () [[]] {};
+
+ auto s = []() noexcept [[]] {};
+ // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES-CXX23: auto s = [] noexcept {{\[\[}}{{\]\]}} {};
}
>From 389cd1a959ff0d7347f1bba2895d597b2dfac82e Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Wed, 8 Apr 2026 18:38:53 +0300
Subject: [PATCH 15/20] [clang-tidy] Address review: refactoring and moving
tests
---
.../RedundantLambdaParenthesesCheck.cpp | 19 +++++-------
.../redundant-lambda-parentheses.cpp | 29 ++++++++++---------
2 files changed, 22 insertions(+), 26 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
index 80eb0e5a7c091..dc554a1eba17d 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
@@ -42,27 +42,22 @@ void RedundantLambdaParenthesesCheck::check(
if (LParenLoc.isInvalid() || RParenLoc.isInvalid())
return;
- std::optional<Token> NextTok =
+ const std::optional<Token> NextTok =
Lexer::findNextToken(RParenLoc, *Result.SourceManager, LangOpts);
+ if (!NextTok)
+ return;
+
// Attributes after '()' have different semantics depending on position.
- if (NextTok && NextTok->is(tok::l_square))
+ if (NextTok->is(tok::l_square))
return;
// requires clause after '()' means parens cannot be removed.
if (Lambda->getCallOperator()->getTrailingRequiresClause())
return;
- if (!LangOpts.CPlusPlus23) {
- if (NextTok && NextTok->is(tok::raw_identifier)) {
- StringRef Id = NextTok->getRawIdentifier();
- if (Id == "constexpr" || Id == "consteval" || Id == "mutable" ||
- Id == "noexcept")
- return;
- }
- if (NextTok && NextTok->is(tok::arrow))
- return;
- }
+ if (!LangOpts.CPlusPlus23 && NextTok->isNot(tok::l_brace))
+ return;
diag(LParenLoc, "redundant empty parameter list in lambda expression")
<< FixItHint::CreateRemoval({LParenLoc, RParenLoc});
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
index d923deb56c51d..dce347e1836d8 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
@@ -2,20 +2,6 @@
// RUN: %check_clang_tidy -std=c++20 -check-suffixes=,CXX20 %s readability-redundant-lambda-parentheses %t
// RUN: %check_clang_tidy -std=c++23-or-later -check-suffixes=,CXX20,CXX23 %s readability-redundant-lambda-parentheses %t
-#if __cplusplus >= 202002L
-template <bool B>
-void testRequires() {
- // Should NOT warn - requires clause after parens
- auto f1 = []() requires B {};
- auto f2 = []() noexcept requires B {};
- auto f3 = []<typename T>() requires B {};
-
- // Should warn - requires clause is before parens, parens are removable
- auto f4 = []<typename T> requires B () {};
- // CHECK-MESSAGES-CXX20: :[[@LINE-1]]:39: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES-CXX20: auto f4 = []<typename T> requires B {};
-}
-#endif
int main() {
// Basic cases - warn in all standards
@@ -101,3 +87,18 @@ int main() {
// CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
// CHECK-FIXES-CXX23: auto s = [] noexcept {{\[\[}}{{\]\]}} {};
}
+
+#if __cplusplus >= 202002L
+template <bool B>
+void testRequires() {
+ // Should NOT warn - requires clause after parens
+ auto f1 = []() requires B {};
+ auto f2 = []() noexcept requires B {};
+ auto f3 = []<typename T>() requires B {};
+
+ // Should warn - requires clause is before parens, parens are removable
+ auto f4 = []<typename T> requires B () {};
+ // CHECK-MESSAGES-CXX20: :[[@LINE-1]]:39: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES-CXX20: auto f4 = []<typename T> requires B {};
+}
+#endif
>From 008c307f11d2865f2ca19ea55a51852a8491c877 Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Wed, 8 Apr 2026 23:52:44 +0300
Subject: [PATCH 16/20] [clang-tidy] Add comment test cases and address
remaining review feedback
---
.../readability/redundant-lambda-parentheses.cpp | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
index dce347e1836d8..9b7f2d709d2ab 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
@@ -86,6 +86,22 @@ int main() {
auto s = []() noexcept [[]] {};
// CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
// CHECK-FIXES-CXX23: auto s = [] noexcept {{\[\[}}{{\]\]}} {};
+
+ auto t = []( /* comment */ ) { return 42; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: auto t = [] { return 42; };
+
+ auto u = []() /* comment */ { return 42; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: auto w = [] { return 42; };
+
+ auto x = [] /* comment */ () { return 42; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-FIXES: auto x = [] /* comment */ { return 42; };
}
#if __cplusplus >= 202002L
>From f5a10a25d37496a270dd1f0a9bba1c0aecaa229a Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Thu, 9 Apr 2026 00:12:06 +0300
Subject: [PATCH 17/20] [clang-tidy] Preserve comments when removing parens
---
.../readability/RedundantLambdaParenthesesCheck.cpp | 3 ++-
.../checkers/readability/redundant-lambda-parentheses.cpp | 4 ++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
index dc554a1eba17d..2b637169ed47c 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
@@ -60,7 +60,8 @@ void RedundantLambdaParenthesesCheck::check(
return;
diag(LParenLoc, "redundant empty parameter list in lambda expression")
- << FixItHint::CreateRemoval({LParenLoc, RParenLoc});
+ << FixItHint::CreateRemoval(LParenLoc)
+ << FixItHint::CreateRemoval(RParenLoc);
}
} // namespace clang::tidy::readability
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
index 9b7f2d709d2ab..b7225a86539a1 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
@@ -89,7 +89,7 @@ int main() {
auto t = []( /* comment */ ) { return 42; };
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto t = [] { return 42; };
+ // 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 [readability-redundant-lambda-parentheses]
@@ -97,7 +97,7 @@ int main() {
auto w = [](/* comment */) { return 42; };
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
- // CHECK-FIXES: auto w = [] { return 42; };
+ // 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 [readability-redundant-lambda-parentheses]
>From 079925419726ae36b98ed8ca388f716145fd77f2 Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Thu, 9 Apr 2026 02:00:08 +0300
Subject: [PATCH 18/20] [clang-tidy] Add void, and macro tests, fix broken
fix-it for non-empty parens
---
.../RedundantLambdaParenthesesCheck.cpp | 13 ++++++-----
.../redundant-lambda-parentheses.cpp | 22 +++++++++++++++++++
2 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
index 2b637169ed47c..6746e0e7e1bfe 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
@@ -17,7 +17,8 @@ namespace {
AST_MATCHER(LambdaExpr, hasRedundantParens) {
return Node.hasExplicitParameters() &&
- Node.getCallOperator()->getNumParams() == 0;
+ Node.getCallOperator()->getNumParams() == 0 &&
+ !Node.getCallOperator()->getTrailingRequiresClause();
}
} // namespace
@@ -42,6 +43,12 @@ void RedundantLambdaParenthesesCheck::check(
if (LParenLoc.isInvalid() || RParenLoc.isInvalid())
return;
+ // Ensure parens are truly empty (reject "(void)")
+ const std::optional<Token> FirstInParens =
+ Lexer::findNextToken(LParenLoc, *Result.SourceManager, LangOpts);
+ if (!FirstInParens || FirstInParens->getLocation() != RParenLoc)
+ return;
+
const std::optional<Token> NextTok =
Lexer::findNextToken(RParenLoc, *Result.SourceManager, LangOpts);
@@ -52,10 +59,6 @@ void RedundantLambdaParenthesesCheck::check(
if (NextTok->is(tok::l_square))
return;
- // requires clause after '()' means parens cannot be removed.
- if (Lambda->getCallOperator()->getTrailingRequiresClause())
- return;
-
if (!LangOpts.CPlusPlus23 && NextTok->isNot(tok::l_brace))
return;
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
index b7225a86539a1..1c916b2713ccc 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
@@ -102,6 +102,28 @@ int main() {
auto x = [] /* comment */ () { return 42; };
// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
// CHECK-FIXES: auto x = [] /* comment */ { return 42; };
+
+ // Should NOT warn - (void) is not truly empty parens
+ auto void1 = [](void) {};
+ auto void2 = [] (void) {};
+
+ // Should NOT warn - macro between parens
+#define EMPTY
+#define VOID void
+ auto macro1 = [](EMPTY) {};
+ auto macro2 = [](VOID) {};
+#undef EMPTY
+#undef VOID
+
+// Should NOT warn - macro for parens themselves
+#define LPAREN (
+#define RPAREN )
+#define PARENS ()
+ auto macro3 = []LPAREN RPAREN {};
+ auto macro4 = []PARENS {};
+#undef LPAREN
+#undef RPAREN
+#undef PARENS
}
#if __cplusplus >= 202002L
>From efcddaf64b6b0c6d59201d4e04f2b76447db6abe Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Fri, 10 Apr 2026 00:00:05 +0300
Subject: [PATCH 19/20] [clang-tidy] Address review and rename check to
readability-redundant-lambda-parameter-list
---
.../clang-tidy/readability/CMakeLists.txt | 2 +-
.../readability/ReadabilityTidyModule.cpp | 6 +-
... => RedundantLambdaParameterListCheck.cpp} | 30 +++++-----
....h => RedundantLambdaParameterListCheck.h} | 12 ++--
clang-tools-extra/docs/ReleaseNotes.rst | 4 +-
.../docs/clang-tidy/checks/list.rst | 4 +-
...st => redundant-lambda-parameter-list.rst} | 6 +-
...pp => redundant-lambda-parameter-list.cpp} | 58 +++++++------------
8 files changed, 50 insertions(+), 72 deletions(-)
rename clang-tools-extra/clang-tidy/readability/{RedundantLambdaParenthesesCheck.cpp => RedundantLambdaParameterListCheck.cpp} (68%)
rename clang-tools-extra/clang-tidy/readability/{RedundantLambdaParenthesesCheck.h => RedundantLambdaParameterListCheck.h} (83%)
rename clang-tools-extra/docs/clang-tidy/checks/readability/{redundant-lambda-parentheses.rst => redundant-lambda-parameter-list.rst} (84%)
rename clang-tools-extra/test/clang-tidy/checkers/readability/{redundant-lambda-parentheses.cpp => redundant-lambda-parameter-list.cpp} (62%)
diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
index 3702600e0496c..0dfdbe69c880d 100644
--- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -44,7 +44,7 @@ add_clang_library(clangTidyReadabilityModule STATIC
RedundantControlFlowCheck.cpp
RedundantDeclarationCheck.cpp
RedundantFunctionPtrDereferenceCheck.cpp
- RedundantLambdaParenthesesCheck.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 6bfeb6c548f48..86e4f4dcc1de1 100644
--- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -46,7 +46,7 @@
#include "RedundantDeclarationCheck.h"
#include "RedundantFunctionPtrDereferenceCheck.h"
#include "RedundantInlineSpecifierCheck.h"
-#include "RedundantLambdaParenthesesCheck.h"
+#include "RedundantLambdaParameterListCheck.h"
#include "RedundantMemberInitCheck.h"
#include "RedundantParenthesesCheck.h"
#include "RedundantPreprocessorCheck.h"
@@ -144,8 +144,8 @@ class ReadabilityModule : public ClangTidyModule {
"readability-redundant-casting");
CheckFactories.registerCheck<RedundantFunctionPtrDereferenceCheck>(
"readability-redundant-function-ptr-dereference");
- CheckFactories.registerCheck<RedundantLambdaParenthesesCheck>(
- "readability-redundant-lambda-parentheses");
+ 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/RedundantLambdaParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParameterListCheck.cpp
similarity index 68%
rename from clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
rename to clang-tools-extra/clang-tidy/readability/RedundantLambdaParameterListCheck.cpp
index 6746e0e7e1bfe..1b12a199c1fdb 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParameterListCheck.cpp
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "RedundantLambdaParenthesesCheck.h"
-#include "clang/Lex/Lexer.h"
+#include "RedundantLambdaParameterListCheck.h"
+#include "../utils/LexerUtils.h"
using namespace clang::ast_matchers;
@@ -23,20 +23,17 @@ AST_MATCHER(LambdaExpr, hasRedundantParens) {
} // namespace
-void RedundantLambdaParenthesesCheck::registerMatchers(MatchFinder *Finder) {
+void RedundantLambdaParameterListCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(lambdaExpr(hasRedundantParens()).bind("lambda"), this);
}
-void RedundantLambdaParenthesesCheck::check(
+void RedundantLambdaParameterListCheck::check(
const MatchFinder::MatchResult &Result) {
const auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda");
- if (Lambda->getBeginLoc().isMacroID())
- return;
-
const LangOptions &LangOpts = getLangOpts();
- const auto FTL = Lambda->getCallOperator()->getFunctionTypeLoc();
+ const FunctionTypeLoc FTL = Lambda->getCallOperator()->getFunctionTypeLoc();
const SourceLocation LParenLoc = FTL.getLParenLoc();
const SourceLocation RParenLoc = FTL.getRParenLoc();
@@ -45,21 +42,20 @@ void RedundantLambdaParenthesesCheck::check(
// Ensure parens are truly empty (reject "(void)")
const std::optional<Token> FirstInParens =
- Lexer::findNextToken(LParenLoc, *Result.SourceManager, LangOpts);
+ utils::lexer::findNextTokenSkippingComments(
+ LParenLoc, *Result.SourceManager, LangOpts);
+
if (!FirstInParens || FirstInParens->getLocation() != RParenLoc)
return;
- const std::optional<Token> NextTok =
- Lexer::findNextToken(RParenLoc, *Result.SourceManager, LangOpts);
-
- if (!NextTok)
- return;
+ const std::optional<Token> NextAfterParenTok =
+ utils::lexer::findNextTokenSkippingComments(
+ RParenLoc, *Result.SourceManager, LangOpts);
- // Attributes after '()' have different semantics depending on position.
- if (NextTok->is(tok::l_square))
+ if (!NextAfterParenTok || NextAfterParenTok->is(tok::l_square))
return;
- if (!LangOpts.CPlusPlus23 && NextTok->isNot(tok::l_brace))
+ if (!LangOpts.CPlusPlus23 && NextAfterParenTok->isNot(tok::l_brace))
return;
diag(LParenLoc, "redundant empty parameter list in lambda expression")
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.h b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParameterListCheck.h
similarity index 83%
rename from clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.h
rename to clang-tools-extra/clang-tidy/readability/RedundantLambdaParameterListCheck.h
index 2f2a716de70cf..408cfa8ddf7e9 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantLambdaParenthesesCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/RedundantLambdaParameterListCheck.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTLAMBDAPARENTHESESCHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTLAMBDAPARENTHESESCHECK_H
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTLAMBDAPARAMETERLISTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTLAMBDAPARAMETERLISTCHECK_H
#include "../ClangTidyCheck.h"
@@ -17,10 +17,10 @@ namespace clang::tidy::readability {
/// it.
///
/// For the user-facing documentation see:
-/// https://clang.llvm.org/extra/clang-tidy/checks/readability/redundant-lambda-parentheses.html
-class RedundantLambdaParenthesesCheck : public ClangTidyCheck {
+/// https://clang.llvm.org/extra/clang-tidy/checks/readability/redundant-lambda-parameter-list.html
+class RedundantLambdaParameterListCheck : public ClangTidyCheck {
public:
- RedundantLambdaParenthesesCheck(StringRef Name, ClangTidyContext *Context)
+ RedundantLambdaParameterListCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
std::optional<TraversalKind> getCheckTraversalKind() const override {
@@ -36,4 +36,4 @@ class RedundantLambdaParenthesesCheck : public ClangTidyCheck {
} // namespace clang::tidy::readability
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTLAMBDAPARENTHESESCHECK_H
+#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 24d4ad2abe64d..baa1e6965afe4 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -163,8 +163,8 @@ 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-parentheses
- <clang-tidy/checks/readability/redundant-lambda-parentheses>` check.
+- 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.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 864df613a332a..88ced73de2656 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -241,7 +241,6 @@ Clang-Tidy Checks
:doc:`google-runtime-int <google/runtime-int>`,
:doc:`google-runtime-operator <google/runtime-operator>`,
:doc:`google-upgrade-googletest-case <google/upgrade-googletest-case>`, "Yes"
- :doc:`hicpp-exception-baseclass <hicpp/exception-baseclass>`,
:doc:`hicpp-multiway-paths-covered <hicpp/multiway-paths-covered>`,
:doc:`hicpp-signed-bitwise <hicpp/signed-bitwise>`,
:doc:`linuxkernel-must-check-errs <linuxkernel/must-check-errs>`,
@@ -351,7 +350,6 @@ Clang-Tidy Checks
:doc:`openmp-use-default-none <openmp/use-default-none>`,
:doc:`performance-avoid-endl <performance/avoid-endl>`, "Yes"
:doc:`performance-enum-size <performance/enum-size>`,
- :doc:`performance-faster-string-find <performance/faster-string-find>`, "Yes"
:doc:`performance-for-range-copy <performance/for-range-copy>`, "Yes"
:doc:`performance-implicit-conversion-in-loop <performance/implicit-conversion-in-loop>`,
:doc:`performance-inefficient-algorithm <performance/inefficient-algorithm>`, "Yes"
@@ -415,7 +413,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-parentheses <readability/redundant-lambda-parentheses>`, "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-parentheses.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parameter-list.rst
similarity index 84%
rename from clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parentheses.rst
rename to clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parameter-list.rst
index 04b870830bedf..5233be86ceb77 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parentheses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-lambda-parameter-list.rst
@@ -1,7 +1,7 @@
-.. title:: clang-tidy - readability-redundant-lambda-parentheses
+.. title:: clang-tidy - readability-redundant-lambda-parameter-list
-readability-redundant-lambda-parentheses
-========================================
+readability-redundant-lambda-parameter-list
+===========================================
Finds lambda expressions with a redundant empty parameter list and removes it.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parameter-list.cpp
similarity index 62%
rename from clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
rename to clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parameter-list.cpp
index 1c916b2713ccc..d21e5839ca147 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-lambda-parameter-list.cpp
@@ -1,113 +1,100 @@
-// RUN: %check_clang_tidy -std=c++11,c++14,c++17 %s readability-redundant-lambda-parentheses %t
-// RUN: %check_clang_tidy -std=c++20 -check-suffixes=,CXX20 %s readability-redundant-lambda-parentheses %t
-// RUN: %check_clang_tidy -std=c++23-or-later -check-suffixes=,CXX20,CXX23 %s readability-redundant-lambda-parentheses %t
+// 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() {
- // Basic cases - warn in all standards
auto a = []() { return 42; };
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: redundant empty parameter list in lambda expression
// CHECK-FIXES: auto call = [&v] { return v; };
- // Should NOT warn - has parameters
auto d = [](int x) { return x; };
auto e = [](int x, int y) { return x + y; };
- // Should NOT warn - macro
#define LAMBDA []() { return 42; }
auto k = LAMBDA;
#undef LAMBDA
- // Generic lambda - warns in C++20 and later
#if __cplusplus >= 202002L
auto f = []<class T>() { return sizeof(T); };
- // CHECK-MESSAGES-CXX20: :[[@LINE-1]]:23: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-MESSAGES-CXX20: :[[@LINE-1]]:23: warning: redundant empty parameter list in lambda expression
// CHECK-FIXES-CXX20: auto f = []<class T> { return sizeof(T); };
- // Should NOT warn - requires clause after parens
auto g = []<class T>() requires (sizeof(T) > 0) {};
- // Should NOT warn - has parameters
auto h = []<class T>(T x) { return x; };
#endif
- // Specifier cases - warn only in C++23, valid syntax in all standards
auto i = []() mutable {};
- // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression
// CHECK-FIXES-CXX23: auto n = [] constexpr { return 42; };
- // consteval only valid in C++20+
#if __cplusplus >= 202002L
auto o = []() consteval { return 42; };
- // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression
// CHECK-FIXES-CXX23: auto o = [] consteval { return 42; };
#endif
- // Should NOT warn - attribute after parens
auto p = []() [[]] {};
- // Should warn - attribute before parens
auto q = [] [[]] () {};
- // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: redundant empty parameter list in lambda expression
// CHECK-FIXES: auto q = [] {{\[\[}}{{\]\]}} {};
- // Should NOT warn - attribute both before and after parens
auto r = [] [[]] () [[]] {};
auto s = []() noexcept [[]] {};
- // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // 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 [readability-redundant-lambda-parentheses]
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: redundant empty parameter list in lambda expression
// CHECK-FIXES: auto x = [] /* comment */ { return 42; };
- // Should NOT warn - (void) is not truly empty parens
auto void1 = [](void) {};
auto void2 = [] (void) {};
- // Should NOT warn - macro between parens
#define EMPTY
#define VOID void
auto macro1 = [](EMPTY) {};
@@ -115,7 +102,6 @@ int main() {
#undef EMPTY
#undef VOID
-// Should NOT warn - macro for parens themselves
#define LPAREN (
#define RPAREN )
#define PARENS ()
@@ -129,14 +115,12 @@ int main() {
#if __cplusplus >= 202002L
template <bool B>
void testRequires() {
- // Should NOT warn - requires clause after parens
auto f1 = []() requires B {};
auto f2 = []() noexcept requires B {};
auto f3 = []<typename T>() requires B {};
- // Should warn - requires clause is before parens, parens are removable
auto f4 = []<typename T> requires B () {};
- // CHECK-MESSAGES-CXX20: :[[@LINE-1]]:39: warning: redundant empty parameter list in lambda expression [readability-redundant-lambda-parentheses]
+ // CHECK-MESSAGES-CXX20: :[[@LINE-1]]:39: warning: redundant empty parameter list in lambda expression
// CHECK-FIXES-CXX20: auto f4 = []<typename T> requires B {};
}
#endif
>From ad79194abc511b267d0a921b6ad9ed6d9937a257 Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Fri, 10 Apr 2026 18:39:21 +0300
Subject: [PATCH 20/20] [clang-tidy] Address review: add auto removed lines
from list.rst file
---
clang-tools-extra/docs/clang-tidy/checks/list.rst | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 88ced73de2656..a2d97fa086a77 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -241,6 +241,7 @@ Clang-Tidy Checks
:doc:`google-runtime-int <google/runtime-int>`,
:doc:`google-runtime-operator <google/runtime-operator>`,
:doc:`google-upgrade-googletest-case <google/upgrade-googletest-case>`, "Yes"
+ :doc:`hicpp-exception-baseclass <hicpp/exception-baseclass>`,
:doc:`hicpp-multiway-paths-covered <hicpp/multiway-paths-covered>`,
:doc:`hicpp-signed-bitwise <hicpp/signed-bitwise>`,
:doc:`linuxkernel-must-check-errs <linuxkernel/must-check-errs>`,
@@ -350,6 +351,7 @@ Clang-Tidy Checks
:doc:`openmp-use-default-none <openmp/use-default-none>`,
:doc:`performance-avoid-endl <performance/avoid-endl>`, "Yes"
:doc:`performance-enum-size <performance/enum-size>`,
+ :doc:`performance-faster-string-find <performance/faster-string-find>`, "Yes"
:doc:`performance-for-range-copy <performance/for-range-copy>`, "Yes"
:doc:`performance-implicit-conversion-in-loop <performance/implicit-conversion-in-loop>`,
:doc:`performance-inefficient-algorithm <performance/inefficient-algorithm>`, "Yes"
More information about the cfe-commits
mailing list