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-...@users.noreply.github.com> Date: Wed, 27 Nov 2024 18:43:38 -0700 Subject: [PATCH 01/23] 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 a67c0b2b367d1..e7417d1a884dc 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-...@users.noreply.github.com> Date: Wed, 27 Nov 2024 18:48:37 -0700 Subject: [PATCH 02/23] 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 ce0c78d677099..ae43d4ebbdf82 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-...@users.noreply.github.com> Date: Wed, 27 Nov 2024 21:52:22 -0700 Subject: [PATCH 03/23] 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 e7417d1a884dc..82a0f926d6af7 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-...@users.noreply.github.com> Date: Wed, 27 Nov 2024 21:58:20 -0700 Subject: [PATCH 04/23] 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 82a0f926d6af7..049cecea0c587 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-...@users.noreply.github.com> Date: Wed, 27 Nov 2024 22:07:07 -0700 Subject: [PATCH 05/23] 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 049cecea0c587..57854f8814617 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-...@users.noreply.github.com> Date: Wed, 27 Nov 2024 22:15:07 -0700 Subject: [PATCH 06/23] 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 57854f8814617..0adf494fdc757 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-...@users.noreply.github.com> Date: Fri, 29 Nov 2024 02:59:55 -0700 Subject: [PATCH 07/23] 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 157d77b38b354..dfbee3569446f 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-...@users.noreply.github.com> Date: Fri, 29 Nov 2024 03:01:12 -0700 Subject: [PATCH 08/23] 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 03a58048e53a9..66cf331589e7a 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-...@users.noreply.github.com> Date: Fri, 29 Nov 2024 03:02:10 -0700 Subject: [PATCH 09/23] 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 0adf494fdc757..d33ed149cb5a9 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-...@users.noreply.github.com> Date: Fri, 20 Dec 2024 15:07:49 -0700 Subject: [PATCH 10/23] 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 d33ed149cb5a9..b2411a4b5f533 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-...@users.noreply.github.com> Date: Fri, 20 Dec 2024 15:08:14 -0700 Subject: [PATCH 11/23] 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 ae43d4ebbdf82..08394419ffe7c 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-...@users.noreply.github.com> Date: Fri, 20 Dec 2024 15:08:48 -0700 Subject: [PATCH 12/23] Update ParseExprCXX.cpp >From 0326d6e9dc3eb75606c5b463945dbd6bd005cdd3 Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Fri, 20 Dec 2024 15:09:30 -0700 Subject: [PATCH 13/23] 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 dfbee3569446f..1b224a0764364 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-...@users.noreply.github.com> Date: Fri, 20 Dec 2024 16:57:51 -0700 Subject: [PATCH 14/23] 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 1b224a0764364..fa967ae953e66 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-...@users.noreply.github.com> Date: Fri, 20 Dec 2024 16:58:52 -0700 Subject: [PATCH 15/23] Update ParseExprCXX.cpp >From cbda68a9a539c8f27f1783061c0e63fe7c3cae76 Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Fri, 20 Dec 2024 16:59:08 -0700 Subject: [PATCH 16/23] 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 b2411a4b5f533..f43b1becd6f8f 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-...@users.noreply.github.com> Date: Fri, 20 Dec 2024 16:59:39 -0700 Subject: [PATCH 17/23] Update fixit-unused-lambda-capture.cpp >From e41a05aeb010f646046522f221b80434b42c920b Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Fri, 20 Dec 2024 17:03:52 -0700 Subject: [PATCH 18/23] Update DiagnosticSemaKinds.td >From a830c8abd14691b159ee96dc49e54607aca5a6a7 Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Fri, 20 Dec 2024 17:04:14 -0700 Subject: [PATCH 19/23] Update ParseExprCXX.cpp >From a7c1d165ddc61d28be2c6511cb861a24c0c3a8b6 Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Fri, 20 Dec 2024 17:07:13 -0700 Subject: [PATCH 20/23] Update ParseExprCXX.cpp >From 82a16671a96f17f83c1bd3024f3cddf419b52706 Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Fri, 20 Dec 2024 17:07:32 -0700 Subject: [PATCH 21/23] Update SemaLambda.cpp >From cd72b630cc77a67c16e415cf2b7c783528dfa524 Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Thu, 26 Dec 2024 16:48:01 -0700 Subject: [PATCH 22/23] Update lambda-expressions.cpp s0 is now valid and doesn't trigger unexpected diagnostics. s0 avoids invalid lambda capture syntax. --- clang/test/SemaCXX/lambda-expressions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp index f3deb6ee3f424..6b31aa8a1f98e 100644 --- a/clang/test/SemaCXX/lambda-expressions.cpp +++ b/clang/test/SemaCXX/lambda-expressions.cpp @@ -598,7 +598,7 @@ struct S1 { }; void foo1() { - auto s0 = S1([name=]() {}); // expected-error {{expected expression}} + auto s0 = S1([]() {}); // Remove invalid capture, no diagnostic expected auto s1 = S1([name=name]() {}); // expected-error {{use of undeclared identifier 'name'; did you mean 'name1'?}} // cxx03-cxx11-warning@-1 {{initialized lambda captures are a C++14 extension}} } >From 0f9b9f86ecd54e6d86003a4d605658c112acd274 Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Thu, 13 Feb 2025 00:30:42 -0700 Subject: [PATCH 23/23] Update SemaLambda.cpp --- clang/lib/Sema/SemaLambda.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index f43b1becd6f8f..758488312e4f2 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1196,7 +1196,7 @@ 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()) { + if (C->InitCaptureType.get().isNull() ) { Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); // continue; // } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits