https://github.com/jjmarr-amd updated https://github.com/llvm/llvm-project/pull/160150
>From 35df1c6ea3af8dbaea2d7049ae79b14ce39f0774 Mon Sep 17 00:00:00 2001 From: JJ Marr <jj.m...@amd.com> Date: Fri, 11 Jul 2025 14:40:57 -0400 Subject: [PATCH 01/15] Bugprone-default-lambda-capture on-behalf-of: @AMD <jj.m...@amd.com> --- .../bugprone/BugproneTidyModule.cpp | 3 + .../clang-tidy/bugprone/CMakeLists.txt | 1 + .../bugprone/DefaultLambdaCaptureCheck.cpp | 35 +++++++ .../bugprone/DefaultLambdaCaptureCheck.h | 26 +++++ clang-tools-extra/docs/ReleaseNotes.rst | 9 ++ .../bugprone/default-lambda-capture.rst | 42 ++++++++ .../docs/clang-tidy/checks/list.rst | 1 + .../bugprone/default-lambda-capture.cpp | 98 +++++++++++++++++++ 8 files changed, 215 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/bugprone/default-lambda-capture.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/bugprone/default-lambda-capture.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp index 491de6acea2b7..db99d57c511b8 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp @@ -23,6 +23,7 @@ #include "CopyConstructorInitCheck.h" #include "CrtpConstructorAccessibilityCheck.h" #include "DanglingHandleCheck.h" +#include "DefaultLambdaCaptureCheck.h" #include "DynamicStaticInitializersCheck.h" #include "EasilySwappableParametersCheck.h" #include "EmptyCatchCheck.h" @@ -134,6 +135,8 @@ class BugproneModule : public ClangTidyModule { "bugprone-copy-constructor-init"); CheckFactories.registerCheck<DanglingHandleCheck>( "bugprone-dangling-handle"); + CheckFactories.registerCheck<DefaultLambdaCaptureCheck>( + "bugprone-default-lambda-capture"); CheckFactories.registerCheck<DynamicStaticInitializersCheck>( "bugprone-dynamic-static-initializers"); CheckFactories.registerCheck<EasilySwappableParametersCheck>( diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt index 46bc8efd44bc5..66125c9d22c1c 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt @@ -19,6 +19,7 @@ add_clang_library(clangTidyBugproneModule STATIC CopyConstructorInitCheck.cpp CrtpConstructorAccessibilityCheck.cpp DanglingHandleCheck.cpp + DefaultLambdaCaptureCheck.cpp DynamicStaticInitializersCheck.cpp EasilySwappableParametersCheck.cpp EmptyCatchCheck.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp new file mode 100644 index 0000000000000..6c95fbc984c5a --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp @@ -0,0 +1,35 @@ +#include "DefaultLambdaCaptureCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::bugprone { + +void DefaultLambdaCaptureCheck::registerMatchers(MatchFinder *Finder) { + // Match any lambda expression + Finder->addMatcher(lambdaExpr().bind("lambda"), this); +} + +void DefaultLambdaCaptureCheck::check(const MatchFinder::MatchResult &Result) { + const auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda"); + if (!Lambda) + return; + + // Check if lambda has a default capture + if (Lambda->getCaptureDefault() == LCD_None) + return; + + SourceLocation DefaultCaptureLoc = Lambda->getCaptureDefaultLoc(); + if (DefaultCaptureLoc.isInvalid()) + return; + + const char *CaptureKind = + (Lambda->getCaptureDefault() == LCD_ByCopy) ? "by-copy" : "by-reference"; + + diag(DefaultCaptureLoc, "lambda %0 default capture is discouraged; " + "prefer to capture specific variables explicitly") + << CaptureKind; +} + +} // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h new file mode 100644 index 0000000000000..ac47c866cfccd --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h @@ -0,0 +1,26 @@ +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULT_LAMBDA_CAPTURE_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULT_LAMBDA_CAPTURE_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::bugprone { + +/** Flags lambdas that use default capture modes + * + * For the user-facing documentation see: + * http://clang.llvm.org/extra/clang-tidy/checks/bugprone/default-lambda-capture.html + */ +class DefaultLambdaCaptureCheck : public ClangTidyCheck { +public: + DefaultLambdaCaptureCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + std::optional<TraversalKind> getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } +}; + +} // namespace clang::tidy::bugprone + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULT_LAMBDA_CAPTURE_H diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 7cdff86beeec6..30d0bffb78f39 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -194,6 +194,15 @@ New checks Finds virtual function overrides with different visibility than the function in the base class. +- New :doc:`bugprone-default-lambda-capture + <clang-tidy/checks/bugprone/default-lambda-capture>` check. + + Finds lambda expressions that use default capture modes (``[=]`` or ``[&]``) + and suggests using explicit captures instead. Default captures can lead to + subtle bugs including dangling references with ``[&]``, unnecessary copies + with ``[=]``, and make code less maintainable by hiding which variables are + actually being captured. + New check aliases ^^^^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/default-lambda-capture.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/default-lambda-capture.rst new file mode 100644 index 0000000000000..026acf9f1894b --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/default-lambda-capture.rst @@ -0,0 +1,42 @@ +.. title:: clang-tidy - bugprone-default-lambda-capture + +bugprone-default-lambda-capture +=============================== + +Warns when lambda expressions use default capture modes (``[=]`` or ``[&]``) +instead of explicitly capturing specific variables. Default captures can make +code less readable and more error-prone by making it unclear which variables +are being captured and how. + +Implements Item 31 of Effective Modern C++ by Scott Meyers. + +Example +------- + +.. code-block:: c++ + + void example() { + int x = 1; + int y = 2; + + // Bad - default capture by copy + auto lambda1 = [=]() { return x + y; }; + + // Bad - default capture by reference + auto lambda2 = [&]() { return x + y; }; + + // Good - explicit captures + auto lambda3 = [x, y]() { return x + y; }; + auto lambda4 = [&x, &y]() { return x + y; }; + } + +The check will warn on: + +- Default capture by copy: ``[=]`` +- Default capture by reference: ``[&]`` +- Mixed captures with defaults: ``[=, &x]`` or ``[&, x]`` + +The check will not warn on: + +- Explicit captures: ``[x]``, ``[&x]``, ``[x, y]``, ``[this]`` +- Empty capture lists: ``[]`` diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index c490d2ece2e0a..cb6254ee36f42 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -91,6 +91,7 @@ Clang-Tidy Checks :doc:`bugprone-copy-constructor-init <bugprone/copy-constructor-init>`, "Yes" :doc:`bugprone-crtp-constructor-accessibility <bugprone/crtp-constructor-accessibility>`, "Yes" :doc:`bugprone-dangling-handle <bugprone/dangling-handle>`, + :doc:`bugprone-default-lambda-capture <bugprone/default-lambda-capture>`, :doc:`bugprone-dynamic-static-initializers <bugprone/dynamic-static-initializers>`, :doc:`bugprone-easily-swappable-parameters <bugprone/easily-swappable-parameters>`, :doc:`bugprone-empty-catch <bugprone/empty-catch>`, diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/default-lambda-capture.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/default-lambda-capture.cpp new file mode 100644 index 0000000000000..f820b4c9b8a0e --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/default-lambda-capture.cpp @@ -0,0 +1,98 @@ +// RUN: %check_clang_tidy %s bugprone-default-lambda-capture %t + +void test_default_captures() { + int value = 42; + int another = 10; + + auto lambda1 = [=](int x) { return value + x; }; + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda by-copy default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + + auto lambda2 = [&](int x) { return value + x; }; + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda by-reference default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + + auto lambda3 = [=, &another](int x) { return value + another + x; }; + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda by-copy default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + + auto lambda4 = [&, value](int x) { return value + another + x; }; + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda by-reference default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] +} + +void test_acceptable_captures() { + int value = 42; + int another = 10; + + auto lambda1 = [value](int x) { return value + x; }; + auto lambda2 = [&value](int x) { return value + x; }; + auto lambda3 = [value, another](int x) { return value + another + x; }; + auto lambda4 = [&value, &another](int x) { return value + another + x; }; + + auto lambda5 = [](int x, int y) { return x + y; }; + + struct S { + int member = 5; + void foo() { + auto lambda = [this]() { return member; }; + } + }; +} + +void test_nested_lambdas() { + int outer_var = 1; + int middle_var = 2; + int inner_var = 3; + + auto outer = [=]() { + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda by-copy default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + + auto inner = [&](int x) { return outer_var + middle_var + inner_var + x; }; + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda by-reference default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + + return inner(10); + }; +} + +void test_lambda_returns() { + int a = 1, b = 2, c = 3; + + auto create_adder = [=](int x) { + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: lambda by-copy default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + return [x](int y) { return x + y; }; // Inner lambda is fine - explicit capture + }; + + auto func1 = [&]() { return a; }; + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda by-reference default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + + auto func2 = [=]() { return b; }; + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda by-copy default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] +} + +class TestClass { + int member = 42; + +public: + void test_member_function_lambdas() { + int local = 10; + + auto lambda1 = [=]() { return member + local; }; + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: lambda by-copy default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + + auto lambda2 = [&]() { return member + local; }; + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: lambda by-reference default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + + auto lambda3 = [this, local]() { return member + local; }; + auto lambda4 = [this, &local]() { return member + local; }; + } +}; + +template<typename T> +void test_template_lambdas() { + T value{}; + + auto lambda = [=](T x) { return value + x; }; + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: lambda by-copy default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] +} + +void instantiate_templates() { + test_template_lambdas<int>(); + test_template_lambdas<double>(); +} >From 689f95b2ba46d6ca319e0735b5f5474bfc14f999 Mon Sep 17 00:00:00 2001 From: jjmarr-amd <jj.m...@amd.com> Date: Mon, 22 Sep 2025 09:58:59 -0400 Subject: [PATCH 02/15] Fix headers on-behalf-of: @amd <jj.m...@amd.com> --- .../clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp | 8 ++++++++ .../clang-tidy/bugprone/DefaultLambdaCaptureCheck.h | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp index 6c95fbc984c5a..0ee65df4b9860 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp @@ -1,3 +1,11 @@ +//===----------------------------------------------------------------------===// +// +// 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 "DefaultLambdaCaptureCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h index ac47c866cfccd..9af861aaf2e93 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h @@ -1,3 +1,11 @@ +//===----------------------------------------------------------------------===// +// +// 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_BUGPRONE_DEFAULT_LAMBDA_CAPTURE_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULT_LAMBDA_CAPTURE_H >From 9991b9ceda13c036e78c0e95978fe16f0bde5959 Mon Sep 17 00:00:00 2001 From: jjmarr-amd <jj.m...@amd.com> Date: Mon, 22 Sep 2025 10:21:44 -0400 Subject: [PATCH 03/15] remove superfluous comments. on-behalf-of: @amd <jj.m...@amd.com> --- .../clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp index 0ee65df4b9860..6db5cc8fc10bb 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp @@ -15,7 +15,6 @@ using namespace clang::ast_matchers; namespace clang::tidy::bugprone { void DefaultLambdaCaptureCheck::registerMatchers(MatchFinder *Finder) { - // Match any lambda expression Finder->addMatcher(lambdaExpr().bind("lambda"), this); } @@ -24,7 +23,6 @@ void DefaultLambdaCaptureCheck::check(const MatchFinder::MatchResult &Result) { if (!Lambda) return; - // Check if lambda has a default capture if (Lambda->getCaptureDefault() == LCD_None) return; >From db17a4c5a29faa47c69ddb48edb2b0316287c5bc Mon Sep 17 00:00:00 2001 From: "Marr, J J" <jj.m...@amd.com> Date: Mon, 22 Sep 2025 10:37:30 -0400 Subject: [PATCH 04/15] add new matcher on-behalf-of: @AMD <jj.m...@amd.com> --- .../bugprone/DefaultLambdaCaptureCheck.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp index 6db5cc8fc10bb..7fc3e571db220 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp @@ -14,8 +14,15 @@ using namespace clang::ast_matchers; namespace clang::tidy::bugprone { +namespace { +AST_MATCHER(LambdaExpr, hasDefaultCapture) { + return Node.getCaptureDefault() != LCD_None; +} + +} // namespace + void DefaultLambdaCaptureCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(lambdaExpr().bind("lambda"), this); + Finder->addMatcher(lambdaExpr(hasDefaultCapture()).bind("lambda"), this); } void DefaultLambdaCaptureCheck::check(const MatchFinder::MatchResult &Result) { @@ -23,8 +30,8 @@ void DefaultLambdaCaptureCheck::check(const MatchFinder::MatchResult &Result) { if (!Lambda) return; - if (Lambda->getCaptureDefault() == LCD_None) - return; + // No need to check getCaptureDefault() != LCD_None since our custom matcher + // hasDefaultCapture() already ensures this condition SourceLocation DefaultCaptureLoc = Lambda->getCaptureDefaultLoc(); if (DefaultCaptureLoc.isInvalid()) >From 7dcf2162c2a6df4057585e2898bc8feb4536a67c Mon Sep 17 00:00:00 2001 From: "Marr, J J" <jj.m...@amd.com> Date: Mon, 22 Sep 2025 11:51:27 -0400 Subject: [PATCH 05/15] Replace if with assert on-behalf-of: @amd <jj.m...@amd.com> --- .../clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp index 7fc3e571db220..4db95101025cc 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp @@ -27,11 +27,7 @@ void DefaultLambdaCaptureCheck::registerMatchers(MatchFinder *Finder) { void DefaultLambdaCaptureCheck::check(const MatchFinder::MatchResult &Result) { const auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda"); - if (!Lambda) - return; - - // No need to check getCaptureDefault() != LCD_None since our custom matcher - // hasDefaultCapture() already ensures this condition + assert(Lambda); SourceLocation DefaultCaptureLoc = Lambda->getCaptureDefaultLoc(); if (DefaultCaptureLoc.isInvalid()) >From 176d195cc753b3c95b9a82305e1fe1267e181cfa Mon Sep 17 00:00:00 2001 From: "Marr, J J" <jj.m...@amd.com> Date: Mon, 22 Sep 2025 11:52:40 -0400 Subject: [PATCH 06/15] Remove specific warning type on-behalf-of: @amd <jj.m...@amd.com> --- .../bugprone/DefaultLambdaCaptureCheck.cpp | 8 ++----- .../bugprone/default-lambda-capture.cpp | 24 +++++++++---------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp index 4db95101025cc..288feb7853e0b 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp @@ -33,12 +33,8 @@ void DefaultLambdaCaptureCheck::check(const MatchFinder::MatchResult &Result) { if (DefaultCaptureLoc.isInvalid()) return; - const char *CaptureKind = - (Lambda->getCaptureDefault() == LCD_ByCopy) ? "by-copy" : "by-reference"; - - diag(DefaultCaptureLoc, "lambda %0 default capture is discouraged; " - "prefer to capture specific variables explicitly") - << CaptureKind; + diag(DefaultCaptureLoc, "lambda default captures are discouraged; " + "prefer to capture specific variables explicitly"); } } // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/default-lambda-capture.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/default-lambda-capture.cpp index f820b4c9b8a0e..010edf11f0a2b 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/default-lambda-capture.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/default-lambda-capture.cpp @@ -5,16 +5,16 @@ void test_default_captures() { int another = 10; auto lambda1 = [=](int x) { return value + x; }; - // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda by-copy default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] auto lambda2 = [&](int x) { return value + x; }; - // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda by-reference default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] auto lambda3 = [=, &another](int x) { return value + another + x; }; - // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda by-copy default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] auto lambda4 = [&, value](int x) { return value + another + x; }; - // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda by-reference default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] } void test_acceptable_captures() { @@ -42,10 +42,10 @@ void test_nested_lambdas() { int inner_var = 3; auto outer = [=]() { - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda by-copy default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] auto inner = [&](int x) { return outer_var + middle_var + inner_var + x; }; - // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda by-reference default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] return inner(10); }; @@ -55,15 +55,15 @@ void test_lambda_returns() { int a = 1, b = 2, c = 3; auto create_adder = [=](int x) { - // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: lambda by-copy default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] return [x](int y) { return x + y; }; // Inner lambda is fine - explicit capture }; auto func1 = [&]() { return a; }; - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda by-reference default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] auto func2 = [=]() { return b; }; - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda by-copy default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] } class TestClass { @@ -74,10 +74,10 @@ class TestClass { int local = 10; auto lambda1 = [=]() { return member + local; }; - // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: lambda by-copy default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] auto lambda2 = [&]() { return member + local; }; - // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: lambda by-reference default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] auto lambda3 = [this, local]() { return member + local; }; auto lambda4 = [this, &local]() { return member + local; }; @@ -89,7 +89,7 @@ void test_template_lambdas() { T value{}; auto lambda = [=](T x) { return value + x; }; - // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: lambda by-copy default capture is discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] } void instantiate_templates() { >From 5f23dfff1a8368ebca7c2da691201ea1277ad128 Mon Sep 17 00:00:00 2001 From: jjmarr-amd <jj.m...@amd.com> Date: Mon, 22 Sep 2025 12:25:50 -0400 Subject: [PATCH 07/15] Sync documentation to release notes on-behalf-of: @amd <jj.m...@amd.com> --- .../checks/bugprone/default-lambda-capture.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/default-lambda-capture.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/default-lambda-capture.rst index 026acf9f1894b..f1fcf3ec52948 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/default-lambda-capture.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/default-lambda-capture.rst @@ -3,10 +3,11 @@ bugprone-default-lambda-capture =============================== -Warns when lambda expressions use default capture modes (``[=]`` or ``[&]``) -instead of explicitly capturing specific variables. Default captures can make -code less readable and more error-prone by making it unclear which variables -are being captured and how. + Finds lambda expressions that use default capture modes (``[=]`` or ``[&]``) + and suggests using explicit captures instead. Default captures can lead to + subtle bugs including dangling references with ``[&]``, unnecessary copies + with ``[=]``, and make code less maintainable by hiding which variables are + actually being captured. Implements Item 31 of Effective Modern C++ by Scott Meyers. >From 4c413327a64669d5254f0d6e343ca5c394701611 Mon Sep 17 00:00:00 2001 From: JJ Marr <jjmar...@amd.com> Date: Mon, 22 Sep 2025 13:00:22 -0400 Subject: [PATCH 08/15] Update clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h Co-authored-by: EugeneZelenko <eugene.zele...@gmail.com> --- .../clang-tidy/bugprone/DefaultLambdaCaptureCheck.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h index 9af861aaf2e93..ad48316708b1b 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h @@ -16,7 +16,7 @@ namespace clang::tidy::bugprone { /** Flags lambdas that use default capture modes * * For the user-facing documentation see: - * http://clang.llvm.org/extra/clang-tidy/checks/bugprone/default-lambda-capture.html + * https://clang.llvm.org/extra/clang-tidy/checks/bugprone/default-lambda-capture.html */ class DefaultLambdaCaptureCheck : public ClangTidyCheck { public: >From 330dbd8ca5eeed45d63d1a44c15eeb5357a8a4ef Mon Sep 17 00:00:00 2001 From: jjmarr-amd <jj.m...@amd.com> Date: Mon, 22 Sep 2025 13:01:23 -0400 Subject: [PATCH 09/15] Remove superfluous include on-behalf-of: @amd <jj.m...@amd.com> --- .../clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp index 288feb7853e0b..8f52aeb59ead6 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "DefaultLambdaCaptureCheck.h" -#include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" using namespace clang::ast_matchers; >From 31366e6b34dce3ab7e5f24d07f81ad10ecd9b875 Mon Sep 17 00:00:00 2001 From: jjmarr-amd <jj.m...@amd.com> Date: Mon, 22 Sep 2025 13:09:55 -0400 Subject: [PATCH 10/15] Fix doc and release notes on-behalf-of: @amd <jj.m...@amd.com> --- clang-tools-extra/docs/ReleaseNotes.rst | 14 +++++--------- .../checks/bugprone/default-lambda-capture.rst | 10 +++++----- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 780cf41373128..9d2e8dcad7045 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -167,6 +167,11 @@ New checks Detects default initialization (to 0) of variables with ``enum`` type where the enum has no enumerator with value of 0. +- New :doc:`bugprone-default-lambda-capture + <clang-tidy/checks/bugprone/default-lambda-capture>` check. + + Warns on default lambda captures (e.g. ``[&](){ ... }``, ``[=](){ ... }``) + - New :doc:`bugprone-derived-method-shadowing-base-method <clang-tidy/checks/bugprone/derived-method-shadowing-base-method>` check. @@ -203,15 +208,6 @@ New checks Finds virtual function overrides with different visibility than the function in the base class. -- New :doc:`bugprone-default-lambda-capture - <clang-tidy/checks/bugprone/default-lambda-capture>` check. - - Finds lambda expressions that use default capture modes (``[=]`` or ``[&]``) - and suggests using explicit captures instead. Default captures can lead to - subtle bugs including dangling references with ``[&]``, unnecessary copies - with ``[=]``, and make code less maintainable by hiding which variables are - actually being captured. - New check aliases ^^^^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/default-lambda-capture.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/default-lambda-capture.rst index f1fcf3ec52948..9cedc6276e1b3 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/default-lambda-capture.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/default-lambda-capture.rst @@ -3,11 +3,11 @@ bugprone-default-lambda-capture =============================== - Finds lambda expressions that use default capture modes (``[=]`` or ``[&]``) - and suggests using explicit captures instead. Default captures can lead to - subtle bugs including dangling references with ``[&]``, unnecessary copies - with ``[=]``, and make code less maintainable by hiding which variables are - actually being captured. +Warns on default lambda captures (e.g. ``[&](){ ... }``, ``[=](){ ... }``) + +Default captures can lead to subtle bugs including dangling references with +``[&]``, unnecessary copies with ``[=]``, and make code less maintainable by +hiding which variables are actually being captured. Implements Item 31 of Effective Modern C++ by Scott Meyers. >From 70df9dff73c3b3de4dcdfbed8b44186ff2000997 Mon Sep 17 00:00:00 2001 From: jjmarr-amd <jj.m...@amd.com> Date: Mon, 22 Sep 2025 14:43:19 -0400 Subject: [PATCH 11/15] Fix const on-behalf-of: @amd <jj.m...@amd.com> --- .../clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp index 8f52aeb59ead6..a7a18ccb30864 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp @@ -28,7 +28,7 @@ void DefaultLambdaCaptureCheck::check(const MatchFinder::MatchResult &Result) { const auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda"); assert(Lambda); - SourceLocation DefaultCaptureLoc = Lambda->getCaptureDefaultLoc(); + const SourceLocation DefaultCaptureLoc = Lambda->getCaptureDefaultLoc(); if (DefaultCaptureLoc.isInvalid()) return; >From 0bcdbc4373a6d320f49f30a64c647b1da3956756 Mon Sep 17 00:00:00 2001 From: jjmarr-amd <jj.m...@amd.com> Date: Tue, 23 Sep 2025 13:15:11 -0400 Subject: [PATCH 12/15] Fix header guard on-behalf-of: @amd <jj.m...@amd.com> --- .../clang-tidy/bugprone/DefaultLambdaCaptureCheck.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h index ad48316708b1b..fa69245b91c94 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULT_LAMBDA_CAPTURE_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULT_LAMBDA_CAPTURE_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULTLAMBDACAPTURE_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULTLAMBDACAPTURE_H #include "../ClangTidyCheck.h" @@ -31,4 +31,4 @@ class DefaultLambdaCaptureCheck : public ClangTidyCheck { } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULT_LAMBDA_CAPTURE_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULTLAMBDACAPTURE_H >From ac709f4fcf092da2b240b9e0a62d1f8c314fdebb Mon Sep 17 00:00:00 2001 From: jjmarr-amd <jj.m...@amd.com> Date: Tue, 23 Sep 2025 16:07:45 -0400 Subject: [PATCH 13/15] Fix header spelling on-behalf-of: @amd <jj.m...@amd.com> --- .../clang-tidy/bugprone/DefaultLambdaCaptureCheck.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h index fa69245b91c94..c41d7257592d5 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULTLAMBDACAPTURE_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULTLAMBDACAPTURE_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULTLAMBDACAPTURECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULTLAMBDACAPTURECHECK_H #include "../ClangTidyCheck.h" @@ -31,4 +31,4 @@ class DefaultLambdaCaptureCheck : public ClangTidyCheck { } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULTLAMBDACAPTURE_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULTLAMBDACAPTURECHECK_H >From 5d4c2ca704cce01a491ac38ecd25bf722b94ad78 Mon Sep 17 00:00:00 2001 From: jjmarr-amd <jj.m...@amd.com> Date: Wed, 24 Sep 2025 13:24:17 -0400 Subject: [PATCH 14/15] Rename check to readability-default-lambda-capture on-behalf-of: @amd <jj.m...@amd.com> --- .../bugprone/BugproneTidyModule.cpp | 3 --- .../clang-tidy/bugprone/CMakeLists.txt | 1 - .../clang-tidy/readability/CMakeLists.txt | 1 + .../DefaultLambdaCaptureCheck.cpp | 4 +-- .../DefaultLambdaCaptureCheck.h | 12 ++++----- .../readability/ReadabilityTidyModule.cpp | 3 +++ clang-tools-extra/docs/ReleaseNotes.rst | 10 +++---- .../docs/clang-tidy/checks/list.rst | 2 +- .../default-lambda-capture.rst | 4 +-- .../default-lambda-capture.cpp | 26 +++++++++---------- 10 files changed, 33 insertions(+), 33 deletions(-) rename clang-tools-extra/clang-tidy/{bugprone => readability}/DefaultLambdaCaptureCheck.cpp (94%) rename clang-tools-extra/clang-tidy/{bugprone => readability}/DefaultLambdaCaptureCheck.h (69%) rename clang-tools-extra/docs/clang-tidy/checks/{bugprone => readability}/default-lambda-capture.rst (91%) rename clang-tools-extra/test/clang-tidy/checkers/{bugprone => readability}/default-lambda-capture.cpp (84%) diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp index 67222cbafb5f9..8baa8f6b35d4c 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp @@ -23,7 +23,6 @@ #include "CopyConstructorInitCheck.h" #include "CrtpConstructorAccessibilityCheck.h" #include "DanglingHandleCheck.h" -#include "DefaultLambdaCaptureCheck.h" #include "DerivedMethodShadowingBaseMethodCheck.h" #include "DynamicStaticInitializersCheck.h" #include "EasilySwappableParametersCheck.h" @@ -137,8 +136,6 @@ class BugproneModule : public ClangTidyModule { "bugprone-copy-constructor-init"); CheckFactories.registerCheck<DanglingHandleCheck>( "bugprone-dangling-handle"); - CheckFactories.registerCheck<DefaultLambdaCaptureCheck>( - "bugprone-default-lambda-capture"); CheckFactories.registerCheck<DerivedMethodShadowingBaseMethodCheck>( "bugprone-derived-method-shadowing-base-method"); CheckFactories.registerCheck<DynamicStaticInitializersCheck>( diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt index c8c31f9f96bb0..b0dbe84a16cd4 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt @@ -19,7 +19,6 @@ add_clang_library(clangTidyBugproneModule STATIC CopyConstructorInitCheck.cpp CrtpConstructorAccessibilityCheck.cpp DanglingHandleCheck.cpp - DefaultLambdaCaptureCheck.cpp DerivedMethodShadowingBaseMethodCheck.cpp DynamicStaticInitializersCheck.cpp EasilySwappableParametersCheck.cpp diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index 4b4c49d3b17d1..829caa15377e6 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -15,6 +15,7 @@ add_clang_library(clangTidyReadabilityModule STATIC ContainerDataPointerCheck.cpp ContainerSizeEmptyCheck.cpp ConvertMemberFunctionsToStatic.cpp + DefaultLambdaCaptureCheck.cpp DeleteNullPointerCheck.cpp DuplicateIncludeCheck.cpp ElseAfterReturnCheck.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp b/clang-tools-extra/clang-tidy/readability/DefaultLambdaCaptureCheck.cpp similarity index 94% rename from clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp rename to clang-tools-extra/clang-tidy/readability/DefaultLambdaCaptureCheck.cpp index a7a18ccb30864..60914fc7e7069 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/DefaultLambdaCaptureCheck.cpp @@ -11,7 +11,7 @@ using namespace clang::ast_matchers; -namespace clang::tidy::bugprone { +namespace clang::tidy::readability { namespace { AST_MATCHER(LambdaExpr, hasDefaultCapture) { @@ -36,4 +36,4 @@ void DefaultLambdaCaptureCheck::check(const MatchFinder::MatchResult &Result) { "prefer to capture specific variables explicitly"); } -} // namespace clang::tidy::bugprone +} // namespace clang::tidy::readability diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h b/clang-tools-extra/clang-tidy/readability/DefaultLambdaCaptureCheck.h similarity index 69% rename from clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h rename to clang-tools-extra/clang-tidy/readability/DefaultLambdaCaptureCheck.h index c41d7257592d5..fd29d71b7c542 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DefaultLambdaCaptureCheck.h +++ b/clang-tools-extra/clang-tidy/readability/DefaultLambdaCaptureCheck.h @@ -6,17 +6,17 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULTLAMBDACAPTURECHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULTLAMBDACAPTURECHECK_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DEFAULTLAMBDACAPTURECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DEFAULTLAMBDACAPTURECHECK_H #include "../ClangTidyCheck.h" -namespace clang::tidy::bugprone { +namespace clang::tidy::readability { /** Flags lambdas that use default capture modes * * For the user-facing documentation see: - * https://clang.llvm.org/extra/clang-tidy/checks/bugprone/default-lambda-capture.html + * https://clang.llvm.org/extra/clang-tidy/checks/readability/default-lambda-capture.html */ class DefaultLambdaCaptureCheck : public ClangTidyCheck { public: @@ -29,6 +29,6 @@ class DefaultLambdaCaptureCheck : public ClangTidyCheck { } }; -} // namespace clang::tidy::bugprone +} // namespace clang::tidy::readability -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DEFAULTLAMBDACAPTURECHECK_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DEFAULTLAMBDACAPTURECHECK_H diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index d01882dfc9daa..4b9bf3d417a7b 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -20,6 +20,7 @@ #include "ContainerDataPointerCheck.h" #include "ContainerSizeEmptyCheck.h" #include "ConvertMemberFunctionsToStatic.h" +#include "DefaultLambdaCaptureCheck.h" #include "DeleteNullPointerCheck.h" #include "DuplicateIncludeCheck.h" #include "ElseAfterReturnCheck.h" @@ -92,6 +93,8 @@ class ReadabilityModule : public ClangTidyModule { "readability-container-size-empty"); CheckFactories.registerCheck<ConvertMemberFunctionsToStatic>( "readability-convert-member-functions-to-static"); + CheckFactories.registerCheck<DefaultLambdaCaptureCheck>( + "readability-default-lambda-capture"); CheckFactories.registerCheck<DeleteNullPointerCheck>( "readability-delete-null-pointer"); CheckFactories.registerCheck<DuplicateIncludeCheck>( diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 9d2e8dcad7045..6f29f0e99d6f7 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -167,11 +167,6 @@ New checks Detects default initialization (to 0) of variables with ``enum`` type where the enum has no enumerator with value of 0. -- New :doc:`bugprone-default-lambda-capture - <clang-tidy/checks/bugprone/default-lambda-capture>` check. - - Warns on default lambda captures (e.g. ``[&](){ ... }``, ``[=](){ ... }``) - - New :doc:`bugprone-derived-method-shadowing-base-method <clang-tidy/checks/bugprone/derived-method-shadowing-base-method>` check. @@ -356,6 +351,11 @@ Changes in existing checks <clang-tidy/checks/readability/uppercase-literal-suffix>` check to recognize literal suffixes added in C++23 and C23. +- New :doc:`readability-default-lambda-capture + <clang-tidy/checks/readability/default-lambda-capture>` check. + + Warns on default lambda captures (e.g. ``[&](){ ... }``, ``[=](){ ... }``) + Removed checks ^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 5232f650f6579..e72cbf75fa03f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -91,7 +91,6 @@ Clang-Tidy Checks :doc:`bugprone-copy-constructor-init <bugprone/copy-constructor-init>`, "Yes" :doc:`bugprone-crtp-constructor-accessibility <bugprone/crtp-constructor-accessibility>`, "Yes" :doc:`bugprone-dangling-handle <bugprone/dangling-handle>`, - :doc:`bugprone-default-lambda-capture <bugprone/default-lambda-capture>`, :doc:`bugprone-derived-method-shadowing-base-method <bugprone/derived-method-shadowing-base-method>`, :doc:`bugprone-dynamic-static-initializers <bugprone/dynamic-static-initializers>`, :doc:`bugprone-easily-swappable-parameters <bugprone/easily-swappable-parameters>`, @@ -378,6 +377,7 @@ Clang-Tidy Checks :doc:`readability-container-data-pointer <readability/container-data-pointer>`, "Yes" :doc:`readability-container-size-empty <readability/container-size-empty>`, "Yes" :doc:`readability-convert-member-functions-to-static <readability/convert-member-functions-to-static>`, "Yes" + :doc:`readability-default-lambda-capture <readability/default-lambda-capture>`, :doc:`readability-delete-null-pointer <readability/delete-null-pointer>`, "Yes" :doc:`readability-duplicate-include <readability/duplicate-include>`, "Yes" :doc:`readability-else-after-return <readability/else-after-return>`, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/default-lambda-capture.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/default-lambda-capture.rst similarity index 91% rename from clang-tools-extra/docs/clang-tidy/checks/bugprone/default-lambda-capture.rst rename to clang-tools-extra/docs/clang-tidy/checks/readability/default-lambda-capture.rst index 9cedc6276e1b3..00734b427d131 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/default-lambda-capture.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/default-lambda-capture.rst @@ -1,6 +1,6 @@ -.. title:: clang-tidy - bugprone-default-lambda-capture +.. title:: clang-tidy - readability-default-lambda-capture -bugprone-default-lambda-capture +readability-default-lambda-capture =============================== Warns on default lambda captures (e.g. ``[&](){ ... }``, ``[=](){ ... }``) diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/default-lambda-capture.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/default-lambda-capture.cpp similarity index 84% rename from clang-tools-extra/test/clang-tidy/checkers/bugprone/default-lambda-capture.cpp rename to clang-tools-extra/test/clang-tidy/checkers/readability/default-lambda-capture.cpp index 010edf11f0a2b..ecc45130a6cdf 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/default-lambda-capture.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/default-lambda-capture.cpp @@ -1,20 +1,20 @@ -// RUN: %check_clang_tidy %s bugprone-default-lambda-capture %t +// RUN: %check_clang_tidy %s readability-default-lambda-capture %t void test_default_captures() { int value = 42; int another = 10; auto lambda1 = [=](int x) { return value + x; }; - // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-default-lambda-capture] auto lambda2 = [&](int x) { return value + x; }; - // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-default-lambda-capture] auto lambda3 = [=, &another](int x) { return value + another + x; }; - // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-default-lambda-capture] auto lambda4 = [&, value](int x) { return value + another + x; }; - // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-default-lambda-capture] } void test_acceptable_captures() { @@ -42,10 +42,10 @@ void test_nested_lambdas() { int inner_var = 3; auto outer = [=]() { - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-default-lambda-capture] auto inner = [&](int x) { return outer_var + middle_var + inner_var + x; }; - // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-default-lambda-capture] return inner(10); }; @@ -55,15 +55,15 @@ void test_lambda_returns() { int a = 1, b = 2, c = 3; auto create_adder = [=](int x) { - // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-default-lambda-capture] return [x](int y) { return x + y; }; // Inner lambda is fine - explicit capture }; auto func1 = [&]() { return a; }; - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-default-lambda-capture] auto func2 = [=]() { return b; }; - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-default-lambda-capture] } class TestClass { @@ -74,10 +74,10 @@ class TestClass { int local = 10; auto lambda1 = [=]() { return member + local; }; - // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-default-lambda-capture] auto lambda2 = [&]() { return member + local; }; - // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-default-lambda-capture] auto lambda3 = [this, local]() { return member + local; }; auto lambda4 = [this, &local]() { return member + local; }; @@ -89,7 +89,7 @@ void test_template_lambdas() { T value{}; auto lambda = [=](T x) { return value + x; }; - // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [bugprone-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-default-lambda-capture] } void instantiate_templates() { >From c0b90d1d0a20ac71d4f6944e0818a1d56eba4acd Mon Sep 17 00:00:00 2001 From: JJ Marr <jjmar...@amd.com> Date: Wed, 24 Sep 2025 13:32:04 -0400 Subject: [PATCH 15/15] Update clang-tools-extra/docs/clang-tidy/checks/readability/default-lambda-capture.rst Co-authored-by: EugeneZelenko <eugene.zele...@gmail.com> --- .../clang-tidy/checks/readability/default-lambda-capture.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/default-lambda-capture.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/default-lambda-capture.rst index 00734b427d131..785f112a70b11 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/default-lambda-capture.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/default-lambda-capture.rst @@ -1,7 +1,7 @@ .. title:: clang-tidy - readability-default-lambda-capture readability-default-lambda-capture -=============================== +================================== Warns on default lambda captures (e.g. ``[&](){ ... }``, ``[=](){ ... }``) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits