[clang] [clang-tools-extra] [clang-tidy] Add readability-avoid-default-lambda-capture (PR #160150)
Baranov Victor via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 9 11:55:30 PDT 2025
================
@@ -0,0 +1,143 @@
+// RUN: %check_clang_tidy %s readability-avoid-default-lambda-capture %t -- -- -Wno-vla-extension
+
+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-avoid-default-lambda-capture]
+ // CHECK-FIXES: auto lambda1 = [value](int x) { return value + x; };
+
+ 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-avoid-default-lambda-capture]
+ // CHECK-FIXES: auto lambda2 = [&value](int x) { return value + x; };
+
+ 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-avoid-default-lambda-capture]
+ // CHECK-FIXES: auto lambda3 = [value, &another](int x) { return value + another + x; };
+
+ 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-avoid-default-lambda-capture]
+ // CHECK-FIXES: auto lambda4 = [&another, value](int x) { return value + another + x; };
+}
+
+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 default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
+ // CHECK-FIXES: auto outer = [outer_var, middle_var, inner_var]() {
+
+ 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-avoid-default-lambda-capture]
+ // CHECK-FIXES: auto inner = [&outer_var, &middle_var, &inner_var](int x) { return outer_var + middle_var + inner_var + x; };
+
+ 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 default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
+ // CHECK-FIXES: auto create_adder = [](int x) {
+ 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-avoid-default-lambda-capture]
+ // CHECK-FIXES: auto func1 = [&a]() { return a; };
+
+ auto func2 = [=]() { return b; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
+ // CHECK-FIXES: auto func2 = [b]() { return b; };
+}
+
+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 default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
+ // CHECK-FIXES: auto lambda1 = [this, local]() { return member + local; };
+
+ auto lambda2 = [&]() { return member + local; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
+ // CHECK-FIXES: auto lambda2 = [this, &local]() { return member + local; };
+
+ auto lambda3 = [this, local]() { return member + local; };
+ auto lambda4 = [this, &local]() { return member + local; };
+ }
+};
+
+// Lambda captures dependent on a template parameter don't have a fix it
+template<typename T>
+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-avoid-default-lambda-capture]
+}
+
+void instantiate_templates() {
+ test_template_lambdas<int>();
+ test_template_lambdas<double>();
+}
+
+void test_init_captures() {
+ int x = 3;
+ int nx = 5;
+
+ int y1 = [&, z = x + 5]() -> int {
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
+ // CHECK-FIXES: int y1 = [&nx, z = x + 5]() -> int {
+ return z * z + nx;
+ }();
+
+ int y2 = [=, &ref = x]() {
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
+ // CHECK-FIXES: int y2 = [nx, &ref = x]() {
+ ref += 1;
+ return nx - ref;
+ }();
+
----------------
vbvictor wrote:
Please test `[&ref = x, =, z = x + 5]` capture
https://github.com/llvm/llvm-project/pull/160150
More information about the cfe-commits
mailing list