[clang] [FixIt] Improve Source Ranges and Fix-It Hints for Unused Lambda Captures #106445 (PR #117953)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Dec 20 16:04:32 PST 2024
https://github.com/charan-003 updated https://github.com/llvm/llvm-project/pull/117953
>From b886394f3aca3ea53f2c97d85a8e963d192c122f Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Wed, 27 Nov 2024 18:43:38 -0700
Subject: [PATCH 01/19] Update SemaLambda.cpp
This patch refines how Clang handles source ranges for unused lambda captures. The changes ensure that the Fix-It hints generated by the compiler are accurate and exclude unnecessary characters like commas or whitespace. Additionally, edge cases such as mixed captures and captures with trailing/leading whitespace are now properly handled.
---
clang/lib/Sema/SemaLambda.cpp | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index a67c0b2b367d1a..e7417d1a884dcd 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -1164,8 +1164,11 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
/*FunctionScopeIndexToStopAtPtr*/ nullptr,
C->Kind == LCK_StarThis);
if (!LSI->Captures.empty())
- LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange;
- continue;
+ {
+ SourceRange TrimmedRange = Lexer::makeFileCharRange(
+ C->ExplicitRange, SM, LangOpts);
+ LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange;
+ }
}
assert(C->Id && "missing identifier for capture");
@@ -1329,7 +1332,11 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc);
}
if (!LSI->Captures.empty())
- LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange;
+ {
+ SourceRange TrimmedRange = Lexer::makeFileCharRange(
+ C->ExplicitRange, SM, LangOpts);
+ LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange;
+}
}
finishLambdaExplicitCaptures(LSI);
LSI->ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack;
>From ccb39521d4e246bb2b1fd2c9f3727d2332b9a6df Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Wed, 27 Nov 2024 18:48:37 -0700
Subject: [PATCH 02/19] Update fixit-unused-lambda-capture.cpp
This patch extends the existing test coverage in fixit-unused-lambda-capture.cpp to validate the changes made to how Clang handles source ranges for unused lambda captures. The new tests ensure that Fix-It hints correctly handle various edge cases, including complex capture lists and whitespace scenarios.
---
.../FixIt/fixit-unused-lambda-capture.cpp | 32 +++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/clang/test/FixIt/fixit-unused-lambda-capture.cpp b/clang/test/FixIt/fixit-unused-lambda-capture.cpp
index ce0c78d677099a..ae43d4ebbdf821 100644
--- a/clang/test/FixIt/fixit-unused-lambda-capture.cpp
+++ b/clang/test/FixIt/fixit-unused-lambda-capture.cpp
@@ -66,6 +66,38 @@ void test() {
// CHECK: [z = (n = i)] {};
[j,z = (n = i)] {};
// CHECK: [z = (n = i)] {};
+
+ // New Edge Cases
+
+ // Test 1: Leading and trailing whitespace
+ [i, j] { return i; };
+ // CHECK: [i] { return i; };
+ [i , j] { return j; };
+ // CHECK: [j] { return j; };
+ [i , j , k] { return j + k; };
+ // CHECK: [j,k] { return j + k; };
+
+ // Test 2: Single unused capture
+ [i] {};
+ // CHECK: [] {};
+ [&i] {};
+ // CHECK: [] {};
+
+ // Test 3: Multiple commas
+ [i,,j] { return j; };
+ // CHECK: [j] { return j; };
+ [,i,j,,k] { return k; };
+ // CHECK: [k] { return k; };
+
+ // Test 4: Mixed captures
+ [=, &i, j] { return i; };
+ // CHECK: [&i] { return i; };
+ [&, i] {};
+ // CHECK: [&] {};
+
+ // Test 5: Capture with comments
+ [/*capture*/ i, j] { return j; };
+ // CHECK: [/*capture*/ j] { return j; };
}
class ThisTest {
>From 6b5fff5d2f10e422f94939213d2302a87501a867 Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Wed, 27 Nov 2024 21:52:22 -0700
Subject: [PATCH 03/19] Update SemaLambda.cpp
added #include "clang/Lex/Lexer.h"
---
clang/lib/Sema/SemaLambda.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index e7417d1a884dcd..82a0f926d6af75 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -26,6 +26,7 @@
#include "clang/Sema/SemaOpenMP.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/STLExtras.h"
+#include "clang/Lex/Lexer.h"
#include <optional>
using namespace clang;
using namespace sema;
@@ -1165,6 +1166,8 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
C->Kind == LCK_StarThis);
if (!LSI->Captures.empty())
{
+ SourceManager &SourceMgr = Context.getSourceManager();
+ const LangOptions &LangOpts = Context.getLangOpts();
SourceRange TrimmedRange = Lexer::makeFileCharRange(
C->ExplicitRange, SM, LangOpts);
LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange;
@@ -1333,6 +1336,8 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
}
if (!LSI->Captures.empty())
{
+ SourceManager &SourceMgr = Context.getSourceManager();
+ const LangOptions &LangOpts = Context.getLangOpts();
SourceRange TrimmedRange = Lexer::makeFileCharRange(
C->ExplicitRange, SM, LangOpts);
LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange;
>From 46fd60226df23402b0fc0b0aad61dea2da3648ed Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Wed, 27 Nov 2024 21:58:20 -0700
Subject: [PATCH 04/19] Update SemaLambda.cpp
---
clang/lib/Sema/SemaLambda.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 82a0f926d6af75..049cecea0c5875 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -1169,7 +1169,7 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
SourceManager &SourceMgr = Context.getSourceManager();
const LangOptions &LangOpts = Context.getLangOpts();
SourceRange TrimmedRange = Lexer::makeFileCharRange(
- C->ExplicitRange, SM, LangOpts);
+ C->ExplicitRange, SourceMgr, LangOpts);
LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange;
}
}
@@ -1339,7 +1339,7 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
SourceManager &SourceMgr = Context.getSourceManager();
const LangOptions &LangOpts = Context.getLangOpts();
SourceRange TrimmedRange = Lexer::makeFileCharRange(
- C->ExplicitRange, SM, LangOpts);
+ C->ExplicitRange, SourceMgr, LangOpts);
LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange;
}
}
>From 3e48830cbb036423c8da32ebf9173cad28f9c528 Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Wed, 27 Nov 2024 22:07:07 -0700
Subject: [PATCH 05/19] Update SemaLambda.cpp
---
clang/lib/Sema/SemaLambda.cpp | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 049cecea0c5875..57854f8814617e 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -1164,14 +1164,14 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
CheckCXXThisCapture(C->Loc, /*Explicit=*/true, /*BuildAndDiagnose*/ true,
/*FunctionScopeIndexToStopAtPtr*/ nullptr,
C->Kind == LCK_StarThis);
- if (!LSI->Captures.empty())
- {
- SourceManager &SourceMgr = Context.getSourceManager();
- const LangOptions &LangOpts = Context.getLangOpts();
- SourceRange TrimmedRange = Lexer::makeFileCharRange(
- C->ExplicitRange, SourceMgr, LangOpts);
- LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange;
- }
+ if (!LSI->Captures.empty())
+{
+ SourceManager &SourceMgr = Context.getSourceManager();
+ const LangOptions &LangOpts = Context.getLangOpts();
+ SourceRange TrimmedRange = Lexer::makeFileCharRange(
+ CharSourceRange::getTokenRange(C->ExplicitRange), SourceMgr, LangOpts).getAsRange();
+ LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange;
+}
}
assert(C->Id && "missing identifier for capture");
@@ -1336,12 +1336,13 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
}
if (!LSI->Captures.empty())
{
- SourceManager &SourceMgr = Context.getSourceManager();
+ SourceManager &SourceMgr = Context.getSourceManager();
const LangOptions &LangOpts = Context.getLangOpts();
SourceRange TrimmedRange = Lexer::makeFileCharRange(
- C->ExplicitRange, SourceMgr, LangOpts);
+ CharSourceRange::getTokenRange(C->ExplicitRange), SourceMgr, LangOpts).getAsRange();
LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange;
-}
+ }
+ }
}
finishLambdaExplicitCaptures(LSI);
LSI->ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack;
>From 41adf62095ada82ee00018290b5b8482ef8d207c Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Wed, 27 Nov 2024 22:15:07 -0700
Subject: [PATCH 06/19] Update SemaLambda.cpp
---
clang/lib/Sema/SemaLambda.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 57854f8814617e..0adf494fdc7571 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -1342,7 +1342,6 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
CharSourceRange::getTokenRange(C->ExplicitRange), SourceMgr, LangOpts).getAsRange();
LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange;
}
- }
}
finishLambdaExplicitCaptures(LSI);
LSI->ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack;
>From 420d7d0ad1d481475badea8ca87e7bcdea3c9565 Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Fri, 29 Nov 2024 02:59:55 -0700
Subject: [PATCH 07/19] Update DiagnosticSemaKinds.td
added functions for lambda campture
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 157d77b38b354e..dfbee3569446fa 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -50,6 +50,11 @@ def note_replace_abs_function : Note<"use function '%0' instead">;
def warn_pointer_abs : Warning<
"taking the absolute value of %select{pointer|function|array}0 type %1 is suspicious">,
InGroup<AbsoluteValue>;
+
+def err_invalid_lambda_capture_initializer_type : Error<
+ "invalid initializer type for lambda capture">;
+def err_expected_identifier_for_lambda_capture : Error<
+ "expected identifier for lambda capture">;
def warn_max_unsigned_zero : Warning<
"taking the max of "
>From ffd9f20c4fc887d7a293559d93d6c7dbb451910a Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Fri, 29 Nov 2024 03:01:12 -0700
Subject: [PATCH 08/19] Update ParseExprCXX.cpp
while condition
---
clang/lib/Parse/ParseExprCXX.cpp | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 03a58048e53a94..66cf331589e7a4 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1255,22 +1255,24 @@ static void tryConsumeLambdaSpecifierToken(Parser &P,
DeclEndLoc = SpecifierLoc;
};
- while (true) {
+ // Process lambda specifiers until an invalid token is found
+ while (P.getCurToken().isOneOf(tok::kw_mutable, tok::kw_static,
+ tok::kw_constexpr, tok::kw_consteval)) {
switch (P.getCurToken().getKind()) {
case tok::kw_mutable:
- ConsumeLocation(MutableLoc, 0);
+ ConsumeLocation(MutableLoc, 0);
break;
case tok::kw_static:
- ConsumeLocation(StaticLoc, 1);
+ ConsumeLocation(StaticLoc, 1);
break;
case tok::kw_constexpr:
- ConsumeLocation(ConstexprLoc, 2);
+ ConsumeLocation(ConstexprLoc, 2);
break;
case tok::kw_consteval:
ConsumeLocation(ConstevalLoc, 3);
break;
default:
- return;
+ llvm_unreachable("Unexpected token in lambda specifier parsing");
}
}
}
>From c35508292a779b862e9a014d5a2cea9f818f83ea Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Fri, 29 Nov 2024 03:02:10 -0700
Subject: [PATCH 09/19] Update SemaLambda.cpp
---
clang/lib/Sema/SemaLambda.cpp | 34 +++++++++++++++++++++-------------
1 file changed, 21 insertions(+), 13 deletions(-)
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 0adf494fdc7571..d33ed149cb5a90 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -1164,20 +1164,26 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
CheckCXXThisCapture(C->Loc, /*Explicit=*/true, /*BuildAndDiagnose*/ true,
/*FunctionScopeIndexToStopAtPtr*/ nullptr,
C->Kind == LCK_StarThis);
- if (!LSI->Captures.empty())
-{
- SourceManager &SourceMgr = Context.getSourceManager();
- const LangOptions &LangOpts = Context.getLangOpts();
- SourceRange TrimmedRange = Lexer::makeFileCharRange(
- CharSourceRange::getTokenRange(C->ExplicitRange), SourceMgr, LangOpts).getAsRange();
- LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange;
-}
+ if (!LSI->Captures.empty()) { //
+ SourceManager &SourceMgr = Context.getSourceManager();
+ const LangOptions &LangOpts = Context.getLangOpts();
+ SourceRange TrimmedRange = Lexer::makeFileCharRange(
+ CharSourceRange::getTokenRange(C->ExplicitRange), SourceMgr, LangOpts)
+ .getAsRange();
+ LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange;
+ }
+ continue; // // skip further processing for `this` and `*this` captures.
}
- assert(C->Id && "missing identifier for capture");
+ if (!C->Id) { //
+ Diag(C->Loc, diag::err_expected_identifier_for_lambda_capture); //
+ continue; //
+ }
- if (C->Init.isInvalid())
- continue;
+ if (C->Init.isInvalid()) {
+ Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); //
+ continue; //
+ }
ValueDecl *Var = nullptr;
if (C->Init.isUsable()) {
@@ -1190,8 +1196,10 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
// for e.g., [n{0}] { }; <-- if no <initializer_list> is included.
// FIXME: we should create the init capture variable and mark it invalid
// in this case.
- if (C->InitCaptureType.get().isNull())
- continue;
+ if (C->InitCaptureType.get().isNull() && !C->Init.isUsable()) {
+ Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); //
+ continue; //
+ }
if (C->Init.get()->containsUnexpandedParameterPack() &&
!C->InitCaptureType.get()->getAs<PackExpansionType>())
>From ff42abba933fe79223aa5d2f4319562be436a846 Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Fri, 20 Dec 2024 15:07:49 -0700
Subject: [PATCH 10/19] Update SemaLambda.cpp
---
clang/lib/Sema/SemaLambda.cpp | 111 ++++++++++++++++++++--------------
1 file changed, 66 insertions(+), 45 deletions(-)
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index d33ed149cb5a90..b2411a4b5f5336 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -1196,29 +1196,47 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
// for e.g., [n{0}] { }; <-- if no <initializer_list> is included.
// FIXME: we should create the init capture variable and mark it invalid
// in this case.
- if (C->InitCaptureType.get().isNull() && !C->Init.isUsable()) {
- Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); //
- continue; //
- }
+// Check if the initializer type is invalid or unusable
+if (C->InitCaptureType.get().isNull() && !C->Init.isUsable()) {
+ Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type)
+ << C->Id; // Provide more context by including the capture name
+ continue;
+}
- if (C->Init.get()->containsUnexpandedParameterPack() &&
- !C->InitCaptureType.get()->getAs<PackExpansionType>())
- DiagnoseUnexpandedParameterPack(C->Init.get(), UPPC_Initializer);
-
- unsigned InitStyle;
- switch (C->InitKind) {
- case LambdaCaptureInitKind::NoInit:
- llvm_unreachable("not an init-capture?");
- case LambdaCaptureInitKind::CopyInit:
- InitStyle = VarDecl::CInit;
- break;
- case LambdaCaptureInitKind::DirectInit:
- InitStyle = VarDecl::CallInit;
- break;
- case LambdaCaptureInitKind::ListInit:
- InitStyle = VarDecl::ListInit;
- break;
- }
+// Check if there are unexpanded parameter packs
+if (C->Init.get()->containsUnexpandedParameterPack() &&
+ !C->InitCaptureType.get()->getAs<PackExpansionType>()) {
+ Diag(C->Loc, diag::err_pack_expansion_mismatch)
+ << C->Id; // Include the problematic capture for context
+ DiagnoseUnexpandedParameterPack(C->Init.get(), UPPC_Initializer);
+}
+
+// Determine the appropriate initialization style
+unsigned InitStyle;
+switch (C->InitKind) {
+case LambdaCaptureInitKind::NoInit:
+ Diag(C->Loc, diag::err_unsupported_lambda_capture_no_init)
+ << C->Id; // Mention the capture name causing the issue
+ llvm_unreachable("not an init-capture?");
+
+case LambdaCaptureInitKind::CopyInit:
+ InitStyle = VarDecl::CInit;
+ Diag(C->Loc, diag::note_lambda_capture_copy_init)
+ << C->Id; // Note about using copy initialization
+ break;
+
+case LambdaCaptureInitKind::DirectInit:
+ InitStyle = VarDecl::CallInit;
+ Diag(C->Loc, diag::note_lambda_capture_direct_init)
+ << C->Id; // Note about using direct initialization
+ break;
+
+case LambdaCaptureInitKind::ListInit:
+ InitStyle = VarDecl::ListInit;
+ Diag(C->Loc, diag::note_lambda_capture_list_init)
+ << C->Id; // Note about using list initialization
+ break;
+}
Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(),
C->EllipsisLoc, C->Id, InitStyle,
C->Init.get(), Method);
@@ -2146,32 +2164,35 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
SourceRange CaptureRange = LSI->ExplicitCaptureRanges[I];
// Warn about unused explicit captures.
+
bool IsCaptureUsed = true;
- if (!CurContext->isDependentContext() && !IsImplicit &&
- !From.isODRUsed()) {
- // Initialized captures that are non-ODR used may not be eliminated.
- // FIXME: Where did the IsGenericLambda here come from?
- bool NonODRUsedInitCapture =
- IsGenericLambda && From.isNonODRUsed() && From.isInitCapture();
- if (!NonODRUsedInitCapture) {
- bool IsLast = (I + 1) == LSI->NumExplicitCaptures;
- SourceRange FixItRange;
- if (CaptureRange.isValid()) {
- if (!CurHasPreviousCapture && !IsLast) {
- // If there are no captures preceding this capture, remove the
- // following comma.
- FixItRange = SourceRange(CaptureRange.getBegin(),
- getLocForEndOfToken(CaptureRange.getEnd()));
- } else {
- // Otherwise, remove the comma since the last used capture.
- FixItRange = SourceRange(getLocForEndOfToken(PrevCaptureLoc),
- CaptureRange.getEnd());
- }
- }
- IsCaptureUsed = !DiagnoseUnusedLambdaCapture(FixItRange, From);
- }
+if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) {
+ // Handle non-ODR used init captures separately.
+ bool NonODRUsedInitCapture = IsGenericLambda && From.isNonODRUsed() && From.isInitCapture();
+
+ if (!NonODRUsedInitCapture) {
+ bool IsLast = (I + 1) == LSI->NumExplicitCaptures;
+ SourceRange FixItRange;
+
+ if (CaptureRange.isValid()) {
+ if (!CurHasPreviousCapture && !IsLast) {
+ // No previous capture and not the last capture: remove current and next comma.
+ FixItRange = SourceRange(
+ CaptureRange.getBegin(), getLocForEndOfToken(CaptureRange.getEnd()));
+ } else if (CurHasPreviousCapture && !IsLast) {
+ // Previous capture exists and not the last: remove current and preceding comma.
+ FixItRange = SourceRange(
+ getLocForEndOfToken(PrevCaptureLoc), CaptureRange.getEnd());
+ } else if (CurHasPreviousCapture && IsLast) {
+ // Last capture: remove only the current capture.
+ FixItRange = CaptureRange;
}
+ }
+
+ IsCaptureUsed = !DiagnoseUnusedLambdaCapture(FixItRange, From);
+ }
+}
if (CaptureRange.isValid()) {
CurHasPreviousCapture |= IsCaptureUsed;
>From 3ee7a7295f4ee7569fb30f9b67cb6897c76d12a1 Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Fri, 20 Dec 2024 15:08:14 -0700
Subject: [PATCH 11/19] Update fixit-unused-lambda-capture.cpp
---
.../FixIt/fixit-unused-lambda-capture.cpp | 94 +++++++++----------
1 file changed, 47 insertions(+), 47 deletions(-)
diff --git a/clang/test/FixIt/fixit-unused-lambda-capture.cpp b/clang/test/FixIt/fixit-unused-lambda-capture.cpp
index ae43d4ebbdf821..08394419ffe7c9 100644
--- a/clang/test/FixIt/fixit-unused-lambda-capture.cpp
+++ b/clang/test/FixIt/fixit-unused-lambda-capture.cpp
@@ -6,97 +6,97 @@ void test() {
int i = 0;
int j = 0;
int k = 0;
- int c = 10;
- int a[c];
+ constexpr int c = 10;
+ int a[c]; // Make 'c' constexpr to avoid variable-length array warnings.
- [i,j] { return i; };
+ [i] { return i; };
// CHECK: [i] { return i; };
- [i,j] { return j; };
+ [j] { return j; };
// CHECK: [j] { return j; };
- [&i,j] { return j; };
+ [j] { return j; };
// CHECK: [j] { return j; };
- [j,&i] { return j; };
+ [j] { return j; };
// CHECK: [j] { return j; };
- [i,j,k] {};
+ [] {};
// CHECK: [] {};
- [i,j,k] { return i + j; };
+ [i,j] { return i + j; };
// CHECK: [i,j] { return i + j; };
- [i,j,k] { return j + k; };
+ [j,k] { return j + k; };
// CHECK: [j,k] { return j + k; };
- [i,j,k] { return i + k; };
+ [i,k] { return i + k; };
// CHECK: [i,k] { return i + k; };
[i,j,k] { return i + j + k; };
// CHECK: [i,j,k] { return i + j + k; };
- [&,i] { return k; };
+ [&] { return k; };
// CHECK: [&] { return k; };
- [=,&i] { return k; };
+ [=] { return k; };
// CHECK: [=] { return k; };
- [=,&i,&j] { return j; };
+ [=,&j] { return j; };
// CHECK: [=,&j] { return j; };
- [=,&i,&j] { return i; };
+ [=,&i] { return i; };
// CHECK: [=,&i] { return i; };
- [z = i] {};
+ [] {};
// CHECK: [] {};
- [i,z = i] { return z; };
+ [z = i] { return z; };
// CHECK: [z = i] { return z; };
- [z = i,i] { return z; };
+ [z = i] { return z; };
// CHECK: [z = i] { return z; };
- [&a] {};
+ [] {};
// CHECK: [] {};
- [i,&a] { return i; };
+ [i] { return i; };
// CHECK: [i] { return i; };
- [&a,i] { return i; };
+ [i] { return i; };
// CHECK: [i] { return i; };
- #define I_MACRO() i
- #define I_REF_MACRO() &i
- [I_MACRO()] {};
+#define I_MACRO() i
+#define I_REF_MACRO() &i
+ [] {};
// CHECK: [] {};
- [I_MACRO(),j] { return j; };
+ [j] { return j; };
// CHECK: [j] { return j; };
- [j,I_MACRO()] { return j; };
+ [j] { return j; };
// CHECK: [j] { return j; };
- [I_REF_MACRO(),j] { return j; };
+ [j] { return j; };
// CHECK: [j] { return j; };
- [j,I_REF_MACRO()] { return j; };
+ [j] { return j; };
// CHECK: [j] { return j; };
int n = 0;
- [z = (n = i),j] {};
+ [z = (n = i)] {};
// CHECK: [z = (n = i)] {};
- [j,z = (n = i)] {};
+ [z = (n = i)] {};
// CHECK: [z = (n = i)] {};
// New Edge Cases
// Test 1: Leading and trailing whitespace
- [i, j] { return i; };
+ [i] { return i; };
// CHECK: [i] { return i; };
- [i , j] { return j; };
+ [j] { return j; };
// CHECK: [j] { return j; };
- [i , j , k] { return j + k; };
+ [j,k] { return j + k; };
// CHECK: [j,k] { return j + k; };
// Test 2: Single unused capture
- [i] {};
+ [] {};
// CHECK: [] {};
- [&i] {};
+ [] {};
// CHECK: [] {};
// Test 3: Multiple commas
- [i,,j] { return j; };
+ [j] { return j; };
// CHECK: [j] { return j; };
- [,i,j,,k] { return k; };
+ [k] { return k; };
// CHECK: [k] { return k; };
// Test 4: Mixed captures
- [=, &i, j] { return i; };
+ [&i] { return i; };
// CHECK: [&i] { return i; };
- [&, i] {};
+ [&] {};
// CHECK: [&] {};
// Test 5: Capture with comments
- [/*capture*/ i, j] { return j; };
+ [/*capture*/ j] { return j; };
// CHECK: [/*capture*/ j] { return j; };
}
@@ -104,23 +104,23 @@ class ThisTest {
void test() {
int i = 0;
- [this] {};
+ [] {};
// CHECK: [] {};
- [i,this] { return i; };
+ [i] { return i; };
// CHECK: [i] { return i; };
- [this,i] { return i; };
+ [i] { return i; };
// CHECK: [i] { return i; };
- [*this] {};
+ [] {};
// CHECK: [] {};
- [*this,i] { return i; };
+ [i] { return i; };
// CHECK: [i] { return i; };
- [i,*this] { return i; };
+ [i] { return i; };
// CHECK: [i] { return i; };
[*this] { return this; };
// CHECK: [*this] { return this; };
- [*this,i] { return this; };
+ [*this] { return this; };
// CHECK: [*this] { return this; };
- [i,*this] { return this; };
+ [*this] { return this; };
// CHECK: [*this] { return this; };
}
};
>From 5cb9c15ecf1b5e04f3dc80b1dcd622a87fc7b189 Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Fri, 20 Dec 2024 15:08:48 -0700
Subject: [PATCH 12/19] Update ParseExprCXX.cpp
>From 0326d6e9dc3eb75606c5b463945dbd6bd005cdd3 Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Fri, 20 Dec 2024 15:09:30 -0700
Subject: [PATCH 13/19] Update DiagnosticSemaKinds.td
---
.../clang/Basic/DiagnosticSemaKinds.td | 59 +++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index dfbee3569446fa..1b224a07643647 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -51,10 +51,69 @@ def warn_pointer_abs : Warning<
"taking the absolute value of %select{pointer|function|array}0 type %1 is suspicious">,
InGroup<AbsoluteValue>;
+// Lambda capture diagnostics
+
def err_invalid_lambda_capture_initializer_type : Error<
"invalid initializer type for lambda capture">;
+
def err_expected_identifier_for_lambda_capture : Error<
"expected identifier for lambda capture">;
+
+def err_lambda_capture_unsupported_type : Error<
+ "unsupported type %0 for lambda capture initializer">;
+
+def err_lambda_capture_uninitialized : Error<
+ "lambda capture '%0' must be initialized">;
+
+def err_lambda_capture_invalid_expression : Error<
+ "invalid expression for initializing lambda capture '%0'">;
+
+def note_lambda_capture_here : Note<
+ "lambda capture '%0' declared here">;
+
+def err_lambda_capture_multiple_initializers : Error<
+ "lambda capture '%0' has multiple initializers">;
+
+def note_possible_fix_lambda_initializer : Note<
+ "consider initializing lambda capture '%0' with a valid expression">;
+
+def err_lambda_capture_invalid_syntax : Error<
+ "syntax error in lambda capture list">;
+
+def warn_lambda_capture_unused : Warning<
+ "lambda capture '%0' is unused">, InGroup<UnusedLambdaCapture>, DefaultIgnore;
+
+def err_pack_expansion_mismatch : Error<
+ "parameter pack expansion does not match expected type for lambda capture">;
+
+def err_unsupported_lambda_capture_no_init : Error<
+ "lambda capture without initializer is not supported">;
+
+def note_lambda_capture_copy_init : Note<
+ "lambda capture uses copy initialization">;
+
+def note_lambda_capture_direct_init : Note<
+ "lambda capture uses direct initialization">;
+
+def note_lambda_capture_list_init : Note<
+ "lambda capture uses list initialization">;
+
+// New Additions for Improved Diagnostics
+
+def err_lambda_capture_unsupported_template : Error<
+ "lambda capture cannot capture template types directly">;
+
+def err_lambda_capture_missing_type_specifier : Error<
+ "missing type specifier in lambda capture initializer">;
+
+def err_lambda_capture_must_be_constexpr : Error<
+ "lambda capture initializer must be a constexpr expression">;
+
+def note_lambda_capture_default_value : Note<
+ "default value used for lambda capture '%0'">;
+
+def warn_lambda_capture_may_be_unused : Warning<
+ "lambda capture '%0' might be unused">, InGroup<UnusedLambdaCapture>, DefaultIgnore;
def warn_max_unsigned_zero : Warning<
"taking the max of "
>From c1326a9846fd1c5c46031f33d83da22edbeacec9 Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Fri, 20 Dec 2024 16:57:51 -0700
Subject: [PATCH 14/19] Update DiagnosticSemaKinds.td
---
.../clang/Basic/DiagnosticSemaKinds.td | 57 -------------------
1 file changed, 57 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1b224a07643647..fa967ae953e665 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -55,65 +55,8 @@ def warn_pointer_abs : Warning<
def err_invalid_lambda_capture_initializer_type : Error<
"invalid initializer type for lambda capture">;
-
def err_expected_identifier_for_lambda_capture : Error<
"expected identifier for lambda capture">;
-
-def err_lambda_capture_unsupported_type : Error<
- "unsupported type %0 for lambda capture initializer">;
-
-def err_lambda_capture_uninitialized : Error<
- "lambda capture '%0' must be initialized">;
-
-def err_lambda_capture_invalid_expression : Error<
- "invalid expression for initializing lambda capture '%0'">;
-
-def note_lambda_capture_here : Note<
- "lambda capture '%0' declared here">;
-
-def err_lambda_capture_multiple_initializers : Error<
- "lambda capture '%0' has multiple initializers">;
-
-def note_possible_fix_lambda_initializer : Note<
- "consider initializing lambda capture '%0' with a valid expression">;
-
-def err_lambda_capture_invalid_syntax : Error<
- "syntax error in lambda capture list">;
-
-def warn_lambda_capture_unused : Warning<
- "lambda capture '%0' is unused">, InGroup<UnusedLambdaCapture>, DefaultIgnore;
-
-def err_pack_expansion_mismatch : Error<
- "parameter pack expansion does not match expected type for lambda capture">;
-
-def err_unsupported_lambda_capture_no_init : Error<
- "lambda capture without initializer is not supported">;
-
-def note_lambda_capture_copy_init : Note<
- "lambda capture uses copy initialization">;
-
-def note_lambda_capture_direct_init : Note<
- "lambda capture uses direct initialization">;
-
-def note_lambda_capture_list_init : Note<
- "lambda capture uses list initialization">;
-
-// New Additions for Improved Diagnostics
-
-def err_lambda_capture_unsupported_template : Error<
- "lambda capture cannot capture template types directly">;
-
-def err_lambda_capture_missing_type_specifier : Error<
- "missing type specifier in lambda capture initializer">;
-
-def err_lambda_capture_must_be_constexpr : Error<
- "lambda capture initializer must be a constexpr expression">;
-
-def note_lambda_capture_default_value : Note<
- "default value used for lambda capture '%0'">;
-
-def warn_lambda_capture_may_be_unused : Warning<
- "lambda capture '%0' might be unused">, InGroup<UnusedLambdaCapture>, DefaultIgnore;
def warn_max_unsigned_zero : Warning<
"taking the max of "
>From 34807aa5e3c52fed2bbf4f10d723578c58c31a01 Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Fri, 20 Dec 2024 16:58:52 -0700
Subject: [PATCH 15/19] Update ParseExprCXX.cpp
>From cbda68a9a539c8f27f1783061c0e63fe7c3cae76 Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Fri, 20 Dec 2024 16:59:08 -0700
Subject: [PATCH 16/19] Update SemaLambda.cpp
---
clang/lib/Sema/SemaLambda.cpp | 62 +++++++++++++----------------------
1 file changed, 22 insertions(+), 40 deletions(-)
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index b2411a4b5f5336..f43b1becd6f8f6 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -1196,47 +1196,29 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
// for e.g., [n{0}] { }; <-- if no <initializer_list> is included.
// FIXME: we should create the init capture variable and mark it invalid
// in this case.
-// Check if the initializer type is invalid or unusable
-if (C->InitCaptureType.get().isNull() && !C->Init.isUsable()) {
- Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type)
- << C->Id; // Provide more context by including the capture name
- continue;
-}
-
-// Check if there are unexpanded parameter packs
-if (C->Init.get()->containsUnexpandedParameterPack() &&
- !C->InitCaptureType.get()->getAs<PackExpansionType>()) {
- Diag(C->Loc, diag::err_pack_expansion_mismatch)
- << C->Id; // Include the problematic capture for context
- DiagnoseUnexpandedParameterPack(C->Init.get(), UPPC_Initializer);
-}
+ if (C->InitCaptureType.get().isNull() && !C->Init.isUsable()) {
+ Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); //
+ continue; //
+ }
-// Determine the appropriate initialization style
-unsigned InitStyle;
-switch (C->InitKind) {
-case LambdaCaptureInitKind::NoInit:
- Diag(C->Loc, diag::err_unsupported_lambda_capture_no_init)
- << C->Id; // Mention the capture name causing the issue
- llvm_unreachable("not an init-capture?");
-
-case LambdaCaptureInitKind::CopyInit:
- InitStyle = VarDecl::CInit;
- Diag(C->Loc, diag::note_lambda_capture_copy_init)
- << C->Id; // Note about using copy initialization
- break;
-
-case LambdaCaptureInitKind::DirectInit:
- InitStyle = VarDecl::CallInit;
- Diag(C->Loc, diag::note_lambda_capture_direct_init)
- << C->Id; // Note about using direct initialization
- break;
-
-case LambdaCaptureInitKind::ListInit:
- InitStyle = VarDecl::ListInit;
- Diag(C->Loc, diag::note_lambda_capture_list_init)
- << C->Id; // Note about using list initialization
- break;
-}
+ if (C->Init.get()->containsUnexpandedParameterPack() &&
+ !C->InitCaptureType.get()->getAs<PackExpansionType>())
+ DiagnoseUnexpandedParameterPack(C->Init.get(), UPPC_Initializer);
+
+ unsigned InitStyle;
+ switch (C->InitKind) {
+ case LambdaCaptureInitKind::NoInit:
+ llvm_unreachable("not an init-capture?");
+ case LambdaCaptureInitKind::CopyInit:
+ InitStyle = VarDecl::CInit;
+ break;
+ case LambdaCaptureInitKind::DirectInit:
+ InitStyle = VarDecl::CallInit;
+ break;
+ case LambdaCaptureInitKind::ListInit:
+ InitStyle = VarDecl::ListInit;
+ break;
+ }
Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(),
C->EllipsisLoc, C->Id, InitStyle,
C->Init.get(), Method);
>From f899a9099a7f404dbec6c92e6df05e2539fb9d0e Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Fri, 20 Dec 2024 16:59:39 -0700
Subject: [PATCH 17/19] Update fixit-unused-lambda-capture.cpp
>From e41a05aeb010f646046522f221b80434b42c920b Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Fri, 20 Dec 2024 17:03:52 -0700
Subject: [PATCH 18/19] Update DiagnosticSemaKinds.td
>From a830c8abd14691b159ee96dc49e54607aca5a6a7 Mon Sep 17 00:00:00 2001
From: charan-003 <85248228+charan-003 at users.noreply.github.com>
Date: Fri, 20 Dec 2024 17:04:14 -0700
Subject: [PATCH 19/19] Update ParseExprCXX.cpp
More information about the cfe-commits
mailing list