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/18] 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/18] 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/18] 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/18] 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/18] 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/18] 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/18] 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/18] 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/18] 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/18] 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/18] 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/18] 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/18] 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/18] 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/18] 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. ``[&](){ ... }``, ``[=](){ ... }``) >From 1172f730ba67151e560dc4ec46a203a8bf83a52b Mon Sep 17 00:00:00 2001 From: jjmarr-amd <jj.m...@amd.com> Date: Thu, 25 Sep 2025 10:29:37 -0400 Subject: [PATCH 16/18] update doc on-behalf-of: @amd <jj.m...@amd.com> --- .../readability/default-lambda-capture.rst | 62 +++++++++++-------- 1 file changed, 37 insertions(+), 25 deletions(-) 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 785f112a70b11..daabdd1a92995 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 @@ -5,39 +5,51 @@ readability-default-lambda-capture 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. +Captures can lead to subtle bugs including dangling references and unnecessary +copies. Writing out the name of the variables being captured reminds programmers +and reviewers to know what is being captured. And knowing is half the battle. -Implements Item 31 of Effective Modern C++ by Scott Meyers. +Coding guidelines that recommend against defaulted lambda captures include: + +* Item 31 of Effective Modern C++ by Scott Meyers +* `AUTOSAR C++ Rule A5-1-2 <https://www.mathworks.com/help//releases/ + R2021a/bugfinder/ref/autosarc14rulea512.html>`__ 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; }; + #include <iostream> + + class Widget { + std::vector<std::function<void(int)>> callbacks; + int widgetId; + void addCallback(int factoryId) { + callbacks.emplace_back( + [&](){ + std::cout << "Widget " << widgetId << " made in factory " << factoryId; + } + ); + } } -The check will warn on: - -- Default capture by copy: ``[=]`` -- Default capture by reference: ``[&]`` -- Mixed captures with defaults: ``[=, &x]`` or ``[&, x]`` +When ``callbacks`` is executed, ``factoryId`` will dangle. Writing the name of +``factoryId`` in the capture list makes it easy to review the captures and +detect obvious bugs. -The check will not warn on: +.. code-block:: c++ -- Explicit captures: ``[x]``, ``[&x]``, ``[x, y]``, ``[this]`` -- Empty capture lists: ``[]`` + #include <iostream> + + class Widget { + std::vector<std::function<void(int)>> callbacks; + int widgetId; + void addCallback(int factoryId) { + callbacks.emplace_back( + [&factoryId, &widgetId](){ // Why isn't factoryId captured by value?? + std::cout << "Widget " << widgetId << " made in factory " << factoryId; + } + ); + } + } >From 66e6aaa168928f18e8a427b0cf4abe21fb52fb9b Mon Sep 17 00:00:00 2001 From: jjmarr-amd <jj.m...@amd.com> Date: Thu, 25 Sep 2025 11:04:26 -0400 Subject: [PATCH 17/18] rename check to readability-avoid-default-lambda-capture on-behalf-of: @amd <jj.m...@amd.com> --- ...cpp => AvoidDefaultLambdaCaptureCheck.cpp} | 7 ++-- ...eck.h => AvoidDefaultLambdaCaptureCheck.h} | 12 +++---- .../clang-tidy/readability/CMakeLists.txt | 2 +- .../readability/ReadabilityTidyModule.cpp | 6 ++-- clang-tools-extra/docs/ReleaseNotes.rst | 4 +-- .../docs/clang-tidy/checks/list.rst | 2 +- ...e.rst => avoid-default-lambda-capture.rst} | 6 ++-- ...e.cpp => avoid-default-lambda-capture.cpp} | 32 +++++++++---------- 8 files changed, 36 insertions(+), 35 deletions(-) rename clang-tools-extra/clang-tidy/readability/{DefaultLambdaCaptureCheck.cpp => AvoidDefaultLambdaCaptureCheck.cpp} (83%) rename clang-tools-extra/clang-tidy/readability/{DefaultLambdaCaptureCheck.h => AvoidDefaultLambdaCaptureCheck.h} (64%) rename clang-tools-extra/docs/clang-tidy/checks/readability/{default-lambda-capture.rst => avoid-default-lambda-capture.rst} (91%) rename clang-tools-extra/test/clang-tidy/checkers/readability/{default-lambda-capture.cpp => avoid-default-lambda-capture.cpp} (83%) diff --git a/clang-tools-extra/clang-tidy/readability/DefaultLambdaCaptureCheck.cpp b/clang-tools-extra/clang-tidy/readability/AvoidDefaultLambdaCaptureCheck.cpp similarity index 83% rename from clang-tools-extra/clang-tidy/readability/DefaultLambdaCaptureCheck.cpp rename to clang-tools-extra/clang-tidy/readability/AvoidDefaultLambdaCaptureCheck.cpp index 60914fc7e7069..1036d764497b4 100644 --- a/clang-tools-extra/clang-tidy/readability/DefaultLambdaCaptureCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/AvoidDefaultLambdaCaptureCheck.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "DefaultLambdaCaptureCheck.h" +#include "AvoidDefaultLambdaCaptureCheck.h" #include "clang/ASTMatchers/ASTMatchFinder.h" using namespace clang::ast_matchers; @@ -20,11 +20,12 @@ AST_MATCHER(LambdaExpr, hasDefaultCapture) { } // namespace -void DefaultLambdaCaptureCheck::registerMatchers(MatchFinder *Finder) { +void AvoidDefaultLambdaCaptureCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher(lambdaExpr(hasDefaultCapture()).bind("lambda"), this); } -void DefaultLambdaCaptureCheck::check(const MatchFinder::MatchResult &Result) { +void AvoidDefaultLambdaCaptureCheck::check( + const MatchFinder::MatchResult &Result) { const auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda"); assert(Lambda); diff --git a/clang-tools-extra/clang-tidy/readability/DefaultLambdaCaptureCheck.h b/clang-tools-extra/clang-tidy/readability/AvoidDefaultLambdaCaptureCheck.h similarity index 64% rename from clang-tools-extra/clang-tidy/readability/DefaultLambdaCaptureCheck.h rename to clang-tools-extra/clang-tidy/readability/AvoidDefaultLambdaCaptureCheck.h index fd29d71b7c542..604cf85b2a71f 100644 --- a/clang-tools-extra/clang-tidy/readability/DefaultLambdaCaptureCheck.h +++ b/clang-tools-extra/clang-tidy/readability/AvoidDefaultLambdaCaptureCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DEFAULTLAMBDACAPTURECHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DEFAULTLAMBDACAPTURECHECK_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_AVOIDDEFAULTLAMBDACAPTURECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_AVOIDDEFAULTLAMBDACAPTURECHECK_H #include "../ClangTidyCheck.h" @@ -16,11 +16,11 @@ 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/readability/default-lambda-capture.html + * https://clang.llvm.org/extra/clang-tidy/checks/readability/avoid-default-lambda-capture.html */ -class DefaultLambdaCaptureCheck : public ClangTidyCheck { +class AvoidDefaultLambdaCaptureCheck : public ClangTidyCheck { public: - DefaultLambdaCaptureCheck(StringRef Name, ClangTidyContext *Context) + AvoidDefaultLambdaCaptureCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; @@ -31,4 +31,4 @@ class DefaultLambdaCaptureCheck : public ClangTidyCheck { } // namespace clang::tidy::readability -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DEFAULTLAMBDACAPTURECHECK_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_AVOIDDEFAULTLAMBDACAPTURECHECK_H diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index 829caa15377e6..b4e0c7b8a4a43 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS add_clang_library(clangTidyReadabilityModule STATIC AmbiguousSmartptrResetCallCheck.cpp AvoidConstParamsInDecls.cpp + AvoidDefaultLambdaCaptureCheck.cpp AvoidNestedConditionalOperatorCheck.cpp AvoidReturnWithVoidValueCheck.cpp AvoidUnconditionalPreprocessorIfCheck.cpp @@ -15,7 +16,6 @@ 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/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index 4b9bf3d417a7b..34c9e71926d18 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -11,6 +11,7 @@ #include "../ClangTidyModuleRegistry.h" #include "AmbiguousSmartptrResetCallCheck.h" #include "AvoidConstParamsInDecls.h" +#include "AvoidDefaultLambdaCaptureCheck.h" #include "AvoidNestedConditionalOperatorCheck.h" #include "AvoidReturnWithVoidValueCheck.h" #include "AvoidUnconditionalPreprocessorIfCheck.h" @@ -20,7 +21,6 @@ #include "ContainerDataPointerCheck.h" #include "ContainerSizeEmptyCheck.h" #include "ConvertMemberFunctionsToStatic.h" -#include "DefaultLambdaCaptureCheck.h" #include "DeleteNullPointerCheck.h" #include "DuplicateIncludeCheck.h" #include "ElseAfterReturnCheck.h" @@ -93,8 +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<AvoidDefaultLambdaCaptureCheck>( + "readability-avoid-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 6f29f0e99d6f7..d3edc1a9865ab 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -351,8 +351,8 @@ 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. +- New :doc:`readability-avoid-default-lambda-capture + <clang-tidy/checks/readability/avoid-default-lambda-capture>` check. Warns on default lambda captures (e.g. ``[&](){ ... }``, ``[=](){ ... }``) diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index e72cbf75fa03f..0b8dcd440e1f6 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -377,7 +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-avoid-default-lambda-capture <readability/avoid-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/readability/default-lambda-capture.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/avoid-default-lambda-capture.rst similarity index 91% rename from clang-tools-extra/docs/clang-tidy/checks/readability/default-lambda-capture.rst rename to clang-tools-extra/docs/clang-tidy/checks/readability/avoid-default-lambda-capture.rst index daabdd1a92995..9851896026be5 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/default-lambda-capture.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/avoid-default-lambda-capture.rst @@ -1,7 +1,7 @@ -.. title:: clang-tidy - readability-default-lambda-capture +.. title:: clang-tidy - readability-avoid-default-lambda-capture -readability-default-lambda-capture -================================== +readability-avoid-default-lambda-capture +========================================= Warns on default lambda captures (e.g. ``[&](){ ... }``, ``[=](){ ... }``) diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/default-lambda-capture.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/avoid-default-lambda-capture.cpp similarity index 83% rename from clang-tools-extra/test/clang-tidy/checkers/readability/default-lambda-capture.cpp rename to clang-tools-extra/test/clang-tidy/checkers/readability/avoid-default-lambda-capture.cpp index ecc45130a6cdf..f452ea6f6ccb1 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/default-lambda-capture.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/avoid-default-lambda-capture.cpp @@ -1,20 +1,20 @@ -// RUN: %check_clang_tidy %s readability-default-lambda-capture %t +// RUN: %check_clang_tidy %s readability-avoid-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 [readability-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-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 [readability-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-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 [readability-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-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 [readability-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-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 [readability-default-lambda-capture] - + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-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 [readability-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-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 [readability-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-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 [readability-default-lambda-capture] - + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture] + auto func2 = [=]() { return b; }; - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-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 [readability-default-lambda-capture] - + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-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 [readability-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-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 [readability-default-lambda-capture] + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture] } void instantiate_templates() { >From 4bf58b6eddee9b1027654653fa409d6bd668e79c Mon Sep 17 00:00:00 2001 From: jjmarr-amd <jj.m...@amd.com> Date: Thu, 25 Sep 2025 11:05:23 -0400 Subject: [PATCH 18/18] use C++ style comments on-behalf-of: @amd <jj.m...@amd.com> --- .../readability/AvoidDefaultLambdaCaptureCheck.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/AvoidDefaultLambdaCaptureCheck.h b/clang-tools-extra/clang-tidy/readability/AvoidDefaultLambdaCaptureCheck.h index 604cf85b2a71f..82262a210e4c4 100644 --- a/clang-tools-extra/clang-tidy/readability/AvoidDefaultLambdaCaptureCheck.h +++ b/clang-tools-extra/clang-tidy/readability/AvoidDefaultLambdaCaptureCheck.h @@ -13,11 +13,10 @@ 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/readability/avoid-default-lambda-capture.html - */ +/// Flags lambdas that use default capture modes +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/readability/avoid-default-lambda-capture.html class AvoidDefaultLambdaCaptureCheck : public ClangTidyCheck { public: AvoidDefaultLambdaCaptureCheck(StringRef Name, ClangTidyContext *Context) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits