Skip to content

Commit 043df7c

Browse files
committed
commit vibe coded work
on-behalf-of: @amd <[email protected]>
1 parent 13b5049 commit 043df7c

File tree

2 files changed

+67
-2
lines changed

2 files changed

+67
-2
lines changed

clang-tools-extra/clang-tidy/readability/AvoidDefaultLambdaCaptureCheck.cpp

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#include "AvoidDefaultLambdaCaptureCheck.h"
1010
#include "clang/ASTMatchers/ASTMatchFinder.h"
11+
#include "clang/Basic/Lambda.h"
12+
#include "clang/Lex/Lexer.h"
1113

1214
using namespace clang::ast_matchers;
1315

@@ -18,6 +20,45 @@ AST_MATCHER(LambdaExpr, hasDefaultCapture) {
1820
return Node.getCaptureDefault() != LCD_None;
1921
}
2022

23+
std::string getCaptureString(const LambdaCapture &Capture) {
24+
if (Capture.capturesThis()) {
25+
return Capture.getCaptureKind() == LCK_StarThis ? "*this" : "this";
26+
}
27+
28+
if (Capture.capturesVariable()) {
29+
std::string Result;
30+
if (Capture.getCaptureKind() == LCK_ByRef) {
31+
Result += "&";
32+
}
33+
Result += Capture.getCapturedVar()->getName().str();
34+
return Result;
35+
}
36+
37+
// Handle VLA captures - these are rare but possible
38+
return "/* VLA capture */";
39+
}
40+
41+
std::string buildExplicitCaptureList(const LambdaExpr *Lambda) {
42+
std::vector<std::string> CaptureStrings;
43+
44+
// Add explicit captures first (preserve their order and syntax)
45+
for (const auto &Capture : Lambda->explicit_captures()) {
46+
CaptureStrings.push_back(getCaptureString(Capture));
47+
}
48+
49+
// Add implicit captures (convert to explicit syntax)
50+
for (const auto &Capture : Lambda->implicit_captures()) {
51+
CaptureStrings.push_back(getCaptureString(Capture));
52+
}
53+
54+
return "[" + llvm::join(CaptureStrings, ", ") + "]";
55+
}
56+
57+
SourceRange getCaptureListRange(const LambdaExpr *Lambda) {
58+
SourceRange IntroducerRange = Lambda->getIntroducerRange();
59+
return IntroducerRange;
60+
}
61+
2162
} // namespace
2263

2364
void AvoidDefaultLambdaCaptureCheck::registerMatchers(MatchFinder *Finder) {
@@ -33,8 +74,20 @@ void AvoidDefaultLambdaCaptureCheck::check(
3374
if (DefaultCaptureLoc.isInvalid())
3475
return;
3576

36-
diag(DefaultCaptureLoc, "lambda default captures are discouraged; "
37-
"prefer to capture specific variables explicitly");
77+
// Build the replacement capture list
78+
std::string NewCaptureList = buildExplicitCaptureList(Lambda);
79+
80+
// Get the range of the entire capture list [...]
81+
SourceRange CaptureListRange = getCaptureListRange(Lambda);
82+
83+
auto Diag = diag(DefaultCaptureLoc,
84+
"lambda default captures are discouraged; "
85+
"prefer to capture specific variables explicitly");
86+
87+
// Only provide fixit if we can determine a valid replacement
88+
if (CaptureListRange.isValid() && !NewCaptureList.empty()) {
89+
Diag << FixItHint::CreateReplacement(CaptureListRange, NewCaptureList);
90+
}
3891
}
3992

4093
} // namespace clang::tidy::readability

clang-tools-extra/test/clang-tidy/checkers/readability/avoid-default-lambda-capture.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,19 @@ void test_default_captures() {
66

77
auto lambda1 = [=](int x) { return value + x; };
88
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
9+
// CHECK-FIXES: auto lambda1 = [value](int x) { return value + x; };
910

1011
auto lambda2 = [&](int x) { return value + x; };
1112
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
13+
// CHECK-FIXES: auto lambda2 = [&value](int x) { return value + x; };
1214

1315
auto lambda3 = [=, &another](int x) { return value + another + x; };
1416
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
17+
// CHECK-FIXES: auto lambda3 = [&another, value](int x) { return value + another + x; };
1518

1619
auto lambda4 = [&, value](int x) { return value + another + x; };
1720
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
21+
// CHECK-FIXES: auto lambda4 = [value, &another](int x) { return value + another + x; };
1822
}
1923

2024
void test_acceptable_captures() {
@@ -43,9 +47,11 @@ void test_nested_lambdas() {
4347

4448
auto outer = [=]() {
4549
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
50+
// CHECK-FIXES: auto outer = [outer_var, middle_var, inner_var]() {
4651

4752
auto inner = [&](int x) { return outer_var + middle_var + inner_var + x; };
4853
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
54+
// CHECK-FIXES: auto inner = [&outer_var, &middle_var, &inner_var](int x) { return outer_var + middle_var + inner_var + x; };
4955

5056
return inner(10);
5157
};
@@ -56,14 +62,17 @@ void test_lambda_returns() {
5662

5763
auto create_adder = [=](int x) {
5864
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
65+
// CHECK-FIXES: auto create_adder = [](int x) {
5966
return [x](int y) { return x + y; }; // Inner lambda is fine - explicit capture
6067
};
6168

6269
auto func1 = [&]() { return a; };
6370
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
71+
// CHECK-FIXES: auto func1 = [&a]() { return a; };
6472

6573
auto func2 = [=]() { return b; };
6674
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
75+
// CHECK-FIXES: auto func2 = [b]() { return b; };
6776
}
6877

6978
class TestClass {
@@ -75,9 +84,11 @@ class TestClass {
7584

7685
auto lambda1 = [=]() { return member + local; };
7786
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
87+
// CHECK-FIXES: auto lambda1 = [this, local]() { return member + local; };
7888

7989
auto lambda2 = [&]() { return member + local; };
8090
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
91+
// CHECK-FIXES: auto lambda2 = [this, &local]() { return member + local; };
8192

8293
auto lambda3 = [this, local]() { return member + local; };
8394
auto lambda4 = [this, &local]() { return member + local; };
@@ -90,6 +101,7 @@ void test_template_lambdas() {
90101

91102
auto lambda = [=](T x) { return value + x; };
92103
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: lambda default captures are discouraged; prefer to capture specific variables explicitly [readability-avoid-default-lambda-capture]
104+
// CHECK-FIXES: auto lambda = [](T x) { return value + x; };
93105
}
94106

95107
void instantiate_templates() {

0 commit comments

Comments
 (0)